#include #include #include #include #include #include #include #include "ParfactorList.h" #include "FactorGraph.h" #include "LiftedOperations.h" #include "LiftedVe.h" #include "VarElim.h" #include "LiftedBp.h" #include "CountingBp.h" #include "BeliefProp.h" #include "LiftedKc.h" #include "ElimGraph.h" #include "BayesBall.h" namespace Horus { namespace { Parfactor* readParfactor (YAP_Term); ObservedFormulas* readLiftedEvidence (YAP_Term); std::vector readUnsignedList (YAP_Term); Params readParameters (YAP_Term); YAP_Term fillSolutionList (const std::vector&); } typedef std::pair LiftedNetwork; static YAP_Bool createLiftedNetwork() { Parfactors parfactors; YAP_Term parfactorList = YAP_ARG1; while (parfactorList != YAP_TermNil()) { YAP_Term pfTerm = YAP_HeadOfTerm (parfactorList); parfactors.push_back (readParfactor (pfTerm)); parfactorList = YAP_TailOfTerm (parfactorList); } // LiftedUtils::printSymbolDictionary(); if (Globals::verbosity > 2) { Util::printHeader ("INITIAL PARFACTORS"); for (size_t i = 0; i < parfactors.size(); i++) { parfactors[i]->print(); std::cout << std::endl; } } ParfactorList* pfList = new ParfactorList (parfactors); if (Globals::verbosity > 2) { Util::printHeader ("SHATTERED PARFACTORS"); pfList->print(); } // read evidence ObservedFormulas* obsFormulas = readLiftedEvidence (YAP_ARG2); LiftedNetwork* network = new LiftedNetwork (pfList, obsFormulas); YAP_Int p = (YAP_Int) (network); return YAP_Unify (YAP_MkIntTerm (p), YAP_ARG3); } static YAP_Bool createGroundNetwork() { std::string factorsType ((char*) YAP_AtomName (YAP_AtomOfTerm (YAP_ARG1))); FactorGraph* fg = new FactorGraph(); if (factorsType == "bayes") { fg->setFactorsAsBayesian(); } YAP_Term factorList = YAP_ARG2; while (factorList != YAP_TermNil()) { YAP_Term factor = YAP_HeadOfTerm (factorList); // read the var ids VarIds varIds = readUnsignedList (YAP_ArgOfTerm (1, factor)); // read the ranges Ranges ranges = readUnsignedList (YAP_ArgOfTerm (2, factor)); // read the parameters Params params = readParameters (YAP_ArgOfTerm (3, factor)); // read dist id unsigned distId = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (4, factor)); fg->addFactor (Factor (varIds, ranges, params, distId)); factorList = YAP_TailOfTerm (factorList); } unsigned nrObservedVars = 0; YAP_Term evidenceList = YAP_ARG3; while (evidenceList != YAP_TermNil()) { YAP_Term evTerm = YAP_HeadOfTerm (evidenceList); unsigned vid = (unsigned) YAP_IntOfTerm ((YAP_ArgOfTerm (1, evTerm))); unsigned ev = (unsigned) YAP_IntOfTerm ((YAP_ArgOfTerm (2, evTerm))); assert (fg->getVarNode (vid)); fg->getVarNode (vid)->setEvidence (ev); evidenceList = YAP_TailOfTerm (evidenceList); nrObservedVars ++; } if (FactorGraph::exportToLibDai()) { fg->exportToLibDai ("model.fg"); } if (FactorGraph::exportToUai()) { fg->exportToUai ("model.uai"); } if (FactorGraph::exportGraphViz()) { fg->exportToGraphViz ("model.dot"); } if (FactorGraph::printFactorGraph()) { fg->print(); } if (Globals::verbosity > 0) { std::cout << "factor graph contains " ; std::cout << fg->nrVarNodes() << " variables and " ; std::cout << fg->nrFacNodes() << " factors " << std::endl; } YAP_Int p = (YAP_Int) (fg); return YAP_Unify (YAP_MkIntTerm (p), YAP_ARG4); } static YAP_Bool runLiftedSolver() { LiftedNetwork* network = (LiftedNetwork*) YAP_IntOfTerm (YAP_ARG1); ParfactorList copy (*network->first); LiftedOperations::absorveEvidence (copy, *network->second); LiftedSolver* solver = 0; switch (Globals::liftedSolver) { case LiftedSolverType::lveSolver: solver = new LiftedVe (copy); break; case LiftedSolverType::lbpSolver: solver = new LiftedBp (copy); break; case LiftedSolverType::lkcSolver: solver = new LiftedKc (copy); break; } if (Globals::verbosity > 0) { solver->printSolverFlags(); std::cout << std::endl; } YAP_Term taskList = YAP_ARG2; std::vector results; while (taskList != YAP_TermNil()) { Grounds queryVars; YAP_Term jointList = YAP_HeadOfTerm (taskList); while (jointList != YAP_TermNil()) { YAP_Term ground = YAP_HeadOfTerm (jointList); if (YAP_IsAtomTerm (ground)) { std::string name ((char*) YAP_AtomName (YAP_AtomOfTerm (ground))); queryVars.push_back (Ground (LiftedUtils::getSymbol (name))); } else { assert (YAP_IsApplTerm (ground)); YAP_Functor yapFunctor = YAP_FunctorOfTerm (ground); std::string name ((char*) (YAP_AtomName ( YAP_NameOfFunctor (yapFunctor)))); unsigned arity = (unsigned) YAP_ArityOfFunctor (yapFunctor); Symbol functor = LiftedUtils::getSymbol (name); Symbols args; for (unsigned i = 1; i <= arity; i++) { YAP_Term ti = YAP_ArgOfTerm (i, ground); assert (YAP_IsAtomTerm (ti)); std::string arg ((char *) YAP_AtomName (YAP_AtomOfTerm (ti))); args.push_back (LiftedUtils::getSymbol (arg)); } queryVars.push_back (Ground (functor, args)); } jointList = YAP_TailOfTerm (jointList); } results.push_back (solver->solveQuery (queryVars)); taskList = YAP_TailOfTerm (taskList); } delete solver; return YAP_Unify (fillSolutionList (results), YAP_ARG3); } static YAP_Bool runGroundSolver() { FactorGraph* fg = (FactorGraph*) YAP_IntOfTerm (YAP_ARG1); std::vector tasks; YAP_Term taskList = YAP_ARG2; while (taskList != YAP_TermNil()) { tasks.push_back (readUnsignedList (YAP_HeadOfTerm (taskList))); taskList = YAP_TailOfTerm (taskList); } FactorGraph* mfg = fg; if (fg->bayesianFactors()) { std::set vids; for (size_t i = 0; i < tasks.size(); i++) { Util::addToSet (vids, tasks[i]); } mfg = BayesBall::getMinimalFactorGraph ( *fg, VarIds (vids.begin(), vids.end())); } GroundSolver* solver = 0; CountingBp::setFindIdenticalFactorsFlag (false); switch (Globals::groundSolver) { case GroundSolverType::veSolver: solver = new VarElim (*mfg); break; case GroundSolverType::bpSolver: solver = new BeliefProp (*mfg); break; case GroundSolverType::CbpSolver: solver = new CountingBp (*mfg); break; } if (Globals::verbosity > 0) { solver->printSolverFlags(); std::cout << std::endl; } std::vector results; results.reserve (tasks.size()); for (size_t i = 0; i < tasks.size(); i++) { results.push_back (solver->solveQuery (tasks[i])); } delete solver; if (fg->bayesianFactors()) { delete mfg; } return YAP_Unify (fillSolutionList (results), YAP_ARG3); } static YAP_Bool setParfactorsParams() { LiftedNetwork* network = (LiftedNetwork*) YAP_IntOfTerm (YAP_ARG1); ParfactorList* pfList = network->first; YAP_Term distIdsList = YAP_ARG2; YAP_Term paramsList = YAP_ARG3; std::unordered_map paramsMap; while (distIdsList != YAP_TermNil()) { unsigned distId = (unsigned) YAP_IntOfTerm ( YAP_HeadOfTerm (distIdsList)); assert (Util::contains (paramsMap, distId) == false); paramsMap[distId] = readParameters (YAP_HeadOfTerm (paramsList)); distIdsList = YAP_TailOfTerm (distIdsList); paramsList = YAP_TailOfTerm (paramsList); } ParfactorList::iterator it = pfList->begin(); while (it != pfList->end()) { assert (Util::contains (paramsMap, (*it)->distId())); (*it)->setParams (paramsMap[(*it)->distId()]); ++ it; } return TRUE; } static YAP_Bool setFactorsParams() { FactorGraph* fg = (FactorGraph*) YAP_IntOfTerm (YAP_ARG1); YAP_Term distIdsList = YAP_ARG2; YAP_Term paramsList = YAP_ARG3; std::unordered_map paramsMap; while (distIdsList != YAP_TermNil()) { unsigned distId = (unsigned) YAP_IntOfTerm ( YAP_HeadOfTerm (distIdsList)); assert (Util::contains (paramsMap, distId) == false); paramsMap[distId] = readParameters (YAP_HeadOfTerm (paramsList)); distIdsList = YAP_TailOfTerm (distIdsList); paramsList = YAP_TailOfTerm (paramsList); } const FacNodes& facNodes = fg->facNodes(); for (size_t i = 0; i < facNodes.size(); i++) { unsigned distId = facNodes[i]->factor().distId(); assert (Util::contains (paramsMap, distId)); facNodes[i]->factor().setParams (paramsMap[distId]); } return TRUE; } static YAP_Bool setVarsInformation() { Var::clearVarsInfo(); std::vector labels; YAP_Term labelsL = YAP_ARG1; while (labelsL != YAP_TermNil()) { YAP_Atom atom = YAP_AtomOfTerm (YAP_HeadOfTerm (labelsL)); labels.push_back ((char*) YAP_AtomName (atom)); labelsL = YAP_TailOfTerm (labelsL); } unsigned count = 0; YAP_Term stateNamesL = YAP_ARG2; while (stateNamesL != YAP_TermNil()) { States states; YAP_Term namesL = YAP_HeadOfTerm (stateNamesL); while (namesL != YAP_TermNil()) { YAP_Atom atom = YAP_AtomOfTerm (YAP_HeadOfTerm (namesL)); states.push_back ((char*) YAP_AtomName (atom)); namesL = YAP_TailOfTerm (namesL); } Var::addVarInfo (count, labels[count], states); count ++; stateNamesL = YAP_TailOfTerm (stateNamesL); } return TRUE; } static YAP_Bool setHorusFlag() { std::string option ((char*) YAP_AtomName (YAP_AtomOfTerm (YAP_ARG1))); std::string value; if (option == "verbosity") { std::stringstream ss; ss << (int) YAP_IntOfTerm (YAP_ARG2); ss >> value; } else if (option == "bp_accuracy") { std::stringstream ss; ss << (float) YAP_FloatOfTerm (YAP_ARG2); ss >> value; } else if (option == "bp_max_iter") { std::stringstream ss; ss << (int) YAP_IntOfTerm (YAP_ARG2); ss >> value; } else { value = ((char*) YAP_AtomName (YAP_AtomOfTerm (YAP_ARG2))); } return Util::setHorusFlag (option, value); } static YAP_Bool freeGroundNetwork() { delete (FactorGraph*) YAP_IntOfTerm (YAP_ARG1); return TRUE; } static YAP_Bool freeLiftedNetwork() { LiftedNetwork* network = (LiftedNetwork*) YAP_IntOfTerm (YAP_ARG1); delete network->first; delete network->second; delete network; return TRUE; } namespace { Parfactor* readParfactor (YAP_Term pfTerm) { // read dist id unsigned distId = YAP_IntOfTerm (YAP_ArgOfTerm (1, pfTerm)); // read the ranges Ranges ranges; YAP_Term rangeList = YAP_ArgOfTerm (3, pfTerm); while (rangeList != YAP_TermNil()) { unsigned range = (unsigned) YAP_IntOfTerm (YAP_HeadOfTerm (rangeList)); ranges.push_back (range); rangeList = YAP_TailOfTerm (rangeList); } // read parametric random vars ProbFormulas formulas; unsigned count = 0; std::unordered_map lvMap; YAP_Term pvList = YAP_ArgOfTerm (2, pfTerm); while (pvList != YAP_TermNil()) { YAP_Term formulaTerm = YAP_HeadOfTerm (pvList); if (YAP_IsAtomTerm (formulaTerm)) { std::string name ((char*) YAP_AtomName (YAP_AtomOfTerm (formulaTerm))); Symbol functor = LiftedUtils::getSymbol (name); formulas.push_back (ProbFormula (functor, ranges[count])); } else { LogVars logVars; YAP_Functor yapFunctor = YAP_FunctorOfTerm (formulaTerm); std::string name ((char*) YAP_AtomName ( YAP_NameOfFunctor (yapFunctor))); Symbol functor = LiftedUtils::getSymbol (name); unsigned arity = (unsigned) YAP_ArityOfFunctor (yapFunctor); for (unsigned i = 1; i <= arity; i++) { YAP_Term ti = YAP_ArgOfTerm (i, formulaTerm); std::unordered_map::iterator it = lvMap.find (ti); if (it != lvMap.end()) { logVars.push_back (it->second); } else { unsigned newLv = lvMap.size(); lvMap[ti] = newLv; logVars.push_back (newLv); } } formulas.push_back (ProbFormula (functor, logVars, ranges[count])); } count ++; pvList = YAP_TailOfTerm (pvList); } // read the parameters Params params = readParameters (YAP_ArgOfTerm (4, pfTerm)); // read the constraint Tuples tuples; if (lvMap.size() >= 1) { YAP_Term tupleList = YAP_ArgOfTerm (5, pfTerm); while (tupleList != YAP_TermNil()) { YAP_Term term = YAP_HeadOfTerm (tupleList); assert (YAP_IsApplTerm (term)); YAP_Functor yapFunctor = YAP_FunctorOfTerm (term); unsigned arity = (unsigned) YAP_ArityOfFunctor (yapFunctor); assert (lvMap.size() == arity); Tuple tuple (arity); for (unsigned i = 1; i <= arity; i++) { YAP_Term ti = YAP_ArgOfTerm (i, term); if (YAP_IsAtomTerm (ti) == false) { std::cerr << "Error: the constraint contains free variables." ; std::cerr << std::endl; exit (EXIT_FAILURE); } std::string name ((char*) YAP_AtomName (YAP_AtomOfTerm (ti))); tuple[i - 1] = LiftedUtils::getSymbol (name); } tuples.push_back (tuple); tupleList = YAP_TailOfTerm (tupleList); } } return new Parfactor (formulas, params, tuples, distId); } ObservedFormulas* readLiftedEvidence (YAP_Term observedList) { ObservedFormulas* obsFormulas = new ObservedFormulas(); while (observedList != YAP_TermNil()) { YAP_Term pair = YAP_HeadOfTerm (observedList); YAP_Term ground = YAP_ArgOfTerm (1, pair); Symbol functor; Symbols args; if (YAP_IsAtomTerm (ground)) { std::string name ((char*) YAP_AtomName (YAP_AtomOfTerm (ground))); functor = LiftedUtils::getSymbol (name); } else { assert (YAP_IsApplTerm (ground)); YAP_Functor yapFunctor = YAP_FunctorOfTerm (ground); std::string name ((char*) (YAP_AtomName ( YAP_NameOfFunctor (yapFunctor)))); functor = LiftedUtils::getSymbol (name); unsigned arity = (unsigned) YAP_ArityOfFunctor (yapFunctor); for (unsigned i = 1; i <= arity; i++) { YAP_Term ti = YAP_ArgOfTerm (i, ground); assert (YAP_IsAtomTerm (ti)); std::string arg ((char *) YAP_AtomName (YAP_AtomOfTerm (ti))); args.push_back (LiftedUtils::getSymbol (arg)); } } unsigned evidence = (unsigned) YAP_IntOfTerm (YAP_ArgOfTerm (2, pair)); bool found = false; for (size_t i = 0; i < obsFormulas->size(); i++) { if ((*obsFormulas)[i].functor() == functor && (*obsFormulas)[i].arity() == args.size() && (*obsFormulas)[i].evidence() == evidence) { (*obsFormulas)[i].addTuple (args); found = true; } } if (found == false) { obsFormulas->push_back (ObservedFormula (functor, evidence, args)); } observedList = YAP_TailOfTerm (observedList); } return obsFormulas; } std::vector readUnsignedList (YAP_Term list) { std::vector vec; while (list != YAP_TermNil()) { vec.push_back ((unsigned) YAP_IntOfTerm (YAP_HeadOfTerm (list))); list = YAP_TailOfTerm (list); } return vec; } Params readParameters (YAP_Term paramL) { Params params; assert (YAP_IsPairTerm (paramL)); while (paramL != YAP_TermNil()) { YAP_Term hd = YAP_HeadOfTerm (paramL); if (YAP_IsFloatTerm (hd)) { params.push_back ((double) YAP_FloatOfTerm (hd)); } else { params.push_back ((double) YAP_IntOfTerm (hd)); } paramL = YAP_TailOfTerm (paramL); } if (Globals::logDomain) { Util::log (params); } return params; } YAP_Term fillSolutionList (const std::vector& results) { YAP_Term list = YAP_TermNil(); for (size_t i = results.size(); i-- > 0; ) { const Params& beliefs = results[i]; YAP_Term queryBeliefsL = YAP_TermNil(); for (size_t j = beliefs.size(); j-- > 0; ) { YAP_Int sl = YAP_InitSlot (list); YAP_Term belief = YAP_MkFloatTerm (beliefs[j]); queryBeliefsL = YAP_MkPairTerm (belief, queryBeliefsL); list = YAP_GetFromSlot (sl); YAP_RecoverSlots (1, sl); } list = YAP_MkPairTerm (queryBeliefsL, list); } return list; } } extern "C" void init_predicates() { YAP_UserCPredicate ("cpp_create_lifted_network", createLiftedNetwork, 3); YAP_UserCPredicate ("cpp_create_ground_network", createGroundNetwork, 4); YAP_UserCPredicate ("cpp_run_lifted_solver", runLiftedSolver, 3); YAP_UserCPredicate ("cpp_run_ground_solver", runGroundSolver, 3); YAP_UserCPredicate ("cpp_set_parfactors_params", setParfactorsParams, 3); YAP_UserCPredicate ("cpp_set_factors_params", setFactorsParams, 3); YAP_UserCPredicate ("cpp_set_vars_information", setVarsInformation, 2); YAP_UserCPredicate ("cpp_set_horus_flag", setHorusFlag, 2); YAP_UserCPredicate ("cpp_free_lifted_network", freeLiftedNetwork, 1); YAP_UserCPredicate ("cpp_free_ground_network", freeGroundNetwork, 1); } } // namespace Horus