Optimation

This commit is contained in:
L3o15 2025-05-13 15:45:41 +02:00
parent e4d54619f6
commit 7cd4664974
4 changed files with 123 additions and 116 deletions

View file

@ -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;
}
}

24
src/Pair.java Normal file
View file

@ -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() + ")";
}
}

View file

@ -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<Element> 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<Element, HashMap<Element, Integer>> linkDirections = new HashMap<>();
for (Element element : selectedElements) {
HashMap<Element, Integer> 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<Element, Integer> 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<Set<Element>, Integer> pairIndex = new HashMap<>();
// Mappa delle direzioni tra elementi (1 = attacca, -1 = subisce)
Map<Element, Map<Element, Integer>> linkDirections = generateValidDirections(selectedElements);
// Mappa indice per ogni coppia (non ordinata) di elementi
Map<Set<Element>, 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<Element> 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<Element, Integer> 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<Set<Element>, Integer> pairIndex) {
return pairIndex.get(Set.of(e1, e2));
private static Map<Element, Map<Element, Integer>> generateValidDirections(List<Element> elements) {
int n = elements.size();
Random rand = new Random();
Map<Element, Map<Element, Integer>> linkDirections = new HashMap<>();
for (Element e : elements) {
linkDirections.put(e, new HashMap<>());
}
// creo le varie coppie (l'ordine conta successivamente)
List<Pair> 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<Element, Integer> exitingArcs = new HashMap<>();
Map<Element, Integer> 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;
}
}