mirror of
https://github.com/mudler/luet.git
synced 2025-09-05 17:20:29 +00:00
update vendor/
This commit is contained in:
171
vendor/github.com/crillab/gophersat/solver/parser.go
generated
vendored
171
vendor/github.com/crillab/gophersat/solver/parser.go
generated
vendored
@@ -1,171 +0,0 @@
|
||||
package solver
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ParseSlice parse a slice of slice of lits and returns the equivalent problem.
|
||||
// The argument is supposed to be a well-formed CNF.
|
||||
func ParseSlice(cnf [][]int) *Problem {
|
||||
var pb Problem
|
||||
for _, line := range cnf {
|
||||
switch len(line) {
|
||||
case 0:
|
||||
pb.Status = Unsat
|
||||
return &pb
|
||||
case 1:
|
||||
if line[0] == 0 {
|
||||
panic("null unit clause")
|
||||
}
|
||||
lit := IntToLit(int32(line[0]))
|
||||
v := lit.Var()
|
||||
if int(v) >= pb.NbVars {
|
||||
pb.NbVars = int(v) + 1
|
||||
}
|
||||
pb.Units = append(pb.Units, lit)
|
||||
default:
|
||||
lits := make([]Lit, len(line))
|
||||
for j, val := range line {
|
||||
if val == 0 {
|
||||
panic("null literal in clause %q")
|
||||
}
|
||||
lits[j] = IntToLit(int32(val))
|
||||
if v := int(lits[j].Var()); v >= pb.NbVars {
|
||||
pb.NbVars = v + 1
|
||||
}
|
||||
}
|
||||
pb.Clauses = append(pb.Clauses, NewClause(lits))
|
||||
}
|
||||
}
|
||||
pb.Model = make([]decLevel, pb.NbVars)
|
||||
for _, unit := range pb.Units {
|
||||
v := unit.Var()
|
||||
if pb.Model[v] == 0 {
|
||||
if unit.IsPositive() {
|
||||
pb.Model[v] = 1
|
||||
} else {
|
||||
pb.Model[v] = -1
|
||||
}
|
||||
} else if pb.Model[v] > 0 != unit.IsPositive() {
|
||||
pb.Status = Unsat
|
||||
return &pb
|
||||
}
|
||||
}
|
||||
pb.simplify()
|
||||
return &pb
|
||||
}
|
||||
|
||||
// readInt reads an int from r.
|
||||
// 'b' is the last read byte. It can be a space, a '-' or a digit.
|
||||
// The int can be negated.
|
||||
// All spaces before the int value are ignored.
|
||||
// Can return EOF.
|
||||
func readInt(b *byte, r *bufio.Reader) (res int, err error) {
|
||||
for err == nil && (*b == ' ' || *b == '\t' || *b == '\n' || *b == '\r') {
|
||||
*b, err = r.ReadByte()
|
||||
}
|
||||
if err == io.EOF {
|
||||
return res, io.EOF
|
||||
}
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("could not read digit: %v", err)
|
||||
}
|
||||
neg := 1
|
||||
if *b == '-' {
|
||||
neg = -1
|
||||
*b, err = r.ReadByte()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot read int: %v", err)
|
||||
}
|
||||
}
|
||||
for err == nil {
|
||||
if *b < '0' || *b > '9' {
|
||||
return 0, fmt.Errorf("cannot read int: %q is not a digit", *b)
|
||||
}
|
||||
res = 10*res + int(*b-'0')
|
||||
*b, err = r.ReadByte()
|
||||
if *b == ' ' || *b == '\t' || *b == '\n' || *b == '\r' {
|
||||
break
|
||||
}
|
||||
}
|
||||
res *= neg
|
||||
return res, err
|
||||
}
|
||||
|
||||
func parseHeader(r *bufio.Reader) (nbVars, nbClauses int, err error) {
|
||||
line, err := r.ReadString('\n')
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("cannot read header: %v", err)
|
||||
}
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 3 {
|
||||
return 0, 0, fmt.Errorf("invalid syntax %q in header", line)
|
||||
}
|
||||
nbVars, err = strconv.Atoi(fields[1])
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("nbvars not an int : %q", fields[1])
|
||||
}
|
||||
nbClauses, err = strconv.Atoi(fields[2])
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("nbClauses not an int : '%s'", fields[2])
|
||||
}
|
||||
return nbVars, nbClauses, nil
|
||||
}
|
||||
|
||||
// ParseCNF parses a CNF file and returns the corresponding Problem.
|
||||
func ParseCNF(f io.Reader) (*Problem, error) {
|
||||
r := bufio.NewReader(f)
|
||||
var (
|
||||
nbClauses int
|
||||
pb Problem
|
||||
)
|
||||
b, err := r.ReadByte()
|
||||
for err == nil {
|
||||
if b == 'c' { // Ignore comment
|
||||
b, err = r.ReadByte()
|
||||
for err == nil && b != '\n' {
|
||||
b, err = r.ReadByte()
|
||||
}
|
||||
} else if b == 'p' { // Parse header
|
||||
pb.NbVars, nbClauses, err = parseHeader(r)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse CNF header: %v", err)
|
||||
}
|
||||
pb.Model = make([]decLevel, pb.NbVars)
|
||||
pb.Clauses = make([]*Clause, 0, nbClauses)
|
||||
} else {
|
||||
lits := make([]Lit, 0, 3) // Make room for some lits to improve performance
|
||||
for {
|
||||
val, err := readInt(&b, r)
|
||||
if err == io.EOF {
|
||||
if len(lits) != 0 { // This is not a trailing space at the end...
|
||||
return nil, fmt.Errorf("unfinished clause while EOF found")
|
||||
}
|
||||
break // When there are only several useless spaces at the end of the file, that is ok
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse clause: %v", err)
|
||||
}
|
||||
if val == 0 {
|
||||
pb.Clauses = append(pb.Clauses, NewClause(lits))
|
||||
break
|
||||
} else {
|
||||
if val > pb.NbVars || -val > pb.NbVars {
|
||||
return nil, fmt.Errorf("invalid literal %d for problem with %d vars only", val, pb.NbVars)
|
||||
}
|
||||
lits = append(lits, IntToLit(int32(val)))
|
||||
}
|
||||
}
|
||||
}
|
||||
b, err = r.ReadByte()
|
||||
}
|
||||
if err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
pb.simplify2()
|
||||
return &pb, nil
|
||||
}
|
Reference in New Issue
Block a user