Skip to content

Commit 1e52111

Browse files
ecordellbenluddy
authored andcommitted
refactor(solver): small naming changes and iterative search
1 parent 9ea0483 commit 1e52111

File tree

6 files changed

+282
-227
lines changed

6 files changed

+282
-227
lines changed

pkg/controller/registry/resolver/solver/constraints.go

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,57 @@ import (
55
"strings"
66
)
77

8+
// constrainer is a reusable accumulator of constraint clause terms.
9+
type constrainer struct {
10+
pos []Identifier
11+
neg []Identifier
12+
}
13+
14+
func (x *constrainer) Add(id Identifier) {
15+
x.pos = append(x.pos, id)
16+
}
17+
18+
func (x *constrainer) AddNot(id Identifier) {
19+
x.neg = append(x.neg, id)
20+
}
21+
22+
// Reset clears the receiver's internal state so that it can be
23+
// reused.
24+
func (x *constrainer) Reset() {
25+
x.pos = x.pos[:0]
26+
x.neg = x.neg[:0]
27+
}
28+
29+
// Empty returns true if and only if the receiver has accumulated no
30+
// positive or negative terms.
31+
func (x *constrainer) Empty() bool {
32+
return len(x.pos) == 0 && len(x.neg) == 0
33+
}
34+
835
// Constraint implementations limit the circumstances under which a
936
// particular Installable can appear in a solution.
1037
type Constraint interface {
1138
String(subject Identifier) string
12-
apply(x constrainer, subject Identifier)
39+
apply(x *constrainer, subject Identifier)
1340
order() []Identifier
1441
}
1542

43+
// zeroConstraint is returned by ConstraintOf in error cases.
44+
type zeroConstraint struct{}
45+
46+
var _ Constraint = zeroConstraint{}
47+
48+
func (zeroConstraint) String(subject Identifier) string {
49+
return ""
50+
}
51+
52+
func (zeroConstraint) apply(x *constrainer, subject Identifier) {
53+
}
54+
55+
func (zeroConstraint) order() []Identifier {
56+
return nil
57+
}
58+
1659
// AppliedConstraint values compose a single Constraint with the
1760
// Installable it applies to.
1861
type AppliedConstraint struct {
@@ -26,25 +69,13 @@ func (a AppliedConstraint) String() string {
2669
return a.Constraint.String(a.Installable.Identifier())
2770
}
2871

29-
// constrainer is the set of operations available to Constraint
30-
// implementations.
31-
type constrainer interface {
32-
// Add appends the Installable identified by the given
33-
// Identifier to the clause representing a Constraint.
34-
Add(Identifier)
35-
// Add appends the negation of the Installable identified by
36-
// the given Identifier to the clause representing a
37-
// Constraint.
38-
AddNot(Identifier)
39-
}
40-
4172
type mandatory struct{}
4273

4374
func (c mandatory) String(subject Identifier) string {
4475
return fmt.Sprintf("%s is mandatory", subject)
4576
}
4677

47-
func (c mandatory) apply(x constrainer, subject Identifier) {
78+
func (c mandatory) apply(x *constrainer, subject Identifier) {
4879
x.Add(subject)
4980
}
5081

@@ -64,7 +95,7 @@ func (c prohibited) String(subject Identifier) string {
6495
return fmt.Sprintf("%s is prohibited", subject)
6596
}
6697

67-
func (c prohibited) apply(x constrainer, subject Identifier) {
98+
func (c prohibited) apply(x *constrainer, subject Identifier) {
6899
x.AddNot(subject)
69100
}
70101

@@ -90,7 +121,7 @@ func (c dependency) String(subject Identifier) string {
90121
return fmt.Sprintf("%s requires at least one of %s", subject, strings.Join(s, ", "))
91122
}
92123

93-
func (c dependency) apply(x constrainer, subject Identifier) {
124+
func (c dependency) apply(x *constrainer, subject Identifier) {
94125
if len(c) == 0 {
95126
return
96127
}
@@ -119,7 +150,7 @@ func (c conflict) String(subject Identifier) string {
119150
return fmt.Sprintf("%s conflicts with %s", subject, c)
120151
}
121152

122-
func (c conflict) apply(x constrainer, subject Identifier) {
153+
func (c conflict) apply(x *constrainer, subject Identifier) {
123154
x.AddNot(subject)
124155
x.AddNot(Identifier(c))
125156
}

pkg/controller/registry/resolver/solver/constraints_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,37 @@ func TestConstraints(t *testing.T) {
1212
Name string
1313
Constraint Constraint
1414
Subject Identifier
15-
Expected cstate
15+
Expected constrainer
1616
}
1717

1818
for _, tt := range []tc{
1919
{
2020
Name: "mandatory",
2121
Constraint: Mandatory(),
2222
Subject: "a",
23-
Expected: cstate{
23+
Expected: constrainer{
2424
pos: []Identifier{"a"},
2525
},
2626
},
2727
{
2828
Name: "prohibited",
2929
Constraint: Prohibited(),
3030
Subject: "a",
31-
Expected: cstate{
31+
Expected: constrainer{
3232
neg: []Identifier{"a"},
3333
},
3434
},
3535
{
3636
Name: "empty dependency",
3737
Constraint: Dependency(),
3838
Subject: "a",
39-
Expected: cstate{},
39+
Expected: constrainer{},
4040
},
4141
{
4242
Name: "single dependency",
4343
Constraint: Dependency("b"),
4444
Subject: "a",
45-
Expected: cstate{
45+
Expected: constrainer{
4646
pos: []Identifier{"b"},
4747
neg: []Identifier{"a"},
4848
},
@@ -51,7 +51,7 @@ func TestConstraints(t *testing.T) {
5151
Name: "multiple dependency",
5252
Constraint: Dependency("x", "y", "z"),
5353
Subject: "a",
54-
Expected: cstate{
54+
Expected: constrainer{
5555
pos: []Identifier{"x", "y", "z"},
5656
neg: []Identifier{"a"},
5757
},
@@ -60,13 +60,13 @@ func TestConstraints(t *testing.T) {
6060
Name: "conflict",
6161
Constraint: Conflict("b"),
6262
Subject: "a",
63-
Expected: cstate{
63+
Expected: constrainer{
6464
neg: []Identifier{"a", "b"},
6565
},
6666
},
6767
} {
6868
t.Run(tt.Name, func(t *testing.T) {
69-
var x cstate
69+
var x constrainer
7070
tt.Constraint.apply(&x, tt.Subject)
7171

7272
// Literals in lexically increasing order:
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package solver
2+
3+
// Identifier values uniquely identify particular Installables within
4+
// the input to a single call to Solve.
5+
type Identifier string
6+
7+
func (id Identifier) String() string {
8+
return string(id)
9+
}
10+
11+
// Installable values are the basic unit of problems and solutions
12+
// understood by this package.
13+
type Installable interface {
14+
// Identifier returns the Identifier that uniquely identifies
15+
// this Installable among all other Installables in a given
16+
// problem.
17+
Identifier() Identifier
18+
// Constraints returns the set of constraints that apply to
19+
// this Installable.
20+
Constraints() []Constraint
21+
}
22+
23+
// zeroInstallable is returned by InstallableOf in error cases.
24+
type zeroInstallable struct{}
25+
26+
var _ Installable = zeroInstallable{}
27+
28+
func (zeroInstallable) Identifier() Identifier {
29+
return ""
30+
}
31+
32+
func (zeroInstallable) Constraints() []Constraint {
33+
return nil
34+
}

0 commit comments

Comments
 (0)