source: cpp/frams/model/similarity/measure-greedy.cpp @ 1071

Last change on this file since 1071 was 1071, checked in by oriona, 3 years ago

Weighted MDS and switching off the alignment fixed.

File size: 47.4 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include "measure-greedy.h"
6#include <assert.h>
7
8#define DB(x)  //define as x if you want to print debug information
9
10const int SimilMeasureGreedy::iNOFactors = 4;
11int fuzzDepth = 0; //TODO make local, but not crucial because currently "fuzzy vertex degree" is not activated by default
12
13#define FIELDSTRUCT SimilMeasureGreedy
14
15static ParamEntry simil_greedy_paramtab[] = {
16                { "Creature: Similarity: Graph greedy", 1, 7, "SimilMeasureGreedy", "Evaluates morphological dissimilarity using greedy measure. More information:\nhttp://www.framsticks.com/bib/Komosinski-et-al-2001\nhttp://www.framsticks.com/bib/Komosinski-and-Kubiak-2011\nhttp://www.framsticks.com/bib/Komosinski-2016\nhttps://doi.org/10.1007/978-3-030-16692-2_8", },
17                { "simil_greedy_parts", 0, 0, "Weight of parts count", "f 0 100 0", FIELD(m_adFactors[0]), "Differing number of parts is also handled by the 'part degree' similarity component.", },
18                { "simil_greedy_partdeg", 0, 0, "Weight of parts' degree", "f 0 100 1", FIELD(m_adFactors[1]), "", },
19                { "simil_greedy_neuro", 0, 0, "Weight of neurons count", "f 0 100 0.1", FIELD(m_adFactors[2]), "", },
20                { "simil_greedy_partgeom", 0, 0, "Weight of parts' geometric distances", "f 0 100 0", FIELD(m_adFactors[3]), "", },
21                { "simil_greedy_fixedZaxis", 0, 0, "Fix 'z' (vertical) axis?", "d 0 1 0", FIELD(fixedZaxis), "", },
22                { "simil_greedy_weightedMDS", 0, 0, "Should weighted MDS be used?", "d 0 1 0", FIELD(wMDS), "If activated, weighted MDS with vertex (i.e., Part) degrees as weights is used for 3D alignment of body structure.", },
23                { "evaluateDistance", 0, PARAM_DONTSAVE | PARAM_USERHIDDEN, "Evaluate model dissimilarity", "p f(oGeno,oGeno)", PROCEDURE(p_evaldistance), "Calculates dissimilarity between two models created from Geno objects.", },
24                { 0, },
25};
26
27#undef FIELDSTRUCT
28
29SimilMeasureGreedy::SimilMeasureGreedy(): localpar(simil_greedy_paramtab, this), m_iDV(0), m_iDD(0), m_iDN(0), m_dDG(0.0)
30{       
31        localpar.setDefault();
32       
33        for (int i = 0; i < 2; i++)
34        {
35                m_aDegrees[0] = nullptr;
36                m_fuzzyNeighb[0] = nullptr;
37                m_Neighbours[0] = nullptr;
38        }
39       
40        m_pMatching = nullptr;
41        tempMatching = nullptr;
42       
43        //Determines whether "fuzzy vertex degree" should be used.
44        //In preliminary experiments in 2017, "fuzzy vertex degree" turned out to be not beneficial.
45        isFuzzy = false;
46        fuzzyDepth = 10;
47        save_matching = false;
48}
49
50double SimilMeasureGreedy::distanceForTransformation()
51{
52        // now the positions are recomputed
53        computeMatching();
54
55        // teraz m_pMatching istnieje i jest pełne
56        assert(m_pMatching != NULL);
57        assert(m_pMatching->isFull() == true);
58        // wykorzystaj to dopasowanie i geometrię do obliczenia tymczasowej wartości miary
59       
60        int iTempRes = countPartsDistance();
61        // załóż sukces
62        assert(iTempRes == 1);
63        double dCurrentSim = m_adFactors[0] * double(m_iDV) +
64                m_adFactors[1] * double(m_iDD) +
65                m_adFactors[2] * double(m_iDN) +
66                m_adFactors[3] * double(m_dDG);
67        // załóż poprawną wartość podobieństwa
68        assert(dCurrentSim >= 0.0);
69        SAFEDELETE(tempMatching);
70        return dCurrentSim;
71}
72
73
74double SimilMeasureGreedy::distanceWithoutAlignment()
75{
76        return distanceForTransformation();
77}
78
79void SimilMeasureGreedy::beforeTransformation()
80{
81        if (m_pMatching != NULL)
82                if (!m_pMatching->isEmpty())
83                        m_pMatching->empty();
84}
85
86/** Computes elements of similarity (m_iDD, m_iDN, m_dDG) based on underlying matching.
87        Assumptions:
88        - Matching (m_pMatching) exists and is full.
89        - Internal arrays m_aDegrees and coordinates exist and are properly filled in
90        Exit conditions:
91        - Elements of similarity are computed (m)iDD, m_iDN, m_dDG).
92        @return 1 if success, otherwise 0.
93        */
94int SimilMeasureGreedy::countPartsDistance()
95{
96        int i, temp;
97
98        // assume existence of m_pMatching
99        assert(m_pMatching != NULL);
100        // musi byc pelne!
101        assert(m_pMatching->isFull() == true);
102
103        // roznica w stopniach
104        m_iDD = 0;
105        // roznica w liczbie neuronów
106        m_iDN = 0;
107        // roznica w odleglosci dopasowanych Parts
108        m_dDG = 0.0;
109
110        int iOrgPart, iOrgMatchedPart; // orginalny indeks Part i jego dopasowanego Part
111        int iMatchedPart; // indeks (wg sortowania) dopasowanego Part
112
113        // wykorzystanie dopasowania do zliczenia m_iDD - roznicy w stopniach
114        // i m_iDN - roznicy w liczbie neuronow
115        // petla w wiekszej tablicy
116        for (i = 0; i < m_aiPartCount[1 - m_iSmaller]; i++)
117        {
118                // dla kazdego elementu [i] z wiekszego organizmu
119                // pobierz jego orginalny indeks w organizmie z tablicy TDN
120                iOrgPart = m_aDegrees[1 - m_iSmaller][i][0];
121                if (!(m_pMatching->isMatched(1 - m_iSmaller, i)))
122                {
123                        // gdy nie zostal dopasowany
124                        // dodaj jego stopien do DD
125                        m_iDD += m_aDegrees[1 - m_iSmaller][i][1];
126                        // dodaj liczbe neuronow do DN
127                        m_iDN += m_aDegrees[1 - m_iSmaller][i][3];
128                        // i oblicz odleglosc tego Part od srodka organizmu (0,0,0)
129                        // (uzyj orginalnego indeksu)
130                        //no need to compute distane when m_dDG weight is 0
131                        m_dDG += m_adFactors[3] == 0 ? 0 : coordinates[1 - m_iSmaller][iOrgPart].length();
132                }
133                else
134                {
135                        // gdy byl dopasowany
136                        // pobierz indeks (po sortowaniu) tego dopasowanego Part
137                        iMatchedPart = m_pMatching->getMatchedIndex(1 - m_iSmaller, i);
138                        // pobierz indeks orginalny tego dopasowanego Part
139                        iOrgMatchedPart = m_aDegrees[m_iSmaller][iMatchedPart][0];
140                        // dodaj ABS roznicy stopni do DD
141                        temp = m_aDegrees[1 - m_iSmaller][i][1] -
142                                m_aDegrees[m_iSmaller][iMatchedPart][1];
143                        m_iDD += abs(temp);
144                        // dodaj ABS roznicy neuronow do DN
145                        temp = m_aDegrees[1 - m_iSmaller][i][3] -
146                                m_aDegrees[m_iSmaller][iMatchedPart][3];
147                        m_iDN += abs(temp);
148                        // pobierz polozenie dopasowanego Part
149                        if (m_adFactors[3] > 0)
150                        {
151                            Pt3D MatchedPartPos(coordinates[m_iSmaller][iOrgMatchedPart]);
152                            // dodaj euklidesowa odleglosc Parts do sumy odleglosci
153                            m_dDG += coordinates[1 - m_iSmaller][iOrgPart].distanceTo(MatchedPartPos);
154                        }
155                }
156        }
157
158        // obliczenie i dodanie różnicy w liczbie neuronów OnJoint...
159        temp = m_aOnJoint[0][3] - m_aOnJoint[1][3];
160        m_iDN += abs(temp);
161        DB(printf("OnJoint DN: %i\n", abs(temp));)
162                // ... i Anywhere
163                temp = m_aAnywhere[0][3] - m_aAnywhere[1][3];
164        m_iDN += abs(temp);
165        DB(printf("Anywhere DN: %i\n", abs(temp));)
166
167                return 1;
168}
169
170void SimilMeasureGreedy::computeMatching()
171{
172        // uniwersalne liczniki
173        int i, j;
174
175        assert(m_pMatching != NULL);
176        assert(m_pMatching->isEmpty() == true);
177
178        // rozpoczynamy etap dopasowywania Parts w organizmach
179        // czy dopasowano już wszystkie Parts?
180        int iCzyDopasowane = 0;
181        // koniec grupy aktualnie dopasowywanej w każdym organizmie
182        int aiKoniecGrupyDopasowania[2] = { 0, 0 };
183        // koniec grupy już w całości dopasowanej
184        // (Pomiedzy tymi dwoma indeksami znajduja sie Parts w tablicy
185        // m_aDegrees, ktore moga byc dopasowywane (tam nadal moga
186        // byc tez dopasowane - ale nie musi to byc w sposob
187        // ciagly)
188        int aiKoniecPierwszejGrupy[2] = { 0, 0 };
189        // Tablica przechowująca odległości poszczególnych Parts z aktualnych
190        // grup dopasowania. Rozmiar - prostokąt o bokach równych liczbie elementów w
191        // dopasowywanych aktualnie grupach. Pierwszy wymiar - pierwszy organizm.
192        // Drugi wymiar - drugi organizm (nie zależy to od tego, który jest mniejszy).
193        // Wliczane w rozmiar tablicy są nawet już dopasowane elementy - tablice
194        // paiCzyDopasowany pamiętają stan dopasowania tych elementów.
195        typedef double *TPDouble;
196        double **aadOdleglosciParts;
197        // dwie tablice okreslajace Parts, ktore moga byc do siebie dopasowywane
198        // rozmiary: [0] - aiRozmiarCalychGrup[1]
199        //                       [1] - aiRozmiarCalychGrup[0]
200        std::vector<bool> *apvbCzyMinimalnaOdleglosc[2];
201        // rozmiar aktualnie dopasowywanej grupy w odpowiednim organizmie (tylko elementy
202        // jeszcze niedopasowane).
203        int aiRozmiarGrupy[2];
204        // rozmiar aktualnie dopasowywanych grup w odpowiednim organizmie (włączone są
205        // w to również elementy już dopasowane).
206        int aiRozmiarCalychGrup[2] = { 0, 0 };
207
208        // DOPASOWYWANIE PARTS
209        while (!iCzyDopasowane)
210        {
211                // znajdz konce obu grup aktualnie dopasowywanych w obu organizmach
212                for (i = 0; i < 2; i++)
213                {
214                        // czyli poszukaj miejsca zmiany stopnia lub konca tablicy
215                        for (j = aiKoniecPierwszejGrupy[i] + 1; j < m_aiPartCount[i]; j++)
216                        {
217                                if (m_aDegrees[i][j][DEG] < m_aDegrees[i][j - 1][DEG])
218                                {
219                                        break;
220                                }
221                        }
222                        aiKoniecGrupyDopasowania[i] = j;
223
224                        // sprawdz poprawnosc tego indeksu
225                        assert((aiKoniecGrupyDopasowania[i] > 0) &&
226                                (aiKoniecGrupyDopasowania[i] <= m_aiPartCount[i]));
227
228                        // oblicz rozmiary całych grup - łącznie z dopasowanymi już elementami
229                        aiRozmiarCalychGrup[i] = aiKoniecGrupyDopasowania[i] -
230                                aiKoniecPierwszejGrupy[i];
231
232                        // sprawdz teraz rozmiar tej grupy w sensie liczby niedopasowanzch
233                        // nie moze to byc puste!
234                        aiRozmiarGrupy[i] = 0;
235                        for (j = aiKoniecPierwszejGrupy[i]; j < aiKoniecGrupyDopasowania[i]; j++)
236                        {
237                                // od poczatku do konca grupy
238                                if (!m_pMatching->isMatched(i, j))
239                                {
240                                        // jesli niedopasowany, to zwieksz licznik
241                                        aiRozmiarGrupy[i]++;
242                                }
243                        }
244                        // grupa nie moze byc pusta!
245                        assert(aiRozmiarGrupy[i] > 0);
246                }
247
248                // DOPASOWYWANIE PARTS Z GRUP
249
250                // stworzenie tablicy odległości lokalnych
251                // stwórz pierwszy wymiar - wg rozmiaru zerowego organizmu
252                aadOdleglosciParts = new TPDouble[aiRozmiarCalychGrup[0]];
253                assert(aadOdleglosciParts != NULL);
254                // stwórz drugi wymiar - wg rozmiaru drugiego organizmu
255                for (i = 0; i < aiRozmiarCalychGrup[0]; i++)
256                {
257                        aadOdleglosciParts[i] = new double[aiRozmiarCalychGrup[1]];
258                        assert(aadOdleglosciParts[i] != NULL);
259                }
260
261                // stworzenie tablic mozliwosci dopasowania (indykatorow minimalnej odleglosci)
262                apvbCzyMinimalnaOdleglosc[0] = new std::vector<bool>(aiRozmiarCalychGrup[1], false);
263                apvbCzyMinimalnaOdleglosc[1] = new std::vector<bool>(aiRozmiarCalychGrup[0], false);
264                // sprawdz stworzenie tablic
265                assert(apvbCzyMinimalnaOdleglosc[0] != NULL);
266                assert(apvbCzyMinimalnaOdleglosc[1] != NULL);
267
268                // wypełnienie elementów macierzy (i,j) odległościami pomiędzy
269                // odpowiednimi Parts: (i) w organizmie 0 i (j) w organizmie 1.
270                // UWAGA! Uwzględniamy tylko te Parts, które nie są jeszcze dopasowane
271                // (reszta to byłaby po prostu strata czasu).
272                int iDeg, iNeu; // ilościowe określenie różnic stopnia, liczby neuronów i połączeń Parts
273                //int iNIt;
274                double dGeo; // ilościowe określenie różnic geometrycznych pomiędzy Parts
275                // indeksy konkretnych Parts - indeksy sa ZERO-BASED, choć właściwy dostep
276                // do informacji o Part wymaga dodania aiKoniecPierwszejGrupy[]
277                // tylko aadOdleglosciParts[][] indeksuje sie bezposrednio zawartoscia iIndex[]
278                int iIndex[2];
279                int iPartIndex[2] = { -1, -1 }; // at [iModel]: original index of a Part for the specified model (iModel)
280
281                // debug - wypisz zakres dopasowywanych indeksow
282                DB(printf("Organizm 0: grupa: (%2i, %2i)\n", aiKoniecPierwszejGrupy[0],
283                        aiKoniecGrupyDopasowania[0]);)
284                        DB(printf("Organizm 1: grupa: (%2i, %2i)\n", aiKoniecPierwszejGrupy[1],
285                                aiKoniecGrupyDopasowania[1]);)
286
287                        for (i = 0; i < aiRozmiarCalychGrup[0]; i++)
288                        {
289
290                                // iterujemy i - Parts organizmu 0
291                                // (indeks podstawowy - aiKoniecPierwszejGrupy[0])
292
293                                if (!(m_pMatching->isMatched(0, aiKoniecPierwszejGrupy[0] + i)))
294                                {
295                                        // interesuja nas tylko te niedopasowane jeszcze (i)
296                                        for (j = 0; j < aiRozmiarCalychGrup[1]; j++)
297                                        {
298
299                                                // iterujemy j - Parts organizmu 1
300                                                // (indeks podstawowy - aiKoniecPierwszejGrupy[1])
301
302                                                if (!(m_pMatching->isMatched(1, aiKoniecPierwszejGrupy[1] + j)))
303                                                {
304                                                        // interesuja nas tylko te niedopasowane jeszcze (j)
305                                                        // teraz obliczymy lokalne różnice pomiędzy Parts
306                                                        iDeg = abs(m_aDegrees[0][aiKoniecPierwszejGrupy[0] + i][1]
307                                                                - m_aDegrees[1][aiKoniecPierwszejGrupy[1] + j][1]);
308
309                                                        //iNit currently is not a component of distance measure
310                                                        //iNIt = abs(m_aDegrees[0][ aiKoniecPierwszejGrupy[0] + i ][2]
311                                                        //- m_aDegrees[1][ aiKoniecPierwszejGrupy[1] + j ][2]);
312
313                                                        iNeu = abs(m_aDegrees[0][aiKoniecPierwszejGrupy[0] + i][3]
314                                                                - m_aDegrees[1][aiKoniecPierwszejGrupy[1] + j][3]);
315
316                                                        // obliczenie także lokalnych różnic geometrycznych pomiędzy Parts
317                                                        // find original indices of Parts for both of the models
318                                                        iPartIndex[0] = m_aDegrees[0][aiKoniecPierwszejGrupy[0] + i][0];
319                                                        iPartIndex[1] = m_aDegrees[1][aiKoniecPierwszejGrupy[1] + j][0];
320                                                        // now compute the geometrical distance of these Parts (use coordinates
321                                                        // which should be computed by SVD)
322                                                        dGeo = 0;
323                                                        if (m_adFactors[3] > 0)
324                                                        {
325                                                                Pt3D Part0Pos(coordinates[0][iPartIndex[0]]);
326                                                                Pt3D Part1Pos(coordinates[1][iPartIndex[1]]);
327                                                                dGeo = Part0Pos.distanceTo(Part1Pos);
328                                                        }
329
330                                                        // tutaj prawdopodobnie należy jeszcze dodać sprawdzanie
331                                                        // identyczności pozostałych własności (oprócz geometrii)
332                                                        // - żeby móc stwierdzić w ogóle identyczność Parts
333
334                                                        // i ostateczna odleglosc indukowana przez te roznice
335                                                        // (tutaj nie ma różnicy w liczbie wszystkich wierzchołków)
336                                                        aadOdleglosciParts[i][j] = m_adFactors[1] * double(iDeg) +
337                                                                m_adFactors[2] * double(iNeu) +
338                                                                m_adFactors[3] * dGeo;
339                                                        DB(printf("Parts Distance (%2i,%2i) = %.3lf\n", aiKoniecPierwszejGrupy[0] + i,
340                                                                aiKoniecPierwszejGrupy[1] + j, aadOdleglosciParts[i][j]);)
341                                                                DB(printf("Parts geometrical distance = %.20lf\n", dGeo);)
342                                                                DB(printf("Pos0: (%.3lf %.3lf %.3lf)\n", Part0Pos.x, Part0Pos.y, Part0Pos.z);)
343                                                                DB(printf("Pos1: (%.3lf %.3lf %.3lf)\n", Part1Pos.x, Part1Pos.y, Part1Pos.z);)
344                                                }
345                                        }
346                                }
347                        }
348
349                // tutaj - sprawdzic tylko, czy tablica odleglosci lokalnych jest poprawnie obliczona
350
351                // WYKORZYSTANIE TABLICY ODLEGLOSCI DO BUDOWY DOPASOWANIA
352
353                // trzeba raczej iterować aż do zebrania wszystkich możliwych dopasowań w grupie
354                // dlatego wprowadzamy dodatkowa zmienna - czy skonczyla sie juz grupa
355                bool bCzyKoniecGrupy = false;
356                while (!bCzyKoniecGrupy)
357                {
358                        for (i = 0; i < 2; i++)
359                        {
360                                // iterujemy (i) po organizmach
361                                // szukamy najpierw jakiegoś niedopasowanego jeszcze Part w organizmach
362
363                                // zakładamy, że nie ma takiego Part
364                                iIndex[i] = -1;
365
366                                for (j = 0; j < aiRozmiarCalychGrup[i]; j++)
367                                {
368                                        // iterujemy (j) - Parts organizmu (i)
369                                        // (indeks podstawowy - aiKoniecPierwszejGrupy[0])
370                                        if (!(m_pMatching->isMatched(i, aiKoniecPierwszejGrupy[i] + j)))
371                                        {
372                                                // gdy mamy w tej grupie jakis niedopasowany element, to ustawiamy
373                                                // iIndex[i] (chcemy w zasadzie pierwszy taki)
374                                                iIndex[i] = j;
375                                                break;
376                                        }
377                                }
378
379                                // sprawdzamy, czy w ogole znaleziono taki Part
380                                if (iIndex[i] < 0)
381                                {
382                                        // gdy nie znaleziono takiego Part - mamy koniec dopasowywania w
383                                        // tych grupach
384                                        bCzyKoniecGrupy = true;
385                                }
386                                // sprawdz poprawnosc indeksu niedopasowanego Part - musi byc w aktualnej grupie
387                                assert((iIndex[i] >= -1) && (iIndex[i] < aiRozmiarCalychGrup[i]));
388                        }
389
390
391                        // teraz mamy sytuacje:
392                        // - mamy w iIndex[0] i iIndex[1] indeksy pierwszych niedopasowanych Part
393                        //              w organizmach, albo
394                        // - nie ma w ogóle już czego dopasowywać (należy przejść do innej grupy)
395                        if (!bCzyKoniecGrupy)
396                        {
397                                // gdy nie ma jeszcze końca żadnej z grup - możemy dopasowywać
398                                // najpierw wyszukujemy w tablicy minimum odległości od tych
399                                // wyznaczonych Parts
400
401                                // najpierw wyczyscimy wektory potencjalnych dopasowan
402                                // dla organizmu 1 (o rozmiarze grupy z 0)
403                                for (i = 0; i < aiRozmiarCalychGrup[0]; i++)
404                                {
405                                        apvbCzyMinimalnaOdleglosc[1]->operator[](i) = false;
406                                }
407                                // dla organizmu 0 (o rozmiarze grup z 1)
408                                for (i = 0; i < aiRozmiarCalychGrup[1]; i++)
409                                {
410                                        apvbCzyMinimalnaOdleglosc[0]->operator[](i) = false;
411                                }
412
413                                // szukanie minimum dla Part o indeksie iIndex[0] w organizmie 0
414                                // wsrod niedopasowanych Parts z organizmu 1
415                                // zakładamy, że nie znaleŸliśmy jeszcze minimum
416                                double dMinimum = HUGE_VAL;
417                                for (i = 0; i < aiRozmiarCalychGrup[1]; i++)
418                                {
419                                        if (!(m_pMatching->isMatched(1, aiKoniecPierwszejGrupy[1] + i)))
420                                        {
421
422                                                // szukamy minimum obliczonej lokalnej odleglosci tylko wsrod
423                                                // niedopasowanych jeszcze Parts
424                                                if (aadOdleglosciParts[iIndex[0]][i] < dMinimum)
425                                                {
426                                                        dMinimum = aadOdleglosciParts[iIndex[0]][i];
427                                                }
428                                                // przy okazji - sprawdz, czy HUGE_VAL jest rzeczywiscie max dla double
429                                                assert(aadOdleglosciParts[iIndex[0]][i] < HUGE_VAL);
430                                        }
431                                }
432                                // sprawdz, czy minimum znaleziono - musi takie byc, bo jest cos niedopasowanego
433                                assert((dMinimum >= 0.0) && (dMinimum < HUGE_VAL));
434
435                                // teraz zaznaczamy w tablicy te wszystkie Parts, ktore maja
436                                // rzeczywiscie te minimalna odleglosc do Part iIndex[0] w organizmie 0
437                                for (i = 0; i < aiRozmiarCalychGrup[1]; i++)
438                                {
439                                        if (!(m_pMatching->isMatched(1, aiKoniecPierwszejGrupy[1] + i)))
440                                        {
441                                                if (aadOdleglosciParts[iIndex[0]][i] == dMinimum)
442                                                {
443                                                        // jesli w danym miejscu tablicy odleglosci jest faktyczne
444                                                        // minimum odleglosci, to mamy potencjalna pare dla iIndex[0]
445                                                        apvbCzyMinimalnaOdleglosc[0]->operator[](i) = true;
446                                                }
447
448                                                // sprawdz poprawnosc znalezionego wczesniej minimum
449                                                assert(aadOdleglosciParts[iIndex[0]][i] >= dMinimum);
450                                        }
451                                }
452
453                                // podobnie szukamy minimum dla Part o indeksie iIndex[1] w organizmie 1
454                                // wsrod niedopasowanych Parts z organizmu 0
455                                dMinimum = HUGE_VAL;
456                                for (i = 0; i < aiRozmiarCalychGrup[0]; i++)
457                                {
458                                        if (!(m_pMatching->isMatched(0, aiKoniecPierwszejGrupy[0] + i)))
459                                        {
460                                                // szukamy minimum obliczonej lokalnej odleglosci tylko wsrod
461                                                // niedopasowanych jeszcze Parts
462                                                if (aadOdleglosciParts[i][iIndex[1]] < dMinimum)
463                                                {
464                                                        dMinimum = aadOdleglosciParts[i][iIndex[1]];
465                                                }
466                                                // przy okazji - sprawdz, czy HUGE_VAL jest rzeczywiscie max dla double
467                                                assert(aadOdleglosciParts[i][iIndex[1]] < HUGE_VAL);
468                                        }
469                                }
470                                // sprawdz, czy minimum znaleziono - musi takie byc, bo jest cos niedopasowanego
471                                assert((dMinimum >= 0.0) && (dMinimum < HUGE_VAL));
472
473                                // teraz zaznaczamy w tablicy te wszystkie Parts, ktore maja
474                                // rzeczywiscie te minimalne odleglosci do Part iIndex[1] w organizmie 1
475                                for (i = 0; i < aiRozmiarCalychGrup[0]; i++)
476                                {
477                                        if (!(m_pMatching->isMatched(0, aiKoniecPierwszejGrupy[0] + i)))
478                                        {
479                                                if (aadOdleglosciParts[i][iIndex[1]] == dMinimum)
480                                                {
481                                                        // jesli w danym miejscu tablicy odleglosci jest faktyczne
482                                                        // minimum odleglosci, to mamy potencjalna pare dla iIndex[1]
483                                                        apvbCzyMinimalnaOdleglosc[1]->operator[](i) = true;
484                                                }
485
486                                                // sprawdz poprawnosc znalezionego wczesniej minimum
487                                                assert(aadOdleglosciParts[i][iIndex[1]] >= dMinimum);
488                                        }
489                                }
490
491                                // teraz mamy juz poszukane potencjalne grupy dopasowania - musimy
492                                // zdecydowac, co do czego dopasujemy!
493                                // szukamy Part iIndex[0] posrod mozliwych do dopasowania dla Part iIndex[1]
494                                // szukamy takze Part iIndex[1] posrod mozliwych do dopasowania dla Part iIndex[0]
495                                bool PartZ1NaLiscie0 = apvbCzyMinimalnaOdleglosc[0]->operator[](iIndex[1]);
496                                bool PartZ0NaLiscie1 = apvbCzyMinimalnaOdleglosc[1]->operator[](iIndex[0]);
497
498                                if (PartZ1NaLiscie0 && PartZ0NaLiscie1)
499                                {
500                                        // PRZYPADEK 1. Oba Parts maja sie wzajemnie na listach mozliwych
501                                        // dopasowan.
502                                        // AKCJA. Dopasowanie wzajemne do siebie.
503
504                                        m_pMatching->match(0, aiKoniecPierwszejGrupy[0] + iIndex[0],
505                                                1, aiKoniecPierwszejGrupy[1] + iIndex[1]);
506
507                                        // zmniejsz liczby niedopasowanych elementow w grupach
508                                        aiRozmiarGrupy[0]--;
509                                        aiRozmiarGrupy[1]--;
510                                        // debug - co zostalo dopasowane
511                                        DB(printf("Przypadek 1.: dopasowane Parts: (%2i, %2i)\n", aiKoniecPierwszejGrupy[0]
512                                                + iIndex[0], aiKoniecPierwszejGrupy[1] + iIndex[1]);)
513
514                                }// PRZYPADEK 1.
515                                else
516                                        if (PartZ1NaLiscie0 || PartZ0NaLiscie1)
517                                        {
518                                                // PRZYPADEK 2. Tylko jeden z Parts ma drugiego na swojej liscie
519                                                // mozliwych dopasowan
520                                                // AKCJA. Dopasowanie jednego jest proste (tego, ktory nie ma
521                                                // na swojej liscie drugiego). Dla tego drugiego nalezy powtorzyc
522                                                // duza czesc obliczen (znalezc mu nowa mozliwa pare)
523
524                                                // indeks organizmu, ktorego Part nie ma dopasowywanego Part
525                                                // z drugiego organizmu na swojej liscie
526                                                int iBezDrugiego;
527
528                                                // okreslenie indeksu organizmu z dopasowywanym Part
529                                                if (!PartZ1NaLiscie0)
530                                                {
531                                                        iBezDrugiego = 0;
532                                                }
533                                                else
534                                                {
535                                                        iBezDrugiego = 1;
536                                                }
537                                                // sprawdz indeks organizmu
538                                                assert((iBezDrugiego == 0) || (iBezDrugiego == 1));
539
540                                                int iDopasowywany = -1;
541                                                // poszukujemy pierwszego z listy dopasowania
542                                                for (i = 0; i < aiRozmiarCalychGrup[1 - iBezDrugiego]; i++)
543                                                {
544                                                        if (apvbCzyMinimalnaOdleglosc[iBezDrugiego]->operator[](i))
545                                                        {
546                                                                iDopasowywany = i;
547                                                                break;
548                                                        }
549                                                }
550                                                // sprawdz poprawnosc indeksu dopasowywanego (musimy cos znalezc!)
551                                                // nieujemny i w odpowiedniej grupie!
552                                                assert((iDopasowywany >= 0) &&
553                                                        (iDopasowywany < aiRozmiarCalychGrup[1 - iBezDrugiego]));
554
555                                                // znalezlismy 1. Part z listy dopasowania - dopasowujemy!
556                                                m_pMatching->match(
557                                                        iBezDrugiego,
558                                                        aiKoniecPierwszejGrupy[iBezDrugiego] + iIndex[iBezDrugiego],
559                                                        1 - iBezDrugiego,
560                                                        aiKoniecPierwszejGrupy[1 - iBezDrugiego] + iDopasowywany);
561                                                DB(printf("Przypadek 2.1.: dopasowane Parts dopasowanie bez drugiego: (%2i, %2i)\n", aiKoniecPierwszejGrupy[iBezDrugiego] + iIndex[iBezDrugiego],
562                                                        aiKoniecPierwszejGrupy[1 - iBezDrugiego] + iDopasowywany);)
563
564                                                        // zmniejsz liczby niedopasowanych elementow w grupach
565                                                        aiRozmiarGrupy[0]--;
566                                                aiRozmiarGrupy[1]--;
567
568                                                // sprawdz, czy jest szansa dopasowania tego Part z drugiej strony
569                                                // (ktora miala mozliwosc dopasowania tego Part z poprzedniego organizmu)
570                                                if ((aiRozmiarGrupy[0] > 0) && (aiRozmiarGrupy[1] > 0))
571                                                {
572                                                        // jesli grupy sie jeszcze nie wyczrpaly
573                                                        // to jest mozliwosc dopasowania w organizmie
574
575                                                        int iZDrugim = 1 - iBezDrugiego;
576                                                        // sprawdz indeks organizmu
577                                                        assert((iZDrugim == 0) || (iZDrugim == 1));
578
579                                                        // bedziemy szukac minimum wsrod niedopasowanych - musimy wykasowac
580                                                        // poprzednie obliczenia minimum
581                                                        // dla organizmu 1 (o rozmiarze grupy z 0)
582                                                        for (i = 0; i < aiRozmiarCalychGrup[0]; i++)
583                                                        {
584                                                                apvbCzyMinimalnaOdleglosc[1]->operator[](i) = false;
585                                                        }
586                                                        // dla organizmu 0 (o rozmiarze grup z 1)
587                                                        for (i = 0; i < aiRozmiarCalychGrup[1]; i++)
588                                                        {
589                                                                apvbCzyMinimalnaOdleglosc[0]->operator[](i) = false;
590                                                        }
591
592                                                        // szukamy na nowo minimum dla Part o indeksie iIndex[ iZDrugim ] w organizmie iZDrugim
593                                                        // wsrod niedopasowanych Parts z organizmu 1 - iZDrugim
594                                                        dMinimum = HUGE_VAL;
595                                                        for (i = 0; i < aiRozmiarCalychGrup[1 - iZDrugim]; i++)
596                                                        {
597                                                                if (!(m_pMatching->isMatched(
598                                                                        1 - iZDrugim,
599                                                                        aiKoniecPierwszejGrupy[1 - iZDrugim] + i)))
600                                                                {
601                                                                        // szukamy minimum obliczonej lokalnej odleglosci tylko wsrod
602                                                                        // niedopasowanych jeszcze Parts
603                                                                        if (iZDrugim == 0)
604                                                                        {
605                                                                                // teraz niestety musimy rozpoznac odpowiedni organizm
606                                                                                // zeby moc indeksowac niesymetryczna tablice
607                                                                                if (aadOdleglosciParts[iIndex[0]][i] < dMinimum)
608                                                                                {
609                                                                                        dMinimum = aadOdleglosciParts[iIndex[0]][i];
610                                                                                }
611                                                                                // przy okazji - sprawdz, czy HUGE_VAL jest rzeczywiscie max dla double
612                                                                                assert(aadOdleglosciParts[iIndex[0]][i] < HUGE_VAL);
613
614                                                                        }
615                                                                        else
616                                                                        {
617                                                                                if (aadOdleglosciParts[i][iIndex[1]] < dMinimum)
618                                                                                {
619                                                                                        dMinimum = aadOdleglosciParts[i][iIndex[1]];
620                                                                                }
621                                                                                // przy okazji - sprawdz, czy HUGE_VAL jest rzeczywiscie max dla double
622                                                                                assert(aadOdleglosciParts[i][iIndex[1]] < HUGE_VAL);
623                                                                        }
624                                                                }
625                                                        }
626                                                        // sprawdz, czy minimum znaleziono - musi takie byc, bo jest cos niedopasowanego
627                                                        assert((dMinimum >= 0.0) && (dMinimum < HUGE_VAL));
628
629                                                        // teraz zaznaczamy w tablicy te wszystkie Parts, ktore maja
630                                                        // rzeczywiscie te minimalne odleglosci do Part w organizmie iZDrugim
631                                                        for (i = 0; i < aiRozmiarCalychGrup[1 - iZDrugim]; i++)
632                                                        {
633                                                                if (!(m_pMatching->isMatched(
634                                                                        1 - iZDrugim,
635                                                                        aiKoniecPierwszejGrupy[1 - iZDrugim] + i)))
636                                                                {
637                                                                        if (iZDrugim == 0)
638                                                                        {
639                                                                                // teraz niestety musimy rozpoznac odpowiedni organizm
640                                                                                // zeby moc indeksowac niesymetryczna tablice
641                                                                                if (aadOdleglosciParts[iIndex[0]][i] == dMinimum)
642                                                                                {
643                                                                                        // jesli w danym miejscu tablicy odleglosci jest faktyczne
644                                                                                        // minimum odleglosci, to mamy potencjalna pare dla iIndex[1]
645                                                                                        apvbCzyMinimalnaOdleglosc[0]->operator[](i) = true;
646                                                                                }
647                                                                        }
648                                                                        else
649                                                                        {
650                                                                                if (aadOdleglosciParts[i][iIndex[1]] == dMinimum)
651                                                                                {
652                                                                                        apvbCzyMinimalnaOdleglosc[1]->operator[](i) = true;
653                                                                                }
654                                                                        }
655                                                                }
656                                                        }
657
658                                                        // a teraz - po znalezieniu potencjalnych elementow do dopasowania
659                                                        // dopasowujemy pierwszy z potencjalnych
660                                                        iDopasowywany = -1;
661                                                        for (i = 0; i < aiRozmiarCalychGrup[1 - iZDrugim]; i++)
662                                                        {
663                                                                if (apvbCzyMinimalnaOdleglosc[iZDrugim]->operator[](i))
664                                                                {
665                                                                        iDopasowywany = i;
666                                                                        break;
667                                                                }
668                                                        }
669                                                        // musielismy znalezc jakiegos dopasowywanego
670                                                        assert((iDopasowywany >= 0) &&
671                                                                (iDopasowywany < aiRozmiarCalychGrup[1 - iZDrugim]));
672
673                                                        // no to juz mozemy dopasowac
674                                                        m_pMatching->match(
675                                                                iZDrugim,
676                                                                aiKoniecPierwszejGrupy[iZDrugim] + iIndex[iZDrugim],
677                                                                1 - iZDrugim,
678                                                                aiKoniecPierwszejGrupy[1 - iZDrugim] + iDopasowywany);
679                                                        DB(printf("Przypadek 2.1.: dopasowane Parts dopasowaniebz drugim: (%2i, %2i)\n", aiKoniecPierwszejGrupy[iZDrugim] + iIndex[iZDrugim], aiKoniecPierwszejGrupy[1 - iZDrugim] + iDopasowywany);)
680
681                                                                //aiKoniecPierwszejGrupy[ 1-iBezDrugiego ] + iDopasowywany ;)
682                                                                //aiKoniecPierwszejGrupy[ 1-iBezDrugiego ] + iDopasowywany ;)
683                                                                // zmniejsz liczby niedopasowanych elementow w grupach
684                                                                aiRozmiarGrupy[0]--;
685                                                        aiRozmiarGrupy[1]--;
686
687                                                }
688                                                else
689                                                {
690                                                        // jedna z grup sie juz wyczerpala
691                                                        // wiec nie ma mozliwosci dopasowania tego drugiego Partu
692                                                        /// i trzeba poczekac na zmiane grupy
693                                                }
694
695                                                DB(printf("Przypadek 2.\n");)
696
697                                        }// PRZYPADEK 2.
698                                        else
699                                        {
700                                                // PRZYPADEK 3. Zaden z Parts nie ma na liscie drugiego
701                                                // AKCJA. Niezalezne dopasowanie obu Parts do pierwszych ze swojej listy
702
703                                                // najpierw dopasujemy do iIndex[0] w organizmie 0
704                                                int iDopasowywany = -1;
705                                                // poszukujemy pierwszego z listy dopasowania - w organizmie 1
706                                                for (i = 0; i < aiRozmiarCalychGrup[1]; i++)
707                                                {
708                                                        if (apvbCzyMinimalnaOdleglosc[0]->operator[](i))
709                                                        {
710                                                                iDopasowywany = i;
711                                                                break;
712                                                        }
713                                                }
714                                                // musielismy znalezc jakiegos dopasowywanego
715                                                assert((iDopasowywany >= 0) &&
716                                                        (iDopasowywany < aiRozmiarCalychGrup[1]));
717
718                                                // teraz wlasnie dopasowujemy
719                                                m_pMatching->match(
720                                                        0,
721                                                        aiKoniecPierwszejGrupy[0] + iIndex[0],
722                                                        1,
723                                                        aiKoniecPierwszejGrupy[1] + iDopasowywany);
724
725                                                // zmniejszamy liczbe niedopasowanych Parts
726                                                aiRozmiarGrupy[0]--;
727                                                aiRozmiarGrupy[1]--;
728
729                                                // debug - dopasowanie
730                                                DB(printf("Przypadek 3.: dopasowane Parts: (%2i, %2i)\n", aiKoniecPierwszejGrupy[0]
731                                                        + iIndex[0], aiKoniecPierwszejGrupy[1] + iDopasowywany);)
732
733                                                        // teraz dopasowujemy do iIndex[1] w organizmie 1
734                                                        iDopasowywany = -1;
735                                                // poszukujemy pierwszego z listy dopasowania - w organizmie 0
736                                                for (i = 0; i < aiRozmiarCalychGrup[0]; i++)
737                                                {
738                                                        if (apvbCzyMinimalnaOdleglosc[1]->operator[](i))
739                                                        {
740                                                                iDopasowywany = i;
741                                                                break;
742                                                        }
743                                                }
744                                                // musielismy znalezc jakiegos dopasowywanego
745                                                assert((iDopasowywany >= 0) &&
746                                                        (iDopasowywany < aiRozmiarCalychGrup[0]));
747
748                                                // no i teraz realizujemy dopasowanie
749                                                m_pMatching->match(
750                                                        0,
751                                                        aiKoniecPierwszejGrupy[0] + iDopasowywany,
752                                                        1,
753                                                        aiKoniecPierwszejGrupy[1] + iIndex[1]);
754
755                                                // zmniejszamy liczbe niedopasowanych Parts
756                                                aiRozmiarGrupy[0]--;
757                                                aiRozmiarGrupy[1]--;
758
759                                                // debug - dopasowanie
760                                                DB(printf("Przypadek 3.: dopasowane Parts: (%2i, %2i)\n", aiKoniecPierwszejGrupy[0]
761                                                        + iDopasowywany, aiKoniecPierwszejGrupy[1] + iIndex[1]);)
762
763
764                                        } // PRZYPADEK 3.
765
766                        }// if (! bCzyKoniecGrupy)
767                        else
768                        {
769                                // gdy mamy juz koniec grup - musimy zlikwidowac tablice aadOdleglosciParts
770                                // bo za chwilke skonczy sie nam petla
771                                for (i = 0; i < aiRozmiarCalychGrup[0]; i++)
772                                {
773                                        SAFEDELETEARRAY(aadOdleglosciParts[i]);
774                                }
775                                SAFEDELETEARRAY(aadOdleglosciParts);
776
777                                // musimy tez usunac tablice (wektory) mozliwosci dopasowania
778                                SAFEDELETE(apvbCzyMinimalnaOdleglosc[0]);
779                                SAFEDELETE(apvbCzyMinimalnaOdleglosc[1]);
780                        }
781                } // while (! bCzyKoniecGrupy)
782
783                // PO DOPASOWANIU WSZYSTKIEGO Z GRUP (CO NAJMNIEJ JEDNEJ GRUPY W CALOSCI)
784
785                // gdy rozmiar ktorejkolwiek z grup dopasowania spadl do zera
786                // to musimy przesunac KoniecPierwszejGrupy (wszystkie dopasowane)
787                for (i = 0; i < 2; i++)
788                {
789                        // grupy nie moga miec mniejszego niz 0 rozmiaru
790                        assert(aiRozmiarGrupy[i] >= 0);
791                        if (aiRozmiarGrupy[i] == 0)
792                                aiKoniecPierwszejGrupy[i] = aiKoniecGrupyDopasowania[i];
793                }
794
795                // sprawdzenie warunku konca dopasowywania - gdy nie
796                // ma juz w jakims organizmie co dopasowywac
797                if (aiKoniecPierwszejGrupy[0] >= m_aiPartCount[0] ||
798                        aiKoniecPierwszejGrupy[1] >= m_aiPartCount[1])
799                {
800                        iCzyDopasowane = 1;
801                }
802        } // koniec WHILE - petli dopasowania
803}
804
805void SimilMeasureGreedy::copyMatching()
806{
807        SAFEDELETE(tempMatching);
808        tempMatching = new SimilMatching(*m_pMatching);
809}
810
811void SimilMeasureGreedy::prepareData()
812{       
813        // create Parts matching object
814        m_pMatching = new SimilMatching(models[0]->getPartCount(), models[1]->getPartCount());
815
816        // utworzenie tablicy rozmiarow
817        for (int i = 0; i < 2; i++)
818        {
819                m_aiPartCount[i] = models[i]->getPartCount();
820        }
821       
822        // difference in the number of vertices (Parts) - positive
823        // find object that has less parts (m_iSmaller)
824        m_iDV = (models[0]->getPartCount() - models[1]->getPartCount());
825        if (m_iDV < 0)
826                m_iDV = -m_iDV;
827
828        // check if index of the smaller organism is a valid index
829        assert((m_iSmaller == 0) || (m_iSmaller == 1));
830        // validate difference in the parts number
831        assert(m_iDV >= 0);
832       
833        if (!createPartInfoTables())
834                logPrintf("GreedyMeasure", "PrepareData", LOG_ERROR, "Unable to create part info tables.");
835        if (!countPartDegrees())
836                logPrintf("GreedyMeasure", "PrepareData", LOG_ERROR, "Unable to count part degrees.");
837        if (!countPartNeurons())
838                logPrintf("GreedyMeasure", "PrepareData", LOG_ERROR, "Unable to count part neurons.");
839
840        DB(printf("Przed sortowaniem:\n");)
841        DB(_PrintDegrees(0);)
842        DB(_PrintDegrees(1);)
843
844        if (!sortPartInfoTables())
845                logPrintf("GreedyMeasure", "PrepareData", LOG_ERROR, "Unable to sort part info tables.");
846
847        DB(printf("Po sortowaniu:\n");)
848        DB(_PrintDegrees(0);)
849        DB(_PrintDegrees(1);)
850}
851
852void SimilMeasureGreedy::cleanData()
853{
854        // delete degree arrays created in CreatePartInfoTables
855        SAFEDELETEARRAY(m_aDegrees[0]);
856        SAFEDELETEARRAY(m_aDegrees[1]);
857       
858        // in fuzzy mode delete arrays of neighbourhood and fuzzy neighbourhood
859        if (isFuzzy)
860        {
861                for (int i = 0; i != 2; ++i)
862                {
863                        for (int j = 0; j != models[i]->getPartCount(); ++j)
864                        {
865                                delete[] m_Neighbours[i][j];
866                                delete[] m_fuzzyNeighb[i][j];
867                        }
868                        delete[] m_Neighbours[i];
869                        delete[] m_fuzzyNeighb[i];
870                }
871
872        }
873       
874        // delete created matching
875        SAFEDELETE(m_pMatching);
876       
877}
878
879/** Creates arrays holding information about organisms' Parts (m_aDegrees) andm_Neigh
880        fills them with initial data (original indices and zeros).
881        Assumptions:
882        - Models (models) are created and available.
883        */
884int SimilMeasureGreedy::createPartInfoTables()
885{
886        int i, j, partCount;
887        // utwórz tablice na informacje o stopniach wierzchołków i liczbie neuroitems
888        for (i = 0; i < 2; i++)
889        {
890                partCount = models[i]->getPartCount();
891                // utworz i wypelnij tablice dla Parts wartosciami poczatkowymi
892                m_aDegrees[i] = new TDN[partCount];
893
894                if (isFuzzy)
895                {
896                        m_Neighbours[i] = new int*[partCount];
897                        m_fuzzyNeighb[i] = new float*[partCount];
898                }
899
900                if (m_aDegrees[i] != NULL && ((!isFuzzy) || (m_Neighbours[i] != NULL && m_fuzzyNeighb[i] != NULL)))
901                {
902                        // wypelnij tablice zgodnie z sensem TDN[0] - orginalny index
903                        // TDN[1], TDN[2], TDN[3] - zerami
904                        DB(printf("m_aDegrees[%i]: %p\n", i, m_aDegrees[i]);)
905                                for (j = 0; j < partCount; j++)
906                                {
907                                        m_aDegrees[i][j][0] = j;
908                                        m_aDegrees[i][j][1] = 0;
909                                        m_aDegrees[i][j][2] = 0;
910                                        m_aDegrees[i][j][3] = 0;
911                                        m_aDegrees[i][j][4] = 0;
912
913                                        // sprawdz, czy nie piszemy po jakims szalonym miejscu pamieci
914                                        assert(m_aDegrees[i][j] != NULL);
915
916                                        if (isFuzzy)
917                                        {
918                                                m_Neighbours[i][j] = new int[partCount];
919                                                for (int k = 0; k < partCount; k++)
920                                                {
921                                                        m_Neighbours[i][j][k] = 0;
922                                                }
923
924                                                m_fuzzyNeighb[i][j] = new float[fuzzyDepth];
925                                                for (int k = 0; k < fuzzyDepth; k++)
926                                                {
927                                                        m_fuzzyNeighb[i][j][k] = 0;
928                                                }
929
930                                                assert(m_Neighbours[i][j] != NULL);
931                                                assert(m_fuzzyNeighb[i][j] != NULL);
932                                        }
933
934                                }
935                }
936                else
937                {
938                        logPrintf("ModelSimil", "CreatePartInfoTables", LOG_ERROR, "Not enough memory?");
939                        return 0;
940                }
941                // wypelnij tablice OnJoints i Anywhere wartościami początkowymi
942                // OnJoint
943                m_aOnJoint[i][0] = 0;
944                m_aOnJoint[i][1] = 0;
945                m_aOnJoint[i][2] = 0;
946                m_aOnJoint[i][3] = 0;
947                // Anywhere
948                m_aAnywhere[i][0] = 0;
949                m_aAnywhere[i][1] = 0;
950                m_aAnywhere[i][2] = 0;
951                m_aAnywhere[i][3] = 0;
952        }
953        return 1;
954}
955
956/** Computes degrees of Parts of both organisms. Fills in the m_aDegrees arrays
957        with proper information about degrees.
958        Assumptions:
959        - Models (models) are created and available.
960        - Arrays m_aDegrees are created.
961        */
962int SimilMeasureGreedy::countPartDegrees()
963{
964        Part *P1, *P2;
965        int i, j, i1, i2;
966
967        // dla obu stworzen oblicz stopnie wierzcholkow
968        for (i = 0; i < 2; i++)
969        {
970                // dla wszystkich jointow
971                for (j = 0; j < models[i]->getJointCount(); j++)
972                {
973                        // pobierz kolejny Joint
974                        Joint *J = models[i]->getJoint(j);
975                        // wez jego konce
976                        P1 = J->part1;
977                        P2 = J->part2;
978                        // znajdz ich indeksy w Modelu (indeksy orginalne)
979                        i1 = models[i]->findPart(P1);
980                        i2 = models[i]->findPart(P2);
981                        // zwieksz stopien odpowiednich Parts
982                        m_aDegrees[i][i1][DEG]++;
983                        m_aDegrees[i][i2][DEG]++;
984                        m_aDegrees[i][i1][FUZ_DEG]++;
985                        m_aDegrees[i][i2][FUZ_DEG]++;
986                        if (isFuzzy)
987                        {
988                                m_Neighbours[i][i1][i2] = 1;
989                                m_Neighbours[i][i2][i1] = 1;
990                        }
991                }
992                // dla elementow nie osadzonych na Parts (OnJoint, Anywhere) -
993                // stopnie wierzchołka są już ustalone na zero
994        }
995
996        if (isFuzzy)
997        {
998                countFuzzyNeighb();
999        }
1000
1001        return 1;
1002}
1003
1004void SimilMeasureGreedy::getNeighbIndexes(int mod, int partInd, std::vector<int> &indexes)
1005{
1006        indexes.clear();
1007        int i, size = models[mod]->getPartCount();
1008
1009        for (i = 0; i < size; i++)
1010        {
1011                if (m_Neighbours[mod][partInd][i] > 0)
1012                {
1013                        indexes.push_back(i);
1014                }
1015        }
1016}
1017
1018int compareFuzzyRows(const void *pa, const void *pb)
1019{
1020        float **a = (float**)pa;
1021        float **b = (float**)pb;
1022
1023        for (int i = 1; i < fuzzDepth; i++)
1024        {
1025                if (a[0][i] > b[0][i])
1026                {
1027                        return -1;
1028                }
1029                if (a[0][i] < b[0][i])
1030                {
1031                        return 1;
1032                }
1033        }
1034
1035        return 0;
1036}
1037
1038void SimilMeasureGreedy::fuzzyOrder()
1039{
1040        int i, depth, partInd, prevPartInd, partCount;
1041        for (int mod = 0; mod < 2; mod++)
1042        {
1043                partCount = models[mod]->getPartCount();
1044                partInd = m_fuzzyNeighb[mod][partCount - 1][0];
1045                m_aDegrees[mod][partInd][FUZ_DEG] = 0;
1046
1047                for (i = (partCount - 2); i >= 0; i--)
1048                {
1049                        prevPartInd = partInd;
1050                        partInd = m_fuzzyNeighb[mod][i][0];
1051                        m_aDegrees[mod][partInd][FUZ_DEG] = m_aDegrees[mod][prevPartInd][FUZ_DEG];
1052                        for (depth = 1; depth < fuzzyDepth; depth++)
1053                        {
1054                                if (m_fuzzyNeighb[mod][i][depth] != m_fuzzyNeighb[mod][i + 1][depth])
1055                                {
1056                                        m_aDegrees[mod][partInd][FUZ_DEG]++;
1057                                        break;
1058                                }
1059                        }
1060                }
1061        }
1062}
1063
1064//sort according to fuzzy degree
1065void SimilMeasureGreedy::sortFuzzyNeighb()
1066{
1067        fuzzDepth = fuzzyDepth;
1068        for (int mod = 0; mod < 2; mod++)
1069        {
1070                std::qsort(m_fuzzyNeighb[mod], (size_t)models[mod]->getPartCount(), sizeof(m_fuzzyNeighb[mod][0]), compareFuzzyRows);
1071        }
1072}
1073
1074//computes fuzzy vertex degree
1075void SimilMeasureGreedy::countFuzzyNeighb()
1076{
1077        std::vector<int> nIndexes;
1078        float newDeg = 0;
1079
1080        for (int mod = 0; mod < 2; mod++)
1081        {
1082                int partCount = models[mod]->getPartCount();
1083
1084                for (int depth = 0; depth < fuzzyDepth; depth++)
1085                {
1086                        //use first column for storing indices
1087                        for (int partInd = 0; partInd < partCount; partInd++)
1088                        {
1089                                if (depth == 0)
1090                                {
1091                                        m_fuzzyNeighb[mod][partInd][depth] = partInd;
1092                                }
1093                                else if (depth == 1)
1094                                {
1095                                        m_fuzzyNeighb[mod][partInd][depth] = m_aDegrees[mod][partInd][DEG];
1096                                }
1097                                else
1098                                {
1099                                        getNeighbIndexes(mod, partInd, nIndexes);
1100                                        for (unsigned int k = 0; k < nIndexes.size(); k++)
1101                                        {
1102                                                newDeg += m_fuzzyNeighb[mod][nIndexes.at(k)][depth - 1];
1103                                        }
1104                                        newDeg /= nIndexes.size();
1105                                        m_fuzzyNeighb[mod][partInd][depth] = newDeg;
1106                                        for (int mod = 0; mod < 2; mod++)
1107                                        {
1108                                                int partCount = models[mod]->getPartCount();
1109                                                for (int i = partCount - 1; i >= 0; i--)
1110                                                {
1111
1112                                                }
1113                                        }
1114                                        newDeg = 0;
1115                                }
1116                        }
1117                }
1118        }
1119
1120        sortFuzzyNeighb();
1121        fuzzyOrder();
1122}
1123
1124/** Computes numbers of neurons and neurons' inputs for each Part of each
1125        organisms and fills in the m_aDegrees array.
1126        Assumptions:
1127        - Models (models) are created and available.
1128        - Arrays m_aDegrees are created.
1129        */
1130int SimilMeasureGreedy::countPartNeurons()
1131{
1132        // sprawdz zalozenie - o modelach
1133        assert((models[0] != NULL) && (models[1] != NULL));
1134        assert(models[0]->isValid() && models[1]->isValid());
1135
1136        // sprawdz zalozenie - o tablicach
1137        assert(m_aDegrees[0] != NULL);
1138        assert(m_aDegrees[1] != NULL);
1139       
1140        Part *P1;
1141        Joint *J1;
1142        int i, j, i2, neuro_connections;
1143
1144        // dla obu stworzen oblicz liczbe Neurons + connections dla Parts
1145        // a takze dla OnJoints i Anywhere
1146        for (i = 0; i < 2; i++)
1147        {
1148                for (j = 0; j < models[i]->getNeuroCount(); j++)
1149                {
1150                        // pobierz kolejny Neuron
1151                        Neuro *N = models[i]->getNeuro(j);
1152                        // policz liczbe jego wejść i jego samego tez
1153                        // czy warto w ogole liczyc polaczenia...? co to da/spowoduje?
1154                        neuro_connections = N->getInputCount() + 1;
1155                        // wez Part, na ktorym jest Neuron
1156                        P1 = N->getPart();
1157                        if (P1)
1158                        {
1159                                // dla neuronow osadzonych na Partach
1160                                i2 = models[i]->findPart(P1); // znajdz indeks Part w Modelu
1161                                m_aDegrees[i][i2][2] += neuro_connections; // zwieksz liczbe Connections+Neurons dla tego Part (TDN[2])
1162                                m_aDegrees[i][i2][3]++; // zwieksz liczbe Neurons dla tego Part (TDN[3])
1163                        }
1164                        else
1165                        {
1166                                // dla neuronow nie osadzonych na partach
1167                                J1 = N->getJoint();
1168                                if (J1)
1169                                {
1170                                        // dla tych na Jointach
1171                                        m_aOnJoint[i][2] += neuro_connections; // zwieksz liczbe Connections+Neurons
1172                                        m_aOnJoint[i][3]++; // zwieksz liczbe Neurons
1173                                }
1174                                else
1175                                {
1176                                        // dla tych "gdziekolwiek"
1177                                        m_aAnywhere[i][2] += neuro_connections; // zwieksz liczbe Connections+Neurons
1178                                        m_aAnywhere[i][3]++; // zwieksz liczbe Neurons
1179                                }
1180                        }
1181                }
1182        }
1183        return 1;
1184}
1185
1186/** Sorts arrays m_aDegrees (for each organism) by Part's degree, and then by
1187        number of neural connections and neurons in groups of Parts with the same
1188        degree.
1189        Assumptions:
1190        - Models (models) are created and available.
1191        - Arrays m_aDegrees are created.
1192        @saeDegrees, CompareItemNo
1193        */
1194int SimilMeasureGreedy::sortPartInfoTables()
1195{
1196        int i;
1197        int(*pfDegreeFunction) (const void*, const void*) = NULL;
1198        pfDegreeFunction = isFuzzy ? &compareFuzzyDegrees : &compareDegrees;
1199        // sortowanie obu tablic wg stopni punktów - TDN[1]
1200        for (i = 0; i < 2; i++)
1201        {
1202                DB(_PrintDegrees(i));
1203                std::qsort(m_aDegrees[i], (size_t)(models[i]->getPartCount()),
1204                        sizeof(TDN), pfDegreeFunction);
1205                DB(_PrintDegrees(i));
1206        }
1207
1208        // sprawdzenie wartosci parametru
1209        DB(i = sizeof(TDN);)
1210                int degreeType = isFuzzy ? FUZ_DEG : DEG;
1211
1212        // sortowanie obu tablic m_aDegrees wedlug liczby neuronów i
1213        // czesci neuronu - ale w obrebie grup o tym samym stopniu
1214        for (i = 0; i < 2; i++)
1215        {
1216                int iPocz = 0;
1217                int iDeg, iNewDeg, iPartCount, j;
1218                // stopien pierwszego punktu w tablicy Degrees  odniesienie
1219                iDeg = m_aDegrees[i][0][degreeType];
1220                iPartCount = models[i]->getPartCount();
1221                // po kolei dla kazdego punktu w organizmie
1222                for (j = 0; j <= iPartCount; j++)
1223                {
1224                        // sprawdz stopien punktu (lub nadaj 0 - gdy juz koniec tablicy)
1225                        //                      iNewDeg = (j != iPartCount) ? m_aDegrees[i][j][1] : 0;
1226                        // usunieto stara wersje porownania!!! wprowadzono znak porownania <
1227
1228                        iNewDeg = (j < iPartCount) ? m_aDegrees[i][j][degreeType] : 0;
1229                        // skoro tablice sa posortowane wg stopni, to mamy na pewno taka kolejnosc
1230                        assert(iNewDeg <= iDeg);
1231                        if (iNewDeg != iDeg)
1232                        {
1233                                // gdy znaleziono koniec grupy o tym samym stopniu
1234                                // sortuj po liczbie neuronow w obrebie grupy
1235                                DB(_PrintDegrees(i));
1236                                DB(printf("qsort( poczatek=%i, rozmiar=%i, sizeof(TDN)=%i)\n", iPocz, (j - iPocz), sizeof(TDN));)
1237                                        // wyswietlamy z jedna komorka po zakonczeniu tablicy
1238                                        DB(_PrintArray(m_aDegrees[i][iPocz], 0, (j - iPocz) * 4);)
1239
1240                                        std::qsort(m_aDegrees[i][iPocz], (size_t)(j - iPocz),
1241                                                sizeof(TDN), SimilMeasureGreedy::compareConnsNo);
1242                                DB(_PrintDegrees(i));
1243                                // wyswietlamy z jedna komorka po zakonczeniu tablicy
1244                                DB(_PrintArray(m_aDegrees[i][iPocz], 0, (j - iPocz) * 4);)
1245                                        // rozpocznij nowa grupe
1246                                        iPocz = j;
1247                                iDeg = iNewDeg;
1248                        }
1249                }
1250        }
1251        return 1;
1252}
1253
1254
1255/** Prints the state of the matching object. Debug method.
1256 */
1257void SimilMeasureGreedy::_PrintPartsMatching()
1258{
1259        // assure that matching exists
1260        assert(m_pMatching != NULL);
1261
1262        printf("Parts matching:\n");
1263        m_pMatching->printMatching();
1264}
1265
1266/** Comparison function required for qsort() call. Used while sorting groups of
1267        Parts with respect to degree. Compares two TDN structures
1268        with respect to their [1] field (degree). Highest degree goes first.
1269        @param pElem1 Pointer to the TDN structure of some Part.
1270        @param pElem2 Pointer to the TDN structure of some Part.
1271        @return (-1) - pElem1 should go first, 0 - equal, (1) - pElem2 should go first.
1272        */
1273int SimilMeasureGreedy::compareDegrees(const void *pElem1, const void *pElem2)
1274{
1275        int *tdn1 = (int *)pElem1;
1276        int *tdn2 = (int *)pElem2;
1277
1278        if (tdn1[1] > tdn2[1])
1279        {
1280                // when degree - tdn1[1] - is BIGGER
1281                return -1;
1282        }
1283        else
1284                if (tdn1[1] < tdn2[1])
1285                {
1286                        // when degree - tdn2[1] - is BIGGER
1287                        return 1;
1288                }
1289                else
1290                {
1291                        return 0;
1292                }
1293}
1294
1295/** Comparison function required for qsort() call. Used while sorting groups of
1296        Parts with respect to fuzzy vertex degree. Compares two TDN structures
1297        with respect to their [4] field ( fuzzy vertex degree). Highest degree goes first.
1298        @param pElem1 Pointer to the TDN structure of some Part.
1299        @param pElem2 Pointer to the TDN structure of some Part.
1300        @return (-1) - pElem1 should go first, 0 - equal, (1) - pElem2 should go first.
1301        */
1302int SimilMeasureGreedy::compareFuzzyDegrees(const void *pElem1, const void *pElem2)
1303{
1304        int *tdn1 = (int *)pElem1;
1305        int *tdn2 = (int *)pElem2;
1306
1307        if (tdn1[4] > tdn2[4])
1308        {
1309                // when degree - tdn1[4] - is BIGGER
1310                return -1;
1311        }
1312        else
1313                if (tdn1[4] < tdn2[4])
1314                {
1315                        // when degree - tdn2[4] - is BIGGER
1316                        return 1;
1317                }
1318                else
1319                {
1320                        return 0;
1321                }
1322}
1323
1324/** Comparison function required for qsort() call. Used while sorting groups of Parts with
1325                the same degree. Firstly, compare NIt. Secondly, compare Neu. If both are equal -
1326                compare Parts' original index (they are never equal). So this sorting assures
1327                that the order obtained is deterministic.
1328                @param pElem1 Pointer to the TDN structure of some Part.
1329                @param pElem2 Pointer to the TDN structure of some Part.
1330                @return (-1) - pElem1 should go first, 0 - equal, (1) - pElem2 should go first.
1331                */
1332int SimilMeasureGreedy::compareConnsNo(const void *pElem1, const void *pElem2)
1333{
1334        // pointers to TDN arrays
1335        int *tdn1, *tdn2;
1336        // definitions of elements being compared
1337        tdn1 = (int *)pElem1;
1338        tdn2 = (int *)pElem2;
1339
1340        // comparison according to Neural Connections (to jest TDN[2])
1341        if (tdn1[NEUR_CONNS] > tdn2[NEUR_CONNS])
1342        {
1343                // when number of NConn Elem1 is BIGGER
1344                return -1;
1345        }
1346        else
1347                if (tdn1[NEUR_CONNS] < tdn2[NEUR_CONNS])
1348                {
1349                        // when number of NConn Elem1 is SMALLER
1350                        return 1;
1351                }
1352                else
1353                {
1354                        // when numbers of NConn are EQUAL
1355                        // compare Neu numbers (TDN[3])
1356                        if (tdn1[NEUROS] > tdn2[NEUROS])
1357                        {
1358                                // when number of Neu is BIGGER for Elem1
1359                                return -1;
1360                        }
1361                        else
1362                                if (tdn1[NEUROS] < tdn2[NEUROS])
1363                                {
1364                                        // when number of Neu is SMALLER for Elem1
1365                                        return 1;
1366                                }
1367                                else
1368                                {
1369                                        // when numbers of Nconn and Neu are equal we check original indices
1370                                        // of Parts being compared
1371
1372                                        // comparison according to OrgIndex
1373                                        if (tdn1[ORG_IND] > tdn2[ORG_IND])
1374                                        {
1375                                                // when the number of NIt Deg1 id BIGGER
1376                                                return -1;
1377                                        }
1378                                        else
1379                                                if (tdn1[ORG_IND] < tdn2[ORG_IND])
1380                                                {
1381                                                        // when the number of NIt Deg1 id SMALLER
1382                                                        return 1;
1383                                                }
1384                                                else
1385                                                {
1386                                                        // impossible, indices are alway different
1387                                                        return 0;
1388                                                }
1389                                }
1390                }
1391}
1392
1393/** Returns number of factors involved in final distance computation.
1394                These factors include differences in numbers of parts, degrees,
1395                number of neurons.
1396                */
1397int SimilMeasureGreedy::getNOFactors()
1398{
1399        return SimilMeasureGreedy::iNOFactors;
1400}
1401
1402/** Prints the array of degrees for the given organism. Debug method.
1403 */
1404void SimilMeasureGreedy::_PrintDegrees(int i)
1405{
1406        int j;
1407        printf("Organizm %i :", i);
1408        printf("\n      ");
1409        for (j = 0; j < models[i]->getPartCount(); j++)
1410                printf("%3i ", j);
1411        printf("\nInd:  ");
1412        for (j = 0; j < models[i]->getPartCount(); j++)
1413                printf("%3i ", (int)m_aDegrees[i][j][0]);
1414        printf("\nDeg:  ");
1415        for (j = 0; j < models[i]->getPartCount(); j++)
1416                printf("%3i ", (int)m_aDegrees[i][j][1]);
1417        printf("\nNIt:  ");
1418        for (j = 0; j < models[i]->getPartCount(); j++)
1419                printf("%3i ", (int)m_aDegrees[i][j][2]);
1420        printf("\nNeu:  ");
1421        for (j = 0; j < models[i]->getPartCount(); j++)
1422                printf("%3i ", (int)m_aDegrees[i][j][3]);
1423        printf("\n");
1424}
1425
1426/** Prints one array of ints. Debug method.
1427        @param array Base pointer of the array.
1428        @param base First index of the array's element.
1429        @param size Number of elements to print.
1430        */
1431void SimilMeasureGreedy::_PrintArray(int *array, int base, int size)
1432{
1433        int i;
1434        for (i = base; i < base + size; i++)
1435        {
1436                printf("%i ", array[i]);
1437        }
1438        printf("\n");
1439}
1440
1441void SimilMeasureGreedy::_PrintArrayDouble(double *array, int base, int size)
1442{
1443        int i;
1444        for (i = base; i < base + size; i++)
1445        {
1446                printf("%f ", array[i]);
1447        }
1448        printf("\n");
1449}
1450
1451/** Prints one array of parts neighbourhood.
1452        @param index of organism
1453        */
1454void SimilMeasureGreedy::_PrintNeighbourhood(int o)
1455{
1456        assert(m_Neighbours[o] != 0);
1457        printf("Neighbourhhod of organism %i\n", o);
1458        int size = models[o]->getPartCount();
1459        for (int i = 0; i < size; i++)
1460        {
1461                for (int j = 0; j < size; j++)
1462                {
1463                        printf("%i ", m_Neighbours[o][i][j]);
1464                }
1465                printf("\n");
1466        }
1467}
1468
1469/** Prints one array of parts fuzzy neighbourhood.
1470        @param index of organism
1471        */
1472void SimilMeasureGreedy::_PrintFuzzyNeighbourhood(int o)
1473{
1474        assert(m_fuzzyNeighb[o] != NULL);
1475        printf("Fuzzy neighbourhhod of organism %i\n", o);
1476        int size = models[o]->getPartCount();
1477        for (int i = 0; i < size; i++)
1478        {
1479                for (int j = 0; j < fuzzyDepth; j++)
1480                {
1481                        printf("%f ", m_fuzzyNeighb[o][i][j]);
1482                }
1483                printf("\n");
1484        }
1485}
1486
1487int SimilMeasureGreedy::setParams(std::vector<double> params)
1488{
1489        int i = 0;
1490        for (i = 0; i < SimilMeasureGreedy::iNOFactors; i++)
1491                m_adFactors[i] = params.at(i);
1492        fixedZaxis = params.at(i);
1493        if (m_adFactors[3] == 0)
1494            with_alignment = false;
1495        return 0;
1496}
Note: See TracBrowser for help on using the repository browser.