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 you wrote a book on how
> CLP(FD) /works./ Even one which expresses propagation in plain
> Prolog with explicit constraint stores rather than attributed
> variables. I think this would benefit us and your students
> tremendously.
Markus did that. Just read his PhD thesis. It is a great document for
understanding (his) clpfd implementation as well as understanding how to
properly engineer non-trivial systems using Prolog. It explains how to
use pure code and retain efficiency, how to exploit code generation and
how to integrate testing (Markus, please extend if I forgot something
important). His clpfd implementation is a great engineering work and
indeed a valuable resource.
--
You received this message because you are subscribed to the Google Groups "SWI-Prolog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swi-prolog+...@googlegroups.com.
?- expr([7,13,2,6],E), 71 is E.
E = 6+13* (7-2) ;
E = 6+13* (7-2) ;
ERROR: //2: Arithmetic: evaluation error: `zero_divisor'
and after a few solutions, evaluated invalid expressions.
Using constraint propagation like:
?- expr([7,13,2,6],E), 71 #= E.
just detected the invalid expressions automatically. So even without
labeling, clp(fd) was pretty useful to me.
Domain error: `clpfd_expression' expected, found `2/6'
You're quite right, Jan! I assumed it would be very advanced, being a PhD thesis, but looking at it for the first time now, I see that it's a highly accessible introduction to CLP(FD). Thank you, Markus!
--
You received this message because you are subscribed to the Google Groups "SWI-Prolog" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swi-prolog+...@googlegroups.com.
On Wednesday, August 26, 2015 at 6:15:44 AM UTC+1, Michael BEN YOSEF wrote:I would say that the typical teaching order "declarative semantics->examples->operational semantics" is at fault here.I think you hit the nail in the head...
You are right. I guess that makes the naive translation invalid, assuming
that the puzzle is about exact division.
Hi Jan,h
On Friday, August 28, 2015 at 9:48:16 PM UTC+1, Stefan Kral wrote:
Hi Michael. Hi to everybody else, too!
I feel the same
I feel the same, so I really want to chime in on praising Markus' work---both his work on clp(FD) / clp(B) and equally, if not even more so, on his Ph.D. thesis!