I'm new in Prolog. I found a code that solved water with three jugs with goal = 4, capacity1 = 3, capacity2 = 5 and capacity3 = 8, also the jug with capacity = 8 is filled with water. I decide to remove the jug with capacity 8 and add a fill procedure that can fill jugs with capacity 3 and 5. The problem now is that for some reason the code can't find the solution with goal = 4 and in that case the code call procedure solution(_, _) which is fail.
find_solution :-
initial_state(Initial),
write('== Starting Search =='), nl,
solution([[Initial]], StateList),
length(StateList, Len),
Transitions is Len - 1,
format('~n** FOUND SOLUTION of length ~p **', [Transitions]), nl,
showlist(StateList).
% Remove the cut operator to find more than one solution.
find_solution.
% Base case for finding a solution.
solution(StateLists, StateList) :-
member(StateList, StateLists),
last(StateList, Last),
goal_state(Last),
report_progress(StateLists, final).
% Recursive rule that looks for a solution by extending each of the generated state lists to add a further state.
solution(StateLists, StateList) :-
report_progress(StateLists, ongoing),
extend(StateLists, Extensions),
solution(Extensions, StateList).
solution(_, _) :-
write('!! Cannot extend statelist !!'), nl,
write('!! FAILED: No plan reaches a goal !!'), nl,
fail.
% Extend each statelist in a set of possible state lists.
extend(StateLists, ExtendedStateLists) :-
setof(
ExtendedStateList,
StateList ^ Last ^ Next ^ (
member(StateList, StateLists),
last(StateList, Last),
transition(Last, Next),
legal_state(Next),
no_loop_or_loopcheck_off(Next, StateLists),
append(StateList, [Next], ExtendedStateList)
),
ExtendedStateLists
).
no_loop_or_loopcheck_off(_, _) :- loopcheck(off), !.
no_loop_or_loopcheck_off(Next, StateLists) :-
\+(already_reached(Next, StateLists)).
already_reached(State, StateLists) :-
member(StateList, StateLists),
member(State1, StateList),
equivalent_states(State, State1).
showlist([]).
showlist([H | T]) :- write(H), nl, showlist(T).
report_progress(StateLists, Status) :-
length(StateLists, NS),
StateLists = [L | _],
length(L, N),
Nminus1 is N - 1,
write('Found '), write(NS),
write(' states reachable in path length '), write(Nminus1), nl,
(Status = ongoing ->
(write('Computing extensions of length : '), write(N), nl)
; true
).
%%% Initially jugs a and b are empty,
%%% State representation will be as follows:
%%% A state is a list: [how_reached, Jugstate1, Jugstate2]
%%% Where each JugstateN is a list of the form: [jugname, capcity, content]
initial_state([initial, [a, 3, 0], [b, 5, 0]]).
%% Define goal state to accept any state where one of the
%% jugs contains 4 liters of water:
goal_state([_, [a, _, _], [b, _, 4]]).
goal_state([_, [a, _, 4], [b, _, _]]).
%%% The state transitions are "pour" operations, where the contents of
%%% one jug are poured into another jug up to the limit of the capacity
%%% of the recipient jug.
%%% There are six possible pour actions from one jug to another:
transition([_, A1], [fill_a, A2]) :- fill(A1, A2).
transition([_,B1], [fill_b, B2]) :- fill(B1, B2).
transition([_, A1, B1], [pour_a_to_b, A2, B2]) :- pour(A1, B1, A2, B2).
transition([_, A1, B1], [pour_b_to_a, A2, B2]) :- pour(B1, A1, B2, A2).
fill([Jug1, Capacity1, 0], [Jug1, Capacity1, Initial1]
) :-
Initial1 is Capacity1.
%fill_a :-
% retractall(initial_state(_)),
% assertz(initial_state([initial, [a, 3, 0], [b, 5, 5]])).
%fill_b :-
% retractall(initial_state(_)),
% assertz(initial_state([initial, [a, 3, 3], [b, 5, 0]])).
%%% The pour operation is defined as follows:
% Case where there is room to pour the full contents of Jug1 to Jug2
% so Jug 1 ends up empty, and its contents are added to Jug2.
pour([Jug1, Capacity1, Initial1], [Jug2, Capacity2, Initial2], % initial jug states
[Jug1, Capacity1, 0], [Jug2, Capacity2, Final2] % final jug states
) :-
Initial1 =< (Capacity2 - Initial2),
Final2 is Initial1 + Initial2.
% Case where only some of Jug1 contents fit into Jug2
% Jug2 ends up full, and some water will be left in Jug1.
pour([Jug1, Capacity1, Initial1], [Jug2, Capacity2, Initial2], % initial jug states
[Jug1, Capacity1, Final1], [Jug2, Capacity2, Capacity2] % final jug states
) :-
Initial1 > (Capacity2 - Initial2),
Final1 is Initial1 - (Capacity2 - Initial2).
%% Define the other helper predicates
legal_state(_). % All states that can be reached are legal
equivalent_states(X, X). % Only identical states are equivalent.
loopcheck(on). % Don't allow search to go into a loop.
%% Call this goal to find a solution.
%find_solution.
fill_a and fill_b should also fill the jugs, but with them I also receive the same result which is: == Starting Search == Found 1 states reachable in path length 0 Computing extensions of length : 1 Found 2 states reachable in path length 1 Computing extensions of length : 2 !! Cannot extend statelist !! !! FAILED: No plan reaches a goal !! !! Cannot extend statelist !! !! FAILED: No plan reaches a goal !! true