You can't really expect clp(fd) to outperform your simple loop :)
Constraint programming is typically about specifying a search space
On Friday, August 21, 2015 at 11:06:47 PM UTC+1, Markus Triska wrote:
In the CLP(FD) version, you get this for example with:labeling([min(Sum)], Counts)Notice that just using [min] only affects the variable selection strategy during labeling, and is not directly related to any optimisation.
Eyal? :)
On Friday, August 21, 2015 at 11:06:47 PM UTC+1, Markus Triska wrote:
---/begin-message/----------------You can use [the "pure"] version in *all* directions
1 ?- [user].
ct(Ratings, Counts, Sum) :-
candies(Ratings, Counts, Sum),
Ratings ins 1 .. 2,
Counts ins 1 .. 10.
ctw(Ratings, Counts, Sum) :-
ct(Ratings, Counts, Sum),
append(Ratings, Counts, Vars),
labeling([min(Sum)], Vars),
format('~w -> ~w (~w)~n', [Ratings, Counts, Sum]).
true.
2 ?- set_prolog_flag(toplevel_print_anon, false).
true.
3 ?- Rs=[1,2,2], Cs=[1,2,1], CsX=[1,2,2], S=4, SX=5.
Rs = CsX, CsX = [1, 2, 2],
Cs = [1, 2, 1],
S = 4,
SX = 5.
4 ?- ctw($Rs, $Cs, $S).
[1,2,2] [1,2,1] (4)
true ;
false.
5 ?- ctw($Rs, $Cs, $SX).
false.
6 ?- ctw($Rs, $CsX, $S).
false.
7 ?- ctw($Rs, $CsX, $SX).
[1,2,2] [1,2,2] (5)
true ;
false.
8 ?- ctw($Rs, $Cs, _S).
[1,2,2] [1,2,1] (4)
true ;
false.
9 ?- ctw($Rs, $CsX, _S).
[1,2,2] [1,2,2] (5)
true ;
false.
10 ?- ctw($Rs, _Cs, $S).
[1,2,2] [1,2,1] (4)
true ;
false.
11 ?- ctw($Rs, _Cs, $SX).
[1,2,2] -> [1,2,2] (5)
true ;
[1,2,2] -> [1,3,1] (5)
true ;
false.
12 ?- ctw(_Rs, $Cs, $S).
[1,1,1] -> [1,2,1] (4)
true ;
[1,2,1] -> [1,2,1] (4)
true ;
[1,2,2] -> [1,2,1] (4)
true ;
[2,2,1] -> [1,2,1] (4)
true ;
[2,2,2] -> [1,2,1] (4)
true ;
false.
13 ?- ctw(_Rs, $Cs, $SX).
false.
14 ?- ctw(_Rs, $CsX, $S).
false.
15 ?- ctw(_Rs, $CsX, $SX).
[1,1,1] -> [1,2,2] (5)
true ;
[1,2,2] -> [1,2,2] (5)
true ;
[2,2,2] -> [1,2,2] (5)
true ;
false.
16 ?- ctw($Rs, _Cs, _S).
[1,2,2] -> [1,2,1] (4)
true ;
[1,2,2] -> [1,2,2] (5)
true ;
[1,2,2] -> [1,3,1] (5)
true ;
[1,2,2] -> [1,2,3] (6)
// ...
[1,2,2] -> [9,10,10] (29)
true ;
false.
17 ?- ctw(_Rs, _Cs, $S).
[1] -> [4] (4)
true ;
[2] -> [4] (4)
true ;
[1,1] -> [1,3] (4)
true ;
[1,1] -> [2,2] (4)
true ;
// ...
[1,1,1,1] -> [1,1,1,1] (4)
true ;
[2,2,2,2] -> [1,1,1,1] (4)
true ;
Action (h for help) ? abort
% Execution Aborted
18 ?- ctw(_Rs, $Cs, _S).
[1,1,1] -> [1,2,1] (4)
true ;
[1,2,1] -> [1,2,1] (4)
true ;
[1,2,2] -> [1,2,1] (4)
true ;
[2,2,1] -> [1,2,1] (4)
true ;
[2,2,2] -> [1,2,1] (4)
true ;
false.
19 ?- ctw(_Rs, _Cs, _S).
[] -> [] (0)
true ;
[1] -> [1] (1)
true ;
[2] -> [1] (1)
true ;
[1] -> [2] (2)
true ;
// ...
[1] -> [10] (10)
true ;
[2] -> [10] (10)
true ;
[1,1] -> [1,1] (2)
true ;
[2,2] -> [1,1] (2)
true ;
[1,1] -> [1,2] (3)
true ;
// ...
All solutions that are not minimal are *invalid*.
[Subject changed from "Performances of CLP(FD)" to "Using CLP(FD)".]
On Sunday, August 23, 2015 at 9:46:13 AM UTC+1, Julio Di Egidio wrote:On Friday, August 21, 2015 at 11:06:47 PM UTC+1, Markus Triska wrote:---/begin-message/----------------You can use [the "pure"] version in *all* directions
The program as is goes short of solving the given problem (it does not pass most tests).
<snip>
[W]ould you be able to fix/complete the code so that it satisfies all requirements?
By all requirements I mean:1) Solutions satisfy the problem statement (*);2) (Optional) Implements a true relationship (all invocation patterns work).(*)- Minimise the number of candies the teacher needs,
subject to the constraints that:
- Every child gets at least 1 candy; and,
- For any two adjacent children, if one's rating is higher than the
other's, s/he must get more candies than the other.
cc_max(r, 10_000).
cc_max(c, 10_000).
cc_3_t(Rs, Cs, S) :-
cc_3(Rs, Cs, S, [2, 3]),
format('~w => ~w (~w)', [Rs, Cs, S]).
cc_3(Rs, Cs, S) :-
cc_max(r, R_max),
cc_max(c, C_max),
cc_3(Rs, Cs, S, [R_max, C_max]).
cc_3(Rs, Cs, S, [R_max, C_max]) :-
cc_3__con(Rs, Cs, S, [Cs_r, S_r], [R_max, C_max]),
cc_3__sol(Rs, Cs, S, [Cs_r, S_r]).
cc_3__con(Rs, Cs, S, [Cs_r, S_r], [R_max, C_max]) :-
cc_3__set(Rs, Cs, S),
cc_3__dom(Rs, Cs_r, S_r, [R_max, C_max]),
cc_3__rel(Rs, Cs_r, S_r).
cc_3__sol(Rs, Cs, S, [Cs_r, S_r]) :-
labeling([], Rs),
once(labeling([min(S_r)], [S_r])),
S = S_r,
labeling([], Cs_r),
Cs = Cs_r.
cc_3__set(Rs, Cs, S) :-
same_length(Rs, Cs),
( var(S) -> true
; length(Rs, L),
( S < L -> !, fail
; S > (L+1)*L/2 -> fail
; true
)
).
cc_3__dom(Rs, Cs, _, [R_max, C_max]) :-
same_length(Rs, Cs),
Rs ins 0 .. R_max,
Cs ins 1 .. C_max.
cc_3__rel([], [], 0).
cc_3__rel([R| Rs], [C| Cs], S) :-
sum([C| Cs], #=, S),
cc_3__rel__i(Rs, Cs, R, C).
cc_3__rel__i([], [], _, _).
cc_3__rel__i([R| Rs], [C| Cs], R0, C0) :-
R0 #< R #==> C0 #< C, R0 #> R #==> C0 #> C,
cc_3__rel__i(Rs, Cs, R, C).
/*?- set_prolog_flag(toplevel_print_anon, false).
true.
?- Rs=[1,2,2], Cs=[1,2,1], CsX=[1,2,2], S=4, SX=5.
Rs = CsX, CsX = [1, 2, 2],
Cs = [1, 2, 1],
S = 4,
SX = 5.
?- cc_3_t($Rs, $Cs, $S).
[1,2,2] => [1,2,1] (4)
true.
?- cc_3_t($Rs, $Cs, $SX).
false.
?- cc_3_t($Rs, $CsX, $S).
false.
?- cc_3_t($Rs, $CsX, $SX).
false.
?- cc_3_t($Rs, $Cs, _S).
[1,2,2] => [1,2,1] (4)
true.
?- cc_3_t($Rs, $CsX, _S).
false.
?- cc_3_t($Rs, _Cs, $S).
[1,2,2] [1,2,1] (4)
true.
?- cc_3_t($Rs, _Cs, $SX).
false.
?- cc_3_t(_Rs, $Cs, $S).
[0,1,0] => [1,2,1] (4)
true ;
[0,1,1] => [1,2,1] (4)
true ;
[0,2,0] => [1,2,1] (4)
true ;
// ...
[1,2,2] => [1,2,1] (4)
true ;
[2,2,0] => [1,2,1] (4)
true ;
[2,2,1] => [1,2,1] (4)
true ;
false.
?- cc_3_t(_Rs, $Cs, $SX).
false.
?- cc_3_t(_Rs, $CsX, $S).
false.
?- cc_3_t(_Rs, $CsX, $SX).
false.
?- cc_3_t($Rs, _Cs, _S).
[1,2,2] => [1,2,1] (4)
true.
?- cc_3_t(_Rs, _Cs, $S).
[0,0,1] => [1,1,2] (4)
true ;
[0,0,2] => [1,1,2] (4)
true ;
[0,1,0] => [1,2,1] (4)
true ;
// ...
[2,2,1] => [1,2,1] (4)
true ;
[0,0,0,0] => [1,1,1,1] (4)
true ;
[1,1,1,1] => [1,1,1,1] (4)
true ;
[2,2,2,2] => [1,1,1,1] (4)
true ;
false.
?- cc_3_t(_Rs, $Cs, _S).
[0,1,0] => [1,2,1] (4)
true ;
[0,1,1] => [1,2,1] (4)
true ;
[0,2,0] => [1,2,1] (4)
true ;
// ...
[1,2,2] => [1,2,1] (4)
true ;
[2,2,0] => [1,2,1] (4)
true ;
[2,2,1] => [1,2,1] (4)
true ;
false.
?- cc_3_t(_Rs, $CsX, _S).
false.
?- cc_3_t(_Rs, _Cs, _S).
[] => [] (0)
true ;
[0] => [1] (1)
true ;
[1] => [1] (1)
true ;
[2] => [1] (1)
true ;
[0,0] => [1,1] (2)
true ;
[0,1] => [1,2] (3)
true ;
// ...
*/
On Sunday, August 23, 2015 at 10:41:57 PM UTC+1, Markus Triska wrote:
On Sunday, August 23, 2015 at 2:19:24 PM UTC+1, Julio Di Egidio wrote:
On 08/25/2015 03:21 PM, Julio Di Egidio wrote:
<snip>
> The original intent was that of comparing style and performances
> between a plain Prolog solution and a solution based on CLP(FD).
> Ensuing discussion noted that a clp-based solution can be meaningfully
> compared to a plain Prolog solution only when the problem involves
> browsing a search space.
I wouldn't say that. Markus claims that clp(fd) is a meaningful
replacement for (integer) arithmetic.
Markus claims that clp(fd) is a meaningful replacement for (integer) arithmetic.
This justifies comparing A is B+C with A #= B+C using instantiated B and C.
Code portability.
https://twitter.com/LogtalkDotOrg/status/605670287410102272
Most Prolog courses teach students to play with sand at the beach, while the ocean is in front of them, invisible to them. It is time to delve into the ocean: All libraries improve when they are being used. Support for them in other systems will inevitably improve too, as soon as there is sufficient user demand.
In the context of SWI, which is already incompatible with other systems in much more fundamental ways than just supporting a few predicates like (#>)/2 in more general ways (unbounded integers), the choice is clear.
I'm following and I'm enthusiastic about your improvements to the CLP(FD) library (thanks!) and I hope one day it would be universal enough (across Prolog systems) for me to consider using it on a regular basis. By universal, I mean not only available but also providing the same feature set. But currently, for writing portable code, is simply not an option. For users that don't care about portability, I would say, go for it!
Btw: where are the standard proposals for attributed variables and constraint systems?
This raises the question: Why bother using (is)/2 at all for integer arithmetic? (is)/2 sure was fashionable in the 70s and 80s, but is it not time that we begin to use and teach more powerful and more declarative language elements that have since become available?
How many more "why does Prolog say 'uninstantiation error' with arithmetic?" questions do we want to see on stackoverflow.com? How many "I desperately need the functionality of constraints, but I want to avoid using constraints at all costs" types of questions? I think the time is near to end this nonsense by pointing users to more general solutions, which were not available or not as easily accessible in the past.
I would say that the typical teaching order "declarative semantics->examples->operational semantics" is at fault here.
You just can't handle having your candy taken away.
> Personally, I would be immensely grateful if yo