source: orange/source/orange/examples.cpp @ 10591:1a543c7924ef

Revision 10591:1a543c7924ef, 11.2 KB checked in by Janez Demšar <janez.demsar@…>, 2 years ago (diff)

Added add_CRC(const int) to remove casting when computing a checksum for TExample

Line 
1/*
2    This file is part of Orange.
3   
4    Copyright 1996-2010 Faculty of Computer and Information Science, University of Ljubljana
5    Contact: janez.demsar@fri.uni-lj.si
6
7    Orange is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
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
18    along with Orange.  If not, see <http://www.gnu.org/licenses/>.
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"
33#include "crc.h"
34
35DEFINE_TOrangeVector_classDescription(PExample, "TExampleList", true, ORANGE_API)
36
37long exampleId = 0;
38
39long getExampleId()
40{ return ++exampleId; }
41 
42TExample::TExample()
43: values(NULL),
44  values_end(NULL),
45  classes_end(NULL),
46  name(NULL),
47  id(getExampleId())
48{}
49
50
51TExample::TExample(PDomain dom, bool initMetas)
52: domain(dom),
53  values(NULL),
54  values_end(NULL),
55  classes_end(NULL),
56  name(NULL),
57  id(getExampleId())
58{ if (!dom)
59    raiseError("example needs domain");
60
61  const int attrs = domain->variables->size();
62  const int classes = domain->classVars->size();
63  TValue *vi = values = mlnew TValue[attrs+classes];
64  values_end = values + attrs;
65  classes_end = values_end + classes;
66  PITERATE(TVarList, di, dom->variables)
67    *(vi++) = (*di)->DK();
68  PITERATE(TVarList, ci, dom->classVars) {
69    *(vi++) = (*ci)->DK();
70  }
71  if (initMetas)
72    ITERATE(TMetaVector, mi, dom->metas)
73      if (!(*mi).optional)
74        setMeta((*mi).id, (*mi).variable->DK());
75}
76
77
78TExample::TExample(const TExample &orig, bool copyMetas)
79: domain(orig.domain),
80  meta(copyMetas ? orig.meta : TMetaValues()),
81  name(orig.name ? new string(*orig.name) : NULL),
82  id(orig.id)
83{ if (domain) {
84    const int attrs = domain->variables->size();
85    const int classes = orig.classes_end - orig.values_end;
86    TValue *vi = values = mlnew TValue[attrs+classes];
87    values_end = values + attrs;
88    classes_end = values_end + classes;
89    for(TValue *origi = orig.values, *thisi = values; thisi != classes_end; *(thisi++) = *(origi++));
90  }
91  else 
92      values = values_end = classes_end = NULL;
93}
94
95
96TExample::TExample(PDomain dom, const TExample &orig, bool copyMetas)
97: domain(dom),
98  meta(),
99  name(NULL),
100  id(orig.id)
101{ if (!dom)
102    raiseError("example needs a domain");
103
104  const int attrs = domain->variables->size();
105  const int classes = domain->classVars->size();
106  values = mlnew TValue[attrs + classes];
107  values_end = values + attrs;
108  classes_end = values_end + classes;
109  domain->convert(*this, orig, !copyMetas);
110}
111
112
113void TExample::insertVal(TValue &srcval, PVariable var, const long &metaID, vector<bool> &defined)
114{
115  int position = var ? domain->getVarNum(var, false) : ILLEGAL_INT;
116
117  if (position != ILLEGAL_INT) {
118    // Check if this is an ordinary attribute
119    if (position >= 0) {
120      if (!mergeTwoValues(values[position], srcval, defined[position]))
121        raiseError("ambiguous value of attribute '%s'", var->get_name().c_str());
122      else
123        defined[position] = true;
124    }
125   
126    else {
127      // Is it meta?
128      if (hasMeta(position)) {
129        if (!mergeTwoValues(meta[metaID], srcval, true))
130          raiseError("ambiguous value for meta-attribute '%s'", var->get_name().c_str());
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)) {
144        if (!mergeTwoValues(meta[metaID], srcval, true))
145          raiseError("ambiguous value for meta-attribute %i", position);
146      }
147      else
148        setMeta(metaID  , srcval);
149  }
150}
151
152
153TExample::TExample(PDomain dom, PExampleList elist)
154: domain(dom),
155  name(NULL),
156  id(elist->size() ? elist->front()->id : getExampleId())
157{
158  if (!dom)
159    raiseError("example needs a domain");
160  if (dom->classVars->size()) {
161      raiseError("example merging does not support multiple classes");
162  }
163
164  const int attrs = domain->variables->size();
165  const int classes = domain->classVars->size();
166  vector<bool> defined(attrs, false);
167
168  TValue *vi = values = mlnew TValue[attrs];
169  values_end = values + attrs;
170  PITERATE(TVarList, di, dom->variables)
171    *(vi++) = (*di)->DK();
172
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())
178        insertVal(*ei, *vli, 0, defined);
179
180    set<int> metasNotToCopy;
181    ITERATE(TMetaVector, mai, (*eli)->domain->metas) {
182      metasNotToCopy.insert((*mai).id);
183      if ((*eli)->hasMeta((*mai).id))
184        insertVal((*eli)->getMeta((*mai).id), (*mai).variable, (*mai).id, defined);
185    }
186
187    set<int>::iterator mend(metasNotToCopy.end());
188    ITERATE(TMetaValues, mi, (*eli)->meta)
189      if (metasNotToCopy.find((*mi).first)==mend)
190        insertVal((*mi).second, PVariable(), (*mi).first, defined);
191  }
192
193  ITERATE(TMetaVector, mai, domain->metas)
194    if (!(*mai).optional && !hasMeta((*mai).id))
195      setMeta((*mai).id, (*mai).variable->DK());
196}
197
198
199TExample::~TExample()
200{ 
201  mldelete[] values; 
202  if (name)
203    delete name;
204}
205
206
207int TExample::traverse(visitproc visit, void *arg) const
208{ TRAVERSE(TOrange::traverse);
209 
210  for(TValue *vi = values, *ve = classes_end; vi!=ve; vi++)
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{
224  for(TValue *vi = values, *ve = classes_end; vi!=ve; vi++)
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
232  delete name;
233  name = NULL;
234
235  return 0;
236}
237
238
239TExample &TExample::operator =(const TExample &orig)
240{
241  if (!orig.domain) {
242    if (values)
243       mldelete[] values;
244    values = values_end = classes_end = NULL;
245    domain = PDomain();
246  }
247
248  else {
249    const int attrs = orig.values_end - orig.values;
250    const int classes = orig.classes_end - orig.values_end;
251    if (domain != orig.domain) {
252      if ((values_end - values != attrs) || (classes_end - values_end != classes)) {
253        if (values)
254          mldelete[] values;
255        values = mlnew TValue[attrs+classes];
256        values_end = values + attrs;
257        classes_end = values_end + classes;
258      }
259      domain = orig.domain;
260    }
261
262    for(TValue *origi = orig.values, *thisi = values; thisi != classes_end; *(thisi++) = *(origi++));
263  }
264
265  meta = orig.meta;
266 
267  if (name) {
268    delete name;
269    name = NULL;
270  }
271  if (orig.name)
272    name = new string(*orig.name);
273
274  id = orig.id;
275 
276  return *this;
277}
278
279
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
287TValue &TExample::operator[] (PVariable &var)
288{ return operator[](domain->getVarNum(var)); }
289
290
291const TValue &TExample::operator[] (PVariable &var) const
292{ return operator[](domain->getVarNum(var)); }
293
294
295TValue &TExample::operator[] (const string &name)
296{ return operator[](domain->getVarNum(name)); }
297
298
299const TValue &TExample::operator[] (const string &name) const
300{ return operator[](domain->getVarNum(name)); }
301
302
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
310      if (md->variable->get_name().size())
311        raiseError("the value of meta attribute '%s' is missing", md->variable->get_name().c_str());
312
313  // no descriptor or no name
314  raiseError("meta value with id %i is missing", i);
315  throw 0;
316}
317
318
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
332  int Na = domain->variables->size() + domain->classVars->size();
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
340int TExample::compare(const TExample &other, const bool ignoreClass) const
341{ if (domain != other.domain)
342    raiseError("examples are from different domains");
343
344  int Na = domain->variables->size();
345  if (ignoreClass) {
346      if (domain->classVar) {
347          Na--;
348      }
349  }
350  else {
351      Na += domain->classVars->size();
352  }
353  if (!Na)
354    return true;
355
356  const_iterator i1(begin()), i2(other.begin());
357  int comp;
358  while (0==(comp= (*(i1++)).compare(*(i2++))) && --Na);
359  return comp;
360}
361
362
363bool TExample::compatible(const TExample &other, const bool ignoreClass) const
364{ if (domain != other.domain)
365    raiseError("examples are from different domains");
366 
367  int Na = domain->variables->size();
368  if (ignoreClass) {
369      if (domain->classVar) {
370          Na--;
371      }
372  }
373  else {
374      Na += domain->classVars->size();
375  }
376  if (!Na)
377    return true;
378  for (const_iterator i1(begin()), i2(other.begin()); (*i1).compatible(*i2) && --Na; i1++, i2++);
379  return !Na;
380}
381
382
383#include "stringvars.hpp"
384
385inline void addToCRC(unsigned long &crc, const PVarList &vars, TValue *&vli)
386{
387  const_PITERATE(TVarList, vi, vars) {
388    if ((*vi)->varType == TValue::INTVAR)
389      add_CRC(vli->isSpecial() ? ILLEGAL_INT : vli->intV, crc);
390    else if (((*vi)->varType == TValue::FLOATVAR))
391      add_CRC(vli->isSpecial() ? ILLEGAL_FLOAT : vli->floatV, crc);
392    else if ((*vi)->varType == STRINGVAR) {
393      if (vli->isSpecial() || !vli->svalV)
394        add_CRC(ILLEGAL_INT, crc);
395      else
396        add_CRC(vli->svalV.AS(TStringValue)->value.c_str(), crc);
397    }
398    vli++;
399  }
400}
401
402void TExample::addToCRC(unsigned long &crc, const bool includeMetas) const
403{
404  TValue *vli = values;
405  ::addToCRC(crc, domain->variables, vli);
406  ::addToCRC(crc, domain->classVars, vli);
407 
408  if (includeMetas) {
409    const_ITERATE(TMetaValues, mi, meta) {
410      add_CRC((const unsigned long)(mi->first), crc);
411      const TValue &val = mi->second;
412      if (val.varType == TValue::INTVAR)
413        add_CRC(val.isSpecial() ? ILLEGAL_INT : val.intV, crc);
414      else if (val.varType == TValue::INTVAR)
415        add_CRC(val.isSpecial() ? ILLEGAL_FLOAT: val.floatV, crc);
416      else if (val.varType == STRINGVAR) {
417        if (val.isSpecial()  || !vli->svalV)
418          add_CRC(ILLEGAL_INT, crc);
419        else
420          add_CRC(val.svalV.AS(TStringValue)->value.c_str(), crc);
421      }
422    }
423  }
424}
425
426
427int TExample::sumValues(const bool includeMetas) const
428{ unsigned long crc;
429  INIT_CRC(crc);
430  addToCRC(crc, includeMetas);
431  FINISH_CRC(crc);
432  return int(crc & 0x7fffffff);
433}
Note: See TracBrowser for help on using the repository browser.