void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // Verify input char* inputError = "Expected 4 parameters\n N - number of nodes\n from - 1xM vector of indices\n to - 1xM vector of indices\n weight - 1xM vector of edge weights\n Example: [value, matches] = lemon_maxweightedperfectmatching(n, from, to, weight);"; if (nrhs != 4 || !mxIsNumeric(prhs[0]) || !mxIsNumeric(prhs[1]) || !mxIsNumeric(prhs[2]) || !mxIsNumeric(prhs[3])) mexErrMsgTxt(inputError); mwSize m = mxGetN(prhs[1]); double* x = mxGetPr(prhs[1]); double* y = mxGetPr(prhs[2]); double* w = mxGetPr(prhs[3]); mwSize n = (mwSize)mxGetScalar(prhs[0]); if (mxGetM(prhs[1]) != 1 || mxGetM(prhs[2]) != 1 || mxGetM(prhs[3]) != 1 || mxGetN(prhs[2]) != m || mxGetN(prhs[3]) != m) mexErrMsgTxt(inputError); // Read input SmartGraph g; g.reserveNode(n); g.reserveEdge(m); typedef SmartGraph::EdgeMap<double> EdgeMap; EdgeMap weight(g); for (mwIndex i = 0; i < n; i++) g.addNode(); for (mwIndex i = 0; i < m; i++) { SmartGraph::Edge edge = g.addEdge(g.nodeFromId(x[i] - 1), g.nodeFromId(y[i] - 1)); weight[edge] = w[i]; } // Do stuff MaxWeightedPerfectMatching<SmartGraph, EdgeMap> mwpm(g, weight); mwpm.run(); // Create output if (nlhs > 0) { plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); double *value = mxGetPr(plhs[0]); value[0] = mwpm.matchingWeight(); } if (nlhs > 1) { const SmartGraph::NodeMap<SmartGraph::Arc> &matchingMap = mwpm.matchingMap(); plhs[1] = mxCreateDoubleMatrix(1, n, mxREAL); double *matches = mxGetPr(plhs[1]); for (mwIndex i = 0; i < n; i++) { SmartGraph::Arc arc = matchingMap[g.nodeFromId(i)]; matches[i] = g.id(g.target(arc)) + 1; } } return; }
void writeEGDot(SmartGraph& g, SmartGraph::EdgeMap<double>& length, ostream& out, SmartGraph::NodeMap<IndexPair>& edgePairs, boost::unordered_set<unsigned>& matched) { out << "graph name {" << endl; out << " node [ shape=ellipse, fontname=Helvetica, fontsize=10 ];" << endl; for (SmartGraph::NodeIt n(g); n != INVALID; ++n) { IndexPair p = edgePairs[n]; if(p.first != p.second) out << " n" << g.id(n) << " [ label=\"" << p.first << ":" << p.second << "\" ]; " << endl; else out << " n" << g.id(n) << " [ shape=triangle, label=\"" << p.first << "\" ]; \n"; } out << " edge [ shape=ellipse, fontname=Helvetica, fontsize=10 ];" << endl; for (SmartGraph::EdgeIt e(g); e != INVALID; ++e) { string extra = ""; if(matched.count(g.id(e))) extra = "style = bold, "; out << " n" << g.id(g.u(e)) << " -- " << " n" << g.id(g.v(e)) << " [ " << extra << "label=\"" << length[e] << "\" ]; " << endl; } out << "}" << endl; }
//write dot file from graph void writeDot(SmartGraph& g, SmartGraph::EdgeMap<double>& length, SmartGraph::NodeMap<unsigned>& index, ostream& out) { out << "graph name {" << endl; out << " node [ shape=ellipse, fontname=Helvetica, fontsize=10 ];" << endl; for (SmartGraph::NodeIt n(g); n != INVALID; ++n) { out << " n" << g.id(n) << " [ label=\"" << index[n] << "\" ]; " << endl; } out << " edge [ shape=ellipse, fontname=Helvetica, fontsize=10 ];" << endl; for (SmartGraph::EdgeIt e(g); e != INVALID; ++e) { out << " n" << g.id(g.u(e)) << " -- " << " n" << g.id(g.v(e)) << " [ label=\"" << length[e] << "\" ]; " << endl; } out << "}" << endl; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // Verify input char* inputError = "Expected 4 parameters\n N - number of nodes\n from - 1xM vector of indices\n to - 1xM vector of indices\n cost - 1xM vector of edge costs\n Example: [mst] = lemon_kruskal(n, from, to, cost);"; if (nrhs != 4 || !mxIsNumeric(prhs[0]) || !mxIsNumeric(prhs[1]) || !mxIsNumeric(prhs[2]) || !mxIsNumeric(prhs[3])) mexErrMsgTxt(inputError); mwSize m = mxGetN(prhs[1]); double* x = mxGetPr(prhs[1]); double* y = mxGetPr(prhs[2]); double* c = mxGetPr(prhs[3]); mwSize n = (mwSize)mxGetScalar(prhs[0]); if (mxGetM(prhs[1]) != 1 || mxGetM(prhs[2]) != 1 || mxGetM(prhs[3]) != 1 || mxGetN(prhs[2]) != m || mxGetN(prhs[3]) != m) mexErrMsgTxt(inputError); // Read input SmartGraph g; g.reserveNode(n); g.reserveEdge(m); typedef SmartGraph::EdgeMap<double> EdgeMap; EdgeMap cost(g); for (mwIndex i = 0; i < n; i++) g.addNode(); for (mwIndex i = 0; i < m; i++) { SmartGraph::Edge edge = g.addEdge(g.nodeFromId(x[i] - 1), g.nodeFromId(y[i] - 1)); cost[edge] = c[i]; } // Do stuff EdgeMap tree(g); kruskal(g, cost, tree); // Create output if (nlhs > 0) { plhs[0] = mxCreateLogicalMatrix(1, m); bool *mst = mxGetLogicals(plhs[0]); for (mwIndex i = 0; i < m; i++) mst[i] = tree[g.edgeFromId(i)]; } return; }
/* find the pseudo-optimal matching of every pair of clusters * use the knn graph instead of the full graph * maxSz is what the largest current cluster should be */ bool MatcherPacker::knnMergeClusters(const DataViewer *D, vector<Cluster>& clusters, unsigned maxSz, DCache& dcache) const { unsigned N = clusters.size(); SmartGraph SG; SmartGraph::EdgeMap<double> Sweights(SG); SmartGraph::NodeMap<unsigned> Sindex(SG); vector<SmartGraph::Node> Snodes; ClusterCache ccache(clusters.size()); makeKNNGraph(D, clusters, maxSz, dcache, ccache, SG, Sweights, Sindex, Snodes); Timer t; MaxWeightedMatching<SmartGraph, SmartGraph::EdgeMap<double> > matcher(SG, Sweights); matcher.run(); //merge clusters that were matched vector<Cluster> newclusters; newclusters.reserve(N / 2 + 1); vector<bool> packed(N, false); bool didmerge = false; for (unsigned i = 0; i < N; i++) { if (!packed[i]) { SmartGraph::Node m = matcher.mate(Snodes[i]); if (!SG.valid(m)) { newclusters.push_back(Cluster()); newclusters.back().moveInto(clusters[i]); } else { unsigned j = Sindex[m]; if (clusters[i].size() + clusters[j].size() <= packSize) //merge { newclusters.push_back(Cluster()); newclusters.back().mergeInto(clusters[i], clusters[j]); didmerge = true; packed[i] = true; packed[j] = true; } else { //didn't merge, keep clusters as is newclusters.push_back(Cluster()); newclusters.back().moveInto(clusters[i]); newclusters.push_back(Cluster()); newclusters.back().moveInto(clusters[j]); packed[i] = true; packed[j] = true; } } } } swap(clusters, newclusters); return didmerge; }