Encodes, solves, and decodes the exact cover problem via reduction to SAT.
"Given a collection
Example of a valid input file format:
{1 2 3 4}
{
{ }
{1 3}
{1 2 3}
{2 4}
}
Input format:
- First line only contains the main set:
$X$ . - Following lines only contain the set of subsets of the main set:
$S$ . - Both subsets of literals and the set of subsets
$S$ need to be contained in{ }
. - Lines after the main set can contain multiple subsets.
- Literals need to be delimited by (one or more) spaces.
- Literals can be strings of various length but without whitespace.
This input file format is also valid:
{alpha bravo charlie delta}
{ { } {alpha charlie} {alpha bravo charlie} {bravo delta} }
Any deviation from the problem's specifications (e.g., subset contains an element that is not present in the main set) should trigger an exception during parsing.
The problem is encoded using one set of variables. Variable
Analogically, variable
The conditions for a collection of subsets to be an exact cover of the main set
- Every element of the main set
$X$ has to be included in at least one subset in$S^*$ .
- Every element of the main set
$X$ can be included in at most one subset in$S^*$ .
Basic usage:
main.py [-h] [-i INPUT] [-o OUTPUT] [-s SOLVER] [-v {0,1}]
Command-line options:
-h
,--help
: Show a help message and exit.-i INPUT
,--input INPUT
: The instance file. Default: "input.in".-o OUTPUT
,--output OUTPUT
: Output file for the DIMACS cnf formula. Default: "output.cnf".-s SOLVER
,--solver SOLVER
: The SAT solver to be used. Default "glucose-syrup" *-v {0,1}
,--verb {0,1}
: Verbosity of the SAT solver used.
* If the provided path cannot be found, the script assumes this to be a global command.
-
input-easy-sat.in
: Simple satisfiable instance provided in the Exact cover wikipedia page where$|X| = 4$ ,$|S| = 4$ . -
input-easy-unsat.in
: Simple unsatisfiable instance where$|X| = 5$ ,$|S| = 5$ . -
input-hard-sat.in
: Complex satisfiable instance generated using instance_generator.py where$|X| = 100$ ,$|S| = 560$ . -
input-hard-unsat.in
: Complex unsatisfiable instance generated using instance_generator.py where$|X| = 100$ ,$|S| = 500$ .
Experiments were run on Intel Core i7-7500U CPU (2.70GHz) and 12 GB RAM on Fedora Linux 40.
The following values are averages over 5 runs of glucose-syrup
on various instances generated by the instance_generator.py with the given parameters and GUARANTEED_SAT
set to True
.
Main set size | Variable count | Clause count | Runtime (s) |
---|---|---|---|
20 | 113 | 25360 | 0.123 |
40 | 226 | 196185 | 1.358 |
60 | 338 | 707458 | 6.892 |
80 | 451 | 1586590 | 20.177 |
100 | 561 | 3081377 | 46.554 |
Main set size | Variable count | Clause count | Runtime (s) |
---|---|---|---|
20 | 214 | 105004 | 0.763 |
40 | 425 | 831246 | 10.331 |
60 | 641 | 2813321 | 49.826 |
80 | 849 | 6402951 | 12.339 |
100 | 1064 | 12434209 | 24.045 |
SUBSET_COUNT_MULT
specifies how many random subsets of MAIN_SET_SIZE = 20
and SUBSET_COUNT_MULT = 5
, then