source: cpp/frams/model/similarity/simil_match.cpp @ 978

Last change on this file since 978 was 869, checked in by Maciej Komosinski, 6 years ago

Added another, improved way of calculating dissimilarity of two creatures/models. Details and comparisons in https://doi.org/10.1007/978-3-030-16692-2_8

  • Property svn:eol-style set to native
File size: 7.0 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2019  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include <assert.h>
6#include <stdio.h>
7#include "simil_match.h"
8
9/** Creates an empty matching for two objects of specified size.
10                @param Obj0Size Size of the first object. Must be positive.
11                @param Obj1Size Size of the second object. Must be positive.
12 */
13SimilMatching::SimilMatching(int Obj0Size, int Obj1Size)
14{
15        // assure that sizes of objects are positive
16        assert(Obj0Size > 0);
17        assert(Obj1Size > 0);
18
19        // create necessary vectors
20        m_apvMatched[0] = new std::vector<int>(Obj0Size);
21        m_apvMatched[1] = new std::vector<int>(Obj1Size);
22
23        // assure that vectors are created
24        assert(m_apvMatched[0] != NULL);
25        assert(m_apvMatched[1] != NULL);
26
27        // fill vectors with "unmatched" indicator
28        for (unsigned int i = 0; i < m_apvMatched[0]->size(); i++)
29        {
30                m_apvMatched[0]->operator[](i) = -1;
31        }
32        for (unsigned int i = 0; i < m_apvMatched[1]->size(); i++)
33        {
34                m_apvMatched[1]->operator[](i) = -1;
35        }
36}
37
38/** A copying constructor.
39                @param Source The object to be copied.
40 */
41SimilMatching::SimilMatching(const SimilMatching &Source)
42{
43        // copy the vectors of the actual matching
44        m_apvMatched[0] = new std::vector<int>(*(Source.m_apvMatched[0]));
45        m_apvMatched[1] = new std::vector<int>(*(Source.m_apvMatched[1]));
46
47        // assure that vectors are created
48        assert(m_apvMatched[0] != NULL);
49        assert(m_apvMatched[1] != NULL);
50}
51
52/** Destroys a matching object.
53 */
54SimilMatching::~SimilMatching()
55{
56        // delete vectors of matching
57        delete m_apvMatched[0];
58        delete m_apvMatched[1];
59}
60
61/** Gets size of the specified object.
62                @param Index of an object (must be 0 or 1).
63                @return Size of the object (in elements).
64 */
65int SimilMatching::GetObjectSize(int Obj)
66{
67        // check parameter
68        assert((Obj == 0) || (Obj == 1));
69
70        // return the result
71        return m_apvMatched[Obj]->size();
72}
73
74/** Matches elements given by indices in the given objects.
75                @param Obj0 Index of the first object. Must be 0 or 1.
76                @param index0 Index of element in the first object. Must be a valid index
77                ( >= 0 and < size of the object).
78                @param Obj1 Index of the second object. Must be 0 or 1 and different from Obj0.
79                @param Index1 index of element in the second object. Must be a valid index
80                ( >= 0 and < size of the object).
81
82 */
83void SimilMatching::Match(int Obj0, int Index0, int Obj1, int Index1)
84{
85        // check parameters of object 0
86        assert((Obj0 == 0) || (Obj0 == 1));
87        assert((Index0 >= 0) && (Index0 < (int)m_apvMatched[Obj0]->size()));
88        // check parameters of object 1
89        assert(((Obj1 == 0) || (Obj1 == 1)) && (Obj0 != Obj1));
90        assert((Index1 >= 0) && (Index1 < (int)m_apvMatched[Obj1]->size()));
91
92        // match given elements
93        // matching_Obj0(Index0) = Index1
94        m_apvMatched[Obj0]->operator[](Index0) = Index1;
95        // matching_Obj1(Index1) = Index0
96        m_apvMatched[Obj1]->operator[](Index1) = Index0;
97}
98
99/** Checks if the given element in the given object is already matched.
100                @param Obj Index of an object (must be 0 or 1).
101                @param Index Index of an element in the given object. Must be a valid index
102                ( >=0 and < size of the object).
103                @return true if the given element is matched, false otherwise.
104 */
105bool SimilMatching::IsMatched(int Obj, int Index)
106{
107        // check parameters
108        assert((Obj == 0) || (Obj == 1));
109        assert((Index >= 0) && (Index < (int)m_apvMatched[Obj]->size()));
110
111        // check if the element is matched
112        if (m_apvMatched[Obj]->operator[](Index) >= 0)
113        {
114                return true;
115        }
116        else
117        {
118                return false;
119        }
120}
121
122/** Gets index of the element thet is matched in the other object withe the element given
123                by parameters.
124                @param Obj Index of an object (must be 0 or 1).
125                @param Index Index of checked element in the given object.
126                @return Index of the element (in the other organism) that is matched with the given
127                element. WARNING! If the given element is not matched, the result may be smaller than 0
128                (check IsMatched() before using GetMatchedIndex()).
129 */
130int SimilMatching::GetMatchedIndex(int Obj, int Index)
131{
132        // check parameters
133        assert((Obj == 0) || (Obj == 1));
134        assert((Index >= 0) && (Index < (int)m_apvMatched[Obj]->size()));
135
136        // return the index of the matched element
137        return m_apvMatched[Obj]->operator[](Index);
138}
139
140/** Checks if the matching is already full, i.e. if the smaller object already has all its
141                elements matched.
142                @return true if matching is full, false otherwise.
143 */
144bool SimilMatching::IsFull()
145{
146        // assume that the matching is full
147        bool bResult = true;
148        // index of the smallest object
149        int nObj;
150
151        // find the smallest object (its index)
152        if (m_apvMatched[0]->size() < m_apvMatched[1]->size())
153        {
154                nObj = 0;
155        }
156        else
157        {
158                nObj = 1;
159        }
160
161        // check if all elements of the smallest object are matched
162        for (unsigned int nElem = 0; nElem < m_apvMatched[nObj]->size(); nElem++)
163        {
164                if (m_apvMatched[nObj]->operator[](nElem) < 0)
165                {
166                        // if any element is not matched, the result is false
167                        bResult = false;
168                        break;
169                }
170        }
171
172        // return the result
173        return bResult;
174}
175
176/** Checks if the matching is empty (i.e. none of elements is matched).
177        @return true if matching is empty, otherwise - false.
178 */
179bool SimilMatching::IsEmpty()
180{
181        // result - assume that matching is empty
182        bool bResult = true;
183
184        // matching is empty if either of objects has only unmatched elements
185        // so it may be first object
186        int nObj = 0;
187        for (unsigned int nElem = 0; nElem < m_apvMatched[nObj]->size(); nElem++)
188        {
189                if (m_apvMatched[nObj]->operator[](nElem) >= 0)
190                {
191                        // if any element of the object is matched (unmatched objects have (-1))
192                        bResult = false;
193                        break;
194                }
195        }
196
197        // return the result from the loop
198        return bResult;
199}
200
201/** Makes the matching completely empty. After a call to this method IsEmpty() should return true.
202 */
203void SimilMatching::Empty()
204{
205        for (int iObj = 0; iObj < 2; iObj++) // a counter of objects
206        {
207                // for each object in the matching
208                for (unsigned int iElem = 0; iElem < m_apvMatched[iObj]->size(); iElem++) // a counter of objects' elements
209                {
210                        // for each element iElem for the object iObj
211                        // set it as unmatched (marker: -1)
212                        m_apvMatched[iObj]->operator[](iElem) = -1;
213                }
214        }
215
216        // the exit condition
217        assert(IsEmpty() == true);
218}
219
220/** Prints the current state of the matching
221 */
222void SimilMatching::PrintMatching()
223{
224        int nBigger;
225
226        // check which object is bigger
227        if (m_apvMatched[0]->size() >= m_apvMatched[1]->size())
228        {
229                nBigger = 0;
230        }
231        else
232        {
233                nBigger = 1;
234        }
235
236        // print first line - indices of objects
237        printf("[ ");
238        for (unsigned int i = 0; i < m_apvMatched[nBigger]->size(); i++)
239        {
240                printf("%2d ", i);
241        }
242        printf("]\n");
243
244        // print second line and third - indices of elements matched with elements of the objects
245        for (int nObj = 0; nObj < 2; nObj++)
246        {
247                // for both objects - print out lines of matched elements
248                printf("[ ");
249                for (unsigned int i = 0; i < m_apvMatched[nObj]->size(); i++)
250                {
251                        if (IsMatched(nObj, i))
252                        {
253                                // if the element is matched - print the index
254                                printf("%2d ", GetMatchedIndex(nObj, i));
255                        }
256                        else
257                        {
258                                // if the element is not matched - print "X"
259                                printf(" X ");
260                        }
261                }
262                printf("]\n");
263        }
264}
Note: See TracBrowser for help on using the repository browser.