Update CLP(BN) with Tiago's latest version of BP solver.
This commit is contained in:
@@ -4,226 +4,44 @@
|
||||
|
||||
#include "BpNode.h"
|
||||
|
||||
bool BpNode::calculateMessageResidual_ = true;
|
||||
|
||||
bool BpNode::parallelSchedule_ = false;
|
||||
|
||||
BpNode::BpNode (string varName,
|
||||
vector<BayesianNode*> parents,
|
||||
Distribution* dist,
|
||||
int evidence) : BayesianNode (varName, parents, dist, evidence)
|
||||
BpNode::BpNode (BayesNode* node)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
BpNode::~BpNode (void)
|
||||
{
|
||||
delete [] piValues_;
|
||||
delete [] lambdaValues_;
|
||||
delete [] oldBeliefs_;
|
||||
map<BpNode*, double*>::iterator iter;
|
||||
for (iter = lambdaMessages_.begin(); iter != lambdaMessages_.end(); ++iter) {
|
||||
delete [] iter->second;
|
||||
ds_ = node->getDomainSize();
|
||||
const NodeSet& childs = node->getChilds();
|
||||
piVals_.resize (ds_, 1);
|
||||
ldVals_.resize (ds_, 1);
|
||||
if (calculateMessageResidual_) {
|
||||
piResiduals_.resize (childs.size(), 0.0);
|
||||
ldResiduals_.resize (childs.size(), 0.0);
|
||||
}
|
||||
for (iter = piMessages_.begin(); iter != piMessages_.end(); ++iter) {
|
||||
delete [] iter->second;
|
||||
}
|
||||
// FIXME delete new messages
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::enableParallelSchedule (void)
|
||||
{
|
||||
parallelSchedule_ = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::allocateMemory (void)
|
||||
{
|
||||
// FIXME do i need this !?
|
||||
int domainSize = getDomainSize();
|
||||
piValues_ = new double [domainSize];
|
||||
lambdaValues_ = new double [domainSize];
|
||||
if (parallelSchedule_) {
|
||||
newPiMessages_ = new map<BpNode*, double*>;
|
||||
newLambdaMessages_ = new map<BpNode*, double*>;
|
||||
}
|
||||
oldBeliefs_ = 0;
|
||||
vector <BayesianNode*> childs = getChilds();
|
||||
for (unsigned int i = 0; i < childs.size(); i++) {
|
||||
BpNode* child = static_cast<BpNode*> (childs[i]);
|
||||
piMessages_.insert (make_pair (child, new double [domainSize]));
|
||||
lambdaMessages_.insert (make_pair (child, new double [domainSize]));
|
||||
if (parallelSchedule_) {
|
||||
newPiMessages_->insert (make_pair (child, new double [domainSize]));
|
||||
newLambdaMessages_->insert (make_pair (child, new double [domainSize]));
|
||||
}
|
||||
childs_ = &childs;
|
||||
for (unsigned i = 0; i < childs.size(); i++) {
|
||||
//indexMap_.insert (make_pair (childs[i]->getVarId(), i));
|
||||
currPiMsgs_.push_back (ParamSet (ds_, 1));
|
||||
currLdMsgs_.push_back (ParamSet (ds_, 1));
|
||||
nextPiMsgs_.push_back (ParamSet (ds_, 1));
|
||||
nextLdMsgs_.push_back (ParamSet (ds_, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
double*
|
||||
BpNode::getPiValues (void) const
|
||||
ParamSet
|
||||
BpNode::getBeliefs (void) const
|
||||
{
|
||||
return piValues_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
BpNode::getPiValue (int index) const
|
||||
{
|
||||
const int c = getDomainSize();
|
||||
assert (index >=0 && index < c);
|
||||
return piValues_[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::setPiValue (int index, double value)
|
||||
{
|
||||
const int c = getDomainSize();
|
||||
assert (index >=0 && index < c);
|
||||
piValues_[index] = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double*
|
||||
BpNode::getLambdaValues (void) const
|
||||
{
|
||||
return lambdaValues_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
BpNode::getLambdaValue (int index) const
|
||||
{
|
||||
const int c = getDomainSize();
|
||||
assert (index >=0 && index < c);
|
||||
return lambdaValues_[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::setLambdaValue (int index, double value)
|
||||
{
|
||||
const int c = getDomainSize();
|
||||
assert (index >=0 && index < c);
|
||||
lambdaValues_[index] = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double*
|
||||
BpNode::getPiMessages (BpNode* node) const
|
||||
{
|
||||
assert (node);
|
||||
map<BpNode*, double*>::const_iterator iter = piMessages_.find (node);
|
||||
assert (iter != piMessages_.end());
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
BpNode::getPiMessage (BpNode* node, int index) const
|
||||
{
|
||||
assert (node);
|
||||
const int c = getDomainSize();
|
||||
assert (index >=0 && index < c);
|
||||
map<BpNode*, double*>::const_iterator iter = piMessages_.find (node);
|
||||
assert (iter != piMessages_.end());
|
||||
return iter->second[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::setPiMessage (BpNode* node, int index, double probability)
|
||||
{
|
||||
assert (node);
|
||||
const int c = getDomainSize();
|
||||
assert (index >=0 && index < c);
|
||||
map<BpNode*, double*>::const_iterator iter;
|
||||
if (parallelSchedule_) {
|
||||
// cerr << "set_pi_message" << endl;
|
||||
iter = newPiMessages_->find (node);
|
||||
assert (iter != newPiMessages_->end());
|
||||
} else {
|
||||
iter = piMessages_.find (node);
|
||||
assert (iter != piMessages_.end());
|
||||
}
|
||||
iter->second[index] = probability;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double*
|
||||
BpNode::getLambdaMessages (BpNode* node) const
|
||||
{
|
||||
assert (node);
|
||||
map<BpNode*, double*>::const_iterator iter = lambdaMessages_.find (node);
|
||||
assert (iter != piMessages_.end());
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
BpNode::getLambdaMessage (BpNode* node, int index) const
|
||||
{
|
||||
assert (node);
|
||||
const int c = getDomainSize();
|
||||
assert (index >=0 && index < c);
|
||||
map<BpNode*, double*>::const_iterator iter = lambdaMessages_.find (node);
|
||||
assert (iter != piMessages_.end());
|
||||
return iter->second[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::setLambdaMessage (BpNode* node, int index, double probability)
|
||||
{
|
||||
assert (node);
|
||||
const int c = getDomainSize();
|
||||
assert (index >=0 && index < c);
|
||||
map<BpNode*, double*>::const_iterator iter;
|
||||
if (parallelSchedule_) {
|
||||
//cerr << "set_lambda_message" << endl;
|
||||
iter = newLambdaMessages_->find (node);
|
||||
assert (iter != newLambdaMessages_->end());
|
||||
} else {
|
||||
iter = lambdaMessages_.find (node);
|
||||
assert (iter != lambdaMessages_.end());
|
||||
}
|
||||
iter->second[index] = probability;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double*
|
||||
BpNode::getBeliefs (void)
|
||||
{
|
||||
double sum = 0.0;
|
||||
double* beliefs = new double [getDomainSize()];
|
||||
for (int xi = 0; xi < getDomainSize(); xi++) {
|
||||
double prod = piValues_[xi] * lambdaValues_[xi];
|
||||
double sum = 0.0;
|
||||
ParamSet beliefs (ds_);
|
||||
for (int xi = 0; xi < ds_; xi++) {
|
||||
double prod = piVals_[xi] * ldVals_[xi];
|
||||
beliefs[xi] = prod;
|
||||
sum += prod;
|
||||
}
|
||||
// normalize the beliefs
|
||||
for (int xi = 0; xi < getDomainSize(); xi++) {
|
||||
assert (sum);
|
||||
//normalize the beliefs
|
||||
for (int xi = 0; xi < ds_; xi++) {
|
||||
beliefs[xi] /= sum;
|
||||
}
|
||||
return beliefs;
|
||||
@@ -231,91 +49,202 @@ BpNode::getBeliefs (void)
|
||||
|
||||
|
||||
|
||||
double
|
||||
BpNode::getPiValue (int idx) const
|
||||
{
|
||||
assert (idx >=0 && idx < ds_);
|
||||
return piVals_[idx];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::setPiValue (int idx, double value)
|
||||
{
|
||||
assert (idx >=0 && idx < ds_);
|
||||
piVals_[idx] = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
BpNode::getLambdaValue (int idx) const
|
||||
{
|
||||
assert (idx >=0 && idx < ds_);
|
||||
return ldVals_[idx];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::setLambdaValue (int idx, double value)
|
||||
{
|
||||
assert (idx >=0 && idx < ds_);
|
||||
ldVals_[idx] = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ParamSet&
|
||||
BpNode::getPiValues (void)
|
||||
{
|
||||
return piVals_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ParamSet&
|
||||
BpNode::getLambdaValues (void)
|
||||
{
|
||||
return ldVals_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
BpNode::getPiMessageValue (const BayesNode* destination, int idx) const
|
||||
{
|
||||
assert (idx >=0 && idx < ds_);
|
||||
return currPiMsgs_[getIndex(destination)][idx];
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
BpNode::getLambdaMessageValue (const BayesNode* source, int idx) const
|
||||
{
|
||||
assert (idx >=0 && idx < ds_);
|
||||
return currLdMsgs_[getIndex(source)][idx];
|
||||
}
|
||||
|
||||
|
||||
|
||||
const ParamSet&
|
||||
BpNode::getPiMessage (const BayesNode* destination) const
|
||||
{
|
||||
return currPiMsgs_[getIndex(destination)];
|
||||
}
|
||||
|
||||
|
||||
|
||||
const ParamSet&
|
||||
BpNode::getLambdaMessage (const BayesNode* source) const
|
||||
{
|
||||
return currLdMsgs_[getIndex(source)];
|
||||
}
|
||||
|
||||
|
||||
|
||||
ParamSet&
|
||||
BpNode::piNextMessageReference (const BayesNode* destination)
|
||||
{
|
||||
return nextPiMsgs_[getIndex(destination)];
|
||||
}
|
||||
|
||||
|
||||
|
||||
ParamSet&
|
||||
BpNode::lambdaNextMessageReference (const BayesNode* source)
|
||||
{
|
||||
return nextLdMsgs_[getIndex(source)];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::updatePiMessage (const BayesNode* destination)
|
||||
{
|
||||
int idx = getIndex (destination);
|
||||
currPiMsgs_[idx] = nextPiMsgs_[idx];
|
||||
Util::normalize (currPiMsgs_[idx]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::updateLambdaMessage (const BayesNode* source)
|
||||
{
|
||||
int idx = getIndex (source);
|
||||
currLdMsgs_[idx] = nextLdMsgs_[idx];
|
||||
Util::normalize (currLdMsgs_[idx]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
BpNode::getBeliefChange (void)
|
||||
{
|
||||
double change = 0.0;
|
||||
if (!oldBeliefs_) {
|
||||
if (oldBeliefs_.size() == 0) {
|
||||
oldBeliefs_ = getBeliefs();
|
||||
change = MAX_CHANGE_;
|
||||
change = 9999999999.0;
|
||||
} else {
|
||||
double* currentBeliefs = getBeliefs();
|
||||
for (int xi = 0; xi < getDomainSize(); xi++) {
|
||||
ParamSet currentBeliefs = getBeliefs();
|
||||
for (int xi = 0; xi < ds_; xi++) {
|
||||
change += abs (currentBeliefs[xi] - oldBeliefs_[xi]);
|
||||
}
|
||||
oldBeliefs_ = currentBeliefs;
|
||||
}
|
||||
//FIXME memory leak
|
||||
return change;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::normalizeMessages (void)
|
||||
BpNode::updatePiResidual (const BayesNode* destination)
|
||||
{
|
||||
map<BpNode*, double*>::iterator iter;
|
||||
|
||||
iter = lambdaMessages_.begin();
|
||||
while (iter != lambdaMessages_.end()) {
|
||||
double* v = iter->second;
|
||||
double sum = 0.0;
|
||||
for (int xi = 0; xi < getDomainSize(); xi++) {
|
||||
sum += v[xi];
|
||||
}
|
||||
for (int xi = 0; xi < getDomainSize(); xi++) {
|
||||
v[xi] /= sum;
|
||||
}
|
||||
iter ++;
|
||||
}
|
||||
|
||||
iter = piMessages_.begin();
|
||||
while (iter != piMessages_.end()) {
|
||||
double* v = iter->second;
|
||||
double sum = 0.0;
|
||||
for (int xi = 0; xi < getDomainSize(); xi++) {
|
||||
sum += v[xi];
|
||||
}
|
||||
for (int xi = 0; xi < getDomainSize(); xi++) {
|
||||
v[xi] /= sum;
|
||||
}
|
||||
iter ++;
|
||||
}
|
||||
int idx = getIndex (destination);
|
||||
Util::normalize (nextPiMsgs_[idx]);
|
||||
//piResiduals_[idx] = Util::getL1dist (
|
||||
// currPiMsgs_[idx], nextPiMsgs_[idx]);
|
||||
piResiduals_[idx] = Util::getMaxNorm (
|
||||
currPiMsgs_[idx], nextPiMsgs_[idx]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::swapMessages (void)
|
||||
BpNode::updateLambdaResidual (const BayesNode* source)
|
||||
{
|
||||
//FIXME fast way to do this
|
||||
map<BpNode*, double*>::iterator iter1;
|
||||
map<BpNode*, double*>::iterator iter2;
|
||||
|
||||
iter1 = lambdaMessages_.begin();
|
||||
iter2 = newLambdaMessages_->begin();
|
||||
while (iter1 != lambdaMessages_.end()) {
|
||||
double* v1 = iter1->second;
|
||||
double* v2 = iter2->second;
|
||||
for (int xi = 0; xi < getDomainSize(); xi++) {
|
||||
//v1[xi] = v2[xi];
|
||||
v1[xi] = (v1[xi] + v2[xi]) / 2;
|
||||
}
|
||||
iter1 ++;
|
||||
iter2 ++;
|
||||
}
|
||||
|
||||
iter1 = piMessages_.begin();
|
||||
iter2 = newPiMessages_->begin();
|
||||
while (iter1 != piMessages_.end()) {
|
||||
double* v1 = iter1->second;
|
||||
double* v2 = iter2->second;
|
||||
for (int xi = 0; xi < getDomainSize(); xi++) {
|
||||
//v1[xi] = v2[xi];
|
||||
v1[xi] = (v1[xi] + v2[xi]) / 2;
|
||||
}
|
||||
iter1 ++;
|
||||
iter2 ++;
|
||||
}
|
||||
int idx = getIndex (source);
|
||||
Util::normalize (nextLdMsgs_[idx]);
|
||||
//ldResiduals_[idx] = Util::getL1dist (
|
||||
// currLdMsgs_[idx], nextLdMsgs_[idx]);
|
||||
ldResiduals_[idx] = Util::getMaxNorm (
|
||||
currLdMsgs_[idx], nextLdMsgs_[idx]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::clearPiResidual (const BayesNode* destination)
|
||||
{
|
||||
piResiduals_[getIndex(destination)] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
BpNode::clearLambdaResidual (const BayesNode* source)
|
||||
{
|
||||
ldResiduals_[getIndex(source)] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BpNode::hasReceivedChildInfluence (void) const
|
||||
{
|
||||
// if all lambda values are equal, then neither
|
||||
// this node neither its descendents have evidence,
|
||||
// we can use this to don't send lambda messages his parents
|
||||
bool childInfluenced = false;
|
||||
for (int xi = 1; xi < ds_; xi++) {
|
||||
if (ldVals_[xi] != ldVals_[0]) {
|
||||
childInfluenced = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return childInfluenced;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user