Skip to content

Commit 9ea0483

Browse files
committed
Introduce preference order for solver.
Installables that appear earlier in a dependency constraint have higher preference than those appearing later in the same constraint, and the dependencies of Installables that appear earlier in the input have higher preference than the dependencies of those appearing later in the input.
1 parent 48951d3 commit 9ea0483

File tree

8 files changed

+561
-301
lines changed

8 files changed

+561
-301
lines changed

pkg/controller/registry/resolver/sat/solve.go

Lines changed: 0 additions & 94 deletions
This file was deleted.

pkg/controller/registry/resolver/sat/bench_test.go renamed to pkg/controller/registry/resolver/solver/bench_test.go

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
package sat
1+
package solver
22

33
import (
44
"context"
55
"math/rand"
66
"strconv"
77
"testing"
8-
9-
"github.com/irifrance/gini"
108
)
119

12-
func generateInput() []Installable {
10+
var BenchmarkInput = func() []Installable {
1311
const (
1412
length = 256
1513
seed = 9
@@ -18,8 +16,6 @@ func generateInput() []Installable {
1816
nDependency = 6
1917
pConflict = .05
2018
nConflict = 3
21-
pWeight = 0
22-
nWeight = 4
2319
)
2420

2521
id := func(i int) Identifier {
@@ -53,10 +49,6 @@ func generateInput() []Installable {
5349
c = append(c, Conflict(id(y)))
5450
}
5551
}
56-
if rand.Float64() < pWeight {
57-
n := rand.Intn(nWeight-1) + 1
58-
c = append(c, Weight(n))
59-
}
6052
return TestInstallable{
6153
identifier: id(i),
6254
constraints: c,
@@ -69,23 +61,14 @@ func generateInput() []Installable {
6961
result[i] = installable(i)
7062
}
7163
return result
72-
}
73-
74-
func BenchmarkCompileDict(b *testing.B) {
75-
input := generateInput()
76-
77-
b.ResetTimer()
78-
for i := 0; i < b.N; i++ {
79-
compileDict(input)
80-
}
81-
}
64+
}()
8265

83-
func BenchmarkDictSolve(b *testing.B) {
84-
d := compileDict(generateInput())
85-
86-
b.ResetTimer()
66+
func BenchmarkSolve(b *testing.B) {
8767
for i := 0; i < b.N; i++ {
88-
g := gini.New()
89-
d.Solve(context.Background(), g)
68+
s, err := New(WithInput(BenchmarkInput))
69+
if err != nil {
70+
b.Fatalf("failed to initialize solver: %s", err)
71+
}
72+
s.Solve(context.Background())
9073
}
9174
}

pkg/controller/registry/resolver/sat/constraints.go renamed to pkg/controller/registry/resolver/solver/constraints.go

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package sat
1+
package solver
22

33
import (
44
"fmt"
@@ -10,6 +10,7 @@ import (
1010
type Constraint interface {
1111
String(subject Identifier) string
1212
apply(x constrainer, subject Identifier)
13+
order() []Identifier
1314
}
1415

1516
// AppliedConstraint values compose a single Constraint with the
@@ -35,9 +36,6 @@ type constrainer interface {
3536
// the given Identifier to the clause representing a
3637
// Constraint.
3738
AddNot(Identifier)
38-
// Weight sets an additional weight to add to the constrained
39-
// Installable. Calls with negative arguments are ignored.
40-
Weight(int)
4139
}
4240

4341
type mandatory struct{}
@@ -50,6 +48,10 @@ func (c mandatory) apply(x constrainer, subject Identifier) {
5048
x.Add(subject)
5149
}
5250

51+
func (c mandatory) order() []Identifier {
52+
return nil
53+
}
54+
5355
// Mandatory returns a Constraint that will permit only solutions that
5456
// contain a particular Installable.
5557
func Mandatory() Constraint {
@@ -66,6 +68,10 @@ func (c prohibited) apply(x constrainer, subject Identifier) {
6668
x.AddNot(subject)
6769
}
6870

71+
func (c prohibited) order() []Identifier {
72+
return nil
73+
}
74+
6975
// Prohibited returns a Constraint that will reject any solution that
7076
// contains a particular Installable. Callers may also decide to omit
7177
// an Installable from input to Solve rather than apply such a
@@ -94,10 +100,15 @@ func (c dependency) apply(x constrainer, subject Identifier) {
94100
}
95101
}
96102

103+
func (c dependency) order() []Identifier {
104+
return []Identifier(c)
105+
}
106+
97107
// Dependency returns a Constraint that will only permit solutions
98108
// containing a given Installable on the condition that at least one
99109
// of the Installables identified by the given Identifiers also
100-
// appears in the solution.
110+
// appears in the solution. Identifiers appearing earlier in the
111+
// argument list have higher preference than those appearing later.
101112
func Dependency(ids ...Identifier) Constraint {
102113
return dependency(ids)
103114
}
@@ -113,25 +124,13 @@ func (c conflict) apply(x constrainer, subject Identifier) {
113124
x.AddNot(Identifier(c))
114125
}
115126

127+
func (c conflict) order() []Identifier {
128+
return nil
129+
}
130+
116131
// Conflict returns a Constraint that will permit solutions containing
117132
// either the constrained Installable, the Installable identified by
118133
// the given Identifier, or neither, but not both.
119134
func Conflict(id Identifier) Constraint {
120135
return conflict(id)
121136
}
122-
123-
type weight int
124-
125-
func (c weight) String(subject Identifier) string {
126-
return fmt.Sprintf("%s has weight %d", subject, c)
127-
}
128-
129-
func (c weight) apply(x constrainer, subject Identifier) {
130-
x.Weight(int(c))
131-
}
132-
133-
// Weight returns a Constraint that increases the weight of the
134-
// constrainted Installable by the given (non-negative) amount.
135-
func Weight(w int) Constraint {
136-
return weight(w)
137-
}

pkg/controller/registry/resolver/sat/constraints_test.go renamed to pkg/controller/registry/resolver/solver/constraints_test.go

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package sat
1+
package solver
22

33
import (
44
"sort"
@@ -64,20 +64,6 @@ func TestConstraints(t *testing.T) {
6464
neg: []Identifier{"a", "b"},
6565
},
6666
},
67-
{
68-
Name: "negative weight",
69-
Constraint: Weight(-1),
70-
Subject: "a",
71-
Expected: cstate{},
72-
},
73-
{
74-
Name: "weight",
75-
Constraint: Weight(5),
76-
Subject: "a",
77-
Expected: cstate{
78-
weight: 5,
79-
},
80-
},
8167
} {
8268
t.Run(tt.Name, func(t *testing.T) {
8369
var x cstate
@@ -95,3 +81,35 @@ func TestConstraints(t *testing.T) {
9581
})
9682
}
9783
}
84+
85+
func TestOrder(t *testing.T) {
86+
type tc struct {
87+
Name string
88+
Constraint Constraint
89+
Expected []Identifier
90+
}
91+
92+
for _, tt := range []tc{
93+
{
94+
Name: "mandatory",
95+
Constraint: Mandatory(),
96+
},
97+
{
98+
Name: "prohibited",
99+
Constraint: Prohibited(),
100+
},
101+
{
102+
Name: "dependency",
103+
Constraint: Dependency("a", "b", "c"),
104+
Expected: []Identifier{"a", "b", "c"},
105+
},
106+
{
107+
Name: "conflict",
108+
Constraint: Conflict("a"),
109+
},
110+
} {
111+
t.Run(tt.Name, func(t *testing.T) {
112+
assert.Equal(t, tt.Expected, tt.Constraint.order())
113+
})
114+
}
115+
}

0 commit comments

Comments
 (0)