This repository has been archived by the owner on Dec 18, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
solver_trail.go
104 lines (84 loc) · 2.35 KB
/
solver_trail.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package sat
import (
"fmt"
"strings"
"github.com/mitchellh/go-sat/cnf"
)
// This file contains the trail-related functions for the solver.
// Assignments returns the assigned variables and their value (true or false).
// This is only valid if Solve returned true, in which case this is the
// solution.
func (s *Solver) Assignments() map[int]bool {
result := make(map[int]bool)
for k, v := range s.assigns {
if v != triUndef {
result[k] = v == triTrue
}
}
return result
}
// ValueLit reads the currently set value for a literal.
func (s *Solver) valueLit(l cnf.Lit) tribool {
result, ok := s.assigns[l.Var()]
if !ok || result == triUndef {
return triUndef
}
// If the literal is negative (signed), then XOR 1 will cause the bool
// to flip. If result is undef, this has no affect.
if l.Sign() {
result ^= 1
}
return result
}
func (s *Solver) assertLiteral(l cnf.Lit, from cnf.Clause) {
// Store the literal in the trail
v := l.Var()
s.assigns[v] = boolToTri(!l.Sign())
s.varinfo[v] = varinfo{reason: from, level: s.decisionLevel()}
s.trail = append(s.trail, l)
}
// level returns the level for the variable specified by v. This variable
// must be assigned for this to be correct.
func (s *Solver) level(v int) int {
return s.varinfo[v].level
}
// newDecisionLevel creates a new decision level within the trail
func (s *Solver) newDecisionLevel() {
s.trailIdx = append(s.trailIdx, len(s.trail))
}
// decisionLevel returns the current decision level
func (s *Solver) decisionLevel() int {
return len(s.trailIdx)
}
// trimToDecisionLevel trims the trail down to the given level (including
// that level).
func (s *Solver) trimToDecisionLevel(level int) {
if s.decisionLevel() <= level {
return
}
lastIdx := s.trailIdx[level]
// Unassign anything in the trail in higher levels
for i := len(s.trail) - 1; i >= lastIdx; i-- {
delete(s.assigns, s.trail[i].Var())
}
// Update our queue head
s.qhead = lastIdx
// Reset the trail length
s.trail = s.trail[:lastIdx]
s.trailIdx = s.trailIdx[:level]
}
// trailString is used for debugging
func (s *Solver) trailString() string {
vs := make([]string, len(s.trail))
for i, l := range s.trail {
decision := ""
for _, idx := range s.trailIdx {
if idx == i {
decision = "| "
break
}
}
vs[i] = fmt.Sprintf("%s%s", decision, l)
}
return fmt.Sprintf("[%s]", strings.Join(vs, ", "))
}