Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
two_sat_example.cc
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
67# include <iostream>
68# include <string>
69
70# include <Two_Sat.H>
71# include <tpl_sgraph.H>
72# include <tpl_agraph.H>
73
74using namespace std;
75using namespace Aleph;
76
77// =========================================================================
78// Example 1: Basic Boolean formula
79// =========================================================================
80
82{
83 cout << "==========================================================\n";
84 cout << "Example 1: Basic Boolean Formula\n";
85 cout << "==========================================================\n\n";
86
87 // Formula: (x0 OR x1) AND (~x0 OR x2) AND (~x1 OR ~x2) AND (x0 OR x2)
88 //
89 // We use the literal-index API:
90 // pos_lit(i) = positive literal for variable i
91 // neg_lit(i) = negative literal for variable i
92
93 Two_Sat<> sat(3);
94
95 sat.add_clause(sat.pos_lit(0), sat.pos_lit(1)); // x0 v x1
96 sat.add_clause(sat.neg_lit(0), sat.pos_lit(2)); // ~x0 v x2
97 sat.add_clause(sat.neg_lit(1), sat.neg_lit(2)); // ~x1 v ~x2
98 sat.add_clause(sat.pos_lit(0), sat.pos_lit(2)); // x0 v x2
99
100 cout << "Formula:\n"
101 << " (x0 OR x1) AND (~x0 OR x2) AND (~x1 OR ~x2) AND (x0 OR x2)\n\n";
102
103 auto [ok, assignment] = sat.solve();
104
105 if (ok)
106 {
107 cout << "SATISFIABLE. Assignment:\n";
108 for (size_t i = 0; i < assignment.size(); ++i)
109 cout << " x" << i << " = " << (assignment(i) ? "true" : "false")
110 << "\n";
111 }
112 else
113 cout << "UNSATISFIABLE\n";
114
115 cout << "\n";
116}
117
118// =========================================================================
119// Example 2: Same formula but using the signed 1-based API
120// =========================================================================
121
123{
124 cout << "==========================================================\n";
125 cout << "Example 2: Signed 1-based Variable API\n";
126 cout << "==========================================================\n\n";
127
128 // Same formula: (x0 OR x1) AND (~x0 OR x2) AND (~x1 OR ~x2) AND (x0 OR x2)
129 //
130 // With signed API: variable k (1-based) is +k, its negation is -k.
131 // So x0 -> +1, x1 -> +2, x2 -> +3, ~x0 -> -1, etc.
132
133 Two_Sat<> sat(3);
134
135 sat.add_clause_signed(1, 2); // x0 v x1
136 sat.add_clause_signed(-1, 3); // ~x0 v x2
137 sat.add_clause_signed(-2, -3); // ~x1 v ~x2
138 sat.add_clause_signed(1, 3); // x0 v x2
139
140 cout << "Formula (same as Example 1, using signed API):\n"
141 << " (+1 OR +2) AND (-1 OR +3) AND (-2 OR -3) AND (+1 OR +3)\n\n";
142
143 auto [ok, assignment] = sat.solve();
144
145 if (ok)
146 {
147 cout << "SATISFIABLE. Assignment:\n";
148 for (size_t i = 0; i < assignment.size(); ++i)
149 cout << " x" << i << " = " << (assignment(i) ? "true" : "false")
150 << "\n";
151 }
152 else
153 cout << "UNSATISFIABLE\n";
154
155 cout << "\n";
156}
157
158// =========================================================================
159// Example 3: Graph 2-coloring
160// =========================================================================
161
163{
164 cout << "==========================================================\n";
165 cout << "Example 3: Graph 2-Coloring via 2-SAT\n";
166 cout << "==========================================================\n\n";
167
168 // A graph is 2-colorable iff it is bipartite.
169 //
170 // For each edge (u, v), we require xu XOR xv (different colors).
171 // xu XOR xv is encoded as two clauses: (xu OR xv) AND (~xu OR ~xv).
172 //
173 // A) Path graph: 0-1-2-3 => bipartite => SAT
174 {
175 cout << "Path graph 0 - 1 - 2 - 3:\n";
176 Two_Sat<> sat(4);
177 sat.add_xor(sat.pos_lit(0), sat.pos_lit(1)); // edge 0-1
178 sat.add_xor(sat.pos_lit(1), sat.pos_lit(2)); // edge 1-2
179 sat.add_xor(sat.pos_lit(2), sat.pos_lit(3)); // edge 2-3
180
181 auto [ok, assignment] = sat.solve();
182 cout << " 2-colorable? " << (ok ? "YES" : "NO") << "\n";
183 if (ok)
184 {
185 cout << " Coloring:";
186 for (size_t i = 0; i < 4; ++i)
187 cout << " node" << i << "=" << (assignment(i) ? "A" : "B");
188 cout << "\n";
189 }
190 cout << "\n";
191 }
192
193 // B) Triangle graph: 0-1-2-0 => odd cycle => NOT bipartite => UNSAT
194 {
195 cout << "Triangle 0 - 1 - 2 - 0:\n";
196 Two_Sat<> sat(3);
197 sat.add_xor(sat.pos_lit(0), sat.pos_lit(1));
198 sat.add_xor(sat.pos_lit(1), sat.pos_lit(2));
199 sat.add_xor(sat.pos_lit(0), sat.pos_lit(2));
200
201 auto [ok, _] = sat.solve();
202 cout << " 2-colorable? " << (ok ? "YES" : "NO") << "\n\n";
203 }
204
205 // C) Cycle of length 4: 0-1-2-3-0 => even cycle => bipartite
206 {
207 cout << "Square 0 - 1 - 2 - 3 - 0:\n";
208 Two_Sat<> sat(4);
209 sat.add_xor(sat.pos_lit(0), sat.pos_lit(1));
210 sat.add_xor(sat.pos_lit(1), sat.pos_lit(2));
211 sat.add_xor(sat.pos_lit(2), sat.pos_lit(3));
212 sat.add_xor(sat.pos_lit(3), sat.pos_lit(0));
213
214 auto [ok, assignment] = sat.solve();
215 cout << " 2-colorable? " << (ok ? "YES" : "NO") << "\n";
216 if (ok)
217 {
218 cout << " Coloring:";
219 for (size_t i = 0; i < 4; ++i)
220 cout << " node" << i << "=" << (assignment(i) ? "A" : "B");
221 cout << "\n";
222 }
223 cout << "\n";
224 }
225}
226
227// =========================================================================
228// Example 4: Team assignment with constraints
229// =========================================================================
230
232{
233 cout << "==========================================================\n";
234 cout << "Example 4: Team Assignment with Constraints\n";
235 cout << "==========================================================\n\n";
236
237 // 5 people must be split into two teams (A = true, B = false).
238 //
239 // Constraints:
240 // - Alice(0) and Bob(1) must be on the same team => equivalence
241 // - Charlie(2) and Diana(3) cannot both be on team A => at-most-one
242 // - Eve(4) must be on team A => unit
243 // - Eve(4) and Bob(1) must be on different teams => XOR
244
245 const char * names[] = {"Alice", "Bob", "Charlie", "Diana", "Eve"};
246
247 Two_Sat<> sat(5);
248
249 sat.add_equiv(sat.pos_lit(0), sat.pos_lit(1)); // Alice <-> Bob
250 sat.add_clause(sat.neg_lit(2), sat.neg_lit(3)); // ~Charlie v ~Diana
251 sat.set_true(sat.pos_lit(4)); // Eve = true (team A)
252 sat.add_xor(sat.pos_lit(4), sat.pos_lit(1)); // Eve XOR Bob
253
254 cout << "Constraints:\n"
255 << " Alice and Bob: same team\n"
256 << " Charlie and Diana: not both on team A\n"
257 << " Eve: must be on team A\n"
258 << " Eve and Bob: different teams\n\n";
259
260 auto [ok, assignment] = sat.solve();
261
262 if (ok)
263 {
264 cout << "SATISFIABLE. Assignment:\n";
265 for (size_t i = 0; i < 5; ++i)
266 cout << " " << names[i] << " -> team "
267 << (assignment(i) ? "A" : "B") << "\n";
268 }
269 else
270 cout << "UNSATISFIABLE: constraints cannot be met\n";
271
272 cout << "\n";
273}
274
275// =========================================================================
276// Example 5: Different graph backends
277// =========================================================================
278
280{
281 cout << "==========================================================\n";
282 cout << "Example 5: Different Graph Backends\n";
283 cout << "==========================================================\n\n";
284
285 // The same formula solved with three graph backends.
286 // Formula: (x0 OR x1) AND (~x0 OR ~x1) (exactly one is true)
287
288 auto run = [](const string & name, auto & sat) {
289 sat.add_xor(sat.pos_lit(0), sat.pos_lit(1));
290
291 auto [ok, assignment] = sat.solve();
292 cout << " " << name << ": ";
293 if (ok)
294 cout << "x0=" << assignment(0) << " x1=" << assignment(1) << "\n";
295 else
296 cout << "UNSAT\n";
297 };
298
299 // 1) Default: List_Digraph (tpl_graph.H)
300 {
301 Two_Sat<> sat(2);
302 run("List_Digraph ", sat);
303 }
304
305 // 2) List_SDigraph (tpl_sgraph.H) — singly-linked lists
306 {
309 Two_Sat<DG> sat(2);
310 run("List_SDigraph", sat);
311 }
312
313 // 3) Array_Digraph (tpl_agraph.H) — array-based adjacency
314 {
317 Two_Sat<DG> sat(2);
318 run("Array_Digraph", sat);
319 }
320
321 cout << "\n";
322}
323
324// =========================================================================
325
326int main()
327{
333
334 return 0;
335}
2-SAT solver based on Tarjan's SCC algorithm.
Generic directed graph (digraph) wrapper template.
Definition graph-dry.H:3854
Arc for graphs implemented with simple adjacency lists.
Definition tpl_sgraph.H:197
2-SAT solver using Tarjan's SCC algorithm.
Definition Two_Sat.H:84
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
STL namespace.
Array-based graph implementation.
Simple graph implementation with adjacency lists.
void example_team_assignment()
void example_graph_backends()
void example_2_coloring()
void example_basic_formula()
void example_signed_api()
int main()