Edspace pershendetje,
Algoritmin tim (iterativ) e kam ndertuar per nje profesor matematike, i cili vertetoi problemen e Nash me ane te metodes "induksion me blloqe." Per kete arsye, mora nje loop "for" per numrat nga 1 deri ne 76, sepse aq mjaftonin per hapat induktive. Pa marre kete gje parasysh (e cila e ngadaleson programin), me lejoni te shpjegoj hapat iterative te algoritmit tim.
1. Kufizat fillestare
Kam deklaruar nje vektor v, i cili do te ruaje kufizat e mundshme per nje shume te dhene n. Per cdo n, vektori inicializohet me n/2 dysha, dhe jo me n njesha (pse?).
2. Loop-i while
Ky loop ndalon se iteruari kur variabli boolean done merr vleren TRUE (do ta shpjegoj me poshte se si). Variabli s kontrollon shumen e kufizave te pranishme tek vektori v.
Per cdo iteracion, nese shuma aktuale e kufizave e kalon ose eshte me e vogel se numri i dhene n, atehere snippet-i i mëposhtem korrigjon elementin e fundit te vektorit:
Kodi:
// elementi i fundit += [shuma - numrin e dhene]:
if (sn) {
v[i-1]-=s-n;
}
Snippet-i i meposhtem kontroll nese shuma e thyesave eshte 1.0, >1.0 ose <1.0:
Kodi:
sum=0.0; // LLOGARIT SHUMEN
for (i=0;i=0.9999999999 && sum<=1.0000000001 && v[k-1]>=v[k-2]){
fprintf(fout," ");
for (i=0;i
Nese shuma eshte 1.0, atehere rezultati printohet ne skedarin “result.txt”.
Kaq per llogaritjet elementare. Me poshte vijon shpjegimi i algoritmit ne baze te programit.
3. Algoritmi
Kemi vektorin v[]=2|2|...|2| (pra n/2 dysha). Sic mund ta kesh vene re, variablet l dhe k merren me indeksimin e kufizave. Fillimisht ato kane vlerat
Brenda loopit, variabli l merr vleren:
Kodi:
l=k-2; // indeksi per el. e parafundit te zones se testimit aktual
Pra keto dy variabla percaktojne hapsiren aktuale te kërkimit. Nese l==-1, atehere hapësira duhet zgjeruar. Kjo behet me ane te kodit:
Kodi:
// zgjero hapesiren e kerkimit:
if (l==-1){
++k; l=0;
while (l
Cdo te thote? Vektori fillimisht ka nje hapesire te vogel: v[]=2, pra l=0 dhe k=1. Brenda loopit, vlera e variablit s eshte s=2. Nese numri i dhene [b]n[/n] eshte me i madh se 2, atehere vlera e fundit e vektorit behet n-s+v[k]. Pra nese n=6, atehere elementi i fundit behet 6-2+2=6, dhe vektori do te jete ne gjendjen: v[]=6. Testohet nese shuma e thyesave eshte 1.0 (qe ne rastin tone nuk eshte e tille), dhe l=k-2. (Kontrollo per rastin n=1).
Megjithate, sic e ke përmendur dhe ti me siper, testimi duhet te ndaloje atehere kur elementet e vektorit ne baze indeksi (pra nga indeksi me vlere zero ne indeksin me vlere n/2) jane me te mëdhenj ne fillim se sa ne fund. Pra, nuk duhen testuar vlera te tilla si: 4|3|3 sepse algoritmi na siguron qe do te kete testuar njehere me pare vlerat 3|3|4. Per kete arsye, snippet-i i meposhtem kontrollon kete kusht:
Kodi:
++v[l]; // Elementi me indeks l inkrementohet, per te testuar vlera te reja.
/* nese elementi i parafundit (dhe para inkrementimit)
eshte me i madh ose baraz me elementin e fundit
atehere mbaron kerkimi ne ate pike.
*/
if (v[l]-1>=v[l+1]) {
l=k-2;
while (v[l]>=v[k-1]){
--l;
}
if (l>=0 && v[l]+1<=v[l+1]) ++v[l];
}
Pra, vereni kushtin e if, dhe loop-in while. Per sa kohe qe elementet e vektorit me indeks me te vogel jane me te medha se elementi me indeksin k-1 (i cili eshte elementi i fundit i hapesires aktuale), dekrementoje indeksin l per te arritur tek ai element i cili eshte me i vogel se v[k-1]. Nese ai element gjendet, atehere indeksi l eshte >=0 dhe rritet me 1 (++v[l]) per te testuar kufizen tjeter. Tani, te gjithe elementet ndermjet indeksit l dhe k-1 do te marrin vleren e elementit v[l], sepse per deri sa ato elemente jane me te mëdhenj, testimi nuk ia vlen, pasi harxhon kohe. Kodi i meposhtem e realizon kete gje:
Kodi:
s=0;
for (i=0;iif (i>=l)
v[i]=v[l];
s+=v[i];
}
Pra, llogaritet shuma e kufizave, por nese indeksi i eshte me i madh ose baraz me indeksin l, atehere vektori do te marre vleren v[l], pasi nese shumon vlerat v[i], algoritmi do te humbase testimin per kombinacionin e ri. SHIHNI SHEMBULLIN E MEPOSHTEM, DO TE JETE ME I QARTE.
Nese loop-i while nuk ekzekutohet, atehere l=k-2 do te mbaje vleren -1 dhe sipas pjeses se fundit te programit, nese l==-1, zgjerohet hapësira e kërkimit.
SHEMBULL
Marrim n=9. Pra, n/2=4.5 dhe rrumbullakoset ne 4. Pra, vektori v do te inicializohet me 4 dysha: v[]=2|2|2|2 (kjo nuk eshte e domosdoshme, por ka qendruar ne program pa arsye).
Fillimisht kemi vlerat l=0 dhe k=1. Pra hapësira aktuale e kërkimit eshte tek elementi: v[]=2.
Loop-i i pare do te llogarise shumen s, qe eshte s=2. If-i i pare do te gjeje qe shuma eshte me e vogel se n=9, prandaj elementi i fundit i vektorit kthehet ne 9 dhe: v[]=9. Indeksi l merr vleren k-2. Ne kete rast, ka vleren l=-1. Shuma e thyesave sum, eshte me vogel se 1.0. ++v[l] rrit elementin me indeks l, per te testuar kufize tjeter. Megjithate, l==-1, prandaj gjuha C e konsideron v[-1] nje dummy value. If-i i dyte nuk do te ekzekutohet. Por if-i i fundit (pra, if (l==-1)) ekzekutohet, dhe rrit vleren k. Pra, k=2, dhe ri-inicializon vektorin.
Loop-i while fillon perseri me vlerat vektoriale: v[]=2|2 (sepse l=0 dhe k=2). Shuma e kufizave, 2+2=4, eshte me e vogel se numri n=9, prandaj vektori kthehet ne gjendjen v[]=2|7. Llogaritet shuma e thyesave, qe nuk eshte 1.0, dhe l=k-2==0. Inkrementohet vlera v[l], pra nga 2 behet 3 dhe rifillon loop-i while me vlerat v[]=3|6. Pastaj vazhdon me vlerat v[]=4|5, pastaj vazhdon me v[]=5|4. POR, ketu ndalon testimi, sepse vlera 5|4 eshte testuar ne rastin 4|5. Per kete arsye, brenda if-it te dyte, loop-i whilee con indeksin l ne -1, dhe hapësira zgjerohet ne 2|2|2.
Ne pergjithesi testimi vazhdon ne kete menyre:
2|2|5
2|3|4
2|4|3 -STOP
3|3|3 -gjeti nje rast
3|4|3 –STOP
4|4|4 – STOP, shuma eshte 12, dhe variabli boolean done merr vleren TRUE, sepse shuma aktuale eshte 12, pra 12>n+2, pra 12>11 dhe programi ndalon, sepse cdo testim tjeter eshte i kote. (KETE GJE REALIZON DHE REKURSIONI I MODIFIKUAR I edspace).
Shembull tjeter per n=11: nga hapësira me e vogel (l=0,k=1) deri ne maksimumin qe arrin:
Hapësira = 1
V[]=11 – STOP
Hapësira = 2
V[]=2|9
3|8
4|7
5|6
6|5 – STOP
Hapsira = 3
V[]=2|2|7
2|3|6 – U GJET NJE VLERE
2|4|5
2|5|4 – STOP
V[]=3|3|5
3|4|4 – STOP
V[]=4|4|4 – STOP
Hapësira = 4
V[]=2|2|2|5
2|2|3|4
2|2|4|3 – STOP
V[]=2|3|3|3 – STOP (3==3)
V[]=3|3|3|2 – STOP (3>2)
V[] = 4|4|4|4 – PROGRAMI NDALON KETU, sepse 16>11+2.
--
Shpresoj te kem qene i qarte ne diskutimin e funksionimit te programit. Megjithate, kur teston nje vlere vete, atehere e kupton me mire.
Algoritmin qe paraqita me siper e kam modifikuar ne daten e dhene, sepse i pari qe bera testonte me shume kombinacione se sa duhej. Nevoje per permiresime ka, si psh ne koken e algoritmit, ku vektori v incializohet. Por keto nuk ndikojne ne kohe, vetem ne hapesire. Kam bere nje analize te kohes, por ky eshte nje algoritem i tipit kombinatorik: Po paraqes rezultate te analizes:
Kodi:
Number n: 84, Seconds: 1.000000
Number n: 85, Seconds: 1.000000
Number n: 86, Seconds: 1.000000
Number n: 87, Seconds: 1.000000
Number n: 88, Seconds: 1.000000
Number n: 89, Seconds: 2.000000
Number n: 90, Seconds: 2.000000
Number n: 91, Seconds: 2.000000
Number n: 92, Seconds: 3.000000
Number n: 93, Seconds: 4.000000
Number n: 94, Seconds: 4.000000
Number n: 95, Seconds: 5.000000
Number n: 96, Seconds: 5.000000
Number n: 97, Seconds: 6.000000
Number n: 98, Seconds: 7.000000
Number n: 99, Seconds: 8.000000
Number n: 100, Seconds: 9.000000
Number n: 101, Seconds: 10.000000
Number n: 102, Seconds: 11.000000
Per me teper, ekzistojne disa teorema ne Teorine e Serive te Fundme, te cilat mund te shtojne permiresimin e kohes te këtij algoritmi. Megjithate, pas nje diskutimi me kete prof. tim te Matematikes, algoritmi behet me kompleks per t’u implementuar. Nje permiresim i mundshem qe kam gjetur eshte përdorimi i mesatares aritmetike te kufizave per te llogaritur vlerat prospektive deri ne nje shkalle thellësia 2-3 nyje, ne menyre qe loop-i while te mos vazhdoje ekzekutimin e kote, por te ndaloje para kohe.
Duhet te kesh parasysh edhe implementimin time ne C. Nuk perdor ndonje data strukture, sic e sheh, dhe asnjë modulim, por vetem tipe te thjeshta. Kam menduar te perdore peme (i kam gjetur me praktike se listat) ne C++. Nje here u mendova rreth 40 sekonda per kete transformim dhe nxora përfundimin qe ishte me e leverdisshme te gjeja dicka tjeter per te bere...
Krijoni Kontakt