📄 filter.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
*/
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include "stladdon.hpp"
#include "random.hpp"
#include "vars.hpp"
#include "stringvars.hpp"
#include "domain.hpp"
#include "distvars.hpp"
#include "examplegen.hpp"
#include "filter.ppp"
DEFINE_TOrangeVector_classDescription(PValueFilter, "TValueFilterList", true, ORANGE_API)
DEFINE_TOrangeVector_classDescription(PFilter, "TFilterList", true, ORANGE_API)
// Sets the negate field (default is false)
TFilter::TFilter(bool anegate, PDomain dom)
: negate(anegate),
domain(dom)
{}
void TFilter::reset()
{}
PFilter TFilter::deepCopy() const
{
raiseWarning("Deep copy not implemented.");
return PFilter();
}
// Sets the maxrand field to RAND_MAX*ap
TFilter_random::TFilter_random(const float ap, bool aneg, PRandomGenerator rgen)
: TFilter(aneg, PDomain()),
prob(ap),
randomGenerator(rgen ? rgen : PRandomGenerator(mlnew TRandomGenerator()))
{};
// Chooses an example (returns true) if rand()<maxrand; example is ignored
bool TFilter_random::operator()(const TExample &)
{
if (!randomGenerator)
randomGenerator = mlnew TRandomGenerator;
return (randomGenerator->randfloat()<prob)!=negate;
}
TFilter_hasSpecial::TFilter_hasSpecial(bool aneg, PDomain dom)
: TFilter(aneg, dom)
{}
// Chooses an example if it has (no) special values.
bool TFilter_hasSpecial::operator()(const TExample &exam)
{ int i=0, Nv;
if (domain) {
TExample example(domain, exam);
for(Nv = domain->variables->size(); (i<Nv) && !example[i].isSpecial(); i++);
}
else
for(Nv = exam.domain->variables->size(); (i<Nv) && !exam[i].isSpecial(); i++);
return ((i==Nv)==negate);
}
TFilter_isDefined::TFilter_isDefined(bool aneg, PDomain dom)
: TFilter(aneg, dom),
check(mlnew TAttributedBoolList(dom ? dom->variables : PVarList(), dom ? dom->variables->size(): 0, true))
{}
bool TFilter_isDefined::operator()(const TExample &exam)
{
TExample *example;
PExample wex;
if (domain && (domain != exam.domain)) {
example = mlnew TExample(domain, exam);
wex = example;
}
else
example = const_cast<TExample *>(&exam);
if (!check || !check->size()) {
const_PITERATE(TExample, ei, example)
if ((*ei).isSpecial())
return negate;
return !negate;
}
else {
TBoolList::const_iterator ci(check->begin()), ce(check->end());
TExample::const_iterator ei(example->begin()), ee(example->end());
for(; (ci!=ce) && (ei!=ee); ci++, ei++)
if (*ci && (*ei).isSpecial())
return negate;
return !negate;
}
}
void TFilter_isDefined::afterSet(const char *name)
{
if (!strcmp(name, "domain") && domain && (!check || !check->size()) && (domain->variables != check->attributes))
check = mlnew TAttributedBoolList(domain->variables, domain->variables->size(), true);
TFilter::afterSet(name);
}
TFilter_hasMeta::TFilter_hasMeta(const int &anid, bool aneg, PDomain dom)
: TFilter(aneg, dom),
id(anid)
{}
bool TFilter_hasMeta::operator()(const TExample &exam)
{
return exam.hasMeta(id) != negate;
}
TFilter_hasClassValue::TFilter_hasClassValue(bool aneg, PDomain dom)
: TFilter(aneg, dom)
{}
// Chooses an example if it has (no) special values.
bool TFilter_hasClassValue::operator()(const TExample &exam)
{ return (domain ? TExample(domain, exam).getClass().isSpecial() : exam.getClass().isSpecial()) ==negate; }
// Constructor; sets the value and position
TFilter_sameValue::TFilter_sameValue(const TValue &aval, int apos, bool aneg, PDomain dom)
: TFilter(aneg, dom),
position(apos),
value(aval)
{}
// Chooses an example if position-th attribute's value equals (or not) the specified value
bool TFilter_sameValue::operator()(const TExample &example)
{
if (domain && (domain != example.domain))
// this is slow & inefficient, but it's the only legal way of doing it
return (TExample(domain, example)[position] == value) != negate;
else
return (example[position] == value) != negate;
}
TValueFilter::TValueFilter(const int &pos, const int &accs)
: position(pos),
acceptSpecial(accs)
{}
PValueFilter TValueFilter::deepCopy() const
{
raiseWarning("Deep copy not implemented.");
return PValueFilter();
}
TValueFilter_continuous::TValueFilter_continuous()
: TValueFilter(ILLEGAL_INT, -1),
min(0.0),
max(0.0),
outside(false),
oper(None)
{}
TValueFilter_continuous::TValueFilter_continuous(const int &pos, const float &amin, const float &amax, const bool &outs, const int &accs)
: TValueFilter(pos, accs),
min(amin),
max(amax),
outside(outs),
oper(None)
{}
TValueFilter_continuous::TValueFilter_continuous(const int &pos, const int &op, const float &amin, const float &amax, const int &accs)
: TValueFilter(pos, accs),
min(amin),
max(amax),
oper(op)
{}
#define EQUAL(x,y) (fabs(x-y) <= y*1e-10) ? 1 : 0
#define LESS_EQUAL(x,y) (x-y < y*1e-10) ? 1 : 0
#define TO_BOOL(x) (x) ? 1 : 0;
int TValueFilter_continuous::operator()(const TExample &example) const
{ const TValue &val = example[position];
if (val.isSpecial())
return acceptSpecial;
switch (oper) {
case None: return TO_BOOL(((val.floatV>=min) && (val.floatV<=max)) != outside);
case Equal: return EQUAL(val.floatV, min);
case NotEqual: return 1 - EQUAL(val.floatV, min);
case Less: return TO_BOOL(val.floatV < min);
case LessEqual: return LESS_EQUAL(val.floatV, min);
case Greater: return TO_BOOL(min < val.floatV);
case GreaterEqual: return LESS_EQUAL(min, val.floatV);
case Between: return (LESS_EQUAL(min, val.floatV)) * (LESS_EQUAL(val.floatV, max));
case Outside: return TO_BOOL((val.floatV < min) || (val.floatV > max));
default: return -1;
}
}
PValueFilter TValueFilter_continuous::deepCopy() const
{
TValueFilter *filter = mlnew TValueFilter_continuous(position,oper,min,max,acceptSpecial);
PValueFilter wfilter = filter;
return wfilter;
}
TValueFilter_discrete::TValueFilter_discrete(const int &pos, PValueList bl, const int &accs, bool neg)
: TValueFilter(pos, accs),
values(bl ? bl : mlnew TValueList()),
negate(neg)
{}
TValueFilter_discrete::TValueFilter_discrete(const int &pos, PVariable var, const int &accs, bool neg)
: TValueFilter(pos, accs),
values(mlnew TValueList(var)),
negate(neg)
{}
int TValueFilter_discrete::operator()(const TExample &example) const
{ const TValue &val = example[position];
if (val.isSpecial())
return negate ? 1-acceptSpecial : acceptSpecial;
const_PITERATE(TValueList, vi, values)
if ((*vi).intV == val.intV)
return negate ? 0 : 1;
return negate ? 1 : 0;
}
PValueFilter TValueFilter_discrete::deepCopy() const
{
if (values->size())
{
TValueList *newValues = mlnew TValueList();
PValueList wnewValues = newValues;
const_PITERATE(TValueList, vi, values)
wnewValues->push_back(TValue(*vi));
TValueFilter *filter = mlnew TValueFilter_discrete(position,wnewValues,acceptSpecial, negate);
PValueFilter wfilter = filter;
return wfilter;
}
TValueFilter *filter = mlnew TValueFilter_discrete(position,PValueList(),acceptSpecial, negate);
PValueFilter wfilter = filter;
return wfilter;
}
TValueFilter_string::TValueFilter_string()
: TValueFilter(ILLEGAL_INT, -1),
min(),
max(),
oper(None),
caseSensitive(true)
{}
TValueFilter_string::TValueFilter_string(const int &pos, const int &op, const string &amin, const string &amax, const int &accs, const bool csens)
: TValueFilter(pos, accs),
min(amin),
max(amax),
oper(op),
caseSensitive(csens)
{}
char *strToLower(string nm)
{
char *s = strcpy(new char[nm.size()+1], nm.c_str());
for(char *i = s; *i; i++)
*i = tolower(*i);
return s;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -