@@ -19,48 +19,137 @@ Settings for the exploration of a search space composed by a collection of domai
19
19
function ExploreSettings (
20
20
domains;
21
21
complete_search_limit = 10 ^ 6 ,
22
- max_samplings = sum (domain_size, domains),
22
+ max_samplings = sum (domain_size, domains; init = 0 ),
23
23
search = :flexible ,
24
24
solutions_limit = floor (Int, sqrt (max_samplings)),
25
25
)
26
26
return ExploreSettings (complete_search_limit, max_samplings, search, solutions_limit)
27
27
end
28
28
29
+ struct ExplorerState{T}
30
+ best:: Vector{T}
31
+ solutions:: Set{Vector{T}}
32
+ non_solutions:: Set{Vector{T}}
33
+
34
+ ExplorerState {T} () where {T} = new {T} ([], Set {Vector{T}} (), Set {Vector{T}} ())
35
+ end
36
+
37
+ ExplorerState (domains) = ExplorerState {Union{map(eltype, domains)...}} ()
38
+
39
+ mutable struct Explorer{F1<: Function ,D<: AbstractDomain ,F2<: Union{Function,Nothing} ,T}
40
+ concepts:: Dict{Int,Tuple{F1,Vector{Int}}}
41
+ domains:: Dict{Int,D}
42
+ objective:: F2
43
+ settings:: ExploreSettings
44
+ state:: ExplorerState{T}
45
+
46
+ function Explorer (
47
+ concepts,
48
+ domains,
49
+ objective = nothing ;
50
+ settings = ExploreSettings (domains),
51
+ )
52
+ F1 = isempty (concepts) ? Function : Union{map (c -> typeof (c[1 ]), concepts)... }
53
+ D = isempty (domains) ? AbstractDomain : Union{map (typeof, domains)... }
54
+ F2 = typeof (objective)
55
+ T = isempty (domains) ? Real : Union{map (eltype, domains)... }
56
+ d_c = Dict (enumerate (concepts))
57
+ d_d = Dict (enumerate (domains))
58
+ return new {F1,D,F2,T} (d_c, d_d, objective, settings, ExplorerState {T} ())
59
+ end
60
+ end
61
+
62
+ function Explorer ()
63
+ concepts = Vector {Tuple{Function,Vector{Int}}} ()
64
+ domains = Vector {AbstractDomain} ()
65
+ objective = nothing
66
+ settings = ExploreSettings (domains)
67
+ return Explorer (concepts, domains, objective; settings)
68
+ end
69
+
70
+ function Base. push! (explorer:: Explorer , concept:: Tuple{Function,Vector{Int}} )
71
+ max_key = maximum (keys (explorer. concepts); init = 0 )
72
+ explorer. concepts[max_key+ 1 ] = concept
73
+ return max_key + 1
74
+ end
75
+
76
+ function delete_concept! (explorer:: Explorer , key:: Int )
77
+ delete! (explorer. concepts, key)
78
+ return nothing
79
+ end
80
+
81
+ function Base. push! (explorer:: Explorer , domain:: AbstractDomain )
82
+ max_key = maximum (keys (explorer. domains); init = 0 )
83
+ explorer. domains[max_key+ 1 ] = domain
84
+ return max_key + 1
85
+ end
86
+
87
+ function delete_domain! (explorer:: Explorer , key:: Int )
88
+ delete! (explorer. domains, key)
89
+ return nothing
90
+ end
91
+
92
+ set! (explorer:: Explorer , objective:: Function ) = explorer. objective = objective
93
+
94
+ function update_exploration! (explorer, f, c, search = explorer. settings. search)
95
+ solutions = explorer. state. solutions
96
+ non_sltns = explorer. state. non_solutions
97
+ obj = explorer. objective
98
+ sl = search == :complete ? Inf : explorer. settings. solutions_limit
99
+
100
+ cv = collect (c)
101
+ if f (cv)
102
+ if length (solutions) < sl
103
+ push! (solutions, cv)
104
+ obj != = nothing && (explorer. state. best = argmin (obj, solutions))
105
+ end
106
+ else
107
+ if length (non_sltns) < sl
108
+ push! (non_sltns, cv)
109
+ end
110
+ end
111
+ return nothing
112
+ end
113
+
29
114
"""
30
115
_explore(args...)
31
116
32
117
Internals of the `explore` function. Behavior is automatically adjusted on the kind of exploration: `:flexible`, `:complete`, `:partial`.
33
118
"""
34
- function _explore (domains , f, s , :: Val{:partial} )
35
- solutions = Set {Vector{Int}} ()
36
- non_sltns = Set {Vector{Int}} ()
119
+ function _explore! (explorer , f, :: Val{:partial} )
120
+ sl = explorer . settings . solutions_limit
121
+ ms = explorer . settings . max_samplings
37
122
38
- sl = s. solutions_limit
123
+ solutions = explorer. state. solutions
124
+ non_sltns = explorer. state. non_solutions
125
+ domains = explorer. domains |> values
39
126
40
- for _ = 1 : s . max_samplings
127
+ for _ = 1 : ms
41
128
length (solutions) ≥ sl && length (non_sltns) ≥ sl && break
42
129
config = map (rand, domains)
43
- c = f (config) ? solutions : non_sltns
44
- length (c) < sl && push! (c, config)
130
+ update_exploration! (explorer, f, config)
45
131
end
46
- return solutions, non_sltns
132
+ return nothing
47
133
end
48
134
49
- function _explore (domains, f, :: ExploreSettings , :: Val{:complete} )
50
- solutions = Set {Vector{Int}} ()
51
- non_sltns = Set {Vector{Int}} ()
52
-
53
- configurations = Base. Iterators. product (map (d -> get_domain (d), domains)... )
54
- foreach (
55
- c -> (cv = collect (c); push! (f (cv) ? solutions : non_sltns, cv)),
56
- configurations,
57
- )
58
- return solutions, non_sltns
135
+ function _explore! (explorer, f, :: Val{:complete} )
136
+ C = Base. Iterators. product (map (d -> get_domain (d), explorer. domains |> values)... )
137
+ foreach (c -> update_exploration! (explorer, f, c, :complete ), C)
138
+ return nothing
59
139
end
60
140
61
- function _explore (domains, f, s, :: Val{:flexible} )
62
- search = s. max_samplings < s. complete_search_limit ? :complete : :partial
63
- return _explore (domains, f, s, Val (search))
141
+ function explore! (explorer:: Explorer )
142
+ c =
143
+ x -> all ([
144
+ f (isempty (vars) ? x : @view x[vars]) for
145
+ (f, vars) in explorer. concepts |> values
146
+ ])
147
+ s = explorer. settings
148
+ search = s. search
149
+ if search == :flexible
150
+ search = s. max_samplings < s. complete_search_limit ? :complete : :partial
151
+ end
152
+ return _explore! (explorer, c, Val (search))
64
153
end
65
154
66
155
"""
@@ -78,7 +167,9 @@ Beware that if the density of the solutions in the search space is low, `solutio
78
167
"""
79
168
function explore (domains, concept; settings = ExploreSettings (domains), parameters... )
80
169
f = x -> concept (x; parameters... )
81
- return _explore (domains, f, settings, Val (settings. search))
170
+ explorer = Explorer ([(f, Vector {Int} ())], domains; settings)
171
+ explore! (explorer)
172
+ return explorer. state. solutions, explorer. state. non_solutions
82
173
end
83
174
84
175
# # SECTION - Test Items
87
178
X, X̅ = explore (domains, allunique)
88
179
@test length (X) == factorial (4 )
89
180
@test length (X̅) == 4 ^ 4 - factorial (4 )
181
+
182
+ explorer = ConstraintDomains. Explorer ()
90
183
end
0 commit comments