From 7cd466497494211f54f576a2315488f23457bcd6 Mon Sep 17 00:00:00 2001 From: L3o15 Date: Tue, 13 May 2025 15:45:41 +0200 Subject: [PATCH] Optimation --- .../unibs/tamagolem/WorldBuilder.class | Bin 5881 -> 5950 bytes src/LinearSystem.java | 16 +- src/Pair.java | 24 +++ src/WorldBuilder.java | 199 ++++++++---------- 4 files changed, 123 insertions(+), 116 deletions(-) create mode 100644 src/Pair.java diff --git a/out/production/TamaGolem/it/arnaldo/unibs/tamagolem/WorldBuilder.class b/out/production/TamaGolem/it/arnaldo/unibs/tamagolem/WorldBuilder.class index fe706118514d190765e46cfcdeb4138216d739de..2744635b0d4bd9ac8379e09628f7c86404bd6eac 100644 GIT binary patch literal 5950 zcmbVQdvp}l8UNjV&F<{v1ui&JDk9(#65<0=*hDl4NF)R#ipHpAk{yyEo87p(;Z+~4 z(x@?~UMzXtZQ|At|D=QFaw31eK zm4G+8c&myaLJCw3VQ2#Lt!$ll&jFh|4tFjpW_L{=O|+e)Tq zVEgujN$hS_wxPva!#ET36r81DKF$^>FDl6cRx$&f`POOC=H`VJYeg z@wStrZBHg^_Aw_?0}OT~FK4CdHm9v*wk?}BjlPB;&J&m+E$(F;t$76?DlWh>1o-E5?_DfBPB$Ycb^LDfB?&h2*SSe6d4B~nt(?iHAR=_Jm-KgP0$fWHyCBSGQ zqOR0#2;*WjDOj!H608v@D{5<#LY~xif#q)N`I2bJd+XNZo-WEVuh!vG1?x35o^{lAd)n=!kSg*x(3a;1iL2Tos7b961 zLWg^dOslz@plRqDDbcB+3vt>{+TEuWbWg>(UCw2%eh~$lzNVc1YKPOd=-! zfTo?3H*vM49MxC{z~6O^jFxns9W}?_L!*;ufj@!vfK0 z^YjczP`7Hh4f_}lBOaHE1eQz(o*ZiPY8D^U@Ns-XK&6I>6{Du45_e=AEuYeGyIj6h zn>FkKGJ&@!_)LMeY|`IiB;%<*6?ecZsh_j(Ie{}v1ZlHjrBw{#^D;Vj3v4Kf%yFP$ zdI6LO@73@H>}N^P{V7!Ekc}*r7Tl-di_$@VSAtn85q(+1{rCzqoCLSdO3O8G5euk< zF9mc``T-3GrF4kWZDv<08J9u%x`qd3{f1>hu1;|oH%P#~OHy$rdWEcz)`7lGGkt~8 zDVMn!EvYUevDHXh^4aP1WqT|ZNJ%8_6{>-=)+rY&yHh4mNm0iMdx|M4cJSBCpT!u) zEi#n1KSlE%^L&8?(}{*0%XP||PVHi|gSxzAW&y2R*6Kt`mIP&^DTJ5dGZG2siBJ|! zYtJKtKG0W`s?3;j17a46f{H3#tFyhS;4UJ;N^-C16|OOI1?LR+GliRzag%)GxAJ$< z#E5lrx0G>~@si%jc`q;{6$VLsET$AQ!@o;zHQr;g9iIv_HfwUy?CCEgPQ44dbgywb zv$u+XZgL6I=V{6P-y-fsykQmp1lp%6E3SUr3rq{nD)*kEumO;|%i6L=S1-M?t4qNV z1*4oh7N6k4?2~iLja;cnNd}{$u({jHa_iKT?qVuw+?bnkCzXE;GS}o@oo|FJ_%vx! zmUq#SJaJNwUz+4NKa0fTp!KdnrxyGvkrcSVrRqHsz;;VUDAZOPazEBTkN5*?>df{0f@H`L)lOnY8*#dd-Y*d zj3TnJ<}gmL@y;2;`@N743tFE*^^9{zaQ-+}w2vYd^Lgw2-ugf!Fy{fRi3EJx>XnGX z_W8Q6CK4D!g9k?utcfUv=3!hE@$d7C!&p0p4PIQePZ2}87xo2sJu*l4jp1^EAL2?+ zEHLMY8dJRW!AOt_@2rUg3p!#UXB-EpHDkC+AQslcW9Sgrk2cvdgtQye^pLJSh`>

ZrT?l(Ef4s zw$IT6x-yEsSWpj+pg$HGN0u?!c@ju>yCIEZSG%r_Vo$8h!CtPHJJ>sA%fViuYkEZi zdjWBaUg1VrN#s5`ZZi6%^;LS=IBsl@R7R?Lbk60?BlyTr?trf9Wh40LP_A27NAO8q zeT>=Qv$N$9e&m6l^**Rjm@hNAF`A8X%tIB^ZYF9miyvyUu@a|aHNS*gaRzsOI&R|g zZQQ~Pa^yYysJ$O&GrJaGlv2OOBD{)o@GhdFg5RsNP%U&U5%W+Z7Gb`q!MP&F&%-7x z6PIDR=s~^6@MCZgE5v>LvO9#BcmWOKH8hGhaiRDdKjr?8i^adtWM}nTw7nk7@dzFz z=0;qK$Jh$c-dsG+RvE1-c!I5RVrjy+@f~_LjJ-I-R)`o=7~xfA+T3N!25Ga#maU}a znK(?@D&pB}%T^HGZj9kcYVM)eQi}$kcnjk=!ssdDA9#uq{F)VS;AuR=N?a&jWX^q; zC0j3!;(KiQ=-E^FKF9enC`|kSTZ#D|v5k2@N*yuk`VoGNAmeff&$2JX=nUg0c#cSa zN;~tYEpOrZ2@5})u?QuCc_%2qygBdwaqc&MXUP3{yJvvJP-~^(!_%4_D`ga&&RUT9jq@~J9tNWdSdEyw#y)3zE6nEMz z6!DWKE{^y~L3uh_s{6(<*j^p+7kHz($Vj8OYYg{zNI#NzULqk4<&OI53l?I50>LQ` zC>FT`YL#p`ph7NI8N&gd9tHG}cY@n=#r-stds_FAQKeJT&k2>nGof;j+!h+amtv~C zeKi)Y8Nt`;wTQMK{k6I}!C+x3TAPnUtt1zR*i_F%H*Kr(=b{VWw&L4>9wyd;q$EPu z+adH#(&{!=P}rh}Cm9RV*#A&RL#q6p9Lms%W7Sgvg2st}1Q`&<)Frwf5gAuk&jEzE z3=K(|KN|7xKM|`f(%QqQW+|*C4Xi^231T*nVwU4F_G}<^wBm9et6anK-pJo7lnH^aD&Wp_PZ=8?uB$l8@oCizPV~5y?UJ>UZ z!>#BO2YGPtB>G7JH;@?8o-$-TmDuH3irtbwLFa^3w6DJXzp@hE=FmLlsBzav$VzKG=aHhooi+UW5gShur18yxz&+*3u}&yZXW zh-dL9+VI-d85{zA~ZrdFsvUkOY<2@v1{m!>G)0)7<3tHcbmbFIGVWn-)qLLMJVXfFF&NFUyLhesJ5QZ6Hlbl7aQHyKvp;q``(w&Mvgf_IX;Xw!&sjO# z{PN!4=kxn`-@Gp!e(XsAOYor%1*!&@fdaS%{F|(;R&~sZcT}%#-4tm{3%D0Yh*>1rz(w_@Q$bx%CnnyOA)T~-PD%fhpdLk)- z@?b?v!|^5RH289!^rWM)>Wi#+IMJn}NP1c#Fv)h(ezi22w0aw&skDwsn5-dSUc?i1V%j@Wut8^)!EbD9*fZTd{wrgil#!$z-bz08kmLC1$?7QvJPvhp4KciIT#9k z&QlFRVtagCFGyP5ojS@Tin9euM$Ob)sm_&Fw~k7v(wVsisxeQ%6HP~wRyvUsm=esl z8*@5OOWx-|;GY*8VQFYJ(1viXk!-2P-c&l$MfQXYFOZETny6lrq{YT`GGcWRhIVvl z=rj<;rd+3vVMmpIKF?4B&8%UsAplGzH8f6ld1k3J0d$wa5Ub*k>|nJiQ%m9bRFNoO&V@C@J-w@wo+_f zR#=OO1jL@y&_VE$6 zC#JKH>DYxkB*J%6Wi?lYFc_Lh*~kR%!rcb$!M#kd z6%I>90<$OLo@BK*uyXvwzBO7f9$v^-$oL3xDG?JU_0thMEdFiWmj z*6OOBuGUC$oz*J$!P16An-y!al2Q5HS#+g4quebk#tS~b9qVYVRd%MmC<7l?)QQb@ zjiO2{sJr!>o)9QAXn7jO1>S;NCQ4Y=!oA=c=?J zFBqo=7Eh##vSRjd%bgm|rpbkQ>R1UAQYGbT^5i6@6BfKaPwu?NPTc1{`A zO+3qEQTo3HRl!N1HzsCKMzN1_D%fUl^Z8SLujZ%VXF=s4 z#KR;M{EScenu~adPs5>qj$iPb7r(?Fu29%>0W|)=f_h*G+KOQmH4k!vdCnS!zqxV< zrGq$eRn-tqs#44L;#3u@hEYzIidxq&DoM<#EvVXyDuG(J>D~)w;7;5msV@sW4Nt9> zWAjv1nc7~|DR6D1#1et-y;!c;OkPKYZt9MTI!QSy3e7^(dp}A|k6Gv%!UY3ZxxOD$ zxT@WUV!5j3Rx{6-1*T?tY?jQH&w2Lme9t870MnQvX;7 zMpR~M`!hw4;BvEI0Fhh<+-i-c)_4LkSi*lVRs=k*jWynYgx_9RP!;gxl2R2Q0NMNu zVRNl+x=lTx^=ZNhvd=5}GcWXc_}n8cxoN4atjrbeEQmdiElRDY>~X!;tJdfawoIdg z?KP5eur(YJ@)i*t!%2wG5h^x|9ic^%a)kV*-!zMS&92XZlC-v${X? zoaqVZW>KT*4e09XKAqm~7)Eb%8FSsb{iUY*~ z-@TYay~T5D{F37a*Aq~h)qtNMG!EfLm0t&N>-xT8Dt?0;1Ne^PIkh;RUneQYbKfv_ zHJiRce6P0HVPr54;~Gghj3p*xaY8IGeOXw{l9AYIO3mV7>~1yDt52cge{hmSGKP-VO22$Kd6QkN>8k1gD^smk5(F z4=3@y$ev8xa8fM}RoQ{tv`5EskPC|v4 zfl4t8b43lR#f6wJHsA~q#saZ}Hwm}$df;xwI+YI)RsN1m%0CfT{>$1tjHK#DN}Z0hx|pBKuvM+ccC{Tl)GgSl z-ij;L+i{h8C$3ia;2QN6T&uo@>(sZycQHQR`8Jc?ft z)16p{Uvte%1bZ<+N+T|NY(AYRy-oxr-^bXWealGw7{XrY;!`ZfV;F{4`~!`6oRo+0 zl;R0eC5*D%*5YT}VLXYaP{imjw)OdlN5a-;FtRdERt|Cce=?pSRm!N&wq;8gV>_N@ z28$W-7F)sxm-;S#gXiU5q3&a5U*P`WQ{TjklvOZQeG$LIOHeUSeFQJ#_pF^o>VtTN zaTJIH+?8G>yc<&6f9&B7 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; } - } -