I'm trying to run the Bellman-Ford algorithm using the Boost Library. I have a labeled graph, but I'm getting an exception invalid conversion from ‘void*’ to ‘int. Any help would only be appreciated. Here is my code:
// g++ -std=c++17 -Wall test.c++ -l boost_system && ./a.out
#include <iostream> // for cout
#include <utility> // for pair
#include <algorithm> // for for_each
#include <vector> // For dist[] and pred[]
#include <limits> // To reliably indicate infinity
#include <map>
#include <list>
#include <boost/config.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/graph/directed_graph.hpp>
#include <boost/graph/labeled_graph.hpp>
#include <boost/graph/bellman_ford_shortest_paths.hpp>
using namespace boost;
using namespace std;
class Node
{
public:
int id;
int group;
};
struct EdgeProperties {
double weight;
EdgeProperties(){}
EdgeProperties(double w){ weight = w; }
};
typedef labeled_graph<adjacency_list<hash_setS, hash_setS, directedS, Node, EdgeProperties>, int> Graph;
int main(){
cout << "Calling main()" << endl;
Graph g;
// populate the graph
{
add_vertex( 0, g );
g[0].id = 0;
g[0].group = 10;
add_vertex( 1, g );
g[1].id = 1;
g[1].group = 20;
add_edge_by_label( 0, 1, EdgeProperties(110), g);
add_edge_by_label( 1, 0, EdgeProperties(222), g);
print_graph(g, get(&Node::id, g));
cout << "There are " << num_vertices(g) << " nodes and " << num_edges(g) << " edges in the graph" << endl;
}
// number of verticies in the graph
auto n = num_vertices(g);
// weight map
auto ewp = weight_map(get(&EdgeProperties::weight, g.graph()));
const int source = 0;
const int target = 1;
// Distance Map (with n elements of value infinity; source's value is 0)
auto inf = numeric_limits<double>::max();
vector<double> dist(n, inf);
dist[source] = 0.0;
// Predecessor Map (with n elements)
vector<int> pred(n);
bellman_ford_shortest_paths(
g.graph(),
n,
ewp
.distance_map(make_iterator_property_map(dist.begin(), get(&Node::id, g)))
.predecessor_map(make_iterator_property_map(pred.begin(), get(&Node::id, g)))
);
return 0;
}
I saw the example on https://www.boost.org/doc/libs/1_53_0/libs/graph/example/bellman-example.cpp but the example uses not a labeled graph.
Here is a live preview of my code:
https://wandbox.org/permlink/WsQA8A0IyRvGWTIj
Thank you
The source of the problem has been touched upon in the existing answer you accepted.
However, there's more to this.
Firstly, you're pretty much "within your right" to want use Node::id as the vertex index, and there could be many good reasons to use something else than vector as the vertex container selector¹.
Secondly, that stuff should... probably have worked. bellman_ford documents:
The PredecessorMap type must be a Read/Write Property Map which key and vertex types the same as the vertex descriptor type of the graph.
And iterator_property_map documents:
This property map is an adaptor that converts any random access iterator into a Lvalue Property Map. The OffsetMap type is responsible for converting key objects to integers that can be used as offsets with the random access iterator.
Now LValuePropertyMap might in fact be readonly, but in this case it clearly shouldn't be.
When using make_iterator_property_map with the additional id-map parameter, it should in fact be behaving like any associative property map both the key and value types vertex_descriptor as required by the algorithm.
UPDATE See "BONUS" below
I might dive in a little more detail later to see why that didn't work, but for now let's just work around the issue without modifying the graph model:
Live On Coliru
auto gg = g.graph();
auto id = get(&Node::id, gg);
std::map<Graph::vertex_descriptor, Graph::vertex_descriptor> assoc_pred;
bellman_ford_shortest_paths(gg, n,
weight_map(get(&EdgeProperties::weight, gg))
.distance_map(make_iterator_property_map(dist.begin(), id))
.predecessor_map(make_assoc_property_map(assoc_pred))
);
That works as it should and as expected:
Calling main()
1 --> 0
0 --> 1
There are 2 nodes and 2 edges in the graph
BONUS
I found the missing link: the predecessor map was defined with the wrong value-type:
vector<Graph::vertex_descriptor> pred(n);
Will obviously work: Live On Coliru
¹ that's subtly different from the vertex descriptor, but related in the sense that the choice of vertex container will usually predict the actual type of vertex descriptor
Related
Here's some example code to create a graph with bgl and iterate over the vertices. I would like to do this iteration in random order - in other words: the loop should manipulate every vertex, but the order of the vertices should be random for every call of the main function. How can I achieve this?
I experimented unsuccessfully with std::random_shuffle. I think there are different kinds of iterator concepts, but I don't understand the differences yet.
#include <iostream>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
using namespace boost;
// vertex struct to store some properties in vertices
struct Vertex {
std::string name;
};
int main(int,char*[]) {
// create a typedef for the graph type
typedef adjacency_list<vecS, vecS, undirectedS, Vertex> Graph;
// declare a graph object
Graph g(3);
// prepare iteration
typedef graph_traits<Graph>::vertex_iterator vertex_iter;
std::pair<vertex_iter, vertex_iter> vp;
// add some property data to the vertices
vp = vertices(g);
g[*vp.first].name = "A";
g[*(++vp.first)].name = "B";
g[*(++vp.first)].name = "C";
// iterate over the vertices
for (vp = vertices(g); vp.first != vp.second; ++vp.first)
std::cout << g[*vp.first].name << " ";
std::cout << std::endl;
return 0;
}
Edit: Here's the solution I came up with thanks to the answer of #Jay.
#include <iostream>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <algorithm> // std::random_shuffle
#include <vector> // std::vector
#include <ctime> // std::time
#include <cstdlib> // std::rand, std::srand
using namespace boost;
// vertex struct to store some properties in vertices
struct Vertex {
std::string name;
};
// random number generator function
int myrandom (int i) {
return std::rand()%i;
}
int main(int,char*[]) {
// create a typedef for the graph type
typedef adjacency_list<vecS, vecS, undirectedS, Vertex> Graph;
// declare a graph object
Graph g(3);
// prepare iteration
typedef graph_traits<Graph>::vertex_iterator vertex_iter;
std::pair<vertex_iter, vertex_iter> vp;
// add some property data to the vertices
vp = vertices(g);
g[*vp.first].name = "A";
g[*(++vp.first)].name = "B";
g[*(++vp.first)].name = "C";
// initialize pseudo random number generator
std::srand(unsigned (std::time(0)));
// create offset vector
std::vector<int> myvector;
for (int i=0; i<3; ++i) {
myvector.push_back(i);
}
// using myrandom to shuffle offset vector
std::random_shuffle(myvector.begin(), myvector.end(), myrandom);
// keep vp.first at the start
vp = vertices(g);
// iterate over the vertices effectively shuffled by the offset
vertex_iter dummy_iter;
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it) {
dummy_iter = vp.first + *it;
std::cout << g[*dummy_iter].name << " ";
}
std::cout << std::endl;
return 0;
}
I think the simplest thing to do is set up a random vector of indices, as outlined here. Then you can iterate the shuffled list and use it as an offset for your vertex iterator.
For example
vp = vertices(g); // Keep vp.first at the start
vertex_iter dummy_iter;
// Looping on a shuffled vector, values should be 0..N-1
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
{
dummy_iter = vp.first + *it;
Vertex* v = *dummy_iter;
...
To create a random number within a given range use the code below.
#include ctime and #include stdlib.h
int getNumberRange(int min, int max)
{
srand(static_cast<unsigned int>(time(0)));
// always call rand(); after srand() on visual vasic;
rand();
static const double fraction = 1.0 / (static_cast<double>(RAND_MAX) + 1.0);
return static_cast<int>(rand() * fraction * (max - min + 1) + min);
}
getNumberRange(1, 100); //picks number between 1 and 100
Every time you need a new number modify the range values (1, 100) and call the function again.
I am trying to use Boost to embed a planar graph using the Chrobak-Payne algorithm.
I am able to run the example successfully, but when I try to modify it and use different graphs it does not work correctly. I am trying to embed the second platonic graph but it does not work, and my code crashes with "Segmentation fault: 11". I assumed it is because I needed to use make_connected, make_biconnected_planar, and make_maximal_planar, but adding them did not fix it.
Here is the modified source example using the second platonic graph and the three helper functions:
//=======================================================================
// Copyright 2007 Aaron Windsor
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/property_map/property_map.hpp>
#include <vector>
#include <boost/graph/planar_canonical_ordering.hpp>
#include <boost/graph/is_straight_line_drawing.hpp>
#include <boost/graph/chrobak_payne_drawing.hpp>
#include <boost/graph/boyer_myrvold_planar_test.hpp>
using namespace boost;
//a class to hold the coordinates of the straight line embedding
struct coord_t
{
std::size_t x;
std::size_t y;
};
int main(int argc, char** argv)
{
typedef adjacency_list
< vecS,
vecS,
undirectedS,
property<vertex_index_t, int>,
property<edge_index_t, int>
>
graph;
graph g(7);
add_edge(0,1,g);
add_edge(1,2,g);
add_edge(2,3,g);
add_edge(3,0,g);
add_edge(0,4,g);
add_edge(1,5,g);
add_edge(2,6,g);
add_edge(3,7,g);
add_edge(4,5,g);
add_edge(5,6,g);
add_edge(6,7,g);
add_edge(7,4,g);
make_connected(g); //Make connected (1/3)
//Compute the planar embedding as a side-effect
typedef std::vector< graph_traits<graph>::edge_descriptor > vec_t;
std::vector<vec_t> embedding(num_vertices(g));
boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
boyer_myrvold_params::embedding =
&embedding[0]
);
make_biconnected_planar(g, &embedding[0]); //Make biconnected planar (2/3)
make_maximal_planar(g, &embedding[0]); //Make maximal planar (3/3)
//Find a canonical ordering
std::vector<graph_traits<graph>::vertex_descriptor> ordering;
planar_canonical_ordering(g, &embedding[0], std::back_inserter(ordering));
//Set up a property map to hold the mapping from vertices to coord_t's
typedef std::vector< coord_t > straight_line_drawing_storage_t;
typedef boost::iterator_property_map
< straight_line_drawing_storage_t::iterator,
property_map<graph, vertex_index_t>::type
>
straight_line_drawing_t;
straight_line_drawing_storage_t straight_line_drawing_storage
(num_vertices(g));
straight_line_drawing_t straight_line_drawing
(straight_line_drawing_storage.begin(),
get(vertex_index,g)
);
// Compute the straight line drawing
chrobak_payne_straight_line_drawing(g,
embedding,
ordering.begin(),
ordering.end(),
straight_line_drawing
);
std::cout << "The straight line drawing is: " << std::endl;
graph_traits<graph>::vertex_iterator vi, vi_end;
for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
{
coord_t coord(get(straight_line_drawing,*vi));
std::cout << *vi << " -> (" << coord.x << ", " << coord.y << ")"
<< std::endl;
}
// Verify that the drawing is actually a plane drawing
if (is_straight_line_drawing(g, straight_line_drawing))
std::cout << "Is a plane drawing." << std::endl;
else
std::cout << "Is not a plane drawing." << std::endl;
return 0;
}
But for some reason I am still getting a segmentation fault. I know it is at the call:
chrobak_payne_straight_line_drawing(g,
embedding,
ordering.begin(),
ordering.end(),
straight_line_drawing
);
because it runs fine without it (but does not compute the embedding). Where is the memory issue causing this segmentation fault? The graph I am embedding is smaller than the example.
From must be a maximal planar graph with at least 3 vertices, the requirement that k > 2 is needed for success. Your call to Planar Canonical Ordering returned two vertices. Catch is chrobak_payne_straight_line_drawing does no checking for you and it asserts at the vector iterator test in the std.
add:
assert( ordering.size( ) > 2 );
before calling, or a conditional, depends what you are up to.
one more edge:
add_edge(1,4,g);
And it would have worked.
I have written an algorithm which does (some sort of) 'topological sorting' (not exact). This algorithm copies the given graph and then manipulates the copy (by removing edges). On a million node boost graph, if my algorithm takes 3.1 seconds, 2.19 seconds are consumed by copying the given graph into a new one.
Can I remove edges without actually removing them permanently e.g. sort of masking in boost::graph library? And when algorithm is done, I unmask all edges the graph regains it original state. I suspect this should make my algorithm run much faster.
Boost.Graph's filtered_graph seems a good fit for what you want. Unfortunately I really have no idea if it will perform better than your current approach (I suspect it will). If you decide to implement this approach I would love to hear about the results.
Example on LWS.
#include <iostream>
#include <tuple>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/filtered_graph.hpp>
#include <boost/graph/topological_sort.hpp>
#include <boost/unordered_set.hpp>
struct Vertex
{
Vertex(){}
Vertex(int val):name(val){}
int name;
};
typedef boost::adjacency_list<boost::vecS,boost::vecS,boost::directedS,Vertex> graph_type;
typedef boost::graph_traits<graph_type>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<graph_type>::edge_descriptor edge_descriptor;
// A hash function for edges.
struct edge_hash:std::unary_function<edge_descriptor, std::size_t>
{
edge_hash(graph_type const& g):g(g){}
std::size_t operator()(edge_descriptor const& e) const {
std::size_t seed = 0;
boost::hash_combine(seed, source(e,g));
boost::hash_combine(seed, target(e,g));
//if you don't use vecS as your VertexList container
//you will need to create and initialize a vertex_index property and then use:
//boost::hash_combine(seed,get(boost::vertex_index, g, source(e,g)));
//boost::hash_combine(seed,get(boost::vertex_index, g, target(e,g)));
return seed;
}
graph_type const& g;
};
typedef boost::unordered_set<edge_descriptor, edge_hash> edge_set;
typedef boost::filtered_graph<graph_type,boost::is_not_in_subset<edge_set> > filtered_graph_type;
template <typename Graph>
void print_topological_order(Graph const& g)
{
std::vector<vertex_descriptor> output;
topological_sort(g,std::back_inserter(output));
std::vector<vertex_descriptor>::reverse_iterator iter=output.rbegin(),end=output.rend();
for(;iter!=end;++iter)
std::cout << g[*iter].name << " ";
std::cout << std::endl;
}
int main()
{
graph_type g;
//BUILD THE GRAPH
vertex_descriptor v0 = add_vertex(0,g);
vertex_descriptor v1 = add_vertex(1,g);
vertex_descriptor v2 = add_vertex(2,g);
vertex_descriptor v3 = add_vertex(3,g);
vertex_descriptor v4 = add_vertex(4,g);
vertex_descriptor v5 = add_vertex(5,g);
edge_descriptor e4,e5;
add_edge(v0,v1,g);
add_edge(v0,v3,g);
add_edge(v2,v4,g);
add_edge(v1,v4,g);
std::tie(e4,std::ignore) = add_edge(v4,v3,g);
std::tie(e5,std::ignore) = add_edge(v2,v5,g);
//GRAPH BUILT
std::cout << "Original graph:" << std::endl;
print_topological_order(g);
edge_hash hasher(g);
edge_set removed(0,hasher); //need to pass "hasher" in the constructor since it is not default constructible
filtered_graph_type fg(g,removed); //creates the filtered graph
removed.insert(e4); //you can "remove" edges from the graph by adding them to this set
removed.insert(e5);
std::cout << "Filtered Graph after \"removing\" 2 edges" << std::endl;
print_topological_order(fg);
removed.clear(); //clearing the set restores your original graph
std::cout << "Filtered Graph after resetting" << std::endl;
print_topological_order(fg);
}
I'm trying to use Boost Graph Library to use graph cut on a 2D image. My goal is to represent each pixel as a node with 4 float edges (less on the borders). Neighborhood pixels' edge will have a value dependant on gradiant or intensity or something.
To do so, I tried using boost::grid_graph with boost::boykov_kolmogorov_max_flow(), without success. The doc says that grid_graph models "Vertex List", "Edge List" and "Incidence graph", which are the requirements for boykov_kolmogorov_max_flow, so I think it should work.
Here's my code:
const unsigned int D = 2;
typedef boost::grid_graph<D> Graph;
typedef boost::graph_traits<Graph>::vertex_descriptor VertexDescriptor;
boost::array<unsigned int, D> lengths = { { 3, 3 } };
Graph graph(lengths, false);
// Add edge's value between pixels
VertexDescriptor s, t; // Should be initialized, I know.
float flow = boost::boykov_kolmogorov_max_flow(graph, s, t);
// error C2039: 'edge_property_type' is not a member of 'boost::grid_graph<Dimensions>'
I know s and t should be initialized, but I only want the program to compile. Is it possible to use grid_graph with boykov_kolmogorov_max_flow? If so, how? If not, then I guess I'm forced to use the more generic (and probably slower) boost::adjacency_list? Thanks.
The problem you have with the other answer is probably caused by an older version of Visual Studio (its code works fine with Visual Studio 2012 Express/g++ 4.8.0 and boost 1.53.0). If that problem is the only one with your compiler it can easily be sidestepped by creating another custom property map similar to the one that uses capacity. The changes required are marked with //ADDED and //CHANGED.
#include <iostream>
#include <boost/graph/grid_graph.hpp>
#include <boost/graph/boykov_kolmogorov_max_flow.hpp>
#include <boost/graph/iteration_macros.hpp>
int main()
{
const unsigned int D = 2;
typedef boost::grid_graph<D> Graph;
typedef boost::graph_traits<Graph>::vertex_descriptor VertexDescriptor;
typedef boost::graph_traits<Graph>::edge_descriptor EdgeDescriptor;//ADDED
typedef boost::graph_traits<Graph>::vertices_size_type VertexIndex;
typedef boost::graph_traits<Graph>::edges_size_type EdgeIndex;
boost::array<std::size_t, D> lengths = { { 3, 3 } };
Graph graph(lengths, false);
float pixel_intensity[]={10.0f,15.0f,25.0f,
5.0f,220.0f,240.0f,
12.0f,15.0,230.0f};
std::vector<int> groups(num_vertices(graph));
std::vector<float> residual_capacity(num_edges(graph)); //this needs to be initialized to 0
std::vector<float> capacity(num_edges(graph)); //this is initialized below, I believe the capacities of an edge and its reverse should be equal, but I'm not sure
std::vector<EdgeDescriptor> reverse_edges(num_edges(graph));//ADDED
BGL_FORALL_EDGES(e,graph,Graph)
{
VertexDescriptor src = source(e,graph);
VertexDescriptor tgt = target(e,graph);
VertexIndex source_idx = get(boost::vertex_index,graph,src);
VertexIndex target_idx = get(boost::vertex_index,graph,tgt);
EdgeIndex edge_idx = get(boost::edge_index,graph,e);
capacity[edge_idx] = 255.0f - fabs(pixel_intensity[source_idx]-pixel_intensity[target_idx]); //you should change this to your "gradiant or intensity or something"
reverse_edges[edge_idx]=edge(tgt,src,graph).first;//ADDED
}
VertexDescriptor s=vertex(0,graph), t=vertex(8,graph);
//in the boykov_kolmogorov_max_flow header it says that you should use this overload with an explicit color property map parameter if you are interested in finding the minimum cut
boykov_kolmogorov_max_flow(graph,
make_iterator_property_map(&capacity[0], get(boost::edge_index, graph)),
make_iterator_property_map(&residual_capacity[0], get(boost::edge_index, graph)),
make_iterator_property_map(&reverse_edges[0], get(boost::edge_index, graph)), //CHANGED
make_iterator_property_map(&groups[0], get(boost::vertex_index, graph)),
get(boost::vertex_index, graph),
s,
t
);
for(size_t index=0; index < groups.size(); ++index)
{
if((index%lengths[0]==0)&&index)
std::cout << std::endl;
std::cout << groups[index] << " ";
}
return 0;
}
Working on Coliru.
PS: One thing that the Boost.Graph documentation fails to clarify is that the concept requirements described there apply to the case when you explicitly pass every one of the arguments. Some of the default arguments may introduce further requirements.
#include <iostream>
#include <boost/graph/grid_graph.hpp>
#include <boost/graph/boykov_kolmogorov_max_flow.hpp>
#include <boost/graph/iteration_macros.hpp>
int main()
{
const unsigned int D = 2;
typedef boost::grid_graph<D> Graph;
typedef boost::graph_traits<Graph>::vertex_descriptor VertexDescriptor;
typedef boost::graph_traits<Graph>::vertices_size_type VertexIndex;
typedef boost::graph_traits<Graph>::edges_size_type EdgeIndex;
boost::array<unsigned int, D> lengths = { { 3, 3 } };
Graph graph(lengths, false);
float pixel_intensity[]={10.0f,15.0f,25.0f,
5.0f,220.0f,240.0f,
12.0f,15.0,230.0f};
std::vector<int> groups(num_vertices(graph));
std::vector<float> residual_capacity(num_edges(graph)); //this needs to be initialized to 0
std::vector<float> capacity(num_edges(graph)); //this is initialized below, I believe the capacities of an edge and its reverse should be equal, but I'm not sure
BGL_FORALL_EDGES(e,graph,Graph)
{
VertexDescriptor src = source(e,graph);
VertexDescriptor tgt = target(e,graph);
VertexIndex source_idx = get(boost::vertex_index,graph,src);
VertexIndex target_idx = get(boost::vertex_index,graph,tgt);
EdgeIndex edge_idx = get(boost::edge_index,graph,e);
capacity[edge_idx] = 255.0f - fabs(pixel_intensity[source_idx]-pixel_intensity[target_idx]); //you should change this to your "gradiant or intensity or something"
}
VertexDescriptor s=vertex(0,graph), t=vertex(8,graph);
//in the boykov_kolmogorov_max_flow header it says that you should use this overload with an explicit color property map parameter if you are interested in finding the minimum cut
boykov_kolmogorov_max_flow(graph,
make_iterator_property_map(&capacity[0], get(boost::edge_index, graph)),
make_iterator_property_map(&residual_capacity[0], get(boost::edge_index, graph)),
get(boost::edge_reverse, graph),
make_iterator_property_map(&groups[0], get(boost::vertex_index, graph)),
get(boost::vertex_index, graph),
s,
t
);
for(size_t index=0; index < groups.size(); ++index)
{
if((index%lengths[0]==0)&&index)
std::cout << std::endl;
std::cout << groups[index] << " ";
}
return 0;
}
I have been looking for a while, but I just can't seem to find any implementation of the 2-Sat algorithm.
I am working in c++ with the boost library (which has a strongly connected component module) and need some guidance to either create an efficient 2-Sat program or find an existing library for me to utilise through c++.
I suppose you know how to model a 2-Sat problem to solve it with SCC.
The way I handle vars and its negation isn't very elegant, but allows a short implementation:
Given n variables numbered from 0 to n-1, in the clauses -i means the negation of variable i, and in the graph i+n means the same (am I clear ?)
#include <boost/config.hpp>
#include <iostream>
#include <vector>
#include <boost/graph/strong_components.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/foreach.hpp>
typedef std::pair<int, int> clause;
//Properties of our graph. By default oriented graph
typedef boost::adjacency_list<> Graph;
const int nb_vars = 5;
int var_to_node(int var)
{
if(var < 0)
return (-var + nb_vars);
else
return var;
}
int main(int argc, char ** argv)
{
std::vector<clause> clauses;
clauses.push_back(clause(1,2));
clauses.push_back(clause(2,-4));
clauses.push_back(clause(1,4));
clauses.push_back(clause(1,3));
clauses.push_back(clause(-2,4));
//Creates a graph with twice as many nodes as variables
Graph g(nb_vars * 2);
//Let's add all the edges
BOOST_FOREACH(clause c, clauses)
{
int v1 = c.first;
int v2 = c.second;
boost::add_edge(
var_to_node(-v1),
var_to_node(v2),
g);
boost::add_edge(
var_to_node(-v2),
var_to_node(v1),
g);
}
// Every node will belong to a strongly connected component
std::vector<int> component(num_vertices(g));
std::cout << strong_components(g, &component[0]) << std::endl;
// Let's check if there is variable having it's negation
// in the same SCC
bool satisfied = true;
for(int i=0; i<nb_vars; i++)
{
if(component[i] == component[i+nb_vars])
satisfied = false;
}
if(satisfied)
std::cout << "Satisfied!" << std::endl;
else
std::cout << "Not satisfied!" << std::endl;
}