This repository was archived by the owner on Aug 9, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.pl
More file actions
197 lines (176 loc) · 7.25 KB
/
search.pl
File metadata and controls
197 lines (176 loc) · 7.25 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
:- module(search, [
func_path/4,
func_path_init/4,
func_path_no_cycles/4,
find_item/3,
find_items/2,
func_search/7,
fn_member_constraint/1
]).
:- use_module(function).
:- use_module(constraints, [
and_constraint/5,
at_most_n_constraint/5,
no_constraint/3,
no_constraints_left/1,
cycle_constraint/5
]).
:- use_module(func_constraints, [input_constraint/4, output_constraint/4, fn_member_constraint/1]).
:- use_module(string_constraints, [add_string_constraint/5]).
:- use_module(path_constraints).
:- meta_predicate find_item(3, ?, -).
:- meta_predicate find_items(3, ?).
:- meta_predicate func_path_init(+, 3, 2, ?).
%% TODO: Type and trait search as well
%% -> eg. what types have this documentation or implement these traits
%% TODO: Allow not specifying input / output types (eg. what functions take this xor return this)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Function level search
%% find_item(+Constraints, ?Item -Score)
% Finds an Item satisfying the constraints, unifying the cost with Cost
find_item(Constraint, Item, Cost) :-
call(Constraint, Item, Cost, NewConstraint),
no_constraints_left(NewConstraint).
second((_, B), B).
%% find_item(+Constraints, ?Items -Score)
%% Finds all items satisfying the constraints, and orders them from
% lowest to highest cost.
find_items(Constraint, Items) :-
%% setof also sorts - very intuitive and obvious from the name.
setof(
(Score, Item),
find_item(Constraint, Item, Score),
ItemPairs
),
maplist(second, ItemPairs, Items).
%% Finds all functions with the constraints.
func_search(FuncName, Inputs, Outputs, Docs, NameCmp, DocCmp, Fns) :-
fn_member_constraint(C0),
add_string_constraint(func_field(name), FuncName, NameCmp, C0, C1),
add_string_constraint(func_field(docs), Docs, DocCmp, C1, C2),
find_items(
and_constraint(
C2,
and_constraint(
input_constraint(Inputs),
output_constraint(Outputs)
)
),
Fns
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Path search implementations
%% func_path_dfs(+Visited:list, +FnConstraint, +PathConstraint, -Path:list)
% Path is a sequence of functions, which satisfy FuncConstraints
% and its continuations, and in aggregate, satisfy PathConstraint.
test_path(Visited, FnConstraint, PathConstraint, Path) :-
call(PathConstraint, Visited, none),
no_constraints_left(FnConstraint),
reverse(Visited, Path).
func_path_dfs(Visited, FnConstraint, PathConstraint, Path) :-
test_path(Visited, FnConstraint, PathConstraint, Path).
func_path_dfs(Visited, FnConstraint, PathConstraint, Path) :-
call(FnConstraint, StartFn, _, NewConstraint),
call(PathConstraint, Visited, StartFn),
func_path_dfs([StartFn|Visited], NewConstraint, PathConstraint, Path).
%% Unifies Path with the next shortest path that transforms InputTypes into OutputTypes
%% Helper function for initializing breadth-first search.
% Return suitable candidate
func_path_bfs([(FnConstraint, Visited)|_], PathConstraint, Path) :-
% If no constraints left, add path to paths
test_path(Visited, FnConstraint, PathConstraint, Path).
%% Adds all paths which can be reached from the current candidate to the queue,
% and continues bfs iteration.
func_path_bfs([(FnConstraint, Path)|Candidates], PathConstraint, NextPath) :-
% Add all new paths
findall((NewConstraint, [StartFn|Path]),
(
call(FnConstraint, StartFn, _, NewConstraint),
call(PathConstraint, Path, StartFn)
),
NewPaths
),
%% No need to turn these into sets, always unique.
append(Candidates, NewPaths, NewCand),
func_path_bfs(NewCand, PathConstraint, NextPath).
%% cmp_constraint_list(?Order, @L1, @L2)
% Determine Cmp between L1 and L2 cost/constraint/list triples.
cmp_candidate(Cmp, (CostA, _, _), (CostB, _, _)) :-
compare(Cmp, CostA, CostB).
cmp_or_continue(=, Cmp, L1, L2) :-
compare(Cmp, L1, L2).
cmp_or_continue(>, >, _, _).
cmp_or_continue(<, <, _, _).
func_path_best_fs([(_, FnConstraint, Visited)|_], PathConstraint, Path) :-
% If no constraints left, add path to paths
test_path(Visited, FnConstraint, PathConstraint, Path).
% NOTE: additive score does not work with best-first search
% Cost: # of constraints unsat, weighed by importance of constraint,
% + path length.
% Should increase w/ addition (so path length)
%% Adds all paths which can be reached from the current candidate to the queue,
% and continues bfs iteration.
func_path_best_fs([(OldCost, FnConstraint, Path)|Candidates], PathConstraint, NextPath) :-
findall((Cost, NewConstraint, [StartFn|Path]),
(
call(FnConstraint, StartFn, FuncCost, NewConstraint),
call(PathConstraint, Path, StartFn),
Cost is FuncCost + OldCost + 1.0
),
NewPaths
),
%% No need to turn these into sets, always unique.
append(Candidates, NewPaths, NewCand),
%% Sort by scores - this will not remove duplicate scores, and will maintain order.
sort(1, @=<, NewCand, SortedCand),
func_path_best_fs(SortedCand, PathConstraint, NextPath).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Exported Path Search
% Easy to use functions for initializing a search with a particular set of parameters.
%% func_path(Strategy, InputTypeList, OutputTypeList, Path:list)
% Path is a sequence of functions, which when applied in sequence,
% accept InputTypeList and produce OutputTypeList.
% try funcPath(["str"], ["None"], Path). (use ; to get more than one path)
func_path(Strategy, InputTypes, OutputTypes, Path) :-
fn_member_constraint(AllFuncs),
func_path_init(
Strategy,
and_constraint(
AllFuncs,
and_constraint(
at_most_n_constraint(999, no_constraint),
input_constraint(InputTypes)
)
),
output_constraint(OutputTypes),
Path
).
%% func_path_init(+Strategy, +FnConstraints, +PathConstraint, -Path:list)
% Unifies the next valid path, using the given strategy, to Path.
func_path_init(dfs, FnConstraint, PathConstraint, Path) :-
func_path_dfs([], FnConstraint, PathConstraint, Path).
func_path_init(bfs, FnConstraint, PathConstraint, Path) :-
func_path_bfs([(FnConstraint, [])], PathConstraint, Path).
func_path_init(bestfs, FnConstraint, PathConstraint, Path) :-
func_path_best_fs([(0.0, FnConstraint, [])], PathConstraint, Path).
%% func_path_no_cycles(+Strategy, ?InputTypeList, ?OutputTypeList, ?Path)
% Path is a sequence of functions, which when applied in sequence,
% accept InputTypeList and produce OutputTypeList. Additionally,
% Path does not contain any cycles.
func_path_no_cycles(Strategy, InputTypes, OutputTypes, Path) :-
fn_member_constraint(AllFuncs),
func_path_init(
Strategy,
and_constraint(
AllFuncs,
and_constraint(
input_constraint(InputTypes),
and_constraint(
cycle_constraint(function:uuid, []),
at_most_n_constraint(999, no_constraint)
)
)
),
output_constraint(OutputTypes),
Path
).