void RegionGraph::constructCVM( const FactorGraph &fg, const std::vector<NodeSet> &cl) { using std::pair; DLOG(INFO) << "constructCVM called (" << fg.nrNodes() << " vars, " << fg.nrFactors() << " facs, " << cl.size() << " clusters)"; // Retain only maximal clusters DLOG(INFO) << " Constructing ClusterGraph"; ClusterGraph cg( cl ); DLOG(INFO) << " Erasing non-maximal clusters"; cg.eraseNonMaximal(); // Create inner regions - first pass DLOG(INFO) << " Creating inner regions (first pass)"; std::set<NodeSet> betas; for( size_t alpha = 0; alpha < cg.nrClusters(); alpha++ ) for( size_t alpha2 = alpha; (++alpha2) != cg.nrClusters(); ) { NodeSet intersection = cg.cluster(alpha) & cg.cluster(alpha2); if( intersection.size() > 0 ) betas.insert( intersection ); } // Create inner regions - subsequent passes DLOG(INFO) << " Creating inner regions (next passes)"; std::set<NodeSet> new_betas; do { new_betas.clear(); for (std::set<NodeSet>::const_iterator gamma = betas.begin(); gamma != betas.end(); gamma++ ) for (std::set<NodeSet>::const_iterator gamma2 = gamma; (++gamma2) != betas.end(); ) { NodeSet intersection = (*gamma) & (*gamma2); if( (intersection.size() > 0) && (betas.count(intersection) == 0) ) new_betas.insert( intersection ); } betas.insert(new_betas.begin(), new_betas.end()); } while( new_betas.size() ); // Create inner regions - final phase DLOG(INFO) << " Creating inner regions (final phase)"; std::vector<Region> irs; irs.reserve( betas.size() ); for (std::set<NodeSet>::const_iterator beta = betas.begin(); beta != betas.end(); beta++ ) irs.push_back( Region(*beta,0.0) ); // Create edges DLOG(INFO) << " Creating edges"; std::vector<std::pair<size_t,size_t> > edges; for( size_t beta = 0; beta < irs.size(); beta++ ) for( size_t alpha = 0; alpha < cg.nrClusters(); alpha++ ) if( cg.cluster(alpha) >> irs[beta] ) edges.push_back( pair<size_t,size_t>(alpha,beta) ); // Construct region graph DLOG(INFO) << " Constructing region graph"; construct( fg, cg.clusters(), irs, edges ); // Calculate counting numbers DLOG(INFO) << " Calculating counting numbers"; calcCVMCountingNumbers(); DLOG(INFO) << "Done."; }
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[] ) { char *filename; // Check for proper number of arguments if ((nrhs != NR_IN) || (nlhs != NR_OUT)) { mexErrMsgTxt("Usage: [psi] = dai_readfg(filename);\n\n" "\n" "INPUT: filename = filename of a .fg file\n" "\n" "OUTPUT: psi = linear cell array containing the factors\n" " (psi{i} is a structure with a Member field\n" " and a P field, like a CPTAB).\n"); } // Get input parameters size_t buflen; buflen = mxGetN( FILENAME_IN ) + 1; filename = (char *)mxCalloc( buflen, sizeof(char) ); mxGetString( FILENAME_IN, filename, buflen ); // Read factorgraph FactorGraph fg; try { fg.ReadFromFile( filename ); } catch( std::exception &e ) { mexErrMsgTxt( e.what() ); } // Save factors vector<Factor> psi; for( size_t I = 0; I < fg.nrFactors(); I++ ) psi.push_back(fg.factor(I)); // Hand over results to MATLAB PSI_OUT = Factors2mx(psi); return; }
int main( int argc, char *argv[] ) { if( argc != 3 ) { cout << "Usage: " << argv[0] << " <in.fg> <tw>" << endl << endl; cout << "Reports some characteristics of the .fg network." << endl; cout << "Also calculates treewidth (which may take some time) unless <tw> == 0." << endl; return 1; } else { // Read factorgraph FactorGraph fg; char *infile = argv[1]; int calc_tw = atoi(argv[2]); fg.ReadFromFile( infile ); cout << "Number of variables: " << fg.nrVars() << endl; cout << "Number of factors: " << fg.nrFactors() << endl; cout << "Connected: " << fg.isConnected() << endl; cout << "Tree: " << fg.isTree() << endl; cout << "Has short loops: " << hasShortLoops(fg.factors()) << endl; cout << "Has negatives: " << hasNegatives(fg.factors()) << endl; cout << "Binary variables? " << fg.isBinary() << endl; cout << "Pairwise interactions? " << fg.isPairwise() << endl; if( calc_tw ) { std::pair<size_t,size_t> tw = treewidth(fg); cout << "Treewidth: " << tw.first << endl; cout << "Largest cluster for JTree has " << tw.second << " states " << endl; } double stsp = 1.0; for( size_t i = 0; i < fg.nrVars(); i++ ) stsp *= fg.var(i).states(); cout << "Total state space: " << stsp << endl; double cavsum_lcbp = 0.0; double cavsum_lcbp2 = 0.0; size_t max_Delta_size = 0; map<size_t,size_t> cavsizes; for( size_t i = 0; i < fg.nrVars(); i++ ) { VarSet di = fg.delta(i); if( cavsizes.count(di.size()) ) cavsizes[di.size()]++; else cavsizes[di.size()] = 1; size_t Ds = fg.Delta(i).nrStates(); if( Ds > max_Delta_size ) max_Delta_size = Ds; cavsum_lcbp += di.nrStates(); for( VarSet::const_iterator j = di.begin(); j != di.end(); j++ ) cavsum_lcbp2 += j->states(); } cout << "Maximum pancake has " << max_Delta_size << " states" << endl; cout << "LCBP with full cavities needs " << cavsum_lcbp << " BP runs" << endl; cout << "LCBP with only pairinteractions needs " << cavsum_lcbp2 << " BP runs" << endl; cout << "Cavity sizes: "; for( map<size_t,size_t>::const_iterator it = cavsizes.begin(); it != cavsizes.end(); it++ ) cout << it->first << "(" << it->second << ") "; cout << endl; cout << "Type: " << (fg.isPairwise() ? "pairwise" : "higher order") << " interactions, " << (fg.isBinary() ? "binary" : "nonbinary") << " variables" << endl; if( fg.isPairwise() ) { bool girth_reached = false; size_t loopdepth; for( loopdepth = 2; loopdepth <= fg.nrVars() && !girth_reached; loopdepth++ ) { size_t nr_loops = countLoops( fg, loopdepth ); cout << "Loops up to " << loopdepth << " variables: " << nr_loops << endl; if( nr_loops > 0 ) girth_reached = true; } if( girth_reached ) cout << "Girth: " << loopdepth-1 << endl; else cout << "Girth: infinity" << endl; } return 0; } }