-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathvariable.ex
More file actions
126 lines (95 loc) · 2.81 KB
/
variable.ex
File metadata and controls
126 lines (95 loc) · 2.81 KB
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
defmodule CPSolver.Variable do
defstruct [:id, :index, :name, :domain, :initial_size, :store, :propagate_on]
@type t :: %__MODULE__{
id: reference(),
index: integer(),
name: term(),
domain: Domain.t(),
initial_size: integer(),
propagate_on: Propagator.propagator_event()
}
alias CPSolver.Variable
alias CPSolver.Variable.View
alias CPSolver.DefaultDomain, as: Domain
require Logger
@callback new(values :: Enum.t(), opts :: Keyword.t()) :: Variable.t()
defmacro __using__(_) do
quote do
@behaviour CPSolver.Variable
def new(values, opts \\ []) do
id = make_ref()
domain = Domain.new(values)
%Variable{
id: id,
name: Keyword.get(opts, :name, id),
domain: domain,
initial_size: Domain.size(domain)
}
end
defp default_opts() do
[domain_impl: CPSolver.DefaultDomain]
end
defoverridable new: 2
end
end
def domain(variable) do
apply_op(:domain, variable)
end
def iterator(%{domain: domain} = _variable, _opts \\ []) do
Domain.iterator(domain)
end
def size(variable) do
apply_op(:size, variable)
end
def fixed?(variable) do
apply_op(:fixed?, variable)
end
def min(variable) do
apply_op(:min, variable)
end
def max(variable) do
apply_op(:max, variable)
end
def contains?(variable, value) do
apply_op(:contains?, variable, value)
end
def remove(variable, value) do
apply_op(:remove, variable, value)
end
def removeAbove(variable, value) do
apply_op(:removeAbove, variable, value)
end
def removeBelow(variable, value) do
apply_op(:removeBelow, variable, value)
end
def fix(variable, value) do
apply_op(:fix, variable, value)
end
defp apply_op(op, %{domain: domain} = variable, value)
when op in [:remove, :removeAbove, :removeBelow, :fix] do
apply(Domain, op, [domain, value])
|> normalize_update_result()
|> tap(fn domain_change -> domain_update_callback(variable, domain_change) end)
end
defp apply_op(:contains?, %{domain: domain} = _variable, value) do
Domain.contains?(domain, value)
end
defp apply_op(op, %View{variable: variable}) do
apply_op(op, variable)
end
defp apply_op(op, %{domain: domain} = _variable)
when op in [:size, :fixed?, :min, :max] do
apply(Domain, op, [domain])
end
defp apply_op(:domain, %{domain: domain}) when not is_nil(domain) do
domain
end
defp domain_update_callback(%{update_callback: callback} = _variable, domain_change) do
callback.(domain_change)
end
defp domain_update_callback(_variable, _domain_change) do
:ignore
end
defp normalize_update_result({change, _}), do: change
defp normalize_update_result(change), do: change
end