-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProblem.pm6
More file actions
82 lines (73 loc) · 2.09 KB
/
Copy pathProblem.pm6
File metadata and controls
82 lines (73 loc) · 2.09 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
unit class Problem;
use State;
has Bool $.stop-on-first-solution = False;
has Bool $!found-solution = False;
has Callable @!constraints handles add-constraint => 'push';
has State $!variables handles <add-variable> .= new;
has &.print-found is rw;
has Array of Callable %!heuristics;
method add-heuristic($var, &heu) {
%!heuristics{$var}.push: &heu
}
method solve {
for $!variables.found-vars -> $key {
self!remove-values($!variables, :variable($key), :value($!variables.get($key))) if %!heuristics{$key}:exists;
}
self!solve-all($!variables)
}
method !solve-all($todo) {
if $todo.found-everything {
my %tmp = $todo.Hash;
if self!run-constraints(%tmp) {
$!found-solution = True;
return %tmp
}
return
}
my @resp;
my $key = $todo.next-var;
for $todo.iterate-over($key) -> $new {
next unless self!run-constraints($new.found-hash);
self!remove-values($new, :variable($key), :value($new.get($key))) if %!heuristics{$key}:exists;
&!print-found($new.found-hash) if &!print-found;
@resp.push: self!solve-all($new);
last if $!stop-on-first-solution and $!found-solution
}
|@resp
}
method !remove-values($todo, Str :$variable, :$value) {
if %!heuristics{$variable}:exists {
for @( %!heuristics{$variable} ) -> &func {
func($todo, $value)
}
}
}
method !run-constraints(%values) {
my @cons = self!get-constraints-for-vars(%values);
for @cons -> &func {
return False if not func(|%values)
}
True
}
method !get-constraints-for-vars(%vars) {
@!constraints.grep: -> &func { %vars ~~ &func.signature }
}
method constraint-vars(&red, @vars) {
my $pars = &red.signature.params.elems;
my @comb = @vars.combinations($pars);
for @comb -> @pars {
my $sig = @pars.map({":\${$_}!"}).join(", ");
my $cal = @pars.map({"\${$_}"}).join(", ");
use MONKEY-SEE-NO-EVAL;
my &func = EVAL "-> $sig, | \{ red($cal)\}";
no MONKEY-SEE-NO-EVAL;
$.add-constraint(&func)
}
for @vars -> $var {
$.add-heuristic($var, -> $todo, $value {
for @vars.grep(* !eq $var) (&) $todo.not-found-vars -> $var {
$todo.find-and-remove-from: $var.key, &red.assuming: $value
}
})
}
}