📄 contingency.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 "stladdon.hpp"
#include "vars.hpp"
#include "domain.hpp"
#include "examples.hpp"
#include "examplegen.hpp"
#include "classify.hpp"
#include "estimateprob.hpp"
#include "learn.hpp"
#include "contingency.ppp"
DEFINE_TOrangeVector_classDescription(PContingencyClass, "TContingencyClassList", true, ORANGE_API)
#define NOTSPEC(v) if (v.isSpecial()) throw mlexception("unknown variable value");
#define NEEDS(ptype) if(varType!=ptype) throw mlexception("invalid variable type");
// Initializes type field and discrete/continuous field, whichever appropriate.
TContingency::TContingency(PVariable var, PVariable innervar)
: outerVariable(var),
innerVariable(innervar),
varType(var ? var->varType : TValue::NONE),
outerDistribution(TDistribution::create(var)),
discrete((TDistributionVector *)NULL),
innerDistribution(TDistribution::create(innervar)),
innerDistributionUnknown(TDistribution::create(innervar))
{
if (varType==TValue::INTVAR) {
discrete = mlnew TDistributionVector();
for(int i=0, e=outerVariable->noOfValues(); i!=e; i++)
discrete->push_back(TDistribution::create(innervar));
}
else if (varType==TValue::FLOATVAR)
continuous = mlnew TDistributionMap();
}
TContingency::TContingency(const TContingency &old)
: outerVariable(old.outerVariable),
innerVariable(old.innerVariable),
varType(old.varType),
discrete((TDistributionVector *)NULL),
outerDistribution(CLONE(TDistribution, old.outerDistribution)),
innerDistribution(CLONE(TDistribution, old.innerDistribution)),
innerDistributionUnknown(CLONE(TDistribution, old.innerDistributionUnknown))
{ if (varType==TValue::INTVAR)
discrete = mlnew TDistributionVector(*old.discrete);
else if (varType==TValue::FLOATVAR)
continuous = mlnew TDistributionMap(*old.continuous);
}
int TContingency::traverse(visitproc visit, void *arg) const
{ TRAVERSE(TOrange::traverse);
if (varType==TValue::INTVAR) {
PITERATE(TDistributionVector, di, discrete)
PVISIT(*di);
}
else if (varType==TValue::FLOATVAR) {
PITERATE(TDistributionMap, di, continuous)
PVISIT((*di).second);
}
return 0;
}
int TContingency::dropReferences()
{ DROPREFERENCES(TOrange::dropReferences);
if (varType==TValue::INTVAR)
mldelete discrete;
else if (varType==TValue::FLOATVAR)
mldelete continuous;
return 0;
}
TContingency &TContingency::operator =(const TContingency &old)
{ outerVariable = old.outerVariable;
innerVariable = old.innerVariable;
varType = old.varType;
innerDistribution = CLONE(TDistribution, old.innerDistribution);
outerDistribution = CLONE(TDistribution, old.outerDistribution);
innerDistributionUnknown = CLONE(TDistribution, old.innerDistributionUnknown);
if (varType==TValue::INTVAR)
discrete=mlnew TDistributionVector(*old.discrete);
else if (varType==TValue::FLOATVAR)
continuous=mlnew TDistributionMap(*old.continuous);
else discrete=NULL;
return *this;
}
TContingency::~TContingency()
{ if (varType==TValue::INTVAR)
mldelete discrete;
else if (varType==TValue::FLOATVAR)
mldelete continuous;
}
PDistribution TContingency::operator [](const int &i)
{ NEEDS(TValue::INTVAR);
while (int(discrete->size())<=i) {
discrete->push_back(TDistribution::create(innerVariable));
if (innerVariable->varType==TValue::INTVAR)
discrete->back()->addint(innerVariable->noOfValues()-1, 0);
}
return (*discrete)[i];
}
const PDistribution TContingency::operator [](const int &i) const
{ NEEDS(TValue::INTVAR);
if (!discrete->size())
raiseError("empty contingency");
if (i>=int(discrete->size()))
raiseError("index %i is out of range 0-%i", i, discrete->size()-1);
return (*discrete)[i];
}
PDistribution TContingency::operator [](const float &i)
{ NEEDS(TValue::FLOATVAR);
TDistributionMap::iterator mi=continuous->find(i);
if (mi==continuous->end()) {
PDistribution ret = (*continuous)[i] = TDistribution::create(innerVariable);
if (innerVariable->varType==TValue::INTVAR)
ret->addint(innerVariable->noOfValues()-1, 0);
return ret;
}
else
return (*mi).second;
}
const PDistribution TContingency::operator [](const float &i) const
{ NEEDS(TValue::FLOATVAR);
TDistributionMap::iterator mi = continuous->find(float(i));
if (mi==continuous->end())
raiseError("index out of range.");
return (*mi).second;
}
PDistribution TContingency::operator [](const TValue &i)
{ NOTSPEC(i);
return (varType==TValue::INTVAR) ? operator[](int(i)) : operator[](float(i));
}
PDistribution const TContingency::operator [](const TValue &i) const // same, but calls 'const' version of operators[]
{ NOTSPEC(i);
return (varType==TValue::INTVAR) ? operator[](int(i)) : operator[](float(i));
}
PDistribution TContingency::operator [](const string &i)
{ TValue val;
checkProperty(outerVariable);
outerVariable->str2val(i, val);
return operator[](val);
}
PDistribution const TContingency::operator [](const string &i) const // same, but calls 'const' version of operators[]
{ TValue val;
checkProperty(outerVariable);
outerVariable.getReference().str2val(i, val);
return operator[](val);
}
void TContingency::add(const TValue &outvalue, const TValue &invalue, const float p)
{
outerDistribution->add(outvalue, p);
if (outvalue.isSpecial()) {
innerDistributionUnknown->add(invalue, p);
}
else {
innerDistribution->add(invalue, p);
switch(outvalue.varType) {
case TValue::INTVAR:
if (!outvalue.svalV) {
(*this)[outvalue]->add(invalue, p);
return;
}
else {
const TDiscDistribution &dv=dynamic_cast<const TDiscDistribution &>(outvalue.svalV.getReference());
int i=0;
float dp=p/dv.abs;
const_ITERATE(TDiscDistribution, vi, dv)
(*this)[i++]->add(invalue, dp*(*vi));
return;
}
case TValue::FLOATVAR:
if (!outvalue.svalV) {
(*this)[outvalue]->add(invalue, p);
return;
}
else {
const TContDistribution &dv=dynamic_cast<const TContDistribution &>(outvalue.svalV.getReference());
float dp=p/dv.abs;
const_ITERATE(TContDistribution, vi, dv)
(*this)[(*vi).first]->add(invalue, dp*(*vi).second);
return;
}
default:
raiseError("unknown value type");
}
}
}
PDistribution TContingency::p(const int &i) const
{ return operator[](i); }
PDistribution TContingency::p(const string &s) const
{ return operator[](s); }
PDistribution TContingency::p(const TValue &val) const
{ NOTSPEC(val);
return (varType==TValue::INTVAR) ? p(int(val)) : p(float(val));
}
PDistribution TContingency::p(const float &f) const
{
NEEDS(TValue::FLOATVAR);
TDistributionMap::const_iterator i1=continuous->lower_bound(f);
if (i1==continuous->end())
if (continuous->size()==0)
raiseError("empty contingency");
else
return CLONE(TDistribution, (*(--i1)).second);
else if (((*i1).first == f) || (i1==continuous->begin()))
return CLONE(TDistribution, (*i1).second);
TDistributionMap::const_iterator i2 = i1;
i1--;
const float &x1 = (*i1).first;
const float &x2 = (*i2).first;
const PDistribution &y1 = (*i1).second;
const PDistribution &y2 = (*i2).second;
const float r = (x1==x2) ? 0.5 : (f-x1)/(x2-x1);
// We want to compute y1*(1-r) + y2*r
// We know that r!=0, so we can compute (y1*(1-r)/r + y2) * r
TDistribution *res = CLONE(TDistribution, y1);
PDistribution wres = res;
*res *= (1-r)/r;
*res += y2;
*res *= r;
return wres;
}
void TContingency::normalize()
{ if (varType==TValue::INTVAR)
ITERATE(TDistributionVector, ci, *discrete)
(*ci)->normalize();
else if (varType==TValue::FLOATVAR)
ITERATE(TDistributionMap, ci, *continuous)
(*ci).second->normalize();
}
TContingencyClass::TContingencyClass(PVariable outer, PVariable inner)
: TContingency(outer, inner)
{}
float TContingencyClass::p_attr(const TValue &, const TValue &) const
{ raiseError("cannot compute p(value|class)");
return 0.0;
}
float TContingencyClass::p_class(const TValue &, const TValue &) const
{ raiseError("cannot compute p(class|value)");
return 0.0;
}
PDistribution TContingencyClass::p_attrs(const TValue &) const
{ raiseError("cannot compute p(.|class)");
return PDistribution();
}
PDistribution TContingencyClass::p_classes(const TValue &) const
{ raiseError("cannot compute p(class|.)");
return PDistribution();
}
void TContingencyClass::constructFromGenerator(PVariable outer, PVariable inner, PExampleGenerator gen, const long &weightID, const int &attrNo)
{
outerVariable = outer;
innerVariable = inner;
outerDistribution = TDistribution::create(outerVariable);
innerDistribution = TDistribution::create(innerVariable);
innerDistributionUnknown = TDistribution::create(innerVariable);
varType = outerVariable->varType;
if (varType==TValue::INTVAR) {
discrete = mlnew TDistributionVector();
for(int i=0, e=outerVariable->noOfValues(); i!=e; i++)
discrete->push_back(TDistribution::create(innerVariable));
}
else {
_ASSERT(varType==TValue::FLOATVAR);
continuous = mlnew TDistributionMap();
}
if (attrNo == ILLEGAL_INT)
add_gen(gen, weightID);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -