mirror of
https://github.com/mudler/luet.git
synced 2025-09-09 19:19:49 +00:00
update vendor
This commit is contained in:
125
vendor/github.com/crillab/gophersat/explain/problem.go
generated
vendored
Normal file
125
vendor/github.com/crillab/gophersat/explain/problem.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
package explain
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A Problem is a conjunction of Clauses.
|
||||
// This package does not use solver's representation.
|
||||
// We want this code to be as simple as possible to be easy to audit.
|
||||
// On the other hand, solver's code must be as efficient as possible.
|
||||
type Problem struct {
|
||||
Clauses [][]int
|
||||
NbVars int
|
||||
NbClauses int
|
||||
units []int // For each var, 0 if the var is unbound, 1 if true, -1 if false
|
||||
Options Options
|
||||
tagged []bool // List of claused used whil proving the problem is unsat. Initialized lazily
|
||||
}
|
||||
|
||||
func (pb *Problem) initTagged() {
|
||||
pb.tagged = make([]bool, pb.NbClauses)
|
||||
for i, clause := range pb.Clauses {
|
||||
// Unit clauses are tagged as they will probably be used during resolution
|
||||
pb.tagged[i] = len(clause) == 1
|
||||
}
|
||||
}
|
||||
|
||||
func (pb *Problem) clone() *Problem {
|
||||
pb2 := &Problem{
|
||||
Clauses: make([][]int, pb.NbClauses),
|
||||
NbVars: pb.NbVars,
|
||||
NbClauses: pb.NbClauses,
|
||||
units: make([]int, pb.NbVars),
|
||||
}
|
||||
copy(pb2.units, pb.units)
|
||||
for i, clause := range pb.Clauses {
|
||||
pb2.Clauses[i] = make([]int, len(clause))
|
||||
copy(pb2.Clauses[i], clause)
|
||||
}
|
||||
return pb2
|
||||
}
|
||||
|
||||
// restore removes all learned clauses, if any.
|
||||
func (pb *Problem) restore() {
|
||||
pb.Clauses = pb.Clauses[:pb.NbClauses]
|
||||
}
|
||||
|
||||
// unsat will be true iff the problem can be proven unsat through unit propagation.
|
||||
// This methods modifies pb.units.
|
||||
func (pb *Problem) unsat() bool {
|
||||
done := make([]bool, len(pb.Clauses)) // clauses that were deemed sat during propagation
|
||||
modified := true
|
||||
for modified {
|
||||
modified = false
|
||||
for i, clause := range pb.Clauses {
|
||||
if done[i] { // That clause was already proved true
|
||||
continue
|
||||
}
|
||||
unbound := 0
|
||||
var unit int // An unbound literal, if any
|
||||
sat := false
|
||||
for _, lit := range clause {
|
||||
v := lit
|
||||
if v < 0 {
|
||||
v = -v
|
||||
}
|
||||
binding := pb.units[v-1]
|
||||
if binding == 0 {
|
||||
unbound++
|
||||
if unbound == 1 {
|
||||
unit = lit
|
||||
} else {
|
||||
break
|
||||
}
|
||||
} else if binding*lit == v { // (binding == -1 && lit < 0) || (binding == 1 && lit > 0) {
|
||||
sat = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if sat {
|
||||
done[i] = true
|
||||
continue
|
||||
}
|
||||
if unbound == 0 {
|
||||
// All lits are false: problem is UNSAT
|
||||
if i < pb.NbClauses {
|
||||
pb.tagged[i] = true
|
||||
}
|
||||
return true
|
||||
}
|
||||
if unbound == 1 {
|
||||
if unit < 0 {
|
||||
pb.units[-unit-1] = -1
|
||||
} else {
|
||||
pb.units[unit-1] = 1
|
||||
}
|
||||
done[i] = true
|
||||
if i < pb.NbClauses {
|
||||
pb.tagged[i] = true
|
||||
}
|
||||
modified = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// Problem is either sat or could not be proven unsat through unit propagation
|
||||
return false
|
||||
}
|
||||
|
||||
// CNF returns a representation of the problem using the Dimacs syntax.
|
||||
func (pb *Problem) CNF() string {
|
||||
lines := make([]string, 1, pb.NbClauses+1)
|
||||
lines[0] = fmt.Sprintf("p cnf %d %d", pb.NbVars, pb.NbClauses)
|
||||
for i := 0; i < pb.NbClauses; i++ {
|
||||
clause := pb.Clauses[i]
|
||||
strClause := make([]string, len(clause)+1)
|
||||
for i, lit := range clause {
|
||||
strClause[i] = fmt.Sprintf("%d", lit)
|
||||
}
|
||||
strClause[len(clause)] = "0"
|
||||
line := strings.Join(strClause, " ")
|
||||
lines = append(lines, line)
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
Reference in New Issue
Block a user