📄 vars.cpp
字号:
/*
This file is part of Orange.
Orange is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Orange is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Orange; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Authors: Janez Demsar, Blaz Zupan, 1996--2002
Contact: janez.demsar@fri.uni-lj.si
*/
// to include Python.h before STL defines a template set (doesn't work with VC 6.0)
#include "garbage.hpp"
#include <set>
#include <stack>
#include <map>
#include <algorithm>
#include <queue>
#include <float.h>
#include "stladdon.hpp"
#include "errors.hpp"
#include "examples.hpp"
#include "examplegen.hpp"
#include "classify.hpp"
#include "domain.hpp"
#include "random.hpp"
#include "orvector.hpp"
#include "vars.ppp"
DEFINE_TOrangeVector_classDescription(PVariable, "TVarList", true, ORANGE_API)
DEFINE_TOrangeVector_classDescription(PVarList, "TVarListList", true, ORANGE_API)
TVariable::TVariable(const int &avarType, const bool &ord)
: varType(avarType),
ordered(ord),
distributed(false),
getValueFromLocked(false),
DC_value(varType, valueDC),
DK_value(varType, valueDK)
{}
TVariable::TVariable(const string &aname, const int &avarType, const bool &ord)
: varType(avarType),
ordered(ord),
distributed(false),
getValueFromLocked(false),
DC_value(varType, valueDC),
DK_value(varType, valueDK)
{ name = aname; };
const TValue &TVariable::DC() const
{ return DC_value; }
const TValue &TVariable::DK() const
{ return DK_value; }
TValue TVariable::specialValue(int spec) const
{ return TValue(varType, spec); }
/* Converts a human-readable string, representing the value (as read from the file, for example) to TValue.
TVariable::str2val_add interprets ? as DK and ~ as DC; otherwise it sets val.varType to varType, other fields
are left intact.*/
bool TVariable::str2special(const string &valname, TValue &valu) const
{ if ((valname=="?") || !valname.length()){
valu = TValue(DK());
return true;
}
else if (valname=="~") {
valu = TValue(DC());
return true;
}
return false;
}
bool TVariable::special2str(const TValue &val, string &str) const
{ switch (val.valueType) {
case 0: return false;
case valueDC : str="~"; break;
case valueDK : str="?"; break;
default: str = ".";
}
return true;
}
bool TVariable::str2val_try(const string &valname, TValue &valu)
{ try {
str2val(valname, valu);
return true;
} catch (exception) {
return false;
}
}
void TVariable::str2val_add(const string &valname, TValue &valu)
{ str2val(valname, valu); }
void TVariable::filestr2val(const string &valname, TValue &valu, TExample &)
{ str2val_add(valname, valu); }
void TVariable::val2filestr(const TValue &val, string &str, const TExample &) const
{ val2str(val, str); }
// Calls classifier, specified in getValueFrom, if one is available
TValue TVariable::computeValue(const TExample &ex)
{ if (getValueFrom && !getValueFromLocked)
try {
if (distributed) {
getValueFromLocked = true;
const PSomeValue val = PSomeValue(getValueFrom->classDistribution(ex));
getValueFromLocked = false;
return TValue(PSomeValue(val));
}
else {
getValueFromLocked = true;
const TValue val = getValueFrom->operator()(ex);
getValueFromLocked = false;
return val;
}
}
catch (...) {
getValueFromLocked = false;
throw;
}
else
return DK();
}
bool TVariable::firstValue(TValue &val) const
{
raiseError("attribute '%s' does not support 'firstValue' method", name.c_str());
return false;
}
bool TVariable::nextValue(TValue &val) const
{
raiseError("attribute '%s' does not support 'nextValue' method", name.c_str());
return false;
}
TValue TVariable::randomValue(const int &rand)
{
raiseError("attribute '%s' does not support 'randomValue' method", name.c_str());
return TValue();
}
// Sets autoValues to true, maxLen to 2 and varType to TValue::INVAR
TEnumVariable::TEnumVariable()
: TVariable(TValue::INTVAR, false),
values(mlnew TStringList()),
baseValue(-1)
{}
TEnumVariable::TEnumVariable(const string &aname)
: TVariable(aname, TValue::INTVAR, false),
values(mlnew TStringList()),
baseValue(-1)
{}
TEnumVariable::TEnumVariable(const string &aname, PStringList val)
: TVariable(aname, TValue::INTVAR, false),
values(val),
baseValue(-1)
{}
TEnumVariable::TEnumVariable(const TEnumVariable &var)
: TVariable(var),
values(mlnew TStringList(var.values.getReference())),
baseValue(var.baseValue)
{}
int TEnumVariable::noOfValues() const
{ return values->size(); };
bool TEnumVariable::firstValue(TValue &val) const
{ if (values->size()) {
val = TValue(0);
return true;
}
else {
val = TValue(DK());
return false;
}
}
bool TEnumVariable::nextValue(TValue &val) const
{ return (++val.intV<int(values->size())); }
TValue TEnumVariable::randomValue(const int &rand)
{
if (!randomGenerator)
randomGenerator = mlnew TRandomGenerator;
if (!values->size())
raiseErrorWho("randomValue", "no values");
return TValue(int(rand<=0 ? randomGenerator->randint(values->size()) : rand%values->size()));
}
void TEnumVariable::addValue(const string &val)
{
if (values->size() > 50) {
if (valuesTree.empty())
createValuesTree();
map<string, int>::iterator lb = valuesTree.lower_bound(val);
if ((lb != valuesTree.end()) && (lb->first != val)) {
// watch the order!
valuesTree.insert(lb, make_pair(val, values->size()));
values->push_back(val);
}
}
else {
if (!exists(values->begin(), values->end(), val))
values->push_back(val);
if ((values->size() == 5) && ((values->front() == "f") || (values->front() == "float"))) {
TStringList::const_iterator vi(values->begin()), ve(values->end());
char *eptr;
char numtest[32];
while(++vi != ve) { // skip the first (f/float)
if ((*vi).length() > 31)
break;
strcpy(numtest, (*vi).c_str());
for(eptr = numtest; *eptr; eptr++)
if (*eptr == ',')
*eptr = '.';
strtod(numtest, &eptr);
while (*eptr==32)
eptr++;
if (*eptr)
break;
}
if (vi==ve)
raiseWarning("is '%s' a continuous attribute unintentionally defined by '%s'?", name.c_str(), values->front().c_str());
}
}
}
/* Converts a value from string representation to TValue by searching for it in value list.
If value is not found, it is added to the list if 'autoValues'==true, else exception is raised. */
void TEnumVariable::str2val_add(const string &valname, TValue &valu)
{
const int noValues = values->size();
if (noValues > 50) {
if (valuesTree.empty())
createValuesTree();
map<string, int>::iterator lb = valuesTree.lower_bound(valname);
if ((lb != valuesTree.end()) && (lb->first == valname))
valu = TValue(lb->second);
else if (!str2special(valname, valu)) {
valuesTree.insert(lb, make_pair(valname, noValues));
values->push_back(valname);
valu = TValue(noValues);
}
}
else {
TStringList::iterator vi = find(values->begin(), values->end(), valname);
if (vi!=values->end())
valu = TValue(int(vi - values->begin()));
else if (!str2special(valname, valu)) {
addValue(valname);
valu = TValue(noValues);
}
}
}
void TEnumVariable::str2val(const string &valname, TValue &valu)
{
if (values->size() > 50) {
if (valuesTree.empty())
createValuesTree();
map<string, int>::const_iterator vi = valuesTree.find(valname);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -