00001
00052 #include <iostream.h>
00053 #include "DAG.h"
00054 #include "HelperFunctions.h"
00055 #include "Exceptions.h"
00056 #include "Debug.h"
00057 #include <LEDA/graphwin.h>
00058 #include <float.h>
00059
00060 #ifdef WIN32
00061 #define isnan _isnan
00062 #define finite _finite
00063 #endif
00064
00065 #define ROOT_NODE_LEVEL 0
00066 #define ROOT_NODE_DFS_INDEX 0
00067
00068 DAG::MatchParams DAG::s_matchParams;
00069 bool DAG::s_bDbgMode = false;
00070
00071 LogFile logFile;
00072
00080 int DAG::ComputeNodesInfo(leda_node v, int nLevel, int nDFSIndex)
00081 {
00082 leda_node u;
00083 DAGNodePtr& ptrNode = GetNode(v);
00084
00085
00086 if (ptrNode->GetLevel() < nLevel)
00087 ptrNode->SetLevel(nLevel);
00088
00089 if (ptrNode->GetDFSIndex() == -1)
00090 ptrNode->SetDFSIndex(nDFSIndex++);
00091
00092 nLevel++;
00093
00094 forall_adj_nodes(u, v)
00095 nDFSIndex = ComputeNodesInfo(u, nLevel, nDFSIndex);
00096
00097 return nDFSIndex;
00098 }
00099
00100 void DAG::ResetNodesInfo()
00101 {
00102 leda_node v;
00103
00104 forall_nodes(v, *this)
00105 {
00106 GetNode(v)->SetLevel(-1);
00107 GetNode(v)->SetDFSIndex(-1);
00108 }
00109 }
00110
00111 void DAG::ComputeTransiveClosure()
00112 {
00113 leda_node u, v;
00114 int i, n = GetNodeCount();
00115
00116 transClosMat.ReSize(n, n, true);
00117
00118 LEDA_GRAPH<leda_node,leda_edge> g = TRANSITIVE_CLOSURE(*this);
00119
00120
00121 forall_nodes(v, g)
00122 {
00123 i = GetNodeDFSIndex(g[v]);
00124
00125 forall_adj_nodes(u, v)
00126 transClosMat[i][GetNodeDFSIndex(g[u])] = 1;
00127 }
00128 }
00129
00130 void DAG::ComputeNodesMass()
00131 {
00132 leda_node v;
00133 ASSERT(GetNodeCount() == transClosMat.GetSize());
00134
00135
00136
00137
00138 SmartArray<int> ones(transClosMat.NRows());
00139 ones.Set(1);
00140
00141 SmartArray<int> relMasses = transClosMat * (transClosMat * ones);
00142
00143 forall_nodes(v, *this)
00144 GetNode(v)->SetMass(relMasses[GetNodeDFSIndex(v)]);
00145 }
00146
00154 void DAG::ComputeDerivedValues()
00155 {
00156 leda_node v = GetFirstRootNode();
00157
00158 ResetNodesInfo();
00159 ComputeNodesInfo(v, ROOT_NODE_LEVEL, ROOT_NODE_DFS_INDEX);
00160 ComputeTransiveClosure();
00161 ComputeNodesMass();
00162 ComputeTSVs(v);
00163
00164 nMaxBFactor = 0;
00165 dTotalTSVSum = 0;
00166
00167 nCumulativeMass = GetNodeMass(v);
00168
00169 forall_nodes(v, *this)
00170 {
00171 GetNode(v)->ComputeDerivedValues();
00172
00173 dTotalTSVSum += GetNodeTSVNorm(v);
00174
00175
00176 if (nMaxBFactor < outdeg(v))
00177 nMaxBFactor = outdeg(v);
00178 }
00179 }
00180
00192 DAGPtr DAG::SplitSubGraph(leda_node v, bool bRecomputeTSVs)
00193 {
00194 DAGPtr subg = CreateObject();
00195
00196 SplitSubGraph(v, subg);
00197
00198 subg->transClosMat = GetTransClosMat();
00199 subg->nCumulativeMass = nCumulativeMass;
00200
00201 if (bRecomputeTSVs)
00202 ComputeTSVs(GetFirstRootNode());
00203
00204 return subg;
00205 }
00206
00218 leda_node DAG::SplitSubGraph(leda_node v, DAGPtr& ptrDag)
00219 {
00220 leda_node a, b;
00221 leda_edge e;
00222 double w;
00223
00224 a = ptrDag->NewNode(inf(v));
00225
00226 forall_adj_edges(e, v)
00227 {
00228 w = inf(e);
00229 b = SplitSubGraph(target(e), ptrDag);
00230 ptrDag->NewEdge(a, b, w);
00231 }
00232
00233 del_node(v);
00234
00235 return a;
00236 }
00237
00239 void DAG::AddEdge(Matrix& adj, leda_edge e, int srcNodeIdx, int tgtNodeIdx) const
00240 {
00241 double w = GetEdgeWeight(e);
00242
00243 adj(srcNodeIdx, tgtNodeIdx) = w;
00244 adj(tgtNodeIdx, srcNodeIdx) = -w;
00245 }
00246
00273 double DAG::ComputeEigenSum(const Matrix& adj, int nVals)
00274 {
00275 using namespace NEWMAT;
00276
00277 int n = adj.Nrows();
00278 Matrix U(n, n);
00279 DiagonalMatrix D(n);
00280 double td = 0.0;
00281 double eigenVals[n];
00282
00283
00284
00285
00286 SVD(adj, D, U);
00287
00288 for (int i = 1; i <= nVals; i++)
00289 td += D(i, i);
00290
00291 return td;
00292 }
00293
00294 double DAG::ComputeLaplacian(const Matrix& adj)
00295 {
00296 using namespace NEWMAT;
00297
00298 int n = adj.Nrows(), i, j;
00299 SymmetricMatrix L(n);
00300 ColumnVector T(n);
00301
00302 for (i = 1; i <= n; i++)
00303 {
00304 T(i) = 0;
00305
00306 for (j = 1; j <= n; j++)
00307 T(i) += fabs(adj(i, j));
00308 }
00309
00310 for (i = 1; i <= n; i++)
00311 {
00312 for (j = 1; j <= n; j++)
00313 {
00314 if (i == j)
00315 L(i, j) = 1;
00316 else if (adj(i, j) != 0)
00317 L(i, j) = -1 / (sqrt(T(i) * T(j)));
00318 else
00319 L(i, j) = 0;
00320 }
00321 }
00322
00323 DiagonalMatrix D(n);
00324
00325 Jacobi(L, D);
00326
00327 SortAscending(D);
00328
00329 return fabs(D(1,1));
00330 }
00331
00335 double DAG::ComputeTSVs(leda_node root)
00336 {
00337 int j = 1, n = GetNodeMass(root);
00338 ASSERT(n > 0);
00339
00340 NodeIndexMap loopyNodeMap;
00341 Matrix adj(n, n);
00342 adj = 0.0;
00343
00344 return ComputeTSVs(root, j, adj, loopyNodeMap);
00345 }
00346
00361 double DAG::ComputeTSVs(leda_node v, int& j, Matrix& adj, NodeIndexMap& loopyNodeMap)
00362 {
00363 using namespace NEWMAT;
00364
00365 leda_node w;
00366 leda_edge e;
00367 double s;
00368 int i = j;
00369 bool bDefined, bHasLoopyChild = false;
00370
00371 TSV& tsv = GetNodeTSV(v);
00372 tsv.ReSize(outdeg(v), true);
00373
00374 forall_adj_edges(e, v)
00375 {
00376 w = target(e);
00377 bDefined = indeg(w) > 1 ? loopyNodeMap.defined(w):false;
00378
00379 if (bDefined)
00380 {
00381 bHasLoopyChild = true;
00382 AddEdge(adj, e, i, loopyNodeMap[w]);
00383 s = GetEigenLbl(w);
00384 }
00385 else
00386 {
00387 AddEdge(adj, e, i, ++j);
00388
00389 if (indeg(w) > 1)
00390 loopyNodeMap[w] = j;
00391
00392 s = ComputeTSVs(w, j, adj, loopyNodeMap);
00393 }
00394
00395 tsv.Add(s);
00396 }
00397
00398
00399
00400 if (bHasLoopyChild && i > 1)
00401 s = ComputeTSVs(v);
00402 else
00403 {
00404 s = ComputeEigenSum(adj.SubMatrix(i, j, i, j), outdeg(v));
00405
00406
00407 SetEigenLbl(v, s);
00408 tsv.Sort();
00409 }
00410
00411 return s;
00412 }
00413
00414 leda_node DAG::GetNode(int nIndex)
00415 {
00416 const leda_list<leda_node>& nodeList = all_nodes();
00417 leda_list_item it = nodeList.get_item(nIndex);
00418
00419 return nodeList[it];
00420 }
00421
00423 leda_node DAG::GetFirstRootNode() const
00424 {
00425 leda_node v;
00426
00427 forall_nodes(v, *this)
00428 if (indeg(v) == 0)
00429 return v;
00430
00431 return nil;
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00463 leda_edge DAG::ComputeBipartiteGraph(LEDA_GRAPH<leda_node, double>& G, const DAG& g1, const DAG& g2,
00464 SimMatrix& simMat, const DAGNodeMap& paired1,
00465 const DAGNodeMap& paired2, MatchedNodePair* pMatchedPair )
00466 {
00467
00468 leda_node u, v, g1Node, g2Node;
00469
00470 leda_list<leda_node> A, B;
00471 leda_list_item lia, lib;
00472
00473
00474 forall_nodes(u, g1)
00475 if (pMatchedPair->GetQueryNode() != g1.GetNodeDFSIndex(u))
00476 A.push(G.new_node(u));
00477
00478 forall_nodes(u, g2)
00479 if (pMatchedPair->GetModelNode() != g2.GetNodeDFSIndex(u))
00480 B.push(G.new_node(u));
00481
00482 leda_node_array<leda_node>& nodes = G.node_data();
00483
00484
00485
00486 for (lia = A.first(); lia != nil; lia = A.succ(lia))
00487 {
00488
00489 u = A[lia];
00490 g1Node = nodes[u];
00491
00492 if (paired1.defined(g1.GetNode(g1Node)))
00493 continue;
00494
00495
00496 for (lib = B.first(); lib != nil; lib = B.succ(lib))
00497 {
00498
00499 v = B[lib];
00500 g2Node = nodes[v];
00501
00502 if (paired2.defined(g2.GetNode(g2Node)))
00503 continue;
00504
00505
00506
00507 if (simMat[g1.GetNodeDFSIndex(g1Node)][g2.GetNodeDFSIndex(g2Node)] > 0.0)
00508 G.new_edge(u, v, 1.0);
00509 }
00510 }
00511
00512
00513
00514 if (G.number_of_edges() == 0)
00515 return nil;
00516
00517
00518 leda_edge_array<double> edgeCosts(G);
00519 leda_edge e;
00520 double w;
00521 int i, j;
00522
00523 ASSERT(s_matchParams.dBreakSibRelPen >= 0 && s_matchParams.dBreakSibRelPen <= 1);
00524
00525 forall_edges(e, G)
00526 {
00527 g1Node = nodes[G.source(e)];
00528 g2Node = nodes[G.target(e)];
00529
00530 i = g1.GetNodeDFSIndex(g1Node);
00531 j = g2.GetNodeDFSIndex(g2Node);
00532
00533 if (DAG::GetMatchParams().nPreserveAncestorRel)
00534 {
00535 if (!pMatchedPair->IsEmpty() && !pMatchedPair->AnsestorRelPreserved(i, j))
00536 simMat[i][j] = 0;
00537 }
00538
00539 edgeCosts[e] = simMat[i][j];
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 MWBM_SCALE_WEIGHTS(G, edgeCosts);
00552
00553
00554
00555 leda_list<leda_edge> tmch = MAX_WEIGHT_BIPARTITE_MATCHING(G, edgeCosts);
00556
00557
00558 leda_list_item lie;
00559 double sim, curr_weight, max_weight = -9999999;
00560 leda_edge curr_edge, max_edge = nil;
00561
00562 const double g1CMass = g1.nCumulativeMass;
00563 const double g2CMass = g2.nCumulativeMass;
00564
00565 double g1RelMass, g2RelMass;
00566
00567
00568 leda_node a = nil, b = nil, c = nil, d = nil;
00569 double x,y, maxsim = -1;
00570 int m1, m2;
00571
00572
00573 const double smw = s_matchParams.dSimilMassWeight;
00574 ASSERT(smw >=0 && smw <= 1);
00575
00576
00577
00578
00579
00580
00581
00582 forall_items(lie, tmch)
00583 {
00584 curr_edge = tmch[lie];
00585
00586 g1Node = nodes[G.source(curr_edge)];
00587 g2Node = nodes[G.target(curr_edge)];
00588
00589 g1RelMass = g1.GetNodeMass(g1Node) / g1CMass;
00590 g2RelMass = g2.GetNodeMass(g2Node) / g2CMass;
00591
00592 ASSERT(g1RelMass >= 0 && g1RelMass <= 1);
00593 ASSERT(g2RelMass >= 0 && g2RelMass <= 1);
00594
00595 sim = edgeCosts[curr_edge];
00596
00597
00598 curr_weight = smw * sim + (1 - smw) * MAX(g1RelMass, g2RelMass);
00599
00600 ASSERT(curr_weight >=0 && curr_weight <= 1)
00601
00602 if (DAG::IsDbgMode() && sim > maxsim)
00603 {
00604 maxsim = sim;
00605 c = g1Node;
00606 d = g2Node;
00607 }
00608
00609 if (curr_weight > max_weight)
00610 {
00611 max_weight = curr_weight;
00612 max_edge = curr_edge;
00613
00614
00615 if (DAG::IsDbgMode())
00616 {
00617 a = g1Node;
00618 b = g2Node;
00619 x = edgeCosts[curr_edge];
00620 y = MAX(g1RelMass, g2RelMass);
00621 m1 = g1.GetNodeMass(g1Node);
00622 m2 = g2.GetNodeMass(g2Node);
00623 }
00624 }
00625 }
00626
00627
00628 if (DAG::IsDbgMode() && max_edge != nil)
00629 {
00630 logFile.Print("\nQuery node: %s (%d)", (LPCTSTR) g1.GetNodeLbl(a), g1.GetNodeDFSIndex(a));
00631 logFile.Print("\nModel node: %s (%d)", (LPCTSTR) g2.GetNodeLbl(b), g2.GetNodeDFSIndex(b));
00632
00633 if (a != c || b != d)
00634 {
00635 logFile.Print("\nTrue max Q node: %s (%d)", (LPCTSTR) g1.GetNodeLbl(c), g1.GetNodeDFSIndex(c));
00636 logFile.Print("\nTrue max M node: %s (%d)", (LPCTSTR) g2.GetNodeLbl(d), g2.GetNodeDFSIndex(d));
00637 }
00638
00639 logFile << "\nM1: " << m1 << "\nM2: " << m2;
00640 logFile << "\nSim: " << x << "\nRel Mass: " << y << "\nWSim: " << max_weight << "\n\n";
00641 }
00642
00643 if (max_edge != nil && max_weight >= s_matchParams.dMinNodeSim)
00644 G[max_edge] = max_weight;
00645 else if (max_edge != nil)
00646 max_edge = nil;
00647
00648 return max_edge;
00649 }
00650
00661
00662 double DAG::Match(DAG& g1, DAG& g2, SimMatrix& simMat, DAGNodeMap& paired1,
00663 DAGNodeMap& paired2, MatchedNodePair* pMatchedPair )
00664 {
00665 int n1 = g1.GetNodeCount();
00666 int n2 = g2.GetNodeCount();
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 if (n1 * n2 == 0)
00682 return 0;
00683
00684
00685
00686 if (((n1 == 1) || (n2 == 1)) && paired1.size() > 0)
00687 return 0;
00688
00689
00690
00691 LEDA_GRAPH<leda_node, double> G;
00692
00693 leda_edge max_edge = ComputeBipartiteGraph(G, g1, g2, simMat, paired1, paired2, pMatchedPair);
00694
00695 if (max_edge == nil)
00696 return 0;
00697
00698
00699 leda_node maxG1Node, maxG2Node;
00700 leda_node_array<leda_node>& nodes = G.node_data();
00701
00702 maxG1Node = nodes[G.source(max_edge)];
00703 maxG2Node = nodes[G.target(max_edge)];
00704
00705
00706
00707 DAGNodePtr maxG1NodePtr = g1.GetNode(maxG1Node);
00708 DAGNodePtr maxG2NodePtr = g2.GetNode(maxG2Node);
00709
00710 paired1[maxG1NodePtr] = maxG2NodePtr;
00711 paired2[maxG2NodePtr] = maxG1NodePtr;
00712
00713
00714
00715
00716
00717 DAGPtr sg1 = g1.SplitSubGraph(maxG1Node);
00718 DAGPtr sg2 = g2.SplitSubGraph(maxG2Node);
00719
00720 int idxG1Node = g1.GetNodeDFSIndex(maxG1Node);
00721 int idxG2Node = g2.GetNodeDFSIndex(maxG2Node);
00722
00723 double max_weight = simMat[idxG1Node][idxG2Node];
00724
00726
00727 DAGNode* pNode = (DAGNode*)(const DAGNode*)maxG2NodePtr;
00728 pNode->SetSimilarity(max_weight);
00730
00731
00732 pMatchedPair->SetEmpty();
00733 max_weight += Match(*sg1, *sg2, simMat, paired1, paired2, pMatchedPair);
00734
00735 pMatchedPair->SetNodes(idxG1Node, idxG2Node);
00736 pMatchedPair->UpdateSimMat(simMat, 1 - s_matchParams.dBreakSibRelPen);
00737 max_weight += Match(g1, g2, simMat, paired1, paired2, pMatchedPair);
00738
00739 return max_weight;
00740 }
00741
00751
00752 double DAG::Similarity(const DAG& query, const DAG& model,
00753 DAGNodeMap& nodeMap, bool bRecomputeTSVs)
00754 {
00755 DAGNodeMap nodeMap2;
00756 leda_node q, m;
00757 int i, j;
00758
00759 int n1 = query.GetNodeCount();
00760 int n2 = model.GetNodeCount();
00761 int min = MIN(n1, n2);
00762
00763
00764 SmartMatrix<double> simMat, dbgMat;
00765
00766 simMat.ReSize(n1, n2, true);
00767
00768
00769 forall_nodes(q, query)
00770 {
00771 forall_nodes(m, model)
00772 {
00773 i = query.GetNodeDFSIndex(q);
00774 j = model.GetNodeDFSIndex(m);
00775
00776 simMat[i][j] = query.NodeSimilarity(q, model, m);
00777 }
00778 }
00779
00780 if (DAG::IsDbgMode())
00781 {
00782 static bool bLogFileCreated = false;
00783
00784 if (!bLogFileCreated)
00785 {
00786 bLogFileCreated = true;
00787 logFile.open("matching.log", ios::out | ios::trunc);
00788 }
00789
00790 logFile.Print("\nQuery: %s\nModel: %s\n\n", (LPCTSTR) query.GetDAGLbl(), (LPCTSTR) model.GetDAGLbl());
00791 simMat.Print(logFile, 6, 3, true);
00792 logFile.Print("\n\n");
00793 s_matchParams.Print(logFile);
00794 dbgMat = simMat;
00795 }
00796
00797
00798 nodeMap.clear();
00799
00800
00801
00802 DAGPtr cpQuery = query.CreateObject();
00803 DAGPtr cpModel = model.CreateObject();
00804
00805 MatchedNodePair matNodes(query, model);
00806
00807 double dMatchedNodes = DAG::Match(*cpQuery = query, *cpModel = model,
00808 simMat, nodeMap, nodeMap2, &matNodes);
00809
00810 if (DAG::IsDbgMode())
00811 {
00812 for (int i = 0; i < simMat.NRows(); i++)
00813 for (int j = 0; j < simMat.NCols(); j++)
00814 if (simMat[i][j] - dbgMat[i][j] != 0.0)
00815 {
00816 if (simMat[i][j] != 0.0)
00817 dbgMat[i][j] = simMat[i][j] - dbgMat[i][j];
00818 }
00819 else
00820 dbgMat[i][j] = 0.0;
00821
00822 dbgMat.Print(logFile, 6, 3, true);
00823 }
00824
00825 return (dMatchedNodes / n1 + dMatchedNodes / n2) / 2.0;
00826
00827 }
00828
00836
00837 double DAG::Distance(const DAG& image, const DAG& model,
00838 DAGNodeMap& nodeMap, bool bRecomputeTSVs)
00839 {
00840 return 1.0 / DAG::Similarity(image, model, nodeMap, bRecomputeTSVs);
00841 }
00842
00843
00845
00846
00848 DAG& DAG::operator=(const DAG& rhs)
00849 {
00850 Clear();
00851
00852 DAG_BASE_CLASS::operator=(rhs);
00853
00854 nFileOffset = rhs.nFileOffset;
00855 nDAGId = rhs.nDAGId;
00856 strGraphLbl = rhs.strGraphLbl;
00857
00858
00859 nMaxBFactor = rhs.nMaxBFactor;
00860 dTotalTSVSum = rhs.dTotalTSVSum;
00861 nViewNumber = rhs.nViewNumber;
00862 strObjectName = rhs.strObjectName;
00863 eigenVals = rhs.eigenVals;
00864 transClosMat = rhs.transClosMat;
00865 nCumulativeMass = rhs.nCumulativeMass;
00866
00867 return *this;
00868 }
00869
00871 void DAG::Clear()
00872 {
00873 DAG_BASE_CLASS::clear();
00874
00875 nFileOffset = 0;
00876 nDAGId = 0;
00877 strGraphLbl.Clear();
00878
00879
00880 nMaxBFactor = 0;
00881 dTotalTSVSum = 0;
00882 nViewNumber = 0;
00883 strObjectName.Clear();
00884 transClosMat.Clear();
00885 nCumulativeMass = 0;
00886 }
00887
00889 double DAG::NodeSimilarity(leda_node u, const DAG& from, leda_node v) const
00890 {
00891 double dNodeSim = 1 - NodeDistance(u, from, v);
00892 double dEigenSim = NodeTSVSimilarity(u, from, v);
00893 double dSimilarity;
00894
00895 if (dNodeSim < 0 || dNodeSim > 1)
00896 {
00897 if (DAG::IsDbgMode())
00898 {
00899 cerr << "\nWrong similarity value (" << dNodeSim << ") when matching: \n"
00900 << GetDAGLbl() << ":" << GetNodeLbl(u) << " against "
00901 << from.GetDAGLbl() << ":" << from.GetNodeLbl(v) << endl;
00902 }
00903
00904 dNodeSim = (dNodeSim < 0) ? 0:1;
00905 }
00906
00907 ASSERT(!isnan(dNodeSim)); ASSERT(finite(dNodeSim));
00908 ASSERT(!isnan(dEigenSim)); ASSERT(finite(dEigenSim));
00909
00910 ASSERT(dNodeSim >= 0 && dNodeSim <= 1);
00911 ASSERT(dEigenSim >= 0 && dEigenSim <= 1);
00912
00913 if (dNodeSim > 0.0)
00914 dSimilarity = s_matchParams.dTSVSimWeight * dEigenSim + (1 - s_matchParams.dTSVSimWeight) * dNodeSim;
00915 else
00916 dSimilarity = 0.0;
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 ASSERT(!isnan(dSimilarity)); ASSERT(finite(dSimilarity));
00938 ASSERT(dSimilarity >= 0); ASSERT(dSimilarity <= 1);
00939
00940 return dSimilarity;
00941 }
00942
00943
00945 double DAG::EigenDistance(leda_node u, const DAG& from, leda_node v) const
00946 {
00947
00948
00949 return Norm2(GetNodeTSV(u) - from.GetNodeTSV(v));
00950 }
00951
00952
00957 void DAG::Print(ostream& os ) const
00958 {
00959 os << "\nDAG label: " << GetDAGLbl() << endl;
00960 os << "Object: " << GetObjName() << ", view: " << GetViewNumber() << endl;
00961
00962
00963
00964
00965 leda_node v;
00966
00967 forall_nodes(v, *this)
00968 {
00969 os << "\nNode:" << index(v) << endl;
00970 GetNode(v)->Print(os);
00971 }
00972 }
00973
00975 void DAG::PrintTSVs(ostream& os ) const
00976 {
00977 os << "\nDAG's adj matrix eigen values:\n";
00978
00979 eigenVals.Print(os);
00980
00981 os << "\n\n--------------- TSV Set ---------------\n";
00982
00983 leda_node v;
00984
00985 forall_nodes(v, *this)
00986 {
00987 os << "\nNode " << GetNodeLbl(v) << ": ";
00988 GetNodeTSV(v).Print(os);
00989 }
00990
00991 os << "\n---------------------------------------\n";
00992 }
00993
00995 istream& DAG::Read(istream& is, bool bOnlyDataForMatching )
00996 {
00997 int n, i;
00998 leda_node v, s, t;
00999 leda_map<long, leda_node> map;
01000 double w;
01001 String strClassName;
01002
01003 Clear();
01004
01005
01006 nFileOffset = is.tellg();
01007
01008 strClassName.Read(is);
01009
01010 if (ClassName() != strClassName) {
01011 DBG_MSG1("Reading DAG from offset:", nFileOffset);
01012 THROW_EXCEPTION("Incorrect DAG class");
01013 }
01014
01015 strGraphLbl.Read(is);
01016
01017 is.read((char*) &n, sizeof(n));
01018
01019 for(i = 0; i < n; i++)
01020 {
01021 is.read((char*) &v, sizeof(v));
01022 map[(long)v] = NewNode(ReadNode(is));
01023 }
01024
01025 is.read((char*) &n, sizeof(n));
01026
01027 for(i = 0; i < n; i++)
01028 {
01029 is.read((char*) &s, sizeof(s));
01030 is.read((char*) &t, sizeof(t));
01031 is.read((char*) &w, sizeof(w));
01032 NewEdge(map[(long)s], map[(long)t], w);
01033 }
01034
01035
01036 is.read((char*) &nMaxBFactor, sizeof(nMaxBFactor));
01037 is.read((char*) &dTotalTSVSum, sizeof(dTotalTSVSum));
01038 is.read((char*) &nViewNumber, sizeof(nViewNumber));
01039 strObjectName.Read(is);
01040 eigenVals.Read(is);
01041
01042 transClosMat.Read(is);
01043 is.read((char*) &nCumulativeMass, sizeof(nCumulativeMass));
01044 ASSERT(nCumulativeMass >= GetNodeCount());
01045
01046 return is;
01047 }
01048
01050 ostream& DAG::Write(ostream& os) const
01051 {
01052 leda_node v, s, t;
01053 leda_edge e;
01054 double w;
01055
01056
01057
01058
01059 ClassName().Write(os);
01060 strGraphLbl.Write(os);
01061
01062 int n = GetNodeCount();
01063
01064 os.write((char*) &n, sizeof(n));
01065
01066 forall_nodes(v, *this)
01067 {
01068 os.write((char*) &v, sizeof(v));
01069 os << inf(v);
01070 }
01071
01072 n = GetEdgeCount();
01073
01074 os.write((char*) &n, sizeof(n));
01075
01076 forall_edges(e, *this)
01077 {
01078 s = source(e);
01079 t = target(e);
01080 w = inf(e);
01081 os.write((char*) &s, sizeof(s));
01082 os.write((char*) &t, sizeof(t));
01083 os.write((char*) &w, sizeof(w));
01084 }
01085
01086
01087 os.write((char*) &nMaxBFactor, sizeof(nMaxBFactor));
01088 os.write((char*) &dTotalTSVSum, sizeof(dTotalTSVSum));
01089 os.write((char*) &nViewNumber, sizeof(nViewNumber));
01090 strObjectName.Write(os);
01091 eigenVals.Write(os);
01092
01093 transClosMat.Write(os);
01094 os.write((char*) &nCumulativeMass, sizeof(nCumulativeMass));
01095
01096 return os;
01097 }
01098
01100 void DAG::DelEdge(Matrix& adj, int srcNodeIdx, int tgtNodeIdx) const
01101 {
01102 adj(srcNodeIdx, tgtNodeIdx) = 0.0;
01103 adj(tgtNodeIdx, srcNodeIdx) = 0.0;
01104 }
01105
01117 double DAG::NodeTSVSimilarity(leda_node u, const DAG& from, leda_node v) const
01118 {
01119 const TSV& tsv1 = GetNodeTSV(u);
01120 const TSV& tsv2 = from.GetNodeTSV(v);
01121 double n1 = GetNodeTSVNorm(u);
01122 double n2 = from.GetNodeTSVNorm(v);
01123
01124 if (n1 == 0 && n2 == 0)
01125 return 1;
01126
01127 TSV diff = tsv1 - tsv2;
01128 double diffNorm = diff.Norm2();
01129
01130 double max = MAX(n1, n2);
01131
01132
01133
01134
01135
01136
01137 if (diffNorm > max)
01138 return 0;
01139
01140 return 1 - diffNorm / max;
01141 }
01142
01149 void DAG::DeleteSubDAG(leda_node v)
01150 {
01151 leda_node u;
01152
01153 forall_adj_nodes(u, v)
01154 DeleteSubDAG(u);
01155
01156 del_node(v);
01157 }
01158
01162 void DAG::PrintAdjMatrix(ostream& os)
01163 {
01164 int j = 1, n = GetNodeCount();
01165 NodeIndexMap loopyNodeMap;
01166 Matrix adj(n, n);
01167
01168 adj = 0.0;
01169 ComputeTSVs(GetFirstRootNode(), j, adj, loopyNodeMap);
01170
01171 os << "\nAdjacency matrix:\n";
01172 os << setw(1) << setprecision(0) << adj << setprecision(6) << endl;
01173 }
01174
01175
01176
01177
01178 leda_node DAG::DFSGetNext(leda_node v, EdgeList& l, bool bVisitNode) const
01179 {
01180 leda_edge e;
01181
01182 ASSERT(v != nil);
01183
01184 if (bVisitNode)
01185 forall_adj_edges(e, v)
01186 l.append(e);
01187
01188 return l.empty() ? nil:target(l.pop_back());
01189 }
01190
01191
01192
01193
01194 leda_node DAG::BFSGetNext(leda_node v, EdgeList& l, bool bVisitNode) const
01195 {
01196 leda_edge e;
01197
01198 ASSERT(v != nil);
01199
01200 if (bVisitNode)
01201 forall_adj_edges(e, v)
01202 l.append(e);
01203
01204 return l.empty() ? nil:target(l.pop_front());
01205 }
01206
01207 void SimilarityGraph::Add(leda_node g1Node, leda_node g2Node, double dSimilarity)
01208 {
01209 new_edge(MapNode(g1Map, g1Node), MapNode(g2Map, g2Node), dSimilarity);
01210 }
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227 void SimilarityGraph::MergeG2Nodes(leda_node remNode, leda_node delNode)
01228 {
01229 leda_node r, d;
01230 leda_edge e;
01231
01232 r = g2Map[remNode];
01233 d = g2Map[delNode];
01234
01235 forall_in_edges(e, d)
01236 move_edge(e, source(e), r);
01237
01238 g2Map.undefine(delNode);
01239 del_node(d);
01240 }
01241
01242 double SimilarityGraph::ComputeBestAssignment(METHOD nMethod, int* pnMatched,
01243 NodeMap* pNodeMap )
01244 {
01245 leda_edge_array<double> edgeCosts(*this, 0.0);
01246 leda_edge e;
01247
01248 forall_edges(e, *this)
01249 {
01250 edgeCosts[e] = inf(e);
01251 operator[](e) = 1.0;
01252 }
01253
01254
01255 MWBM_SCALE_WEIGHTS(*this, edgeCosts);
01256
01257 EdgeList l;
01258
01259 if (nMethod == MWMC)
01260 {
01261 NodeList setA, setB;
01262 bool bBipartite = Is_Bipartite(*this, setA, setB);
01263
01264 ASSERT(bBipartite);
01265 l = MWMCB_MATCHING(*this, setA, setB, edgeCosts);
01266 }
01267 else
01268 l = MAX_WEIGHT_BIPARTITE_MATCHING(*this, edgeCosts);
01269
01270 leda_list_item i;
01271 leda_node u, v;
01272 double s = 0;
01273
01274 forall_items(i, l)
01275 {
01276 e = l[i];
01277 s += inf(e);
01278
01279 if (pNodeMap)
01280 {
01281 if (g1MatchedNodeMap.defined(e))
01282 {
01283 u = g1MatchedNodeMap[e];
01284 v = g2MatchedNodeMap[e];
01285 }
01286 else
01287 {
01288 u = inf(source(e));
01289 v = inf(target(e));
01290 }
01291
01292 (*pNodeMap)[u] = v;
01293 }
01294 }
01295
01296 if (pnMatched)
01297 *pnMatched = l.size();
01298
01299 return s;
01300 }
01301
01302 DAG::MatchParams::MatchParams()
01303 {
01304 memset(this, 0, sizeof(*this));
01305 }
01306
01307 void DAG::MatchParams::Print(ostream& os) const
01308 {
01309 PRINT_OPEN(os, (int)nSimFuncType);
01310 PRINT(os, nNodeDistFunc);
01311 PRINT(os, dTSVSimWeight);
01312 PRINT(os, dSimilMassWeight);
01313 PRINT(os, dRelMassWeight);
01314 PRINT(os, dMinNodeSim);
01315 PRINT(os, dBreakSibRelPen);
01316 PRINT(os, nPreserveAncestorRel);
01317 PRINT(os, nUseNewVoteWeightFunc);
01318 PRINT_CLOSE(os, nUseMOOVC);
01319 }
01320
01321
01322 NodeIdxArray MatchedNodePair::GetSiblingsVector(int node, const SmartMatrix<int>& tcm, const NodeIdxMatrix& parents)
01323 {
01324 const NodeIdxArray& vpar = parents[node];
01325 NodeIdxArray sibs;
01326 int parent;
01327
01328
01329
01330
01331 for (int i = 0; i < vpar.GetSize(); i++)
01332 {
01333 parent = vpar[i];
01334
01335 if (sibs.GetSize() == 0)
01336 sibs = tcm[parent];
01337 else
01338 {
01339 const NodeIdxArray& halfSibs = tcm[parent];
01340 ASSERT(sibs.GetSize() == halfSibs.GetSize());
01341
01342
01343 for (int j = 0; j < halfSibs.GetSize(); j++)
01344 if (halfSibs[j] == 1 && sibs[j] != 1)
01345 sibs[j] = 1;
01346 }
01347
01348
01349
01350 sibs[parent] = 0;
01351 }
01352
01353 if (sibs.Sum() <= 1)
01354 sibs.Clear();
01355
01356 return sibs;
01357 }
01358
01377 void MatchedNodePair::UpdateSimMat(SimMatrix& simMat, const double& alpha) const
01378 {
01379 int rows = simMat.NRows(), cols = simMat.NCols();
01380 ASSERT(alpha >= 0 && alpha <= 1);
01381
01382 if (alpha == 1)
01383 return;
01384
01385 SmartArray<int> sq, sm;
01386 int i, j;
01387
01388 sq = GetSiblingsVector(q, *pQueryTCM, qparents);
01389 sm = GetSiblingsVector(m, *pModelTCM, mparents);
01390
01391 rows = sq.GetSize();
01392 cols = sm.GetSize();
01393
01394
01395
01396
01397
01398 if (rows == 0 || cols == 0)
01399 return;
01400
01401
01402 for (i = 0; i < rows; i++)
01403 if (sq[i] == 1)
01404 for (j = 0; j < cols; j++)
01405 if (sm[j] == 0)
01406 simMat[i][j] *= alpha;
01407
01408 for (j = 0; j < cols; j++)
01409 if (sm[j] == 1)
01410 for (i = 0; i < rows; i++)
01411 if (sq[i] == 0)
01412 simMat[i][j] *= alpha;
01413 }
01414
01415