I'm trying to initialize the list [ 0.0, 0.17, 0.33, 0.5, 0.67, 0.83, 1] with the following code:
#!/usr/bin/swipl
floorsMax( 6 ).
floorLocations( _, 0, TmpLocs, Locs ) :-
Locs is [0.0 | TmpLocs ].
floorLocations( FloorsMax, FloorsCount, TmpLocs, Locs ) :-
Loc is FloorsCount / FloorsMax,
Count is FloorsCount - 1,
floorLocations( FloorsMax, Count, [Loc|TmpLocs], Locs ).
floorLocations( Locs ) :-
floorsMax( FloorsMax ),
trace,
floorLocations( FloorsMax, FloorsMax, [], Locs ).
The executions steps are:
?- floorLocations(Fl).
Call: (11) floorLocations(6, 6, [], _2732) ? creep
Call: (12) _3158 is 6/6 ? creep
Exit: (12) 1 is 6/6 ? creep
Call: (12) _3264 is 6+ -1 ? creep
Exit: (12) 5 is 6+ -1 ? creep
Call: (12) floorLocations(6, 5, [1], _2732) ? creep
Call: (13) _3410 is 5/6 ? creep
Exit: (13) 0.8333333333333334 is 5/6 ? creep
Call: (13) _3522 is 5+ -1 ? creep
Exit: (13) 4 is 5+ -1 ? creep
Call: (13) floorLocations(6, 4, [0.8333333333333334, 1], _2732) ? creep
Call: (14) _3668 is 4/6 ? creep
Exit: (14) 0.6666666666666666 is 4/6 ? creep
Call: (14) _3780 is 4+ -1 ? creep
Exit: (14) 3 is 4+ -1 ? creep
Call: (14) floorLocations(6, 3, [0.6666666666666666, 0.8333333333333334, 1], _2732) ? creep
Call: (15) _3926 is 3/6 ? creep
Exit: (15) 0.5 is 3/6 ? creep
Call: (15) _4038 is 3+ -1 ? creep
Exit: (15) 2 is 3+ -1 ? creep
Call: (15) floorLocations(6, 2, [0.5, 0.6666666666666666, 0.8333333333333334, 1], _2732) ? creep
Call: (16) _4184 is 2/6 ? creep
Exit: (16) 0.3333333333333333 is 2/6 ? creep
Call: (16) _4296 is 2+ -1 ? creep
Exit: (16) 1 is 2+ -1 ? creep
Call: (16) floorLocations(6, 1, [0.3333333333333333, 0.5, 0.6666666666666666, 0.8333333333333334, 1], _2732) ? creep
Call: (17) _4442 is 1/6 ? creep
Exit: (17) 0.16666666666666666 is 1/6 ? creep
Call: (17) _4554 is 1+ -1 ? creep
Exit: (17) 0 is 1+ -1 ? creep
Call: (17) floorLocations(6, 0, [0.16666666666666666, 0.3333333333333333, 0.5, 0.6666666666666666, 0.8333333333333334, 1], _2732) ? creep
Call: (18) _2732 is [0.0, 0.16666666666666666, 0.3333333333333333, 0.5, 0.6666666666666666, 0.8333333333333334, 1] ? creep
ERROR: Type error: `character' expected, found `0.0' (a float)
ERROR: In:
ERROR: [18] _214 is [0.0,0.16666666666666666|...]
ERROR: [17] floorLocations(6,0,[0.16666666666666666,0.3333333333333333|...],_258) at /home/aubin/Dev/IA/prolog-Ascenseur/Stimulus.pl:7
ERROR: [16] floorLocations(6,1,[0.3333333333333333,0.5|...],_300) at /home/aubin/Dev/IA/prolog-Ascenseur/Stimulus.pl:11
ERROR: [15] floorLocations(6,2,[0.5,0.6666666666666666|...],_342) at /home/aubin/Dev/IA/prolog-Ascenseur/Stimulus.pl:11
ERROR: [14] floorLocations(6,3,[0.6666666666666666,0.8333333333333334|...],_384) at /home/aubin/Dev/IA/prolog-Ascenseur/Stimulus.pl:11
ERROR: [13] floorLocations(6,4,[0.8333333333333334,1],_426) at /home/aubin/Dev/IA/prolog-Ascenseur/Stimulus.pl:11
ERROR: [12] floorLocations(6,5,[1],_468) at /home/aubin/Dev/IA/prolog-Ascenseur/Stimulus.pl:11
ERROR: [11] floorLocations(6,6,[],_504) at /home/aubin/Dev/IA/prolog-Ascenseur/Stimulus.pl:11
ERROR: [10] floorLocations(_528) at /home/aubin/Dev/IA/prolog-Ascenseur/Stimulus.pl:15
ERROR: [9] toplevel_call(user:user: ...) at /usr/lib/swi-prolog/boot/toplevel.pl:1113
Exception...
The trace is good, the intermediate result is as expected but the final assignment doesn't work, why?
EDIT after reading the good advices by damianodamiano, here is a solution (with a cut, sorry for the purists):
floorLocations( _, 0, TmpLocs, [0.0 | TmpLocs ] ) :- !.
floorLocations( FloorsMax, FloorsCount, TmpLocs, Locs ) :-
FloorsCount > 0,
Loc is FloorsCount / FloorsMax,
Count is FloorsCount - 1,
floorLocations( FloorsMax, Count, [Loc|TmpLocs], Locs ).
floorLocations( Locs ) :-
floorsMax( FloorsMax ),
floorLocations( FloorsMax, FloorsMax, [], Locs ).
This happens because is/2
is used to evaluate mathematical expressions, but [0.0 | TmpLocs ]
is not a mathematical expression. To fix your code, you need to write something like:
floorLocations( _, 0, TmpLocs, [0.0 | TmpLocs ] ).
instead of
floorLocations( _, 0, TmpLocs, Locs ) :-
Locs is [0.0 | TmpLocs ].
in this way, you will have the whole list. Furthermore, there is a problem with your code. If you ask the first solution, you will get the answer you expect.
Fl = [0.0, 0.16666666666666666, 0.3333333333333333, 0.5, 0.6666666666666666, 0.8333333333333334, 1]
But there is a choice point open and more solutions available. What happens if we ask for a second solution? The program loops forever, and eventually finishes the memory. This because the value of FloorsCount
gets negative and so there is not a termination for the recusion. To fix this, simply add FloorsCount > 0
as first check in the second floorLocations/4
clause.