|
1 | | -use ProblemSolver::State; |
2 | 1 | unit class ProblemSolver; |
3 | 2 |
|
4 | | -has Bool $.stop-on-first-solution = False; |
5 | | -has Bool $!found-solution = False; |
6 | | -has Array of Callable %!constraints{Signature}; |
7 | | -has $!variables handles <add-variable> = ProblemSolver::State.new; |
8 | | -#has ProblemSolver::State $!variables handles <add-variable> .= new; |
9 | | -has &.print-found is rw; |
10 | | -has Array of Callable %!heuristics; |
| 3 | +has %.variables; |
| 4 | +has Bag $.vars .= new; |
| 5 | +has %.constraints{Set}; |
| 6 | +has %.heuristics{Str}; |
| 7 | +has %.found; |
11 | 8 |
|
12 | | -method add-constraint(&const) { |
13 | | - %!constraints{&const.signature}.push: &const |
| 9 | +multi method create-variable(Str $name where { not %!variables{$_}:exists }, Bag() \values) { |
| 10 | + $!vars = |$!vars (+) Pair.new: $name, 1; |
| 11 | + %!variables = |%!variables, $name => values; |
14 | 12 | } |
15 | 13 |
|
16 | | -method add-heuristic($var, &heu) { |
17 | | - %!heuristics{$var}.push: &heu |
| 14 | +multi method create-variable(Bag $names where { %!variables{$_.none}:exists }, Bag() \values) { |
| 15 | + $!vars = $!vars (+) $names; |
| 16 | + %!variables = |%!variables, |do for $names.keys -> $name { $name => values } |
18 | 17 | } |
19 | 18 |
|
20 | | -method solve { |
21 | | - for $!variables.found-vars -> $key { |
22 | | - self!remove-values($!variables, :variable($key), :value($!variables.get($key))) if %!heuristics{$key}:exists; |
23 | | - } |
24 | | - self!solve-all($!variables) |
25 | | -} |
26 | | - |
27 | | -method !solve-all($todo) { |
28 | | - do if $todo.found-everything { |
29 | | - my %tmp = $todo.found-hash; |
30 | | - do if self!run-constraints(%tmp, :debug) { |
31 | | - $!found-solution = True; |
32 | | - %tmp |
33 | | - } |
34 | | - } else { |
35 | | - my @resp; |
36 | | - my $key = $todo.next-var; |
37 | | - for $todo.iterate-over($key) -> $new { |
38 | | - next unless self!run-constraints($new.found-hash) or $new.has-empty-vars; |
39 | | - self!remove-values($new, :variable($key), :value($new.get($key))) if %!heuristics{$key}:exists; |
40 | | - &!print-found($new.found-hash) if &!print-found; |
41 | | - @resp.push: self!solve-all($new); |
42 | | - last if $!stop-on-first-solution and $!found-solution |
43 | | - } |
44 | | - |@resp |
45 | | - } |
| 19 | +method add-constraint(Set() \vars where {%!variables{vars.keys.all}:exists}, &constraint) { |
| 20 | + %!constraints{vars}.push: &constraint |
46 | 21 | } |
47 | 22 |
|
48 | | -method !remove-values($todo, Str :$variable, :$value) { |
49 | | - if %!heuristics{$variable}:exists { |
50 | | - for @( %!heuristics{$variable} ) -> &func { |
51 | | - func($todo, $value) |
52 | | - } |
53 | | - } |
| 23 | +method add-heuristic(Set() \vars where {%!variables{vars.keys.all}:exists}, &heuristic) { |
| 24 | + %!heuristics{$_}.push: &heuristic for vars.keys |
54 | 25 | } |
55 | 26 |
|
56 | | -method !run-constraints(%values, :$debug) { |
57 | | - my @cons = self!get-constraints-for-vars(%values); |
58 | | - for @cons -> &func { |
59 | | - return False if not func(|%values) |
60 | | - } |
61 | | - True |
| 27 | +multi method remove-possibility(Str \name where {%!variables{name}:exists}, \value) { |
| 28 | + %!variables{name} = %!variables{name} (-) bag(value xx %!variables{name}{value}); |
| 29 | + fail if %!variables{name}.elems == 0; |
| 30 | + %!variables{name} = %!variables{name}.keys[0] if %!variables{name}.elems == 1; |
62 | 31 | } |
63 | 32 |
|
64 | | -method !get-constraints-for-vars(%vars) { |
65 | | - my @keys = %!constraints.keys.grep: -> \sig { %vars ~~ sig } |
66 | | - |%!constraints{@keys}.map: |* |
| 33 | +method variable-bag { |
| 34 | + %!variables.keys.map(-> Str \var { |
| 35 | + slip var xx (($!vars{var} * %!constraints.pairs.grep(var ∈ *.key).map(*.value.elems).sum) || 1) |
| 36 | + }).Bag |
67 | 37 | } |
68 | 38 |
|
69 | | -method constraint-vars(&red, @vars) { |
70 | | - my $pars = &red.signature.params.elems; |
71 | | - my @comb = @vars.combinations($pars); |
72 | | - for @comb -> @pars { |
73 | | - my $sig = @pars.map({":\${$_}!"}).join(", "); |
74 | | - my $cal = @pars.map({"\${$_}"}).join(", "); |
75 | | - use MONKEY-SEE-NO-EVAL; |
76 | | - my &func = EVAL "-> $sig, | \{ red($cal)\}"; |
77 | | - no MONKEY-SEE-NO-EVAL; |
78 | | - $.add-constraint(&func) |
79 | | - } |
80 | | - for @vars -> $var { |
81 | | - my @v = @vars.grep(* !eq $var); |
82 | | - $.add-heuristic($var, -> $todo, $value { |
83 | | - for @v (&) $todo.not-found-vars -> $var { |
84 | | - $todo.find-and-remove-from: $var.key, -> $v { not red($v, $value) } |
85 | | - } |
86 | | - }) |
87 | | - } |
| 39 | +method variable-order { |
| 40 | + |$.variable-bag.pairs.sort({-.value}).map: {.key} |
88 | 41 | } |
89 | 42 |
|
90 | | -method unique-vars(@vars) { |
91 | | - my @comb = @vars.combinations(2); |
92 | | - for @comb -> @pars { |
93 | | - my $sig = @pars.map({":\${$_}!"}).join(", "); |
94 | | - my $cal = @pars.map({"\${$_}"}).join(", "); |
95 | | - use MONKEY-SEE-NO-EVAL; |
96 | | - my &func = EVAL "-> $sig, | \{ [!~~] $cal \}"; |
97 | | - no MONKEY-SEE-NO-EVAL; |
98 | | - $.add-constraint(&func) |
99 | | - } |
100 | | - for @vars -> $var { |
101 | | - my @v = @vars.grep(* !eq $var); |
102 | | - $.add-heuristic($var, -> $todo, $value { |
103 | | - for @v (&) $todo.not-found-vars -> $var { |
104 | | - $todo.remove-from: $var.key, $value |
105 | | - } |
106 | | - }) |
107 | | - } |
108 | | -} |
109 | | - |
110 | | -method no-order-vars(+@vars) { |
111 | | - for @vars -> $var { |
112 | | - my @v = @vars.grep(* !eq $var); |
113 | | - $.add-heuristic($var, -> $todo, $value { |
114 | | - $todo.recursive-remove-from-vars: @v, $value |
115 | | - }) |
116 | | - } |
| 43 | +method solve { |
| 44 | + # TODO: Run constraints |
| 45 | + # TODO: Run heuristics |
| 46 | + for $.variable-order -> $var { |
| 47 | + for |%!variables{$var}.pairs.sort(-*.value).map: *.key -> $value { |
| 48 | + my %variables = |%!variables, $var => $value; |
| 49 | + my $clone = self.clone: :variables(%variables), :vars($!vars (-) bag($var xx $!vars{$var})); |
| 50 | + note $clone |
| 51 | + } |
| 52 | + } |
117 | 53 | } |
118 | | - |
0 commit comments