Include Paulo Moura's Logtalk OO LP system

git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@53 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
vsc
2001-06-06 19:40:57 +00:00
parent 38247e38fc
commit cc4531cd1e
344 changed files with 27125 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.8.4
Copyright (c) 1998-2001 Paulo Moura. All Rights Reserved.
=================================================================
To load all objects in this example consult the searching.loader utility
file (note that the *.loader files are Prolog files).
You will need to also load the objects in the roots example.
You will also need to load the following files in the library directory:
dates.loader, types.loader, events.loader, metapredicates.loader, and
hierarchies.loader.
Some of the code in this folder is adopted from the book "Prolog Programming
for Artificial Intelligence" by Ivan Bratko.
The object "performance" only provides correct results for the first solution.

View File

@@ -0,0 +1,248 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.8.4
Copyright (c) 1998-2001 Paulo Moura. All Rights Reserved.
=================================================================
% farmer, cabbage, goat and wolf problem
| ?- farmer::initial_state(Initial), depth_first(10)::solve(farmer, Initial, Path), farmer::print_path(Path).
cgwf.<__>..........____
c_w_..........<__>.f_g_
c_wf.<__>..........__g_
__w_..........<__>.fcg_
_gwf.<__>.........._c__
_g__..........<__>.fc_w
_g_f.<__>.........._c_w
____..........<__>.fcgw
Path = [(north,north,north,north),(north,south,north,south),(north,south,north,north),(south,south,north,south),(south,north,north,north),(south,north,south,south),(south,north,south,north),(south,south,south,south)],
Initial = (north,north,north,north) ?
yes
% missionaires and cannibals problem, solved using a hill-climbing strategy
| ?- miss_cann::initial_state(Initial), hill_climbing(16)::solve(miss_cann, Initial, Path, Cost), miss_cann::print_path(Path).
MMMCCC.<__>..........
MMCC..........<__>.MC
MMMCC.<__>..........C
MMM..........<__>.CCC
MMMC.<__>..........CC
MC..........<__>.MMCC
MMCC.<__>..........MC
CC..........<__>.MMMC
CCC.<__>..........MMM
C..........<__>.MMMCC
CC.<__>..........MMMC
..........<__>.MMMCCC
Cost = 15,
Path = [((3,3),esq,0,0),((2,2),dir,1,1),((3,2),esq,0,1),((3,0),dir,0,3),((3,1),esq,0,2),((1,1),dir,2,2),((2,2),esq,1,1),((0,2),dir,3,1),((0,3),esq,3,0),((0,1),dir,3,2),((0,2),esq,3,1),((0,0),dir,3,3)],
Initial = ((3,3),esq,0,0)
yes
% same problem as above with the addition of a monitor to measure hill-climbing performance
| ?- performance::init, miss_cann::initial_state(Initial), hill_climbing(16)::solve(miss_cann, Initial, Path, Cost), miss_cann::print_path(Path), performance::report.
MMMCCC.<__>..........
MMCC..........<__>.MC
MMMCC.<__>..........C
MMM..........<__>.CCC
MMMC.<__>..........CC
MC..........<__>.MMCC
MMCC.<__>..........MC
CC..........<__>.MMMC
CCC.<__>..........MMM
C..........<__>.MMMCC
CC.<__>..........MMMC
..........<__>.MMMCCC
solution length: 12
number of state transitions: 27
ratio solution length / state transitions: 0.4444444444444444
minimum branching degree: 2
average branching degree: 2.5555555555555554
maximum branching degree: 3
time: 0.067999999999756255
Cost = 15,
Path = [((3,3),esq,0,0),((2,2),dir,1,1),((3,2),esq,0,1),((3,0),dir,0,3),((3,1),esq,0,2),((1,1),dir,2,2),((2,2),esq,1,1),((0,2),dir,3,1),((0,3),esq,3,0),((0,1),dir,3,2),((0,2),esq,3,1),((0,0),dir,3,3)],
Initial = ((3,3),esq,0,0) ?
yes
% water jugs problem solved using a breadth and a depth first strategy, with performance monitors
% it's interesting to compare the results
| ?- performance::init, water_jug::initial_state(Initial), breadth_first(6)::solve(water_jug, Initial, Path), water_jug::print_path(Path), performance::report.
4-gallon jug: 0
3-gallon jug: 0
4-gallon jug: 0
3-gallon jug: 3
4-gallon jug: 3
3-gallon jug: 0
4-gallon jug: 3
3-gallon jug: 3
4-gallon jug: 4
3-gallon jug: 2
4-gallon jug: 0
3-gallon jug: 2
solution length: 6
number of state transitions: 105
ratio solution length / state transitions: 0.05714285714285714
minimum branching degree: 2
average branching degree: 3.6315789473684212
maximum branching degree: 4
time: 0.20000000000027285
Path = [(0,0),(0,3),(3,0),(3,3),(4,2),(0,2)],
Initial = (0,0) ?
yes
| ?- performance::init, water_jug::initial_state(Initial), depth_first(10)::solve(water_jug, Initial, Path), water_jug::print_path(Path), performance::report.
4-gallon jug: 0
3-gallon jug: 0
4-gallon jug: 4
3-gallon jug: 0
4-gallon jug: 4
3-gallon jug: 3
4-gallon jug: 0
3-gallon jug: 3
4-gallon jug: 3
3-gallon jug: 0
4-gallon jug: 3
3-gallon jug: 3
4-gallon jug: 4
3-gallon jug: 2
4-gallon jug: 0
3-gallon jug: 2
solution length: 8
number of state transitions: 12
ratio solution length / state transitions: 0.6666666666666666
minimum branching degree: 1
average branching degree: 2.0
maximum branching degree: 3
time: 0.021999999999934516
Path = [(0,0),(4,0),(4,3),(0,3),(3,0),(3,3),(4,2),(0,2)],
Initial = (0,0) ?
yes
% eight puzzle solved using a hill-climbing strategy
| ?- performance::init, eight_puzzle::initial_state(five_steps, Initial), hill_climbing(25)::solve(eight_puzzle, Initial, Path, Cost), eight_puzzle::print_path(Path), performance::report.
283
164
7 5
283
1 4
765
2 3
184
765
23
184
765
123
84
765
123
8 4
765
solution length: 6
number of state transitions: 15
ratio solution length / state transitions: 0.4
minimum branching degree: 2
average branching degree: 3.1333333333333333
maximum branching degree: 4
time: 0.050000000000181899
Cost = 5,
Path = [[2/1,1/2,1/3,3/3,3/2,3/1,2/2,1/1,2/3],[2/2,1/2,1/3,3/3,3/2,3/1,2/1,1/1,2/3],[2/3,1/2,1/3,3/3,3/2,3/1,2/1,1/1,2/2],[1/3,1/2,2/3,3/3,3/2,3/1,2/1,1/1,2/2],[1/2,1/3,2/3,3/3,3/2,3/1,2/1,1/1,2/2],[2/2,1/3,2/3,3/3,3/2,3/1,2/1,1/1,1/2]],
Initial = [2/1,1/2,1/3,3/3,3/2,3/1,2/2,1/1,2/3] ?
yes
% eight puzzle solved using a best-first strategy
| ?- performance::init, eight_puzzle::initial_state(five_steps, Initial), best_first(25)::solve(eight_puzzle, Initial, Path, Cost), eight_puzzle::print_path(Path), performance::report.
283
164
7 5
283
1 4
765
2 3
184
765
23
184
765
123
84
765
123
8 4
765
solution length: 6
number of state transitions: 15
ratio solution length / state transitions: 0.4
minimum branching degree: 2
average branching degree: 3.1333333333333333
maximum branching degree: 4
time: 0.046000000000276486
Cost = 5,
Path = [[2/1,1/2,1/3,3/3,3/2,3/1,2/2,1/1,2/3],[2/2,1/2,1/3,3/3,3/2,3/1,2/1,1/1,2/3],[2/3,1/2,1/3,3/3,3/2,3/1,2/1,1/1,2/2],[1/3,1/2,2/3,3/3,3/2,3/1,2/1,1/1,2/2],[1/2,1/3,2/3,3/3,3/2,3/1,2/1,1/1,2/2],[2/2,1/3,2/3,3/3,3/2,3/1,2/1,1/1,1/2]],
Initial = [2/1,1/2,1/3,3/3,3/2,3/1,2/2,1/1,2/3] ?
yes
% turn off performance monitor
| ?- performance::stop.

View File

@@ -0,0 +1,103 @@
:- object(best_first(Threshold),
instantiates(heuristic_search(Threshold))).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'Best first heuristic state space search strategy.',
parnames is ['Threshold']]).
:- uses(list).
:- private(expand/8).
:- private(succlist/5).
:- private(bestf/3).
:- private(continue/9).
:- private(f/2).
:- private(insert/4).
search(Space, State, Threshold, Solution, Cost) :-
expand([], l(State, 0/0), Threshold, _, yes, Path, Space, Cost),
list::reverse(Path, Solution).
expand(Path, l(State,Cost/_), _, _, yes, [State|Path], Space, Cost) :-
Space::goal_state(State).
expand(Path, l(State,F/G), Threshold, Tree, Solved, Solution, Space, Cost) :-
F =< Threshold,
(bagof(Next/Cost,
(Space::next_state(State, Next, Cost), \+ list::member(Next, Path)),
Successors) ->
succlist(G, Successors, Trees, Threshold, Space),
bestf(Trees, F2, Threshold),
expand(Path, t(State, F2/G, Trees), Threshold, Tree, Solved, Solution, Space, Cost)
;
Solved = never).
expand(Path, t(State, F/G,[Tree| Trees]), Threshold, Tree3, Solved, Solution, Space, Cost) :-
F =< Threshold,
bestf(Trees, Threshold2, Threshold),
expand([State|Path], Tree, Threshold2, Tree2, Solved2, Solution, Space, Cost),
continue(Path, t(State, F/G, [Tree2| Trees]), Threshold, Tree3, Solved2, Solved, Solution, Space, Cost).
expand(_, t(_, _, []), _, _, never, _, _, _) :-
!.
expand(_, Tree, Threshold, Tree, no, _, _, _) :-
f(Tree, F),
F > Threshold.
continue(_, _, _, _, yes, yes, _, _, _).
continue(Path, t(State, _/G, [Tree| Trees]), Threshold, Tree2, no, Solved, Solution, Space, Cost) :-
insert(Tree, Trees, NewTrees, Threshold),
bestf(NewTrees, F, Threshold),
expand(Path, t(State, F/G, NewTrees), Threshold, Tree2, Solved, Solution, Space, Cost).
continue(Path,t(State, _/G, [_| Trees]), Threshold, Tree2, never, Solved, Solution, Space, Cost) :-
bestf(Trees, F, Threshold),
expand(Path, t(State, F/G, Trees), Threshold, Tree2, Solved, Solution, Space, Cost).
succlist(_, [], [], _, _).
succlist(G0, [State/Cost| Rest], Trees, Threshold, Space) :-
G is G0 + Cost,
Space::heuristic(State, H),
F is G + H,
succlist(G0, Rest, Trees2, Threshold, Space),
insert(l(State, F/G), Trees2, Trees, Threshold).
insert(Tree, [], [Tree], _) :-
!.
insert(Tree, Trees, [Tree| Trees], Threshold) :-
f(Tree, F),
bestf(Trees, F2, Threshold),
F =< F2,
!.
insert(Tree, [Tree1| Trees], [Tree1| Trees1], Threshold) :-
insert(Tree, Trees, Trees1, Threshold).
f(l(_, F/_), F).
f(t(_, F/_, _), F).
bestf([Tree| _], F, _) :-
f(Tree, F).
bestf([], Threshold, Threshold).
:- end_object.

View File

@@ -0,0 +1,43 @@
:- object(blind_search(_),
instantiates(class),
specializes(search_strategy)).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'Blind search state space strategies.',
parnames is ['Bound']]).
:- public(bound/1).
:- mode(bound(?integer), zero_or_one).
:- info(bound/1,
[comment is 'Search depth bound.',
argnames is ['Bound']]).
:- protected(search/4).
:- mode(search(+object, +nonvar, +integer, -list), zero_or_more).
:- info(search/4,
[comment is 'State space search solution.',
argnames is ['Space', 'State', 'Bound', 'Path']]).
bound(Bound) :-
parameter(1, Bound).
solve(Space, State, Path) :-
::bound(Bound),
::search(Space, State, Bound, Path).
:- end_object.

View File

@@ -0,0 +1,61 @@
:- object(breadth_first(Bound),
instantiates(blind_search(Bound))).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'Breadth first state space search strategy.',
parnames is ['Bound']]).
:- calls(state_space).
:- uses(list).
search(Space, State, Bound, Solution) :-
breadt(Space, l(State), Bound, Path),
list::reverse(Path, Solution).
breadt(Space, Tree, Bound, Solution) :-
expand([], Tree, Tree2, Solved, Solution, Space, Bound),
(Solved ->
true
;
breadt(Space, Tree2, Bound, Solution)).
expand(Path, l(State), _, true, [State| Path], Space, _) :-
Space::goal_state(State).
expand(Path, l(State), t(State, Subs), fail, _, Space, Bound) :-
Bound > 0,
bagof(l(Next),
(Space::next_state(State, Next),
\+ list::member(Next, [State| Path])),
Subs).
expand(Path, t(State,Subs), t(State, Subs2), Solved, Solution, Space, Bound) :-
expandall([State| Path], Subs, [], Subs2, Solved, Solution, Space, Bound).
expandall(_, [], [Tree| Trees], [Tree| Trees], fail, _, _, _).
expandall(Path, [Tree| Trees], Trees2, Subs2, Solved, Solution, Space, Bound) :-
Bound > 0,
Bound2 is Bound -1,
expand(Path, Tree, Tree2, Solved2, Solution, Space, Bound2),
(Solved2 ->
Solved = true
;
expandall(Path, Trees, [Tree2| Trees2], Subs2, Solved, Solution, Space, Bound))
;
expandall(Path, Trees, Trees2, Subs2, Solved, Solution, Space, Bound).
:- end_object.

View File

@@ -0,0 +1,33 @@
:- object(depth_first(Bound),
instantiates(blind_search(Bound))).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'Depth first state space search strategy.',
parnames is ['Bound']]).
:- uses(list).
search(Space, State, Bound, Solution) :-
depth(Space, State, Bound, [], Path),
list::reverse(Path, Solution).
depth(Space, State, _, Path, [State| Path]) :-
Space::goal_state(State).
depth(Space, State, Bound, Path, Solution) :-
Bound > 0,
Space::next_state(State, Next),
\+ list::member(Next, [State| Path]),
Bound2 is Bound - 1,
depth(Space, Next, Bound2, [State| Path], Solution).
:- end_object.

View File

@@ -0,0 +1,105 @@
:- object(eight_puzzle,
instantiates(heuristic_state_space)).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'Eight puzzle heuristic state space search problem.']).
:- uses(list).
initial_state(four_steps, [2/2,1/3,3/2,2/3,3/3,3/1,2/1,1/1,1/2]).
initial_state(five_steps, [2/1,1/2,1/3,3/3,3/2,3/1,2/2,1/1,2/3]).
initial_state(eighteen_steps, [2/2,2/3,1/3,3/1,1/2,2/1,3/3,1/1,3/2]).
goal_state(goal, [2/2,1/3,2/3,3/3,3/2,3/1,2/1,1/1,1/2]).
print_state([S0,S1,S2,S3,S4,S5,S6,S7,S8]) :-
list::member(Y, [3, 2, 1]),
nl,
list::member(X, [1, 2, 3]),
list::member(Tile-X/Y, [' '-S0,1-S1,2-S2,3-S3,4-S4,5-S5,6-S6,7-S7,8-S8]),
write(Tile),
fail.
print_state(_) :-
nl.
next_state([Empty| L], [Tile| L2], 1) :-
swap(Empty, Tile, L, L2).
swap(Empty, Tile, [Tile| L], [Empty| L]) :-
dist(Empty, Tile, 1).
swap(Empty, Tile, [Tile2| L], [Tile2| L2]) :-
swap(Empty, Tile, L, L2).
dist(X/Y, X2/Y2, D) :-
abs_diff(X, X2, Dx),
abs_diff(Y, Y2, Dy),
D is Dx + Dy.
abs_diff(A, B, D) :-
A > B ->
D is A - B
;
D is B - A.
heuristic([_| L], H) :-
goal_state(_, [_| G]),
totdist(L, G, 0, D),
seq(L, S),
H is D + 3*S.
totdist([], [], D, D).
totdist([T| L], [T2| L2], Acc, D) :-
dist(T, T2, D1),
Acc2 is Acc + D1,
totdist(L, L2, Acc2, D).
seq([First| L], S) :-
seq([First| L], First, 0, S).
seq([T1, T2| L], First, Acc, S) :-
score(T1, T2, S1),
Acc2 is Acc + S1,
seq([T2| L], First, Acc2, S).
seq([Last], First, Acc, S) :-
score(Last, First, Score),
S is Acc + Score.
score(2/2, _, 1) :- !.
score(1/3, 2/3, 0) :- !.
score(2/3, 3/3, 0) :- !.
score(3/3, 3/2, 0) :- !.
score(3/2, 3/1, 0) :- !.
score(3/1, 2/1, 0) :- !.
score(2/1, 1/1, 0) :- !.
score(1/1, 1/2, 0) :- !.
score(1/2, 1/3, 0) :- !.
score(_, _, 2) :- !.
:- end_object.

View File

@@ -0,0 +1,63 @@
:- object(farmer,
instantiates(state_space)).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'Farmer, cabbage, goat, and wolf state space search problem.']).
initial_state(start, (north, north, north, north)).
goal_state(end, (south, south, south, south)).
next_state((Cabbage, Goat, Wolf, Farmer), (FCabbage, Goat, Wolf, FFarmer)) :-
same_side(Farmer, Cabbage),
\+ same_side(Goat, Wolf),
flip(Farmer, FFarmer),
flip(Cabbage, FCabbage).
next_state((Cabbage, Goat, Wolf, Farmer), (Cabbage, FGloat, Wolf, FFarmer)) :-
same_side(Farmer, Goat),
flip(Farmer, FFarmer),
flip(Goat, FGloat).
next_state((Cabbage, Goat, Wolf, Farmer), (Cabbage, Goat, FWolf, FFarmer)) :-
same_side(Farmer, Wolf),
\+ same_side(Cabbage, Goat),
flip(Farmer, FFarmer),
flip(Wolf, FWolf).
next_state((Cabbage, Goat, Wolf, Farmer), (Cabbage, Goat, Wolf, FFarmer)) :-
\+ same_side(Cabbage, Goat),
\+ same_side(Goat, Wolf),
flip(Farmer, FFarmer).
flip(north, south).
flip(south, north).
same_side(north, north).
same_side(south, south).
print_state((Cabbage, Goat, Wolf, Farmer)) :-
(Cabbage = north -> write(c); write('_')),
(Goat = north -> write(g); write('_')),
(Wolf = north -> write(w); write('_')),
(Farmer = north -> write('f.<__>.........._'); write('_..........<__>.f')),
(Cabbage = north -> write('_'); write(c)),
(Goat = north -> write('_'); write(g)),
(Wolf = north -> write('_'); write(w)),
nl.
:- end_object.

View File

@@ -0,0 +1,55 @@
:- object(heuristic_search(_),
instantiates(class),
specializes(search_strategy)).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'Heuristic state space search strategies.',
parnames is ['Threshold']]).
:- public(threshold/1).
:- mode(threshold(?number), one).
:- info(threshold/1,
[comment is 'Search cost threshold.',
argnames is ['Threshold']]).
:- public(solve/4).
:- mode(solve(+object, +nonvar, -list, -number), zero_or_more).
:- info(solve/4,
[comment is 'State space search solution.',
argnames is ['Space', 'State', 'Path', 'Cost']]).
:- protected(search/5).
:- mode(search(+object, +nonvar, +number, -list, -number), zero_or_more).
:- info(search/5,
[comment is 'State space search solution.',
argnames is ['Space', 'State', 'Threshold', 'Path', 'Cost']]).
solve(Space, State, Path) :-
::solve(Space, State, Path, _).
solve(Space, State, Path, Cost) :-
::threshold(Threshold),
::search(Space, State, Threshold, Path, Cost).
threshold(Threshold) :-
parameter(1, Threshold).
:- end_object.

View File

@@ -0,0 +1,36 @@
:- object(heuristic_state_space,
instantiates(class),
specializes(state_space)).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'Heuristic state space.']).
:- public(next_state/3).
:- mode(next_state(+nonvar, -nonvar, -number), zero_or_more).
:- info(next_state/2,
[comment is 'Generates a state sucessor.',
argnames is ['State', 'Next', 'Cost']]).
:- public(heuristic/2).
:- mode(heuristic(+nonvar, -number), one).
:- info(heuristic/2,
[comment is 'Estimates state distance to a goal state.',
argnames is ['State', 'Estimate']]).
next_state(Prev, Next) :-
::next_state(Prev, Next, _).
:- end_object.

View File

@@ -0,0 +1,42 @@
:- object(hill_climbing(Threshold),
instantiates(heuristic_search(Threshold))).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'Hill climbing heuristic state space search strategy.',
parnames is ['Threshold']]).
:- uses(list).
:- private(hill/7).
search(Space, State, Threshold, Solution, Cost) :-
hill(Space, State, Threshold, [], Path, 0, Cost),
list::reverse(Path, Solution).
hill(Space, State, _, Path, [State| Path], Cost, Cost) :-
Space::goal_state(State).
hill(Space, State, Threshold, Path, Solution, SoFar, Total) :-
SoFar < Threshold,
findall(
(Estimate, Cost, Next),
(Space::next_state(State, Next, Cost),
\+ list::member(Next, [State| Path]),
Space::heuristic(Next, Guess),
Estimate is Guess + Cost),
States),
list::sort(States, SortedStates),
list::member((_, Cost, Next), SortedStates),
SoFar2 is SoFar + Cost,
hill(Space, Next, Threshold, [State| Path], Solution, SoFar2, Total).
:- end_object.

View File

@@ -0,0 +1,85 @@
:- object(miss_cann,
instantiates(heuristic_state_space)).
:- info([
version is 1.1,
authors is 'Paulo Moura',
date is 2000/11/21,
comment is 'Missionaries and cannibals heuristic state space search problem.']).
:- uses(loop).
initial_state(start, ((3,3), left, (0,0))).
goal_state(end, ((0,0), right, (3,3))).
print_state(((Me,Ce), B, (Md,Cd))) :-
loop::forto(1, Me, write('M')),
loop::forto(1, Ce, write('C')),
(B = left ->
write('.<__>..........')
;
write('..........<__>.')),
loop::forto(1, Md, write('M')),
loop::forto(1, Cd, write('C')),
nl.
next_state(((Me,Ce),left,(Md,Cd)), ((Me2,Ce2),right,(Md2,Cd2)), 1) :- %mm
Me >= 2,
once((Me - 2 =:= 0; Me - 2 >= Ce)),
Cd =< 2,
Me2 is Me - 2,
Ce2 is Ce,
Md2 is Md + 2,
Cd2 is Cd.
next_state(((Me,Ce),left,(Md,Cd)), ((Me2,Ce2),right,(Md2,Cd2)), 2) :- %m
Me >= 1,
once((Me - 1 =:= 0; Me - 1 >= Ce)),
Cd =< 1,
Me2 is Me - 1,
Ce2 is Ce,
Md2 is Md + 1,
Cd2 is Cd.
next_state(((Me,Ce),left,(Md,Cd)), ((Me2,Ce2),right,(Md2,Cd2)), 1) :- %cc
Ce >= 2,
once((Md >= Cd + 2; Md =:= 0)),
Me2 is Me,
Ce2 is Ce - 2,
Md2 is Md,
Cd2 is Cd + 2.
next_state(((Me,Ce),left,(Md,Cd)), ((Me2,Ce2),right,(Md2,Cd2)), 2) :- %c
Ce >= 1,
once((Md >= Cd + 1; Md =:= 0)),
Me2 is Me,
Ce2 is Ce - 1,
Md2 is Md,
Cd2 is Cd + 1.
next_state(((Me,Ce),left,(Md,Cd)), ((Me2,Ce2),right,(Md2,Cd2)), 1) :- %mc
Me >= 1,
Ce >= 1,
Md >= Cd,
Me2 is Me - 1,
Ce2 is Ce - 1,
Md2 is Md + 1,
Cd2 is Cd + 1.
next_state(((Me,Ce),right,(Md,Cd)), ((Me2,Ce2),left,(Md2,Cd2)), Cost) :-
next_state(((Md,Cd),left,(Me,Ce)), ((Md2,Cd2),right,(Me2,Ce2)), Cost).
heuristic(((_, _), _, (Md, Cd)), Cost) :-
Cost is 6 - (Md + Cd).
:- end_object.

View File

@@ -0,0 +1,163 @@
:- object(performance,
implements(event_handlersp)).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'Performance monitor for state space searches.']).
:- uses(event_registry).
:- uses(before_event_registry).
:- uses(after_event_registry).
:- uses(list).
:- uses(numberlist).
:- uses(time).
:- private(transitions/3).
:- dynamic(transitions/3).
:- mode(transitions(?state, ?state, ?integer), zero_or_more).
:- private(solution_length/1).
:- dynamic(solution_length/1).
:- mode(solution_length(?integer), zero_or_one).
:- private(start_time/1).
:- dynamic(start_time/1).
:- mode(start_time(-number), zero_or_one).
:- private(end_time/1).
:- dynamic(end_time/1).
:- mode(end_time(-number), zero_or_one).
:- public(time/1).
:- mode(time(-number), zero_or_one).
:- public(transitions/1).
:- mode(transitions(-number), zero_or_one).
:- public(branching/3).
:- mode(branching(-integer, -float, -integer), zero_or_one).
:- public(report/0).
:- mode(report, zero_or_one).
:- public(init/0).
:- mode(init, one).
:- public(stop/0).
:- mode(stop, one).
report :-
::solution_length(Length),
::transitions(Number),
Ratio is Length / Number,
::branching(Minimum, Average, Maximum),
::time(Time),
write('solution length: '), write(Length), nl,
write('state transitions: '), write(Number), nl,
write('ratio solution length / state transitions: '), write(Ratio), nl,
write('minimum branching degree: '), write(Minimum), nl,
write('average branching degree: '), write(Average), nl,
write('maximum branching degree: '), write(Maximum), nl,
write('time: '), write(Time), nl,
!.
transitions(Number) :-
findall(N, ::transitions(_, _, N), List),
numberlist::sum(List, Number).
time(Time) :-
::start_time(Start),
::end_time(End),
Time is End - Start.
branching(Minimum, Average, Maximum) :-
findall(
Length,
(::transitions(State1, _, _),
findall(State2, ::transitions(State1, State2, _), States2),
list::length(States2, Length)),
Lengths),
list::sort(Lengths, SortedLengths),
SortedLengths = [Minimum| _],
list::reverse(SortedLengths, [Maximum| _]),
numberlist::sum(Lengths, Sum),
list::length(Lengths, Length),
Average is Sum / Length.
init :-
self(Self),
event_registry::set_monitor(_, solve(_, _, _), _, Self),
after_event_registry::set_monitor(_, next_state(_, _), _, Self),
event_registry::set_monitor(_, solve(_, _, _, _), _, Self),
after_event_registry::set_monitor(_, next_state(_, _, _), _, Self),
::retractall(transitions(_, _, _)),
::retractall(start_time(_)),
::retractall(end_time(_)),
::retractall(solution_length(_)).
stop :-
self(Self),
before_event_registry::del_monitors(_, _, _, Self),
after_event_registry::del_monitors(_, _, _, Self).
before(_, solve(_, _, _), _) :-
!,
time::cpu_time(Time),
::assertz(start_time(Time)).
before(_, solve(_, _, _, _), _) :-
!,
time::cpu_time(Time),
::assertz(start_time(Time)).
after(_, next_state(S1, S2), _) :-
!,
(::transitions(S1, S2, N) ->
N2 is N + 1
;
N2 is 1),
::retractall(transitions(S1, S2, _)),
::assertz(transitions(S1, S2, N2)).
after(_, next_state(S1, S2, _), _) :-
!,
(::transitions(S1, S2, N) ->
N2 is N + 1
;
N2 is 1),
::retractall(transitions(S1, S2, _)),
::assertz(transitions(S1, S2, N2)).
after(_, solve(_, _, Solution), _) :-
!,
time::cpu_time(Time),
::assertz(end_time(Time)),
list::length(Solution, Length),
::retractall(solution_length(_)),
::asserta(solution_length(Length)).
after(_, solve(_, _, Solution, _), _) :-
!,
time::cpu_time(Time),
::assertz(end_time(Time)),
list::length(Solution, Length),
::retractall(solution_length(_)),
::asserta(solution_length(Length)).
:- end_object.

View File

@@ -0,0 +1,23 @@
:- object(search_strategy,
instantiates(abstract_class),
specializes(object)).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'State space search strategies.']).
:- public(solve/3).
:- mode(solve(+object, +nonvar, -list), zero_or_more).
:- info(solve/3,
[comment is 'State space search solution.',
argnames is ['Space', 'State', 'Path']]).
:- end_object.

View File

@@ -0,0 +1,17 @@
:- initialization(
logtalk_load([
best_first1,
blind_search1,
breadth_first1,
depth_first1,
eight_puzzle,
farmer,
heuristic_search1,
heuristic_state_space,
hill_climbing1,
miss_cann,
performance,
search_strategy,
state_space,
water_jug])).

View File

@@ -0,0 +1,96 @@
:- object(state_space,
instantiates(class),
specializes(object)).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'State space description predicates.']).
:- public(initial_state/1).
:- mode(initial_state(?nonvar), one_or_more).
:- info(initial_state/1,
[comment is 'Initial state.',
argnames is ['State']]).
:- public(initial_state/2).
:- mode(initial_state(?atom, ?nonvar), zero_or_more).
:- info(initial_state/2,
[comment is 'Named initial state.',
argnames is ['Name', 'State']]).
:- public(next_state/2).
:- mode(next_state(+nonvar, -nonvar), zero_or_more).
:- info(next_state/2,
[comment is 'Generates a state sucessor.',
argnames is ['State', 'Next']]).
:- public(goal_state/1).
:- mode(goal_state(?nonvar), one_or_more).
:- info(goal_state/1,
[comment is 'Goal state.',
argnames is ['State']]).
:- public(goal_state/2).
:- mode(goal_state(?atom, ?nonvar), zero_or_more).
:- info(goal_state/2,
[comment is 'Named goal state.',
argnames is ['Name', 'State']]).
:- public(print_state/1).
:- mode(print_state(+nonvar), one).
:- info(print_state/1,
[comment is 'Pretty print state.',
argnames is ['State']]).
:- public(print_path/1).
:- mode(print_path(+list), one).
:- info(print_path/1,
[comment is 'Pretty print a path (list of states).',
argnames is ['Path']]).
initial_state(State) :-
::initial_state(_, State).
goal_state(State) :-
::goal_state(_, State).
print_state(State) :-
writeq(State), nl.
print_path([]).
print_path([State| States]) :-
::print_state(State),
print_path(States).
:- end_object.

View File

@@ -0,0 +1,59 @@
:- object(water_jug,
instantiates(state_space)).
:- info([
version is 1.0,
authors is 'Paulo Moura',
date is 1998/3/23,
comment is 'Water jug state space search problem.']).
initial_state(start, (0, 0)).
goal_state(end1, (2, 0)).
goal_state(end2, (0, 2)).
next_state((X, Y), (4, Y)) :-
X < 4.
next_state((X, Y),(X, 3)) :-
Y < 3.
next_state((X, Y), (4, Z)) :-
Y > 0, X < 4,
Aux is X + Y, Aux >= 4,
Z is Y - (4 - X).
next_state((X, Y), (Z, 3)) :-
X > 0, Y < 3,
Aux is X + Y, Aux >= 4,
Z is X - (3 - Y).
next_state((X, Y),(Z, 0)) :-
Y > 0,
Aux is X + Y, Aux =< 4,
Z is Y + X.
next_state((X, Y),(0, Z)) :-
X > 0,
Aux is X + Y, Aux =< 3,
Z is Y + X.
next_state((X, Y), (0, Y)) :-
X > 0.
next_state((X, Y), (X, 0)) :-
Y > 0.
print_state((X, Y)) :-
write('4-gallon jug: '), write(X), nl,
write('3-gallon jug: '), write(Y), nl, nl.
:- end_object.