/** * Check that two maxsum::DiscreteFunction objects have the same domain. * Two functions have the same domain, if they depend on the same set of * variables. * @param[in] f1 First function to compare * @param[in] f2 Second functions to compare * @returns true if both function have the same domain. */ bool maxsum::sameDomain(const DiscreteFunction& f1, const DiscreteFunction& f2) { if(f1.noVars()!=f2.noVars()) { return false; } return std::equal(f1.varBegin(),f1.varEnd(),f2.varBegin()); } // function sameDomain
/** * Check that two maxsum::DiscreteFunction objects are equal within a * specified tolerance. This function returns true if and only if, for all * <code>k</code>: * <p> * <code> * -tol < 1-f1(k)/f2(k) < tol * </code> * </p> * @param[in] f1 First function to compare * @param[in] f2 Second function to compare * @param[in] tol tolerance used for comparing values * @see maxsum::DEFAULT_VALUE_TOLERANCE */ bool maxsum::equalWithinTolerance ( const DiscreteFunction& f1, const DiscreteFunction& f2, ValType tol ) { //*************************************************************************** // Iterator over the combined domain of f1 and f2 //*************************************************************************** DomainIterator it(f1); it.addVars(f2.varBegin(),f2.varEnd()); while(it.hasNext()) { //************************************************************************ // Check that the difference in value for the current positions are // equal within tolerance. //************************************************************************ ValType diff = 1-f1(it)/f2(it); if( (diff > tol) || (diff < -tol) ) { return false; } ++it; } // for loop //*************************************************************************** // If we get to here, everything is equal within tolerance //*************************************************************************** return true; } // function equalWithinTolerance
/** * Construct Domain Iterator using domain of a given function. * This is more efficient that creating from sratch. * @param[in] fun Function whose domain should be copied. */ DomainIterator::DomainIterator(const DiscreteFunction& fun) : vars_i(fun.varBegin(),fun.varEnd()), // copy variables subInd_i(fun.noVars(),0), // set all subindices to zero ind_i(0), // set linear index to zero fixed_i(fun.noVars(),false), // all variables are initially free sizes_i(fun.sizeBegin(),fun.sizeEnd()), // copy variable sizes finished_i(false) // iterator is not done yet {} // nothing left to do in constructor body
/** * Make the domain of this function include the domain of another. * If necessary, the domain of this function is expanded to include the * domain of the parameter fun. * @param[in] fun function whose domain we want to expand to. * @todo Make this more efficient by using fun.size_i cache. * @post domain of this is union of its previous domain, with that of fun. */ void DiscreteFunction::expand(const DiscreteFunction& fun) { this->expand(fun.varBegin(),fun.varEnd()); }
/** * Accessor method for factor function. * @param[in] id the unique identifier of the desired factor. * @param[in] factor the function representing this factor. * @returns a reference to the function associated with the factor with * unique identifier <code>id</code>. * @post A copy of <code>factor</code> is stored internally by * this maxsum::MaxSumController and used to form part of a factor graph. * @post Any previous value of the specified factor is overwritten. */ void MaxSumController::setFactor(FactorID id, const DiscreteFunction& factor) { //*************************************************************************** // Set the specified factor. (Note: oldValue is created automatically if // necessary). //*************************************************************************** DiscreteFunction& oldValue = factors_i[id]; //*************************************************************************** // If this factor is currently related to any variables that it is no // longer related to, delete the appropriate edges. //*************************************************************************** std::vector<VarID> toRemove(oldValue.noVars()); std::set_difference(oldValue.varBegin(),oldValue.varEnd(), factor.varBegin(),factor.varEnd(),toRemove.begin()); for(std::vector<VarID>::const_iterator it=toRemove.begin(); it!=toRemove.end(); ++it) { //************************************************************************ // Remove the redundant edges from the postoffice graphs //************************************************************************ fac2varMsgs_i.removeEdge(id,*it); var2facMsgs_i.removeEdge(*it,id); //************************************************************************ // If the variable is no longer related to any factors, then we remove // it from the value list. //************************************************************************ if(!var2facMsgs_i.hasSender(*it)) { values_i.erase(*it); } } // for loop //*************************************************************************** // For each variable in this factor's domain //*************************************************************************** for(DiscreteFunction::VarIterator it=factor.varBegin(); it!=factor.varEnd(); ++it) { //************************************************************************ // Initialise input and output messages between the factor and // the current variable //************************************************************************ DiscreteFunction msgTemplate(*it,0); fac2varMsgs_i.addEdge(id,*it,msgTemplate); var2facMsgs_i.addEdge(*it,id,msgTemplate); //************************************************************************ // Touch the variable to ensure that it is in the value list. //************************************************************************ ValueMap::iterator pos = values_i.find(*it); if(values_i.end()==pos) { values_i[*it]=0; } } // for loop //*************************************************************************** // Set the specified factor to its new value. //*************************************************************************** factors_i[id] = factor; //*************************************************************************** // Tell everyone to recheck their mail. Telling everyone to recheck is the // safest option, because the factor graph may have changed. //*************************************************************************** var2facMsgs_i.notifyAll(); } // function setFactor