Skip to content

Commit 00da991

Browse files
authored
Merge pull request #12 from irifrance/m
Incremental Performance Improvements
2 parents 376a6a8 + 385e5d9 commit 00da991

File tree

7 files changed

+112
-51
lines changed

7 files changed

+112
-51
lines changed

Diff for: gen/rands.go

+7
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ func (r *randS) Solve() int {
102102
defer r.unlock()
103103
return r.solve()
104104
}
105+
106+
func (r *randS) Try(dur time.Duration) int {
107+
r.lock()
108+
defer r.unlock()
109+
return r.solve()
110+
}
111+
105112
func (r *randS) solve() int {
106113
r.ms = r.ms[:0]
107114
ns := r.dur.Nanoseconds()

Diff for: gini.go

+9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package gini
55

66
import (
77
"io"
8+
"time"
89

910
"github.com/irifrance/gini/dimacs"
1011
"github.com/irifrance/gini/inter"
@@ -124,6 +125,14 @@ func (g *Gini) Solve() int {
124125
return res
125126
}
126127

128+
// Try solves with a timeout. Try returns
129+
// 1 if sat
130+
// -1 if unsat
131+
// 0 if timeout
132+
func (g *Gini) Try(dur time.Duration) int {
133+
return g.xo.Try(dur)
134+
}
135+
127136
// GoSolve provides a connection to a single background
128137
// solving goroutine, a goroutine which calls Solve()
129138
func (g *Gini) GoSolve() inter.Solve {

Diff for: inter/s.go

+8-3
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,25 @@
33

44
package inter
55

6-
import "github.com/irifrance/gini/z"
6+
import (
7+
"time"
8+
9+
"github.com/irifrance/gini/z"
10+
)
711

812
// Interface Solveable encapsulates a decision
913
// procedure which may run for a long time.
1014
//
11-
// Solve returns
15+
// Solve/Try returns
1216
//
1317
// 1 If the problem is SAT
14-
// 0 If the problem is undetermined
18+
// 0 If the problem is undetermined (Try only)
1519
// -1 If the problem is UNSAT
1620
//
1721
// These error codes are used throughout gini.
1822
type Solvable interface {
1923
Solve() int
24+
Try(dur time.Duration) int
2025
}
2126

2227
// Interface GoSolvable encapsulates a handle

Diff for: internal/xo/cdb.go

+16-10
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ type Cdb struct {
2424
Added []z.C
2525
Learnts []z.C
2626

27-
Tracer Tracer
27+
Tracer Tracer
28+
checkModel bool
2829

2930
// for multi-scheduling gc frequency
3031
gc *Cgc
@@ -46,15 +47,16 @@ func NewCdb(v *Vars, capHint int) *Cdb {
4647
capHint = 3
4748
}
4849
clss := &Cdb{
49-
Vars: v,
50-
CDat: *NewCDat(capHint * 5),
51-
AddLits: make([]z.Lit, 0, 24),
52-
AddVals: make([]int8, v.Top),
53-
Bot: CNull,
54-
Added: make([]z.C, 0, capHint/3),
55-
Learnts: make([]z.C, 0, capHint-capHint/3),
56-
Tracer: nil,
57-
gc: NewCgc()}
50+
Vars: v,
51+
CDat: *NewCDat(capHint * 5),
52+
AddLits: make([]z.Lit, 0, 24),
53+
AddVals: make([]int8, v.Top),
54+
Bot: CNull,
55+
Added: make([]z.C, 0, capHint/3),
56+
Learnts: make([]z.C, 0, capHint-capHint/3),
57+
Tracer: nil,
58+
gc: NewCgc(),
59+
checkModel: true}
5860
return clss
5961
}
6062

@@ -409,6 +411,9 @@ func (c *Cdb) CheckWatches() []error {
409411

410412
// by default, called when sat as a sanity check.
411413
func (c *Cdb) CheckModel() []error {
414+
if !c.checkModel {
415+
return nil
416+
}
412417
if c.Active != nil {
413418
// deactivations and simplificaations remove Added clauses, which are unlinked
414419
// until sufficiently large to compact. compaction
@@ -453,6 +458,7 @@ func (c *Cdb) CopyWith(ov *Vars) *Cdb {
453458
copy(other.Learnts, c.Learnts)
454459
c.CDat.CopyTo(&other.CDat)
455460
other.gc = c.gc.Copy()
461+
other.checkModel = c.checkModel
456462
return other
457463
}
458464

Diff for: internal/xo/phases.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package xo
2+
3+
import "github.com/irifrance/gini/z"
4+
5+
type phases z.Var
6+
7+
func (p phases) init(s *S) phases {
8+
if s.Vars.Max == z.Var(p) {
9+
return p
10+
}
11+
M := s.Vars.Max
12+
N := 2*M + 2
13+
counts := make([]uint64, N)
14+
L := uint64(16)
15+
D := s.Cdb.CDat.D
16+
for _, p := range s.Cdb.Added {
17+
hd := Chd(D[p-1])
18+
sz := uint64(hd.Size())
19+
if sz >= L {
20+
continue
21+
}
22+
var m z.Lit
23+
q := p
24+
for uint32(q-p) < uint32(sz) {
25+
m = D[q]
26+
if m == z.LitNull {
27+
break
28+
}
29+
counts[m] += 1 << (L - sz)
30+
q++
31+
}
32+
}
33+
cache := s.Guess.cache
34+
for i := z.Var(1); i <= M; i++ {
35+
m, n := i.Pos(), i.Neg()
36+
if counts[m] > counts[n] {
37+
cache[i] = 1
38+
} else {
39+
cache[i] = -1
40+
}
41+
}
42+
return phases(M)
43+
}

Diff for: internal/xo/s.go

+23-38
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"log"
1010
"runtime"
1111
"sync"
12+
"time"
1213

1314
"github.com/irifrance/gini/dimacs"
1415
"github.com/irifrance/gini/inter"
@@ -49,10 +50,13 @@ type S struct {
4950
assumptLevel int
5051
assumes []z.Lit // only last set of requested assumptions before solve/test.
5152
failed []z.Lit
53+
phases phases
5254

5355
// Control
5456
control *Ctl
5557
restartStopwatch int
58+
startTime time.Time
59+
deadline time.Time // synchronous (no pause)
5660

5761
// Stats (each object has its own, read by ReadStats())
5862
stRestarts int64
@@ -123,6 +127,8 @@ func NewSCdb(cdb *Cdb) *S {
123127
return st
124128
}
125129
s.control.xo = s
130+
s.startTime = time.Now()
131+
s.deadline = s.startTime
126132
return s
127133
}
128134

@@ -139,6 +145,7 @@ func (s *S) Copy() *S {
139145
other.Active = s.Active.Copy()
140146
other.Cdb.Active = other.Active
141147
}
148+
other.phases = s.phases
142149
luby := NewLuby()
143150
*luby = *(s.luby)
144151
other.luby = luby
@@ -158,6 +165,8 @@ func (s *S) Copy() *S {
158165
other.ReadStats(st)
159166
return st
160167
}
168+
other.startTime = s.startTime
169+
other.deadline = s.deadline
161170
return other
162171
}
163172

@@ -180,6 +189,12 @@ func (s *S) String() string {
180189
return fmt.Sprintf("<xo@%d>", s.Trail.Level)
181190
}
182191

192+
func (s *S) Try(dur time.Duration) int {
193+
s.startTime = time.Now()
194+
s.deadline = s.startTime.Add(dur)
195+
return s.Solve()
196+
}
197+
183198
// Method Solve solves the problem added to the solver under
184199
// assumptions specified by Assume.
185200
//
@@ -237,6 +252,9 @@ func (s *S) Solve() int {
237252
nxtTick += PropTick
238253
tick++
239254
if tick%CancelTicks == 0 {
255+
if s.deadline != s.startTime && time.Until(s.deadline) <= 0 {
256+
return 0
257+
}
240258
if !s.control.Tick() {
241259
s.stEnded++
242260
trail.Back(s.endTestLevel)
@@ -258,6 +276,9 @@ func (s *S) Solve() int {
258276
m := guess.Guess(vars.Vals)
259277
if m == z.LitNull {
260278
errs := cdb.CheckModel()
279+
if s.Active != nil {
280+
s.Cdb.checkModel = false
281+
}
261282
if len(errs) != 0 {
262283
for _, e := range errs {
263284
log.Println(e)
@@ -266,7 +287,6 @@ func (s *S) Solve() int {
266287
log.Println(s.Trail)
267288

268289
log.Printf("%p %p internal error: sat model\n", s, s.control)
269-
270290
}
271291
s.stSat++
272292
// don't do this, we store the model returned to the user
@@ -484,6 +504,7 @@ func (s *S) Add(m z.Lit) {
484504
s.ensureLitCap(m)
485505
if m == z.LitNull {
486506
s.ensure0()
507+
s.Cdb.checkModel = true
487508
}
488509
loc, u := s.Cdb.Add(m)
489510
if u != z.LitNull {
@@ -610,7 +631,7 @@ func (s *S) solveInit() int {
610631
//log.Printf("%s\n", s.Vars)
611632

612633
// initialize phase
613-
s.phaseInit()
634+
s.phases = s.phases.init(s)
614635
return 0
615636
}
616637

@@ -685,42 +706,6 @@ func (s *S) makeAssumptions() int {
685706
return 0
686707
}
687708

688-
// TBD: make this understand solved clauses
689-
// and assumptions.
690-
func (s *S) phaseInit() {
691-
M := s.Vars.Max
692-
N := 2*M + 2
693-
L := uint64(16)
694-
counts := make([]uint64, N, N)
695-
D := s.Cdb.CDat.D
696-
for _, p := range s.Cdb.Added {
697-
hd := Chd(D[p-1])
698-
sz := uint64(hd.Size())
699-
if sz >= L {
700-
continue
701-
}
702-
var m z.Lit
703-
q := p
704-
for uint32(q-p) < uint32(sz) {
705-
m = D[q]
706-
if m == z.LitNull {
707-
break
708-
}
709-
counts[m] += 1 << (L - sz)
710-
q++
711-
}
712-
}
713-
cache := s.Guess.cache
714-
for i := z.Var(1); i <= M; i++ {
715-
m, n := i.Pos(), i.Neg()
716-
if counts[m] > counts[n] {
717-
cache[i] = 1
718-
} else {
719-
cache[i] = -1
720-
}
721-
}
722-
}
723-
724709
func (s *S) final(ms []z.Lit) {
725710
marks := make([]bool, s.Vars.Max+1)
726711
for _, m := range ms {

Diff for: sv.go

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
package gini
55

66
import (
7+
"time"
8+
79
"github.com/irifrance/gini/inter"
810
"github.com/irifrance/gini/z"
911
)
@@ -67,6 +69,10 @@ func (w *svWrap) Solve() int {
6769
return w.S.Solve()
6870
}
6971

72+
func (w *svWrap) Try(dur time.Duration) int {
73+
return w.S.Try(dur)
74+
}
75+
7076
func (w *svWrap) GoSolve() inter.Solve {
7177
return w.S.GoSolve()
7278
}

0 commit comments

Comments
 (0)