source: orange/source/orange/examples.cpp @ 11703:9b8d8ab7820c

Revision 11703:9b8d8ab7820c, 10.4 KB checked in by janezd <janez.demsar@…>, 7 months ago (diff)

Removed the GPL copyright notice from all files except orangeqt.

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