source: orange/source/orange/examples.cpp @ 11661:b05f82fd1660

Revision 11661:b05f82fd1660, 11.2 KB checked in by Ales Erjavec <ales.erjavec@…>, 8 months ago (diff)

Fixed comparison of Orange.data.Instance when the domain is empty.

RevLine 
[34]1/*
2    This file is part of Orange.
[6531]3   
4    Copyright 1996-2010 Faculty of Computer and Information Science, University of Ljubljana
5    Contact: janez.demsar@fri.uni-lj.si
[34]6
[6531]7    Orange is free software: you can redistribute it and/or modify
[34]8    it under the terms of the GNU General Public License as published by
[6531]9    the Free Software Foundation, either version 3 of the License, or
[34]10    (at your option) any later version.
11
12    Orange is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
[6531]18    along with Orange.  If not, see <http://www.gnu.org/licenses/>.
[34]19*/
20
21
22#include <algorithm>
23#include <iomanip>
24#include "stladdon.hpp"
25#include "vars.hpp"
26#include "domain.hpp"
27
28#include "examplegen.hpp"
29#include "values.hpp"
30#include "distvars.hpp"
31
32#include "examples.ppp"
[272]33#include "crc.h"
[34]34
[1337]35DEFINE_TOrangeVector_classDescription(PExample, "TExampleList", true, ORANGE_API)
[580]36
[4928]37long exampleId = 0;
38
[4937]39long getExampleId()
40{ return ++exampleId; }
41 
[34]42TExample::TExample()
43: values(NULL),
[823]44  values_end(NULL),
[9401]45  classes_end(NULL),
[4928]46  name(NULL),
47  id(getExampleId())
[34]48{}
49
50
[316]51TExample::TExample(PDomain dom, bool initMetas)
[34]52: domain(dom),
53  values(NULL),
[823]54  values_end(NULL),
[9401]55  classes_end(NULL),
[4928]56  name(NULL),
57  id(getExampleId())
[34]58{ if (!dom)
59    raiseError("example needs domain");
60
61  const int attrs = domain->variables->size();
[9410]62  const int classes = domain->classVars->size();
[9401]63  TValue *vi = values = mlnew TValue[attrs+classes];
[34]64  values_end = values + attrs;
[9401]65  classes_end = values_end + classes;
[34]66  PITERATE(TVarList, di, dom->variables)
67    *(vi++) = (*di)->DK();
[9410]68  PITERATE(TVarList, ci, dom->classVars) {
69    *(vi++) = (*ci)->DK();
[9401]70  }
[316]71  if (initMetas)
72    ITERATE(TMetaVector, mi, dom->metas)
[2751]73      if (!(*mi).optional)
74        setMeta((*mi).id, (*mi).variable->DK());
[34]75}
76
77
[316]78TExample::TExample(const TExample &orig, bool copyMetas)
[34]79: domain(orig.domain),
[823]80  meta(copyMetas ? orig.meta : TMetaValues()),
[4928]81  name(orig.name ? new string(*orig.name) : NULL),
82  id(orig.id)
[34]83{ if (domain) {
84    const int attrs = domain->variables->size();
[9401]85    const int classes = orig.classes_end - orig.values_end;
86    TValue *vi = values = mlnew TValue[attrs+classes];
[34]87    values_end = values + attrs;
[9401]88    classes_end = values_end + classes;
89    for(TValue *origi = orig.values, *thisi = values; thisi != classes_end; *(thisi++) = *(origi++));
[34]90  }
[9401]91  else 
92      values = values_end = classes_end = NULL;
[34]93}
94
95
[316]96TExample::TExample(PDomain dom, const TExample &orig, bool copyMetas)
[34]97: domain(dom),
[834]98  meta(),
[4928]99  name(NULL),
100  id(orig.id)
[34]101{ if (!dom)
[580]102    raiseError("example needs a domain");
[34]103
104  const int attrs = domain->variables->size();
[9410]105  const int classes = domain->classVars->size();
[9401]106  values = mlnew TValue[attrs + classes];
[34]107  values_end = values + attrs;
[9401]108  classes_end = values_end + classes;
[834]109  domain->convert(*this, orig, !copyMetas);
[34]110}
111
112
[1337]113void TExample::insertVal(TValue &srcval, PVariable var, const long &metaID, vector<bool> &defined)
[580]114{
[603]115  int position = var ? domain->getVarNum(var, false) : ILLEGAL_INT;
[580]116
[603]117  if (position != ILLEGAL_INT) {
118    // Check if this is an ordinary attribute
119    if (position >= 0) {
[1337]120      if (!mergeTwoValues(values[position], srcval, defined[position]))
[7665]121        raiseError("ambiguous value of attribute '%s'", var->get_name().c_str());
[1337]122      else
123        defined[position] = true;
[603]124    }
125   
126    else {
127      // Is it meta?
128      if (hasMeta(position)) {
[1337]129        if (!mergeTwoValues(meta[metaID], srcval, true))
[7665]130          raiseError("ambiguous value for meta-attribute '%s'", var->get_name().c_str());
[603]131      }
132      else
133        setMeta(position, srcval);
134    }
135  }
136
137
138  else {
139    /* This attribute is not required in the example.
140       But if it is meta and there is no other meta-attribute with same id,
141       we shall copy it nevertheless */
142    if (metaID && !domain->getMetaVar(metaID, false))
143      if (hasMeta(metaID)) {
[1337]144        if (!mergeTwoValues(meta[metaID], srcval, true))
[580]145          raiseError("ambiguous value for meta-attribute %i", position);
[603]146      }
147      else
[1337]148        setMeta(metaID  , srcval);
[580]149  }
150}
151
152
153TExample::TExample(PDomain dom, PExampleList elist)
[823]154: domain(dom),
[4928]155  name(NULL),
156  id(elist->size() ? elist->front()->id : getExampleId())
[580]157{
158  if (!dom)
159    raiseError("example needs a domain");
[9410]160  if (dom->classVars->size()) {
[9401]161      raiseError("example merging does not support multiple classes");
162  }
[580]163
[603]164  const int attrs = domain->variables->size();
[9410]165  const int classes = domain->classVars->size();
[1337]166  vector<bool> defined(attrs, false);
167
[603]168  TValue *vi = values = mlnew TValue[attrs];
169  values_end = values + attrs;
170  PITERATE(TVarList, di, dom->variables)
171    *(vi++) = (*di)->DK();
172
[580]173  PITERATE(TExampleList, eli, elist) {
174    TVarList::iterator vli((*eli)->domain->variables->begin());
175    TExample::iterator ei((*eli)->begin()), ee((*eli)->end());
176    for(; ei!=ee; ei++, vli++) 
177      if (!(*ei).isSpecial())
[1337]178        insertVal(*ei, *vli, 0, defined);
[580]179
180    set<int> metasNotToCopy;
181    ITERATE(TMetaVector, mai, (*eli)->domain->metas) {
182      metasNotToCopy.insert((*mai).id);
[603]183      if ((*eli)->hasMeta((*mai).id))
[1337]184        insertVal((*eli)->getMeta((*mai).id), (*mai).variable, (*mai).id, defined);
[580]185    }
186
187    set<int>::iterator mend(metasNotToCopy.end());
188    ITERATE(TMetaValues, mi, (*eli)->meta)
189      if (metasNotToCopy.find((*mi).first)==mend)
[1337]190        insertVal((*mi).second, PVariable(), (*mi).first, defined);
[603]191  }
192
193  ITERATE(TMetaVector, mai, domain->metas)
[2751]194    if (!(*mai).optional && !hasMeta((*mai).id))
[603]195      setMeta((*mai).id, (*mai).variable->DK());
[580]196}
197
198
[34]199TExample::~TExample()
[823]200{ 
201  mldelete[] values; 
202  if (name)
203    delete name;
204}
[34]205
206
[70]207int TExample::traverse(visitproc visit, void *arg) const
208{ TRAVERSE(TOrange::traverse);
209 
[9401]210  for(TValue *vi = values, *ve = classes_end; vi!=ve; vi++)
[70]211    if (vi->svalV)
212      PVISIT(vi->svalV);
213
214  const_ITERATE(TMetaValues, mi, meta)
215    if ((*mi).second.svalV)
216      PVISIT((*mi).second.svalV);
217
218  return 0;
219}
220
221
222int TExample::dropReferences()
223{
[9401]224  for(TValue *vi = values, *ve = classes_end; vi!=ve; vi++)
[70]225    if (vi->svalV)
226      vi->svalV.~PSomeValue();
227
228  const_ITERATE(TMetaValues, mi, meta)
229    if ((*mi).second.svalV)
230      (*mi).second.svalV.~PSomeValue();
231
[823]232  delete name;
233  name = NULL;
234
[70]235  return 0;
236}
237
238
[34]239TExample &TExample::operator =(const TExample &orig)
[284]240{
241  if (!orig.domain) {
[9401]242    if (values)
243       mldelete[] values;
244    values = values_end = classes_end = NULL;
[284]245    domain = PDomain();
246  }
[34]247
[284]248  else {
[9401]249    const int attrs = orig.values_end - orig.values;
250    const int classes = orig.classes_end - orig.values_end;
[284]251    if (domain != orig.domain) {
[9401]252      if ((values_end - values != attrs) || (classes_end - values_end != classes)) {
[284]253        if (values)
254          mldelete[] values;
[9401]255        values = mlnew TValue[attrs+classes];
[284]256        values_end = values + attrs;
[9401]257        classes_end = values_end + classes;
[284]258      }
259      domain = orig.domain;
260    }
261
[9401]262    for(TValue *origi = orig.values, *thisi = values; thisi != classes_end; *(thisi++) = *(origi++));
[34]263  }
264
265  meta = orig.meta;
[823]266 
267  if (name) {
268    delete name;
269    name = NULL;
270  }
271  if (orig.name)
272    name = new string(*orig.name);
273
[4928]274  id = orig.id;
275 
[34]276  return *this;
277}
278
279
[1580]280TValue TExample::getValue(PVariable &var) const
281{
282  // if there is no getValueFrom, throw an exception
283  const int position = domain->getVarNum(var, var->getValueFrom);
284  return position != ILLEGAL_INT ? operator[](position) : var->computeValue(*this);
285}
286
[34]287TValue &TExample::operator[] (PVariable &var)
[131]288{ return operator[](domain->getVarNum(var)); }
[34]289
290
291const TValue &TExample::operator[] (PVariable &var) const
[131]292{ return operator[](domain->getVarNum(var)); }
[34]293
294
295TValue &TExample::operator[] (const string &name)
[131]296{ return operator[](domain->getVarNum(name)); }
[34]297
298
299const TValue &TExample::operator[] (const string &name) const
[131]300{ return operator[](domain->getVarNum(name)); }
[34]301
302
[2788]303const TValue &TExample::missingMeta(const int &i) const
304{
305  const TMetaDescriptor *md = domain->metas[i];
306  if (md)
307    if (md->optional)
308      return md->variable->DK();
309    else
[7665]310      if (md->variable->get_name().size())
311        raiseError("the value of meta attribute '%s' is missing", md->variable->get_name().c_str());
[2788]312
313  // no descriptor or no name
314  raiseError("meta value with id %i is missing", i);
315  throw 0;
316}
317
318
[34]319bool TExample::operator < (const TExample &other) const
320{ 
321  if (domain != other.domain)
322    raiseError("examples are from different domains");
323  return compare(other)<0;
324}
325
326
327bool TExample::operator == (const TExample &other) const
328{ 
329  if (domain != other.domain)
330    raiseError("examples are from different domains");
331
[9410]332  int Na = domain->variables->size() + domain->classVars->size();
[34]333  if (!Na)
334    return true;
335  for (const_iterator vi1(begin()), vi2(other.begin()); (*vi1==*vi2) && --Na; vi1++, vi2++);
336  return !Na;
337}
338
339
[2501]340int TExample::compare(const TExample &other, const bool ignoreClass) const
[34]341{ if (domain != other.domain)
342    raiseError("examples are from different domains");
[9401]343  int Na = domain->variables->size();
344  if (ignoreClass) {
345      if (domain->classVar) {
346          Na--;
347      }
348  }
349  else {
[9410]350      Na += domain->classVars->size();
[9401]351  }
[34]352  if (!Na)
[11661]353    return 0;
[34]354
[9401]355  const_iterator i1(begin()), i2(other.begin());
[34]356  int comp;
357  while (0==(comp= (*(i1++)).compare(*(i2++))) && --Na);
358  return comp;
359}
360
361
[2501]362bool TExample::compatible(const TExample &other, const bool ignoreClass) const
[34]363{ if (domain != other.domain)
364    raiseError("examples are from different domains");
365 
[9401]366  int Na = domain->variables->size();
367  if (ignoreClass) {
368      if (domain->classVar) {
369          Na--;
370      }
371  }
372  else {
[9410]373      Na += domain->classVars->size();
[9401]374  }
[34]375  if (!Na)
376    return true;
377  for (const_iterator i1(begin()), i2(other.begin()); (*i1).compatible(*i2) && --Na; i1++, i2++);
378  return !Na;
379}
380
[59]381
[4238]382#include "stringvars.hpp"
383
[10596]384inline void addToCRC(unsigned int &crc, const PVarList &vars, TValue *&vli)
[1262]385{
[9401]386  const_PITERATE(TVarList, vi, vars) {
[59]387    if ((*vi)->varType == TValue::INTVAR)
[10591]388      add_CRC(vli->isSpecial() ? ILLEGAL_INT : vli->intV, crc);
[4238]389    else if (((*vi)->varType == TValue::FLOATVAR))
390      add_CRC(vli->isSpecial() ? ILLEGAL_FLOAT : vli->floatV, crc);
391    else if ((*vi)->varType == STRINGVAR) {
392      if (vli->isSpecial() || !vli->svalV)
[10591]393        add_CRC(ILLEGAL_INT, crc);
[4238]394      else
395        add_CRC(vli->svalV.AS(TStringValue)->value.c_str(), crc);
396    }
[273]397    vli++;
398  }
[9401]399}
400
[10596]401void TExample::addToCRC(unsigned int &crc, const bool includeMetas) const
[9401]402{
403  TValue *vli = values;
404  ::addToCRC(crc, domain->variables, vli);
[9410]405  ::addToCRC(crc, domain->classVars, vli);
[4238]406 
407  if (includeMetas) {
408    const_ITERATE(TMetaValues, mi, meta) {
409      add_CRC((const unsigned long)(mi->first), crc);
410      const TValue &val = mi->second;
411      if (val.varType == TValue::INTVAR)
[10591]412        add_CRC(val.isSpecial() ? ILLEGAL_INT : val.intV, crc);
[4238]413      else if (val.varType == TValue::INTVAR)
414        add_CRC(val.isSpecial() ? ILLEGAL_FLOAT: val.floatV, crc);
415      else if (val.varType == STRINGVAR) {
416        if (val.isSpecial()  || !vli->svalV)
[10591]417          add_CRC(ILLEGAL_INT, crc);
[4238]418        else
419          add_CRC(val.svalV.AS(TStringValue)->value.c_str(), crc);
420      }
421    }
422  }
[1262]423}
[272]424
[1262]425
[4238]426int TExample::sumValues(const bool includeMetas) const
[10596]427{ unsigned int crc;
[1262]428  INIT_CRC(crc);
[4238]429  addToCRC(crc, includeMetas);
[272]430  FINISH_CRC(crc);
[281]431  return int(crc & 0x7fffffff);
[59]432}
Note: See TracBrowser for help on using the repository browser.