-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconstraint.go
55 lines (47 loc) · 1.33 KB
/
constraint.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
// SPDX-License-Identifier: BSD-3-Clause
package kiwi
import (
"fmt"
"math"
)
type Constraint struct {
Expression Expression
Operator Operator
Strength Strength
}
type ConstraintOption func(*Constraint)
// WithStrength is a constraint option to set the strength of the constraint
func WithStrength(strength Strength) ConstraintOption {
return func(c *Constraint) {
optional, strength, required := float64(OPTIONAL), float64(strength), float64(REQUIRED)
c.Strength = Strength(math.Max(optional, math.Min(strength, required)))
}
}
func NewConstraint(expr Expression, op Operator, options ...ConstraintOption) *Constraint {
// reduce: c + pv + qv + rw -> c + (p+q)v + rw
vars := make(map[*Variable]int)
collapsed := 0
for i, t := range expr.Terms {
if j, present := vars[t.Variable]; present {
expr.Terms[j].Coefficient += t.Coefficient
collapsed++
} else {
vars[t.Variable] = i - collapsed
if collapsed > 0 {
expr.Terms[i-collapsed] = t
}
}
}
expr.Terms = expr.Terms[:len(expr.Terms)-collapsed]
cns := &Constraint{expr, op, REQUIRED}
cns.ApplyOptions(options...)
return cns
}
func (c *Constraint) ApplyOptions(options ...ConstraintOption) {
for _, opt := range options {
opt(c)
}
}
func (c *Constraint) String() string {
return fmt.Sprint(c.Expression, c.Operator, " 0 | Strength = ", c.Strength)
}