Segédosztályok

Mint az előzőekben látható volt, sok metódust bitekkel dolgozó osztályok metódusaira vezettünk vissza. Ideje ezeket az osztályokat is bemutatni. Lássunk először is áttekintő ábrát!

5.8. ábra - Bitek tárolására használt osztályok

Bitek tárolására használt osztályok

E két osztály ismertetését a program futásához nélkülözhetetlen osztályok bemutatása követi.

Mivel a Main osztályban dolgozzuk fel az operációs rendszertől származó inputot, újra sok osztályra kell hivatkozni. Attribútum ebben az osztályban nincs, viszont bevezetünk pár konstanst, ha változik a program indításakor használt paraméterek száma vagy sorrendje, akkor a ne kelljen a main metódusban sokat változtatni. Jelen állapotban a következő módon kell futtatni a programot:

java -jar particio.jar run.txt HCAll2 Value

A run.txt tartalmazza az egyes gráfokat tartalmazó állományok nevét, és a rajta futtatandó tesztek számát. A HCAll2 a keresési módszer nevét, és az ábrázolás kódját tartalmazza. Jelenleg ez a kód 1,2 vagy 3 lehet. Ezt követi a kiírás módja. Mivel ez a keresi módszer nem használ paramétereket, így a negyedik argumentum elhagyható.

5.9. ábra - Tesztek futtatását intéző osztályok

Tesztek futtatását intéző osztályok

A programban használt konstansok jelentős részét egy külön osztályba szerveztük, hogy egységesen, egy helyen lehessen megváltoztatni azokat.

BitMatrix

Mind a gráf mátrixa, mind a csoportosítás leírás lehetséges bitmátrix segítségével. Ez a mátrix egy négyzetes mátrix, melynek sorait bitvektorokba fogjuk össze:

package hu.unideb.inf.optimization.clustering;
import java.util.Arrays;
/**
 * A bitmátrix egy négyzetes bitmátrix.
 * @see BitVector
 * @author ASZALÓS László
 */
class BitMatrix {

A bitmátrix valójában bitvektorok vektora:

private BitVector[] data;

Az egyedüli konstruktor a bitmátrix méretét kapja meg:

/**
 * Bitmátrix megadásánál a méretére van szükség.
 * @param size négyzetes mátrix egy oldalának mérete bitekben.
 */
BitMatrix(final int size) {
    data = new BitVector[size];
    for (int i = 0; i < size; i++) {
        data[i] = new BitVector(size);
    }
}

Ha törölni kívánjuk a mátrixot, akkor minden sorát törölni kell:

/** BitMátrix törlése.*/
final void clean() {
    for (int i = 0; i < data.length; i++) {
        data[i].clean();
    }
}

Létrehozunk egy új mátrixot, melybe átmásoljuk az adatokat, és ezt adjuk vissza:

/** Bitmátrix klónozása.*/
final BitMatrix copy() {
    BitMatrix c = new BitMatrix(data.length);
    for (int i = 0; i < data.length; i++) {
        c.data[i] = data[i].copy();
    }
    return c;
}

A mátrix méretét kifejezhetjük bit-ben és long-ban is:

/** Mekkora a mátrix oldalának hossza?
 * @return bitMátrix mérete
 */
final int getSize() {
    return data.length;
}

/**
 * Hány <code>long</code> alkotja a mátrix egy sorát?
 * @return mátrix mérete
 */
final int getLongs() {
    return data[0].getLongs();
}

Lekérdezhetjük a mátrix egy adott bitjét, egy long-ját, és teljes sorát:

/**
 * Lekérdezi a bitmátrix (<code>i</code>, <code>j</code>) indexű bitjét.
 * @param i sorindex
 * @param j oszlopindex
 * @return adott bit értéke
 */
final int getXY(final int i, final int j) {
    return data[i].getX(j);
}

/**
 * Lekérjük az <code>i</code>-dik sor <code>j</code>-dik egészét.
 * @param i sorindex
 * @param j oszlopindex
 * @return <code>BITSIZE</code>-nyi bit
 */
final long getLong(final int i, final int j) {
    return data[i].getLong(j);
}

/**
 * Lekérjük a mátrix <code>i</code>-dik sorát.
 * @param i kért sor indexe
 * @return a sort tartalmazó bitvektor
 */
final BitVector getVector(final int i) {
    return data[i];
}

A csoportosítások bitmátrixos ábrázolása esetén egy-egy sor alkot egy-egy csoportot, és minden egyes csúcsnak egy oszlop felel meg, így ha arra vagyunk kíváncsiak, hogy adott elemnek mi a csoportja, akkor az oszlopot kell ellenőrizni:

/**
 * Melyik csoportba tartozik az <code>i</code>-dik elem?
 * A mátrix melyik sorában van az <code>i</code>-dik oszlopban 1-es?
 * @param i elem indexe
 * @return csoport (sor) azonosítója
 */
final int getX(final int i) {
    int j = 0;
    while (j < getSize() && getXY(j,i) == 0) {
        j++;
    }
    return j;
}

A legnagyobb csoportnak az a sor felel meg, melyben a legtöbb egyes található. Így a sorokban található egyeseket kell összeszámolni, és megkeresni a maximumot:

/**
 * A bitmátrix soraiban mennyi maximális egyes található?
 * @return maximális csoport mérete
 */
final int maxGroup() {
    int max = 0;
    int current;
    for (int i = 0; i < getSize(); i++) {
        current = data[i].countBits();
        if (max < current) {
            max = current;
        }
    }
    return max;
}

Az ábrázolás sajátosságai miatt a normalizálás igen egyszerűen megy, azok a sorok kerülnek előre, melyekben legkorábban szerepel egyes:

/**
 * A mátrix sorait átrendezzük.
 */
final void normalize() {
    Arrays.sort(data);
}

A mátrix elemeinek törlésére és beállítására vonatkozó kéréseket továbbadjuk a sorok vektorainak:

/**
 * Állítsa 1-re a  bitmátrix (<code>i</code>,
 * <code>j</code>) indexű bitjét!
 * @param i sorindex
 * @param j oszlopindex
 */
final void setXY(final int i, final int j) {
    if (i < 0 || getSize() <= i) {
        throw new IllegalArgumentException();
    }
    data[i].setX(j);
}

/**
 * Törölje a bitmátrix (<code>i</code>, <code>j</code>) indexű bitjét!
 *
 * @param i sorindex
 * @param j oszlopindex
 */
final void unSetXY(final int i, final int j) {
    data[i].unSetX(j);
}

Ha a csoportosítás számára használjuk mátrixot, akkor egy elem beállítása egy törlést is igényel, amit persze megint átdobunk a vektoroknak:

/**
 * Bitmátrix egy elemének beállítása.
 * @param i elem indexe
 * @param x új csoport azonosítója
 * @param j régi csoport azonosítója
 */
final void setX(final int i, final int x, final int j) {
    unSetXY(j, i);
    setXY(x, i);
}

A tesztelést megint elősegítjük átlátható formában megjelenített mátrixokkal:

@Override
public final String toString() {
    StringBuilder st = new StringBuilder();
    for (int i = 0; i < getSize(); i++) {
        st.append(data[i].toString());
        st.append("\n");
    }
    return st.toString();
}}

Bitvektor

A bitmátrix sorait külön kezeljük, hogy átláthatóbbá váljon a kód:

package hu.unideb.inf.optimization.clustering;
import static hu.unideb.inf.optimization.clustering.Constants.*;
/**
 * A bitmátrix sorait külön adatszerkezet tárolja.
 * @see BitMatrix
 * @author ASZALÓS László
 */
class BitVector implements Comparable<BitVector> {

Adatainkat hosszú egészek tömbjében tároljuk, hogy a processzor bitműveleteit kihasználhassuk:

private long[] data;

Feljegyezzük, hogy hány bittel kell dolgoznunk, mert a long adatszerkezet miatt rendszerint marad kihasználatlan bitsorozat, melyet nem kell bolygatni:

private int mySize;

Az egyedüli konstruktor a vektor hosszát kapja meg:

/**
 * Meg kell adnunk, mekkora lesz a bitvektor mérete.
 * @param size tárolandó bitek száma
 */
BitVector(final int size) {
    int number = (int) Math.ceil((float) size / BITSIZE);
    data = new long[number];
    mySize = size;
}

A bitműveletek alapból a long típusra adottak. Ezt mi két esetben kibővítjük egész vektorokra, ami persze a long-on alapul:

final int bitAnd(final BitVector b) {
    int count = 0;
    for (int i = 0; i < getLongs(); i++) {
        count += Long.bitCount(getLong(i) & b.getLong(i));
    }
    return count;
}

final int bitNotAnd(final BitVector b) {
    int count = 0;
    for (int i = 0; i < getLongs(); i++) {
        count += Long.bitCount(~getLong(i) & b.getLong(i));
    }
    return count;
}

Nem bitenként törlünk, hanem a long-ot használjuk:

/** Bitvektor törlése */
final void clean() {
    for (int j = 0; j < getLongs(); j++) {
        data[j] = 0;
    }
}

A másolathoz megalkotunk egy vektort, melyet az eredeti alapján töltünk fel. A sebesség miatt itt is a long-ot használjuk:

/** Bitvektor klónozása
 */
final BitVector copy() {
    BitVector w = new BitVector(getSize());
    for (int j = 0; j < getLongs(); j++) {
        w.setLong(j, getLong(j));
    }
    return w;
}

A vektor hosszát lekérdezhetjük bitben és long-ban is:

/** Mekkora a méret?
 * @return bitMátrix mérete
 */
final int getSize() {
    return mySize;
}
/**
 * Hány egészből áll a bitvektor ?
 * @return vektor mérete egészekben
 */
final int getLongs() {
    return data.length;
}

Lekérdezhetünk és be is állíthatunk a vektorból/ban akár egy bitet, akár egy long-ot. A bitek beállítását bitműveletek felhasználásával gyorsítjuk fel:

/**
 * Lekérdezzük a <code>j</code>-dik bitet.
 * @param j keresett bit indexe
 * @return a bit értéke
 */
final int getX(final int j) {
    int no = j / BITSIZE;
    int bit = j % BITSIZE;
    long mask = (long) 1 << bit;
    long result = data[no] & mask;
    if (0 < result) {
        return 1;
    }
    return 0;
}
/**
 * Visszaadunk <code>BITSIZE</code> bitet
 * @param j keresett <code>long</code> indexe
 * @return a <code>long</code> értéke
 */
final long getLong(final int j) {
    return this.data[j];
}

/**
 * A bitVektor <code>j</code>-dik bitjét állítsuk 1-re.
 * @param j beállítandó bit indexe
 */
final void setX(final int j) {
    int no = j / BITSIZE;
    int bit = j % BITSIZE;
    long mask = (long) 1 << bit;
    data[no] |= mask;
}

/**
 * A bitVektor <code>j</code>-dik bitjét töröljük.
 * @param j törlendő bit indexe
 */
final void unSetX(final int j) {
    int no = j / BITSIZE;
    int bit = j % BITSIZE;
    long mask = (long) 1 << bit;
    data[no] &= ~mask;
}

/** Beállít egyszerre <code>BITSIZE</code> bitet.
 * @param j beállítandó <code>long</code> indexe
 * @param x beállítandó érték
 */
final void setLong(final int j, final long x) {
    this.data[j] = x;
}

Annak érdekében, hogy a bitmátrixnál a normalizálás működjön, szükséges a vektorok összehasonlíthatósága. Mint ott leírtuk, az számít, hogy hol van az első egyes, azaz a vektor hány nullással kezdődik:

public int compareTo(final BitVector bv) {
    return trailingZeros() - bv.trailingZeros();
}

Sajnos ilyen rutin nincs a Java-ban, nekünk kell megírni egy kis segítséggel:

/** Melyik az első egyes bit a vektorban?
 * forrás: http://www.hackersdelight.org/
 * @return első egyes indexe
 */
final protected int trailingZeros() {
    int i = 0;
    while (i < getLongs() && getLong(i) == 0) { i++; }
    if (i == getLongs()) { return getSize(); }
    long x = getLong(i);
    int n = 1;
    long u = x & 0xFFFFFFFFL;
    if ((x & 0xFFFFFFFFL) == 0) { n = n + 32; x = x >> 32; }
    if ((x & 0x0000FFFF) == 0)  { n = n + 16; x = x >> 16; }
    if ((x & 0x000000FF) == 0)  { n = n +  8; x = x >>  8; }
    if ((x & 0x0000000F) == 0)  { n = n +  4; x = x >>  4; }
    if ((x & 0x00000003) == 0)  { n = n +  2; x = x >>  2; }
    return n - (int) (x & 1) + i * BITSIZE;
}

A legnagyobb csoport meghatározásához szükség volt a vektor egyeseinek számára. Így összegeznünk kell a long-ok egyeseinek a számát:

/** Hány 1-es bit van a bitvektorban?
 * @return bitvektor egyeseinek száma
 */
final int countBits() {
    int sum = 0;
    for (int i = 0; i < data.length; i++) {
        sum += Long.bitCount(getLong(i));
    }
    return sum;
}

Itt is hasznos a debug számára az érthető kiírás

@Override
public final String toString() {
    StringBuilder st = new StringBuilder();
    for (int j = 0; j < getSize(); j++) {
        st.append(getX(j));
    }
    return st.toString();
}
}

Solution

Annak érdekében, hogy a Main osztály minél egyszerűbb legyen, a programnak átadott paramétereket feldolgozó, illetve az eredményeket kiíró rutinokat egy külön osztályba szerveztük:

package hu.unideb.inf.optimization.clustering;
import static hu.unideb.inf.optimization.clustering.Constants.MYPACKAGE;
import hu.unideb.inf.optimization.methods.PrintSolution;
import hu.unideb.inf.optimization.methods.SolvingMethod;
import java.net.URL;
/**
 * Correlációs klaszterezés megoldásához segédmódszerek
 * @author ASZALÓS László
 */
public class Solution {

Annak érdekében, hogy futtatni tudjuk a keresési módszert valamely gráfra, szükséges a klaszterezés feladatát leíró adatszerkezet (benne a gráf mátrixával):

private Cluster x;

Valamint majd azt is tudnunk kell, hogy milyen módszerrel kívánjuk keresni a megoldást:

SolvingMethod method = null;

A módszerek felsorolását nem építettük be a programba. Így egy új módszer megadásakor nem kell ehhez az osztályhoz hozzányúlni. Lustaság miatt a módszer nevéhez a főprogram inputjában hozzácsapjuk az ábrázolás azonosító kódját. Az alábbi metódus ezt a két adatok dolgozza fel.

Természetesen a névről le kell választani ezt az egy karaktert, és meg kell vizsgálni, hogy létezik-e a megadott nevű keresési módszer. Ha ez bármilyen okból nem létezik, vagy nem vehető használatba, akkor felesleges elindítani a keresést. Ha viszont használható, a method változóba bekerül a módszer:

/**
 * Feldolgozzuk a megadott eljárást.
 * @param nameType eljárás neve és ábrázolás kódja
 */
void manageMethod(String nameType) {
    String name = nameType.substring(0, nameType.length() - 1);
    String fullname = MYPACKAGE + ".methods." + name;
    try {
        Object obj = Class.forName(fullname).newInstance();
        if (!(obj instanceof SolvingMethod)) {
            System.err.println("Unknow solving method: " + name);
            System.exit(1);
        }
        method = (SolvingMethod) obj;
    } catch (ClassNotFoundException e) {
        System.out.println("Name: " + name + "  Full: " + fullname);
        System.err.printf("Class %s is not found.\n", name);
        System.exit(1); 
    } catch (InstantiationException e) {
        System.err.printf("Cannot instantiante %s.\n", name);
        System.exit(1); 
    } catch (IllegalAccessException e) {
        System.err.printf("Illegal access of %s.\n", name);
        System.exit(1); 
    }
}

A megoldási módszernek attribútuma, hogy hogyan írjuk ki az eredményeket. Ennek az attribútumnak itt adunk értéket. Az előzőekben látott módszerrel dolgozunk. Ha a kiírási módszer nem értelmezhető a rendszer számára, a feldolgozás megszakad, egyébként az attribútumot beállítjuk:

/**
 * Megadjuk, hogy hogyan írjuk ki az eredményeket.
 * @param prMethod a kiírásra használt módszer
 */
void managePrint(String prMethod) {
    PrintSolution print = null;
    try {
        String printName = MYPACKAGE + ".clustering.Print" + prMethod;
        Object obj = Class.forName(printName).newInstance();
        if (!(obj instanceof PrintSolution)) {
            System.err.println("Unknow printing method: " + prMethod);
            System.exit(1);
        }
        print = (PrintSolution) obj;
    } catch (ClassNotFoundException e) {
        System.err.printf("Class Print%s is not found.%n", prMethod);
        System.exit(1); 
    } catch (InstantiationException e) {
        System.err.printf("Cannot instantiante %s.\n", prMethod);
        System.exit(1); 
    } catch (IllegalAccessException e) {
        System.err.printf("Illegal access of %s.\n", prMethod);
        System.exit(1); 
    }
    method.setPrint(print);
}

Két hasonló metódus következik, eltérés csak a függvényparaméterek típusában van. Szükségünk lesz egy mátrixra és egy csoportosításra. Majd megállapítjuk az inputként kapott paraméterekben melyik adatábrázolási módszert kérte a felhasználó. Ennek megfelelő típusú mátrixot hozunk létre az adott cím (URL vagy lokális fájl) alapján, és természetesen neki megfelelő méretű és típusú csoportosítást generálunk mellé. Végül a mátrixból és csoportosításból kész a klaszter, mellyel elkezdhetjük a keresést:

/**
 * Beolvassuk a mátrixot az internetről.
 * @param matrix mátrixot leíró fájl URL-je
 */
void manageMatrixURL(URL matrix, String myMethod) {
    Matrix m=null;
    Groups  g=null;
    int ch = myMethod.codePointAt(myMethod.length() - 1) - 48;
    switch (ch) {
        case 1:
            m = new MatrixBits(matrix);
            g = new GroupsB(m.getSize());
            break;
        case 2:
            m = new MatrixBits(matrix);
            g = new GroupsBN(m.getSize());
            break;
        case 3:
            m = new MatrixByte(matrix);
            g = new GroupsN(m.getSize());
            break;
        default:
            System.err.println("Unknow storage method!");
            System.exit(1);
    }
    x=new Cluster(g,m);
}

/**
 * Beolvassuk a mátrixot egy helyi fájlból
 * @param matrix mátrixot leíró fájl neve
 */
void manageMatrixString(String matrix, String myMethod) {
    Matrix m=null;
    Groups  g=null;
    int ch = myMethod.codePointAt(myMethod.length() - 1) - 48;
    switch (ch) {
        case 1:
            m = new MatrixBits(matrix);
            g = new GroupsB(m.getSize());
            break;
        case 2:
            m = new MatrixBits(matrix);
            g = new GroupsBN(x.m.getSize());
            break;
        case 3:
            m = new MatrixByte(matrix);
            g = new GroupsN(m.getSize());
            break;
        default:
            System.err.println("Unknow storage method!");
            System.exit(1);
    }
     x=new Cluster(g,m);
}

A módszereink viselkedését azok paraméterei befolyásolják. Az alábbi metódusokkal kicsit egyszerűbben tudjuk ezeket beállítani:

/**
 * Beállítjuk a paramétereket egy külső fájlból.
 * @param file módszer paramétereit tartalmazó fájl
 * @param print kiirjuk-e a konstansokat a standard outputra
 */
void initializeConstants(String file, boolean print) {
    method.initializeConstants(file, print);
}
/**
 * Beállítjuk a paramétereket egy külső fájlból.
 * @param url módszer paramétereit tartalmazó fájl
 * @param print kiirjuk-e a konstansokat a standard outputra
 */
void initializeConstants(URL url, boolean print) {
    method.initializeConstants(url, print);
}

/**
 * 
 * @param name
 * @param n
 * @param q 
 */
void constant(String name, int n, int q){
        method.constants(name, n, q);
}

Hasonlóképpen csak az egyszerűbb írásmód miatt vezetjük be a futást kommentáló metódusok variánsait:

/**
 * Kiiratás és beállítások a tesztek előtt.
 * @param myMethod alkalmazott keresési mód elnevezése
 * @return komment szövege
 */
String printBefore(String myMethod) {
    return method.print.printBefore(myMethod);
}

/**
 * kiíratás és számolás két fájl között
 * @param str jellemzően a feldolgozandó állomány neve
 * @return komment szövege
 */
String printBetween(String str) {
    return method.print.printBetween(str);
}

/**
 * kiírás és számolás a tesztek után
 * @return komment (számolás eredménye)
 */
String printAfter() {
    return method.print.printAfter();
}

Az eredmény kiírásához először végre kell hajtani a megfelelő kereső algoritmust az adatszerkezetünkön. Majd kiszámolni a kapott eredmény célfüggvényértékét. Nem árt ha a kiíratás egységessége érdekében az eredményt normalizáljuk, és végül a kiválasztott módszerrel és formában kiírjuk a várt adatot:

/**
 * Számolás és teszt eredményének kiírása
 * @param i teszt sorszáma
 * @return eredmény értéke vagy üres sztring, ha statisztika készül
 */
String printResult(int i) {
    x = (Cluster) method.solve(x);
    x.calculate();
    x.getG().normalize();
    return method.print.printData(x,i);
}

Annak érdekében, hogy mind a mátrixot, mind a csoportosítást manipulálni tudjuk, ezeket kívülről is beállíthatjuk:

void setG(Groups g) {
    x.setG(g);
}

void setM(Matrix m) {
    x.setM(m);
}

void dInit(Groups g, Matrix m){
    x = new Cluster(g,m);
}
}

Main osztály

A paraméterül megadott parancsfájl és az utána megadott keresési módszert dolgozza fel, és a harmadik paraméterként megadott módon írja ki a megoldásokat. Ha a módszer paramétereket használ, a paramétere Ha a módszer paramétereket használ, a paramétereket tartalmazó fájl lesz a parancssor negyedik paramétere.

A parancsfájl minden sorában egy-egy adatállomány neve szerepel, amit az követ, hogy hány alkalommal kell ezen a módszert végrehajtani:

package hu.unideb.inf.optimization.clustering;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
/**
 * A klaszterezés feladatának belépési pontja.
 * @author ASZALÓS László
 */
public class Main {

//A paraméterek sorrendjét az alábbi nevesített konstansok adják meg::     
    private final static int INPUT = 0;
    private final static int CALC  = 1;
    private final static int PRINT = 2;
    private final static int CNSTS = 3; 

    /**
     * Feldolgozza a felhasználó által megadott paramétereket,
     * mellyel elindítható a klaszterezés optimalizációs megoldása.
     * @param args az optimalizációt vezérlő paraméterek
     */

    public static void main(final String[] args) {
        Solution solution = new Solution();
        try {
            FileInputStream fstream = new FileInputStream(args[INPUT]);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;
            String[] line;

A Solution segédosztály metódusaival feldolgozzuk a program paramétereit, és tároljuk a program futásának kezdési idejét:

long startTime = System.currentTimeMillis();
solution.manageMethod(args[CALC]);
System.out.println("#m " + args[CALC] + " ");
solution.managePrint(args[PRINT]);
if (4 == args.length) {
    solution.initializeConstants(args[CNSTS],false);
}

Most kezdődik a számítási rész. Ehhez a feladatokat leíró fájlt soronként beolvassuk. A sor két részből áll: a mátrixot tartalmazó fájl nevéből, és a mátrixon végrehajtandó tesztek darabszámából. A mátrix és a tárolást jelző karakter alapján a program megalkotja a megfelelő klasztert, és igény szerint kiírja a mátrix fájljának nevét. Ezután a megadott darabszámnak megfelelő hosszúságú ciklust indít, és abban végrehajt egy-egy keresést.

System.out.print(solution.printBefore(args[CALC]));
while ((strLine = br.readLine()) != null) {
    line = strLine.split(" "); 
    int ch = args[CALC].codePointAt(args[CALC].length() - 1) - 48;
    solution.manageMatrixString(line[0], args[CALC]);
    System.out.print(solution.printBetween(line[0]));
    int limit = Integer.parseInt(line[1]);
    for (int i = 0; i < limit; i++) {
        System.out.print(solution.printResult(i));
    }   }

Miután ez a ciklus minden mátrixra lefutott, a program kiírja az összegzést, és kiszámolja a program futási idejét:

System.out.print(solution.printAfter());
long endTime = System.currentTimeMillis();
System.out.println((endTime - startTime) + " ms");
} catch (Exception e) {
System.err.println("Main: " + e.getMessage());
}   }   }

Konstansok

A program különböző helyein használt konstansokat egy helyre gyűjtöttük, így egy helyen tudjuk megváltoztatni:

package hu.unideb.inf.optimization.clustering;
/**
 * A programra jellemző konstansokat egy külön helyre gyűjtöttük.
 * @author ASZALÓS László 
 * */
public class Constants {

Egy egész hány bitet képes tárolni?

public static final int BITSIZE = 63;

Figyelembe vett minták száma statisztika készítésekor

public static final int MAXSAMPLE = 500;

Maximális méret mátrixok számára

public static final int MAXSIZE = 500;

Saját csomag elnevezése.

static final String MYPACKAGE = "hu.unideb.inf.optimization";

Biztos esemény, azaz 100%

public static final int SURE = 100;
}