deba@2420
|
1 |
/* -*- C++ -*-
|
deba@2420
|
2 |
*
|
deba@2420
|
3 |
* This file is a part of LEMON, a generic C++ optimization library
|
deba@2420
|
4 |
*
|
alpar@2553
|
5 |
* Copyright (C) 2003-2008
|
deba@2420
|
6 |
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
|
deba@2420
|
7 |
* (Egervary Research Group on Combinatorial Optimization, EGRES).
|
deba@2420
|
8 |
*
|
deba@2420
|
9 |
* Permission to use, modify and distribute this software is granted
|
deba@2420
|
10 |
* provided that this copyright notice appears in all copies. For
|
deba@2420
|
11 |
* precise terms see the accompanying LICENSE file.
|
deba@2420
|
12 |
*
|
deba@2420
|
13 |
* This software is provided "AS IS" with no warranty of any kind,
|
deba@2420
|
14 |
* express or implied, and with no claim as to its suitability for any
|
deba@2420
|
15 |
* purpose.
|
deba@2420
|
16 |
*
|
deba@2420
|
17 |
*/
|
deba@2420
|
18 |
|
deba@2420
|
19 |
/// \ingroup demos
|
deba@2420
|
20 |
/// \file
|
deba@2420
|
21 |
/// \brief Solver for SAT-2 problems.
|
deba@2420
|
22 |
///
|
deba@2420
|
23 |
/// This demo progam solves the SAT-2 problem, i.e. the boolean
|
deba@2420
|
24 |
/// satisfiability problem where each disjuction consists at most 2
|
deba@2420
|
25 |
/// terms.
|
deba@2420
|
26 |
///
|
deba@2420
|
27 |
/// The program generates a graph from the boolean expression. Two
|
deba@2420
|
28 |
/// nodes are assigned to each boolean variable, an <tt>x</tt> and a
|
deba@2420
|
29 |
/// <tt>not x</tt> nodes. If there is an <tt>x or y</tt> disjunction
|
deba@2420
|
30 |
/// in the formula, then the <tt>not x => y</tt> and the <tt>not y =>
|
deba@2420
|
31 |
/// x</tt> edges are added to the graph. If there is a single
|
deba@2420
|
32 |
/// <tt>x</tt> term disjunction in the formula then the <tt>not x
|
deba@2420
|
33 |
/// =>x</tt> edge is added to the graph.
|
deba@2420
|
34 |
///
|
deba@2420
|
35 |
/// The boolean formula could be satified if and only if the
|
deba@2420
|
36 |
/// <tt>x</tt> and <tt>not x</tt> nodes are in different strongly connected
|
deba@2420
|
37 |
/// components. A feasible solution could be get from the current
|
deba@2420
|
38 |
/// component numbering.
|
deba@2420
|
39 |
///
|
deba@2420
|
40 |
/// \include sat-2.cc
|
deba@2420
|
41 |
|
deba@2420
|
42 |
#include <iostream>
|
deba@2420
|
43 |
#include <fstream>
|
deba@2420
|
44 |
#include <sstream>
|
deba@2420
|
45 |
#include <string>
|
deba@2420
|
46 |
#include <map>
|
deba@2420
|
47 |
|
deba@2420
|
48 |
#include <lemon/smart_graph.h>
|
deba@2420
|
49 |
#include <lemon/topology.h>
|
deba@2420
|
50 |
|
deba@2420
|
51 |
using namespace std;
|
deba@2420
|
52 |
using namespace lemon;
|
deba@2420
|
53 |
|
deba@2420
|
54 |
|
deba@2420
|
55 |
int main(int argc, const char *argv[]) {
|
deba@2420
|
56 |
if (argc != 2) {
|
deba@2420
|
57 |
std::cerr << "The SAT-2 solver demo" << std::endl << std::endl;
|
deba@2420
|
58 |
std::cerr << "The parameter should be a filename" << std::endl;
|
deba@2420
|
59 |
std::cerr << "Each line of the file should contain a bool expression:"
|
deba@2420
|
60 |
<< std::endl;
|
deba@2420
|
61 |
std::cerr << " [not] <variable> [or [not] <variable>]" << std::endl;
|
deba@2420
|
62 |
std::cerr << "The program prints a feasible solution if it exists"
|
deba@2420
|
63 |
<< std::endl;
|
deba@2420
|
64 |
return -1;
|
deba@2420
|
65 |
}
|
deba@2420
|
66 |
ifstream is(argv[1]);
|
deba@2420
|
67 |
|
deba@2420
|
68 |
SmartGraph graph;
|
deba@2420
|
69 |
map<string, pair<SmartGraph::Node, SmartGraph::Node> > var;
|
deba@2420
|
70 |
|
deba@2420
|
71 |
string line;
|
deba@2420
|
72 |
while (getline(is, line)) {
|
deba@2420
|
73 |
istringstream ls(line);
|
deba@2420
|
74 |
string var1, var2, op;
|
deba@2420
|
75 |
bool neg1 = false, neg2 = false;
|
deba@2420
|
76 |
|
deba@2420
|
77 |
ls >> var1;
|
deba@2420
|
78 |
if (var1 == "not") {
|
deba@2420
|
79 |
neg1 = true;
|
deba@2420
|
80 |
ls >> var1;
|
deba@2420
|
81 |
}
|
deba@2420
|
82 |
if (ls >> op) {
|
deba@2420
|
83 |
if (op != "or") {
|
deba@2420
|
84 |
cerr << "Wrong bool expression" << std::endl;
|
deba@2420
|
85 |
return -1;
|
deba@2420
|
86 |
} else {
|
deba@2420
|
87 |
ls >> var2;
|
deba@2420
|
88 |
if (var2 == "not") {
|
deba@2420
|
89 |
neg2 = true;
|
deba@2420
|
90 |
ls >> var2;
|
deba@2420
|
91 |
}
|
deba@2420
|
92 |
}
|
deba@2420
|
93 |
if (ls >> op) {
|
deba@2420
|
94 |
cerr << "Wrong bool expression" << std::endl;
|
deba@2420
|
95 |
return -1;
|
deba@2420
|
96 |
}
|
deba@2420
|
97 |
|
deba@2420
|
98 |
map<string, pair<SmartGraph::Node, SmartGraph::Node> >::iterator it1;
|
deba@2420
|
99 |
map<string, pair<SmartGraph::Node, SmartGraph::Node> >::iterator it2;
|
deba@2420
|
100 |
it1 = var.find(var1);
|
deba@2420
|
101 |
if (it1 == var.end()) {
|
deba@2420
|
102 |
SmartGraph::Node node = graph.addNode();
|
deba@2420
|
103 |
SmartGraph::Node negNode = graph.addNode();
|
deba@2420
|
104 |
it1 = var.insert(make_pair(var1, make_pair(node, negNode))).first;
|
deba@2420
|
105 |
}
|
deba@2420
|
106 |
|
deba@2420
|
107 |
it2 = var.find(var2);
|
deba@2420
|
108 |
if (it2 == var.end()) {
|
deba@2420
|
109 |
SmartGraph::Node node = graph.addNode();
|
deba@2420
|
110 |
SmartGraph::Node negNode = graph.addNode();
|
deba@2420
|
111 |
it2 = var.insert(make_pair(var2, make_pair(node, negNode))).first;
|
deba@2420
|
112 |
}
|
deba@2420
|
113 |
|
deba@2420
|
114 |
graph.addEdge(neg1 ? it1->second.first : it1->second.second,
|
deba@2420
|
115 |
neg2 ? it2->second.second : it2->second.first);
|
deba@2420
|
116 |
|
deba@2420
|
117 |
graph.addEdge(neg2 ? it2->second.first : it2->second.second,
|
deba@2420
|
118 |
neg1 ? it1->second.second : it1->second.first);
|
deba@2420
|
119 |
} else {
|
deba@2420
|
120 |
|
deba@2420
|
121 |
map<string, pair<SmartGraph::Node, SmartGraph::Node> >::iterator it1;
|
deba@2420
|
122 |
it1 = var.find(var1);
|
deba@2420
|
123 |
if (it1 == var.end()) {
|
deba@2420
|
124 |
SmartGraph::Node node = graph.addNode();
|
deba@2420
|
125 |
SmartGraph::Node negNode = graph.addNode();
|
deba@2420
|
126 |
it1 = var.insert(make_pair(var1, make_pair(node, negNode))).first;
|
deba@2420
|
127 |
}
|
deba@2420
|
128 |
graph.addEdge(neg1 ? it1->second.first : it1->second.second,
|
deba@2420
|
129 |
neg1 ? it1->second.second : it1->second.first);
|
deba@2420
|
130 |
|
deba@2420
|
131 |
}
|
deba@2420
|
132 |
|
deba@2420
|
133 |
}
|
deba@2420
|
134 |
|
deba@2420
|
135 |
SmartGraph::NodeMap<int> comp(graph);
|
deba@2420
|
136 |
|
deba@2420
|
137 |
stronglyConnectedComponents(graph, comp);
|
deba@2420
|
138 |
|
deba@2420
|
139 |
for (map<string, pair<SmartGraph::Node, SmartGraph::Node> >::iterator
|
deba@2420
|
140 |
it = var.begin(); it != var.end(); ++it) {
|
deba@2420
|
141 |
if (comp[it->second.first] == comp[it->second.second]) {
|
deba@2420
|
142 |
std::cout << "There is no feasible solution." << std::endl;
|
deba@2420
|
143 |
return 0;
|
deba@2420
|
144 |
}
|
deba@2420
|
145 |
}
|
deba@2420
|
146 |
|
deba@2420
|
147 |
for (map<string, pair<SmartGraph::Node, SmartGraph::Node> >::iterator
|
deba@2420
|
148 |
it = var.begin(); it != var.end(); ++it) {
|
deba@2420
|
149 |
if (comp[it->second.first] < comp[it->second.second]) {
|
deba@2420
|
150 |
std::cout << it->first << " = false " << std::endl;
|
deba@2420
|
151 |
} else {
|
deba@2420
|
152 |
std::cout << it->first << " = true " << std::endl;
|
deba@2420
|
153 |
}
|
deba@2420
|
154 |
}
|
deba@2420
|
155 |
|
deba@2420
|
156 |
return 0;
|
deba@2420
|
157 |
}
|