@@ -3,40 +3,16 @@ package solver
3
3
import (
4
4
"fmt"
5
5
"strings"
6
- )
7
-
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
6
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
- }
7
+ "github.com/irifrance/gini/logic"
8
+ "github.com/irifrance/gini/z"
9
+ )
34
10
35
11
// Constraint implementations limit the circumstances under which a
36
12
// particular Installable can appear in a solution.
37
13
type Constraint interface {
38
14
String (subject Identifier ) string
39
- apply (x * constrainer , subject Identifier )
15
+ apply (c * logic. C , lm * litMapping , subject Identifier ) z. Lit
40
16
order () []Identifier
41
17
}
42
18
@@ -49,7 +25,8 @@ func (zeroConstraint) String(subject Identifier) string {
49
25
return ""
50
26
}
51
27
52
- func (zeroConstraint ) apply (x * constrainer , subject Identifier ) {
28
+ func (zeroConstraint ) apply (c * logic.C , lm * litMapping , subject Identifier ) z.Lit {
29
+ return z .LitNull
53
30
}
54
31
55
32
func (zeroConstraint ) order () []Identifier {
@@ -71,15 +48,15 @@ func (a AppliedConstraint) String() string {
71
48
72
49
type mandatory struct {}
73
50
74
- func (c mandatory ) String (subject Identifier ) string {
51
+ func (constraint mandatory ) String (subject Identifier ) string {
75
52
return fmt .Sprintf ("%s is mandatory" , subject )
76
53
}
77
54
78
- func (c mandatory ) apply (x * constrainer , subject Identifier ) {
79
- x . Add (subject )
55
+ func (constraint mandatory ) apply (_ * logic. C , lm * litMapping , subject Identifier ) z. Lit {
56
+ return lm . LitOf (subject )
80
57
}
81
58
82
- func (c mandatory ) order () []Identifier {
59
+ func (constraint mandatory ) order () []Identifier {
83
60
return nil
84
61
}
85
62
@@ -91,15 +68,15 @@ func Mandatory() Constraint {
91
68
92
69
type prohibited struct {}
93
70
94
- func (c prohibited ) String (subject Identifier ) string {
71
+ func (constraint prohibited ) String (subject Identifier ) string {
95
72
return fmt .Sprintf ("%s is prohibited" , subject )
96
73
}
97
74
98
- func (c prohibited ) apply (x * constrainer , subject Identifier ) {
99
- x . AddNot (subject )
75
+ func (constraint prohibited ) apply (c * logic. C , lm * litMapping , subject Identifier ) z. Lit {
76
+ return lm . LitOf (subject ). Not ( )
100
77
}
101
78
102
- func (c prohibited ) order () []Identifier {
79
+ func (constraint prohibited ) order () []Identifier {
103
80
return nil
104
81
}
105
82
@@ -113,26 +90,24 @@ func Prohibited() Constraint {
113
90
114
91
type dependency []Identifier
115
92
116
- func (c dependency ) String (subject Identifier ) string {
117
- s := make ([]string , len (c ))
118
- for i , each := range c {
93
+ func (constraint dependency ) String (subject Identifier ) string {
94
+ s := make ([]string , len (constraint ))
95
+ for i , each := range constraint {
119
96
s [i ] = string (each )
120
97
}
121
98
return fmt .Sprintf ("%s requires at least one of %s" , subject , strings .Join (s , ", " ))
122
99
}
123
100
124
- func (c dependency ) apply (x * constrainer , subject Identifier ) {
125
- if len (c ) == 0 {
126
- return
127
- }
128
- x .AddNot (subject )
129
- for _ , each := range c {
130
- x .Add (each )
101
+ func (constraint dependency ) apply (c * logic.C , lm * litMapping , subject Identifier ) z.Lit {
102
+ m := lm .LitOf (subject ).Not ()
103
+ for _ , each := range constraint {
104
+ m = c .Or (m , lm .LitOf (each ))
131
105
}
106
+ return m
132
107
}
133
108
134
- func (c dependency ) order () []Identifier {
135
- return [] Identifier ( c )
109
+ func (constraint dependency ) order () []Identifier {
110
+ return constraint
136
111
}
137
112
138
113
// Dependency returns a Constraint that will only permit solutions
@@ -146,16 +121,15 @@ func Dependency(ids ...Identifier) Constraint {
146
121
147
122
type conflict Identifier
148
123
149
- func (c conflict ) String (subject Identifier ) string {
150
- return fmt .Sprintf ("%s conflicts with %s" , subject , c )
124
+ func (constraint conflict ) String (subject Identifier ) string {
125
+ return fmt .Sprintf ("%s conflicts with %s" , subject , constraint )
151
126
}
152
127
153
- func (c conflict ) apply (x * constrainer , subject Identifier ) {
154
- x .AddNot (subject )
155
- x .AddNot (Identifier (c ))
128
+ func (constraint conflict ) apply (c * logic.C , lm * litMapping , subject Identifier ) z.Lit {
129
+ return c .Or (lm .LitOf (subject ).Not (), lm .LitOf (Identifier (constraint )).Not ())
156
130
}
157
131
158
- func (c conflict ) order () []Identifier {
132
+ func (constraint conflict ) order () []Identifier {
159
133
return nil
160
134
}
161
135
@@ -165,3 +139,38 @@ func (c conflict) order() []Identifier {
165
139
func Conflict (id Identifier ) Constraint {
166
140
return conflict (id )
167
141
}
142
+
143
+ type leq struct {
144
+ ids []Identifier
145
+ n int
146
+ }
147
+
148
+ func (constraint leq ) String (subject Identifier ) string {
149
+ s := make ([]string , len (constraint .ids ))
150
+ for i , each := range constraint .ids {
151
+ s [i ] = string (each )
152
+ }
153
+ return fmt .Sprintf ("%s permits at most %d of %s" , subject , constraint .n , strings .Join (s , ", " ))
154
+ }
155
+
156
+ func (constraint leq ) apply (c * logic.C , lm * litMapping , subject Identifier ) z.Lit {
157
+ ms := make ([]z.Lit , len (constraint .ids ))
158
+ for i , each := range constraint .ids {
159
+ ms [i ] = lm .LitOf (each )
160
+ }
161
+ return c .CardSort (ms ).Leq (constraint .n )
162
+ }
163
+
164
+ func (constraint leq ) order () []Identifier {
165
+ return nil
166
+ }
167
+
168
+ // AtMost returns a Constraint that forbids solutions that contain
169
+ // more than n of the Installables identified by the given
170
+ // Identifiers.
171
+ func AtMost (n int , ids ... Identifier ) Constraint {
172
+ return leq {
173
+ ids : ids ,
174
+ n : n ,
175
+ }
176
+ }
0 commit comments