e70e4bfa9e81d35de2380d0264caedb4319a8e12
1 /* This file is part of libDAI - http://www.libdai.org/
2 *
4 * 2, or (at your option) any later version. libDAI is distributed without any
5 * warranty. See the file COPYING for more details.
6 *
7 * Copyright (C) 2006-2009 Joris Mooij [joris dot mooij at libdai dot org]
9 */
12 #include <algorithm>
13 #include <dai/weightedgraph.h>
14 #include <dai/util.h>
15 #include <dai/exceptions.h>
18 namespace dai {
21 using namespace std;
24 RootedTree::RootedTree( const GraphEL &T, size_t Root ) {
25 if( T.size() != 0 ) {
26 // Make a copy
27 GraphEL Gr = T;
29 // Nodes in the tree
30 set<size_t> nodes;
33 nodes.insert( Root );
35 // Keep adding edges until done
36 while( !(Gr.empty()) )
37 for( GraphEL::iterator e = Gr.begin(); e != Gr.end(); ) {
38 bool e1_in_nodes = nodes.count( e->n1 );
39 bool e2_in_nodes = nodes.count( e->n2 );
40 DAI_ASSERT( !(e1_in_nodes && e2_in_nodes) );
41 if( e1_in_nodes ) {
42 // Add directed edge, pointing away from the root
43 push_back( DEdge( e->n1, e->n2 ) );
44 nodes.insert( e->n2 );
45 // Erase the edge
46 Gr.erase( e++ );
47 } else if( e2_in_nodes ) {
48 // Add directed edge, pointing away from the root
49 push_back( DEdge( e->n2, e->n1 ) );
50 nodes.insert( e->n1 );
51 // Erase the edge
52 Gr.erase( e++ );
53 } else
54 e++;
55 }
56 }
57 }
60 GraphEL RandomDRegularGraph( size_t N, size_t d ) {
61 DAI_ASSERT( (N * d) % 2 == 0 );
64 std::vector<UEdge> G;
66 size_t tries = 0;
68 tries++;
70 // Start with N*d points {0,1,...,N*d-1} (N*d even) in N groups.
71 // Put U = {0,1,...,N*d-1}. (U denotes the set of unpaired points.)
72 vector<size_t> U;
73 U.reserve( N * d );
74 for( size_t i = 0; i < N * d; i++ )
75 U.push_back( i );
77 // Repeat the following until no suitable pair can be found: Choose
78 // two random points i and j in U, and if they are suitable, pair
79 // i with j and delete i and j from U.
80 G.clear();
81 bool finished = false;
82 while( !finished ) {
83 random_shuffle( U.begin(), U.end() );
84 size_t i1, i2;
85 bool suit_pair_found = false;
86 for( i1 = 0; i1 < U.size()-1 && !suit_pair_found; i1++ )
87 for( i2 = i1+1; i2 < U.size() && !suit_pair_found; i2++ )
88 if( (U[i1] / d) != (U[i2] / d) ) {
89 // they are suitable
90 suit_pair_found = true;
91 G.push_back( UEdge( U[i1] / d, U[i2] / d ) );
92 U.erase( U.begin() + i2 ); // first remove largest
93 U.erase( U.begin() + i1 ); // remove smallest
94 }
95 if( !suit_pair_found || U.empty() )
96 finished = true;
97 }
99 if( U.empty() ) {
100 // G is a graph with edge from vertex r to vertex s if and only if
101 // there is a pair containing points in the r'th and s'th groups.
102 // If G is d-regular, output, otherwise return to Step 1.
104 vector<size_t> degrees;
105 degrees.resize( N, 0 );
106 foreach( const UEdge &e, G ) {
107 degrees[e.n1]++;
108 degrees[e.n2]++;
109 }