diff --git a/out/production/TamaGolem/it/arnaldo/unibs/tamagolem/WorldBuilder.class b/out/production/TamaGolem/it/arnaldo/unibs/tamagolem/WorldBuilder.class index fe70611..2744635 100644 Binary files a/out/production/TamaGolem/it/arnaldo/unibs/tamagolem/WorldBuilder.class and b/out/production/TamaGolem/it/arnaldo/unibs/tamagolem/WorldBuilder.class differ diff --git a/src/LinearSystem.java b/src/LinearSystem.java index a1c6725..386c750 100644 --- a/src/LinearSystem.java +++ b/src/LinearSystem.java @@ -34,7 +34,7 @@ public class LinearSystem { while (tries-- > 0) { int[] lambdaValues = new int[indipendentVariables]; for (int i = 0; i < indipendentVariables; i++) { - lambdaValues[i] = (rand.nextInt(m) + 1); // valori tra 1 e 9 + lambdaValues[i] = (rand.nextInt(m) + 1); // valori tra 1 e m } solutions = constructSolution(extendedMatrix, lambdaValues, rank); @@ -111,9 +111,9 @@ public class LinearSystem { int b = mat[row][col]; if (a == 0) continue; - int lcm = lcm(Math.abs(a), Math.abs(b)); - int f1 = lcm / Math.abs(a); - int f2 = lcm / Math.abs(b); + int mcm = mcm(Math.abs(a), Math.abs(b)); + int f1 = mcm / Math.abs(a); + int f2 = mcm / Math.abs(b); if (a * b < 0) f2 = -f2; for (int j = col; j <= m; j++) { @@ -126,11 +126,11 @@ public class LinearSystem { return row; } - private int gcd(int a, int b) { - return b == 0 ? a : gcd(b, a % b); + private int mcd(int a, int b) { + return b == 0 ? a : mcd(b, a % b); } - private int lcm(int a, int b) { - return a / gcd(a, b) * b; + private int mcm(int a, int b) { + return a / mcd(a, b) * b; } } diff --git a/src/Pair.java b/src/Pair.java new file mode 100644 index 0000000..3f4ede0 --- /dev/null +++ b/src/Pair.java @@ -0,0 +1,24 @@ +package it.arnaldo.unibs.tamagolem; + +// Utility pair class +public class Pair { + private final Element first; + private final Element second; + Pair(Element first, Element second) { + this.first = first; + this.second = second; + } + + public Element getFirst() { + return first; + } + + public Element getSecond() { + return second; + } + + @Override + public String toString(){ + return "(" + first.toString() + ", " + second.toString() + ")"; + } +} \ No newline at end of file diff --git a/src/WorldBuilder.java b/src/WorldBuilder.java index 813ecd4..70b10b0 100644 --- a/src/WorldBuilder.java +++ b/src/WorldBuilder.java @@ -3,141 +3,124 @@ package it.arnaldo.unibs.tamagolem; import java.util.*; public class WorldBuilder { + public static ElementGraph buildWorld() { Element[] allElements = Element.values(); - Random rand = new Random(); - // da cambiare il numero a 8 - //int numElements = 3 + rand.nextInt(8); + int numElements = (int)(Math.random() * 10); - // numero di elementi estratti a caso - int numElements = 5; List selectedElements = new ArrayList<>(Arrays.asList(allElements)); - - // elementi scelti Collections.shuffle(selectedElements); selectedElements = selectedElements.subList(0, numElements); - ElementGraph world = new ElementGraph(); - - // mappa che contiene una mappa in modo che dato un elemento ti da una mappa con chiave un secondo elemento il cui valore è 1 se l'elemento infligge o -1 se l'elemento subisce - HashMap> linkDirections = new HashMap<>(); - for (Element element : selectedElements) { - HashMap links = new HashMap<>(); - Element followingElement = selectedElements.get((selectedElements.indexOf(element) + 1) % selectedElements.size()); - for (Element el : selectedElements) { - if (el == followingElement) { - links.put(el, 1); - } else if (el != element) { - links.put(el, 0); - } - } - - linkDirections.put(element, links); - } - - for (Element element : selectedElements) { - HashMap elementLinks = linkDirections.get(element); - for (Element el : selectedElements) { - if (el == element) { - continue; - } - - // controllo anche prima per evitare che magari da un estrazione si vada a togliere - if (elementLinks.get(el) == 1){ - linkDirections.get(el).put(element, -1); - } - - if (elementLinks.get(el) == 0) { - if (Math.random() < 0.5) { - linkDirections.get(el).put(element, 1); - } else { - linkDirections.get(el).put(element, -1); - } - } - - if (elementLinks.get(el) == 1){ - linkDirections.get(el).put(element, -1); - } else { - linkDirections.get(el).put(element, 1); - } - } - } - - - System.out.println(linkDirections); - - // hashmap che dato una coppia di element (è un set cosi AB = BA) ti torna la posizione all0interno dell'array di valori passato al sistema lineare - HashMap, Integer> pairIndex = new HashMap<>(); + // Mappa delle direzioni tra elementi (1 = attacca, -1 = subisce) + Map> linkDirections = generateValidDirections(selectedElements); + // Mappa indice per ogni coppia (non ordinata) di elementi + Map, Integer> pairIndex = new HashMap<>(); int index = 0; - for (int i = 0; i < selectedElements.size(); i++) { - for (int j = i + 1; j < selectedElements.size(); j++) { - Set pair = Set.of(selectedElements.get(i), selectedElements.get(j)); - - pairIndex.put(pair, index++); + for (int i = 0; i < numElements; i++) { + for (int j = i + 1; j < numElements; j++) { + pairIndex.put(Set.of(selectedElements.get(i), selectedElements.get(j)), index++); } } - System.out.println(pairIndex); - - // matrice incognite - int[][] A = new int[numElements][numElements * (numElements - 1) / 2]; - - // matrice termini noti + // Costruzione del sistema lineare Ax = b (b = 0) + int[][] A = new int[numElements][pairIndex.size()]; int[] b = new int[numElements]; - // popolo le 2 matrici - int i = 0; - for (Element element : selectedElements) { - int[] line = new int[numElements * (numElements - 1) / 2]; - HashMap elementLinks = linkDirections.get(element); - for (Element el : selectedElements) { - if (el == element) { - continue; - } else { - int idx = getIndex(element, el, pairIndex); - line[idx] = elementLinks.get(el); - } - + for (int i = 0; i < numElements; i++) { + Element e1 = selectedElements.get(i); + int[] row = new int[pairIndex.size()]; + for (Element e2 : selectedElements) { + if (e1 == e2) continue; + int dir = linkDirections.get(e1).get(e2); + int pos = pairIndex.get(Set.of(e1, e2)); + row[pos] = dir; } - A[i] = line; + A[i] = row; b[i] = 0; - i++; } - - // creo e risolvo il sistema lineare associato + // sistema lineare per trovare le soluzioni che verificano l'equilibrio LinearSystem system = new LinearSystem(numElements, A, b); - - int[] solution = system.resolve(); - System.out.println("Soluzione trovata:"); - for (int x : solution) { - System.out.printf(String.format("%d ", x)); - } - System.out.println(); - - // popola il grafo in base ai risultati del sistema lineare - for (Element element : selectedElements) { - GraphElement graphElement = new GraphElement(element); - for (Element el : selectedElements) { - if (el == element) { - continue; - } - int direction = linkDirections.get(element).get(el); - graphElement.addLink(new ElementLink(solution[getIndex(element, el, pairIndex)] * direction, el)); + // dalle soluzioni del sistema popolo il grafo + ElementGraph world = new ElementGraph(); + for (Element e1 : selectedElements) { + GraphElement graphElement = new GraphElement(e1); + for (Element e2 : selectedElements) { + if (e1 == e2) continue; + int dir = linkDirections.get(e1).get(e2); + int val = solution[pairIndex.get(Set.of(e1, e2))]; + graphElement.addLink(new ElementLink(dir * val, e2)); } world.addElement(graphElement); } - world.printGraph(); + world.printGraph(); return world; } - private static int getIndex(Element e1, Element e2, HashMap, Integer> pairIndex) { - return pairIndex.get(Set.of(e1, e2)); + private static Map> generateValidDirections(List elements) { + int n = elements.size(); + Random rand = new Random(); + Map> linkDirections = new HashMap<>(); + + for (Element e : elements) { + linkDirections.put(e, new HashMap<>()); + } + + // creo le varie coppie (l'ordine conta successivamente) + List pairs = new ArrayList<>(); + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + pairs.add(new Pair(elements.get(i), elements.get(j))); + } + } + + boolean valid; + // controllo che ci sia almeno un arco entrante e uno uscente + do { + valid = true; + Map exitingArcs = new HashMap<>(); + Map enteringArcs = new HashMap<>(); + + // resetto i valori per evitare che cicli precedenti abbiano variato qualcosa + for (Element e : elements) { + linkDirections.get(e).clear(); + exitingArcs.put(e, 0); + enteringArcs.put(e, 0); + } + + // mescolo le coppie e determino i collegamenti (1 uscente, -1 entrante) + Collections.shuffle(pairs); + for (Pair pair : pairs) { + Element e1 = pair.getFirst(); + Element e2 = pair.getSecond(); + boolean dir = rand.nextBoolean(); + if (dir) { + linkDirections.get(e1).put(e2, 1); + linkDirections.get(e2).put(e1, -1); + enteringArcs.put(e1, enteringArcs.get(e1) + 1); + exitingArcs.put(e2, exitingArcs.get(e2) + 1); + } else { + linkDirections.get(e2).put(e1, 1); + linkDirections.get(e1).put(e2, -1); + enteringArcs.put(e2, enteringArcs.get(e2) + 1); + exitingArcs.put(e1, exitingArcs.get(e1) + 1); + } + } + + // controllo se la struttura è valida + for (Element e : elements) { + if (exitingArcs.get(e) == 0 || enteringArcs.get(e) == 0) { + valid = false; + break; + } + } + + } while (!valid); + return linkDirections; } - } -