Skip to content
Browse files

switch to seresye and switch ams to simple_agent

  • Loading branch information...
1 parent 92878d7 commit 77e665d1f691f7795be712990064bd49ce020be5 @gleber committed Apr 19, 2012
View
3 .gitignore
@@ -1,2 +1,3 @@
*.beam
-*.bak
+*.bak
+/lib/*
View
4 Makefile
@@ -1,4 +1,6 @@
-all:
+all: deps fast
+
+fast:
./rebar compile
deps:
View
34 examples/eresye/Makefile
@@ -1,34 +0,0 @@
-#
-# Makefile
-#
-
-BEAM=erlc
-
-OBJS=\
-auto.beam \
-cannibals.beam \
-journal.beam \
-journal_sample.beam \
-phil.beam \
-prodcons.beam \
-sieve.beam
-
-
-ERL_OBJS=$(foreach file, $(OBJS), $(file))
-
-OTHER_OBJS=
-FIND=find
-
-all: $(ERL_OBJS) $(OTHER_OBJS)
-
-journal.erl: journal.onto
- sh compile_ontology.sh journal
-
-%.beam: %.erl
- $(BEAM) $<
-
-clean:
- $(RM) -f *.beam journal.hrl journal.erl
-
-clearbak:
- @$(FIND) . -type f -name \*~ -exec rm {} \;
View
252 examples/eresye/auto.erl
@@ -1,252 +0,0 @@
-%%
-%% auto.erl
-%%
-%% -------------------------------------------------------------------------
-%%
-%% ERESYE, an ERlang Expert SYstem Engine
-%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com)
-%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it)
-%%
-%% This program is free software: you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation, either version 3 of the License, or
-%% (at your option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with this program. If not, see <http://www.gnu.org/licenses/>
-%%
-%% ======================================================
-%% Automotive Expert System
-%%
-%% This expert system diagnoses some simple
-%% problems with a car.
-%%
-%% It is a bare translation of the same example
-%% provided in CLIPS Version 6.0
-%%
-%% To execute, type 'auto:start().'
-%% ======================================================
-%%
-
--module(auto).
-
--export([determine_battery_state/2,
- determine_conductivity_test/4, determine_engine_state/2,
- determine_gas_level/3, determine_knocking/2,
- determine_low_output/2, determine_misfiring/2,
- determine_point_surface_state_1/3,
- determine_point_surface_state_2/2,
- determine_rotation_state/2, determine_sluggishness/2,
- no_repairs/2, normal_engine_state_conclusions/2,
- print_repair/3, start/0,
- unsatisfactory_engine_state_conclusions/2]).
-
-ask_yn(Prompt) ->
- [Response | _] = io:get_line(Prompt),
- case Response of
- $y -> true;
- _ -> false
- end.
-
-ask_question(Prompt) -> io:get_line(Prompt).
-
-%% **********************
-%% * ENGINE STATE RULES *
-%% **********************
-normal_engine_state_conclusions(Engine,
- {'working-state', engine, normal}) ->
- eresye:assert(Engine, {repair, "No repair needed."}),
- eresye:assert(Engine, {'spark-state', engine, normal}),
- eresye:assert(Engine,
- {'charge-state', battery, charged}),
- eresye:assert(Engine,
- {'rotation-state', engine, rotates}).
-
-unsatisfactory_engine_state_conclusions(Engine,
- {'working-state', engine,
- unsatisfactory}) ->
- eresye:assert(Engine,
- {'charge-state', battery, charged}),
- eresye:assert(Engine,
- {'rotation-state', engine, rotates}).
-
-%% ***************
-%% * QUERY RULES *
-%% ***************
-determine_engine_state(Engine, {start, _})
- when not
- ["{'working-state', engine, _}", "{repair, _}"];
- true ->
- case ask_yn('Does the engine start (yes/no)? ') of
- true ->
- case ask_yn('Does the engine run normally (yes/no)? ')
- of
- true ->
- eresye:assert(Engine,
- {'working-state', engine, normal});
- _ ->
- eresye:assert(Engine,
- {'working-state', engine, unsatisfactory})
- end;
- _ ->
- eresye:assert(Engine,
- {'working-state', engine, 'does-not-start'})
- end.
-
-determine_rotation_state(Engine,
- {'working-state', engine, 'does-not-start'})
- when not
- ["{'rotation-state', engine, _}", "{repair, _}"];
- true ->
- case ask_yn('Does the engine rotate (yes/no)? ') of
- true ->
- eresye:assert(Engine,
- {'rotation-state', engine, rotates}),
- eresye:assert(Engine,
- {'spark-state', engine, 'irregular-spark'});
- _ ->
- eresye:assert(Engine,
- {'rotation-state', engine, 'does-not-rotate'}),
- eresye:assert(Engine,
- {'spark-state', engine, 'does-not-spark'})
- end.
-
-determine_sluggishness(Engine,
- {'working-state', engine, unsatisfactory})
- when not ["{repair, _}"]; true ->
- case ask_yn('Is the engine sluggish (yes/no)? ') of
- true ->
- eresye:assert(Engine, {repair, "Clean the fuel line."});
- _ -> ok
- end.
-
-determine_misfiring(Engine,
- {'working-state', engine, unsatisfactory})
- when not ["{repair, _}"]; true ->
- case ask_yn('Does the engine misfire (yes/no)? ') of
- true ->
- eresye:assert(Engine,
- {repair, "Point gap adjustment."}),
- eresye:assert(Engine,
- {'spark-state', engine, 'irregular-spark'});
- _ -> ok
- end.
-
-determine_knocking(E,
- {'working-state', engine, unsatisfactory})
- when not ["{repair, _}"]; true ->
- case ask_yn('Does the engine knock (yes/no)? ') of
- true ->
- eresye:assert(E, {repair, "Timing adjustment."});
- _ -> ok
- end.
-
-determine_low_output(E,
- {'working-state', engine, unsatisfactory})
- when not ["{symptom, engine, _}", "{repair, _}"];
- true ->
- case
- ask_yn('Is the output of the engine low (yes/no)? ')
- of
- true ->
- eresye:assert(E, {symptom, engine, 'low-output'});
- _ ->
- eresye:assert(E, {symptom, engine, 'not-low-output'})
- end.
-
-determine_gas_level(E,
- {'working-state', engine, 'does-not-start'},
- {'rotation-state', engine, rotates})
- when not ["{repair, _}"]; true ->
- case
- ask_yn('Does the tank have any gas in it (yes/no)? ')
- of
- false -> eresye:assert(E, {repair, "Add gas."});
- _ -> ok
- end.
-
-determine_battery_state(E,
- {'rotation-state', engine, 'does-not-rotate'})
- when not
- ["{'charge-state', battery, _}", "{repair, _}"];
- true ->
- case ask_yn('Is the battery charged (yes/no)? ') of
- true ->
- eresye:assert(E, {'charge-state', battery, charged});
- _ ->
- eresye:assert(E, {repair, "Charge the battery."}),
- eresye:assert(E, {'charge-state', battery, dead})
- end.
-
-determine_point_surface_state_1(E,
- {'working-state', engine, 'does-not-start'},
- {'spark-state', engine, 'irregular-spark'})
- when not ["{repair, _}"]; true ->
- dpss(E).
-
-determine_point_surface_state_2(E,
- {symptom, engine, 'low-output'})
- when not ["{repair, _}"]; true ->
- dpss(E).
-
-dpss(E) ->
- case
- ask_question('What is the surface state of the points (normal/burned/contaminated)? ')
- of
- [$b, $u, $r, $n, $e, $d | _] ->
- eresye:assert(E, {repair, "Replace the points."});
- [$c, $o, $n, $t, $a, $m, $i, $n, $a, $t, $e, $d | _] ->
- eresye:assert(E, {repair, "Clean the points."});
- _ -> ok
- end.
-
-determine_conductivity_test(E,
- {'working-state', engine, 'does-not-start'},
- {'spark-state', engine, 'does-not-spark'},
- {'charge-state', battery, charged})
- when not ["{repair, _}"]; true ->
- case
- ask_yn('Is the conductivity test for the ignition coil positive (yes/no)? ')
- of
- true ->
- eresye:assert(E,
- {repair, "Repair the distributor lead wire."});
- _ ->
- eresye:assert(E, {repair, "Replace the ignition coil."})
- end.
-
-no_repairs(E, {start, _})
- when not ["{repair, _}"]; true ->
- eresye:assert(E,
- {repair, "Take your car to a mechanic."}).
-
-print_repair(_, {repair, X}, {start, Pid}) ->
- io:format("Suggested Repair: ~p~n", [X]), Pid ! ok.
-
-start() ->
- eresye:start(auto),
- %% Rules with high priority (10)
- [eresye:add_rule(auto, {?MODULE, X}, 10)
- || X
- <- [normal_engine_state_conclusions,
- unsatisfactory_engine_state_conclusions, print_repair]],
- %% Rules with normal priority (0)
- [eresye:add_rule(auto, {?MODULE, X})
- || X
- <- [determine_engine_state, determine_rotation_state,
- determine_sluggishness, determine_misfiring,
- determine_knocking, determine_low_output,
- determine_gas_level, determine_battery_state,
- determine_point_surface_state_1,
- determine_point_surface_state_2,
- determine_conductivity_test]],
- %% Rules with low priority (-10)
- eresye:add_rule(auto, {?MODULE, no_repairs}, -10),
- eresye:assert(auto, {start, self()}),
- receive _ -> ok end,
- eresye:stop(auto).
View
236 examples/eresye/cannibals.erl
@@ -1,236 +0,0 @@
-%%
-%% cannibals.erl
-%%
-%% -------------------------------------------------------------------------
-%%
-%% ERESYE, an ERlang Expert SYstem Engine
-%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com)
-%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it)
-%%
-%% This program is free software: you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation, either version 3 of the License, or
-%% (at your option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with this program. If not, see <http://www.gnu.org/licenses/>
-%%
-%% ======================================================
-%% Cannibals and Missionaries Problem
-%%
-%% Another classic AI problem. The point is
-%% to get three cannibals and three missionaries
-%% across a stream with a boat that can only
-%% hold two people. If the cannibals outnumber
-%% the missionaries on either side of the stream,
-%% then the cannibals will eat the missionaries.
-%%
-%% It is a bare translation of the same example
-%% provided in CLIPS Version 6.0
-%%
-%% To execute, type 'cannibals:start().'
-%% ======================================================
-
--module(cannibals).
-
--compile([export_all]).
-
--record(status,
- {'search-depth', parent, 'shore-1-missionaries',
- 'shore-1-cannibals', 'shore-2-missionaries',
- 'shore-2-cannibals', 'boat-location', 'last-move'}).
-
--record(moves, {id, 'moves-list'}).
-
--define(INITIAL_MISSIONARIES, 3).
-
--define(INITIAL_CANNIBALS, 3).
-
-for(Min, Max) when Min > Max -> [];
-for(Min, Max) -> lists:seq(Min, Max).
-
-shore_1_move(Engine,
- #status{'boat-location' = 'shore-1'} = Node,
- {'boat-can-host', Limit}) ->
- Num = Node#status.'search-depth',
- S1M = Node#status.'shore-1-missionaries',
- S1C = Node#status.'shore-1-cannibals',
- S2M = Node#status.'shore-2-missionaries',
- S2C = Node#status.'shore-2-cannibals',
- MaxMissionaries = lists:min([S1M, Limit]),
- lists:foreach(fun (Missionaries) ->
- MinCannibals = lists:max([0, 1 - Missionaries]),
- MaxCannibals = lists:min([S1C, Limit - Missionaries]),
- %%io:format ("Shore 1 ~p,~p~n", [MinCannibals, MaxCannibals]),
- lists:foreach(fun (Cannibals) ->
- NewNode = #status{'search-depth'
- = Num + 1,
- parent = Node,
- 'shore-1-missionaries'
- =
- S1M -
- Missionaries,
- 'shore-1-cannibals'
- =
- S1C -
- Cannibals,
- 'shore-2-missionaries'
- =
- Missionaries
- + S2M,
- 'shore-2-cannibals'
- =
- Cannibals
- + S2C,
- 'boat-location'
- =
- 'shore-2',
- 'last-move' =
- move_string(Missionaries,
- Cannibals,
- "shore-2")},
- eresye:assert(Engine, NewNode)
- end,
- for(MinCannibals, MaxCannibals))
- end,
- for(0, MaxMissionaries)).
-
-shore_2_move(Engine,
- #status{'boat-location' = 'shore-2'} = Node,
- {'boat-can-host', Limit}) ->
- Num = Node#status.'search-depth',
- S1M = Node#status.'shore-1-missionaries',
- S1C = Node#status.'shore-1-cannibals',
- S2M = Node#status.'shore-2-missionaries',
- S2C = Node#status.'shore-2-cannibals',
- MaxMissionaries = lists:min([S2M, Limit]),
- lists:foreach(fun (Missionaries) ->
- MinCannibals = lists:max([0, 1 - Missionaries]),
- MaxCannibals = lists:min([S2C, Limit - Missionaries]),
- %%io:format ("Shore 2 ~p,~p~n", [MinCannibals, MaxCannibals]),
- lists:foreach(fun (Cannibals) ->
- NewNode = #status{'search-depth'
- = Num + 1,
- parent = Node,
- 'shore-1-missionaries'
- =
- S1M +
- Missionaries,
- 'shore-1-cannibals'
- =
- S1C +
- Cannibals,
- 'shore-2-missionaries'
- =
- S2M -
- Missionaries,
- 'shore-2-cannibals'
- =
- S2C -
- Cannibals,
- 'boat-location'
- =
- 'shore-1',
- 'last-move' =
- move_string(Missionaries,
- Cannibals,
- "shore-1")},
- eresye:assert(Engine, NewNode)
- end,
- for(MinCannibals, MaxCannibals))
- end,
- for(0, MaxMissionaries)).
-
-cannibals_eat_missionaries(Engine,
- #status{'shore-1-missionaries' = S1M,
- 'shore-1-cannibals' = S1C,
- 'shore-2-missionaries' = S2M,
- 'shore-2-cannibals' = S2C} =
- Node) ->
- if (S2C > S2M) and (S2M =/= 0) or
- (S1C > S1M) and (S1M =/= 0) ->
- %%io:format ("Invalid ~p~n", [Node]),
- eresye:retract(Engine, Node);
- true -> ok
- end.
-
-circular_path(Engine,
- #status{'search-depth' = SD1, 'boat-location' = BL,
- 'shore-1-missionaries' = S1M, 'shore-1-cannibals' = S1C,
- 'shore-2-missionaries' = S2M,
- 'shore-2-cannibals' = S2C},
- #status{'search-depth' = SD2, 'boat-location' = BL,
- 'shore-1-missionaries' = S1M, 'shore-1-cannibals' = S1C,
- 'shore-2-missionaries' = S2M,
- 'shore-2-cannibals' = S2C} =
- Node) ->
- if SD1 < SD2 -> eresye:retract(Engine, Node);
- true -> ok
- end.
-
-recognize_solution(Engine,
- #status{parent = Parent, 'shore-2-missionaries' = M,
- 'shore-2-cannibals' = C, 'last-move' = Move} =
- Node) ->
- if (M == (?INITIAL_MISSIONARIES)) and
- (C == (?INITIAL_CANNIBALS)) ->
- eresye:retract(Engine, Node),
- eresye:assert(Engine,
- #moves{id = Parent, 'moves-list' = Move});
- true -> ok
- end.
-
-move_string(0, 1, Shore) ->
- lists:concat(["Move 1 cannibal to ", Shore]);
-move_string(0, N, Shore) ->
- lists:concat(["Move ", N, " cannibals to ", Shore]);
-move_string(1, 0, Shore) ->
- lists:concat(["Move 1 missionary to ", Shore]);
-move_string(1, 1, Shore) ->
- lists:concat(["Move 1 missionary and 1 cannibal to ",
- Shore]);
-move_string(1, N, Shore) ->
- lists:concat(["Move 1 missionary and ", N,
- " cannibals to ", Shore]);
-move_string(M, 0, Shore) ->
- lists:concat(["Move ", M, " missionaries to ", Shore]);
-move_string(M, 1, Shore) ->
- lists:concat(["Move ", M,
- " missionaries and 1 cannibal to ", Shore]);
-move_string(M, N, Shore) ->
- lists:concat(["Move ", M, " missionaries and ", N,
- " cannibals to ", Shore]).
-
-print_solution(#status{parent = 'no-parent'}) -> ok;
-print_solution(S) ->
- print_solution(S#status.parent),
- io:format("~p~n", [S#status.'last-move']).
-
-start() ->
- eresye:start(cannibals),
- eresye:add_rule(cannibals, {cannibals, shore_1_move}),
- eresye:add_rule(cannibals, {cannibals, shore_2_move}),
- eresye:add_rule(cannibals,
- {cannibals, cannibals_eat_missionaries}, 10),
- eresye:add_rule(cannibals, {cannibals, circular_path},
- 10),
- eresye:add_rule(cannibals,
- {cannibals, recognize_solution}),
- eresye:assert(cannibals,
- #status{'search-depth' = 1, parent = 'no-parent',
- 'shore-1-missionaries' = ?INITIAL_MISSIONARIES,
- 'shore-2-missionaries' = 0,
- 'shore-1-cannibals' = ?INITIAL_CANNIBALS,
- 'shore-2-cannibals' = 0, 'boat-location' = 'shore-1',
- 'last-move' = 'No move.'}),
- eresye:assert(cannibals, {'boat-can-host', 2}),
- P = eresye:wait(cannibals,
- #moves{id = '_', 'moves-list' = '_'}),
- print_solution(P#moves.id),
- io:format("~p~n", [P#moves.'moves-list']),
- eresye:stop(cannibals).
View
4 examples/eresye/compile_ontology.sh
@@ -1,4 +0,0 @@
-erl -pa ../../ebin << EOF
-ontology:compile ("$1", [include, source]).
-halt ().
-EOF
View
87 examples/eresye/journal.erl
@@ -1,87 +0,0 @@
--module(journal).
-
--include("journal.hrl").
-
--export([childof/1, 'international-journal'/1, is_a/2,
- is_class/1, journal/1, 'national-journal'/1]).
-
-is_class(journal) -> true;
-is_class('international-journal') -> true;
-is_class('national-journal') -> true;
-is_class('IEEE-journal') -> true;
-is_class('ACM-journal') -> true;
-is_class('italian-journal') -> true;
-is_class(_) -> false.
-
-is_a('international-journal', journal) -> true;
-is_a('national-journal', journal) -> true;
-is_a('IEEE-journal', 'international-journal') -> true;
-is_a('IEEE-journal', journal) -> true;
-is_a('ACM-journal', 'international-journal') -> true;
-is_a('ACM-journal', journal) -> true;
-is_a('italian-journal', 'national-journal') -> true;
-is_a('italian-journal', journal) -> true;
-is_a(_, _) -> false.
-
-childof(journal) ->
- ['international-journal', 'national-journal',
- 'IEEE-journal', 'ACM-journal', 'italian-journal'];
-childof('international-journal') ->
- ['IEEE-journal', 'ACM-journal'];
-childof('national-journal') -> ['italian-journal'];
-childof('IEEE-journal') -> [];
-childof('ACM-journal') -> [];
-childof('italian-journal') -> [];
-childof(_) -> exit(undef_class).
-
-journal(X = #'international-journal'{}) ->
- #journal{title = X#'international-journal'.title,
- main_topic = X#'international-journal'.main_topic,
- publisher = X#'international-journal'.publisher,
- type = X#'international-journal'.type,
- impact_factor =
- X#'international-journal'.impact_factor};
-journal(X = #'national-journal'{}) ->
- #journal{title = X#'national-journal'.title,
- main_topic = X#'national-journal'.main_topic,
- publisher = X#'national-journal'.publisher,
- type = X#'national-journal'.type,
- impact_factor = X#'national-journal'.impact_factor};
-journal(X = #'IEEE-journal'{}) ->
- #journal{title = X#'IEEE-journal'.title,
- main_topic = X#'IEEE-journal'.main_topic,
- publisher = X#'IEEE-journal'.publisher,
- type = X#'IEEE-journal'.type,
- impact_factor = X#'IEEE-journal'.impact_factor};
-journal(X = #'ACM-journal'{}) ->
- #journal{title = X#'ACM-journal'.title,
- main_topic = X#'ACM-journal'.main_topic,
- publisher = X#'ACM-journal'.publisher,
- type = X#'ACM-journal'.type,
- impact_factor = X#'ACM-journal'.impact_factor};
-journal(X = #'italian-journal'{}) ->
- #journal{title = X#'italian-journal'.title,
- main_topic = X#'italian-journal'.main_topic,
- publisher = X#'italian-journal'.publisher,
- type = X#'italian-journal'.type,
- impact_factor = X#'italian-journal'.impact_factor}.
-
-'international-journal'(X = #'IEEE-journal'{}) ->
- #'international-journal'{title = X#'IEEE-journal'.title,
- main_topic = X#'IEEE-journal'.main_topic,
- publisher = X#'IEEE-journal'.publisher,
- type = X#'IEEE-journal'.type,
- impact_factor = X#'IEEE-journal'.impact_factor};
-'international-journal'(X = #'ACM-journal'{}) ->
- #'international-journal'{title = X#'ACM-journal'.title,
- main_topic = X#'ACM-journal'.main_topic,
- publisher = X#'ACM-journal'.publisher,
- type = X#'ACM-journal'.type,
- impact_factor = X#'ACM-journal'.impact_factor}.
-
-'national-journal'(X = #'italian-journal'{}) ->
- #'national-journal'{title = X#'italian-journal'.title,
- main_topic = X#'italian-journal'.main_topic,
- publisher = X#'italian-journal'.publisher,
- type = X#'italian-journal'.type,
- impact_factor = X#'italian-journal'.impact_factor}.
View
42 examples/eresye/journal.hrl
@@ -1,42 +0,0 @@
--record('journal',{
- 'title',
- 'main_topic',
- 'publisher',
- 'type',
- 'impact_factor'}).
-
--record('international-journal',{
- 'title',
- 'main_topic',
- 'publisher',
- 'type' = 'international',
- 'impact_factor'}).
-
--record('national-journal',{
- 'title',
- 'main_topic',
- 'publisher',
- 'type' = 'national',
- 'impact_factor'}).
-
--record('IEEE-journal',{
- 'title',
- 'main_topic',
- 'publisher' = 'IEEE',
- 'type' = 'international',
- 'impact_factor'}).
-
--record('ACM-journal',{
- 'title',
- 'main_topic',
- 'publisher' = 'ACM',
- 'type' = 'international',
- 'impact_factor'}).
-
--record('italian-journal',{
- 'title',
- 'main_topic',
- 'publisher',
- 'type' = 'national',
- 'impact_factor'}).
-
View
24 examples/eresye/journal.onto
@@ -1,24 +0,0 @@
-%
-%
-%
-class (journal) ->
- { title = [string, mandator, nodefault],
- main_topic = [string, mandator, nodefault],
- publisher = [string, mandatory, nodefault],
- type = [string, mandatory, nodefault],
- impact_factor = [number, mandatory, nodefault] };
-
-class ('international-journal') -> is_a (journal),
- { type = [string, mandatory, default(international)] };
-
-class ('national-journal') -> is_a (journal),
- { type = [string, mandatory, default(national)] };
-
-class ('IEEE-journal') -> is_a ('international-journal'),
- { publisher = [string, mandatory, default('IEEE')] };
-
-class ('ACM-journal') -> is_a ('international-journal'),
- { publisher = [string, mandatory, default('ACM')] };
-
-class ('italian-journal') -> is_a ('national-journal').
-
View
134 examples/eresye/journal_sample.erl
@@ -1,134 +0,0 @@
-%%
-%%journal_sample.erl
-%%
-%%-------------------------------------------------------------------------
-%%
-%% ERESYE, an ERlang Expert SYstem Engine
-%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com)
-%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it)
-%%
-%% This program is free software: you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation, either version 3 of the License, or
-%% (at your option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with this program. If not, see <http://www.gnu.org/licenses/>
-%%
--module(journal_sample).
-
--compile([export_all]).
-
--include("journal.hrl").
-
-- define ( AddDefaultRule ( Fun , Class ) , Fun ( _ , _ , _ , # Class { } ) -> ok ; Fun ( E , T , I , Y ) -> Fun ( E , T , I , journal : Class ( Y ) ) ) .
-
-
-ask_question(Prompt) ->
- lists:reverse(tl(lists:reverse(io:get_line(Prompt)))).
-
-national_journal ( _ , { topic , Topic } , { ifactor , MinimumIF } , # 'national-journal' { main_topic = Topic , impact_factor = IF } = J ) when IF >= MinimumIF -> io : format ( "The journal is ~p~n" , [ J ] ) ; ? AddDefaultRule ( national_journal , 'national-journal' ) .
-
-
-intl_journal ( _ , { topic , Topic } , { ifactor , MinimumIF } , # 'international-journal' { main_topic = Topic , impact_factor = IF } = J ) when IF >= MinimumIF -> io : format ( "The journal is ~p~n" , [ J ] ) ; ? AddDefaultRule ( intl_journal , 'international-journal' ) .
-
-
-ieee_journal ( _ , { topic , Topic } , { ifactor , MinimumIF } , # 'IEEE-journal' { main_topic = Topic , impact_factor = IF } = J ) when IF >= MinimumIF -> io : format ( "The journal is ~p~n" , [ J ] ) ; ? AddDefaultRule ( ieee_journal , 'IEEE-journal' ) .
-
-
-acm_journal ( _ , { topic , Topic } , { ifactor , MinimumIF } , # 'ACM-journal' { main_topic = Topic , impact_factor = IF } = J ) when IF >= MinimumIF -> io : format ( "The journal is ~p~n" , [ J ] ) ; ? AddDefaultRule ( acm_journal , 'ACM-journal' ) .
-
-
-get_journal_type(Engine, {any_publisher}) ->
- T =
- ask_question('Select the type (i)nternational/(n)ational): '),
- case T of
- "i" ->
- eresye:add_rule(Engine,
- {journal_sample, intl_journal, 1}, 8);
- "n" ->
- eresye:add_rule(Engine,
- {journal_sample, national_journal, 1}, 8)
- end.
-
-get_publisher(Engine, {start, _})
- when not ["{publisher_selected}"]; true ->
- Pub =
- ask_question('Select the publisher (ieee/acm/any): '),
- case Pub of
- "ieee" ->
- eresye:add_rule(Engine,
- {journal_sample, ieee_journal, 1}, 8),
- eresye:assert(Engine, {publisher_selected});
- "acm" ->
- eresye:add_rule(Engine,
- {journal_sample, acm_journal, 1}, 8),
- eresye:assert(Engine, {publisher_selected});
- _ ->
- eresye:assert(Engine,
- [{publisher_selected}, {any_publisher}])
- end.
-
-get_if(Engine, {start, _})
- when not ["{ifactor, _}"]; true ->
- IF =
- ask_question('What is your minimum impact factor: '),
- eresye:assert(Engine, {ifactor, list_to_float(IF)}).
-
-get_topics(Engine, {start, _} = X)
- when not ["{topic, end_of_list}"]; true ->
- Topic =
- ask_question('Enter topic of your paper ("q" to end): '),
- case Topic of
- "q" -> eresye:assert(Engine, {topic, end_of_list});
- _ ->
- eresye:assert(Engine, {topic, list_to_atom(Topic)}),
- eresye:retract(Engine, X),
- eresye:assert(Engine, X)
- end.
-
-final_rule(_, {start, Pid}) -> Pid ! ok.
-
-start() ->
- eresye:start(js, journal),
- eresye:add_rule(js, {journal_sample, get_topics}, 10),
- eresye:add_rule(js, {journal_sample, get_if}, 9),
- eresye:add_rule(js, {journal_sample, get_publisher}, 9),
- eresye:add_rule(js, {journal_sample, get_journal_type},
- 9),
- eresye:add_rule(js, {journal_sample, final_rule}, 1),
- eresye:assert(js,
- [#'IEEE-journal'{title = 'Trans. on Soft. Eng.',
- main_topic = any,
- impact_factor = 5.99999999999999977796e-1},
- #'IEEE-journal'{title = 'Trans. on PAMI',
- main_topic = 'artificial intelligence',
- impact_factor = 8.0e-1},
- #'IEEE-journal'{title = 'Trans. on Parallel and ...',
- main_topic = any, impact_factor = 9.0e-1},
- #'IEEE-journal'{title = 'Trans. on Mobile Computing',
- main_topic = 'mobile systems',
- impact_factor = 6.99999999999999955591e-1},
- #'IEEE-journal'{title = 'Internet Computing',
- main_topic = internet,
- impact_factor = 9.0e-1},
- #'ACM-journal'{title =
- 'Transaction on Internet Computing',
- main_topic = internet,
- impact_factor = 9.2e-1},
- #'ACM-journal'{title = 'TOPLAS',
- main_topic = 'programming languages',
- impact_factor = 9.2e-1},
- #'italian-journal'{title = 'Intelligenza Artificiale',
- publisher = 'AI*IA',
- main_topic = 'artificial intelligence',
- impact_factor = 2.0e-1}]),
- eresye:assert(js, {start, self()}),
- receive _ -> ok end,
- eresye:get_rete(js),
- eresye:stop(js).
View
70 examples/eresye/phil.erl
@@ -1,70 +0,0 @@
-%%
-%%phil.erl
-%%
-%%-------------------------------------------------------------------------
-%%
-%% ERESYE, an ERlang Expert SYstem Engine
-%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com)
-%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it)
-%%
-%% This program is free software: you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation, either version 3 of the License, or
-%% (at your option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with this program. If not, see <http://www.gnu.org/licenses/>
-%%
--module(phil).
-
--compile([export_all]).
-
--define(N_PHIL, 5).
-
-start() -> eresye:start(restaurant), phil_spawn(0).
-
-phil_spawn(?N_PHIL) -> ok;
-phil_spawn(N) ->
- eresye:assert(restaurant, {fork, N}),
- spawn(phil, philosopher, [N, init]),
- if N < (?N_PHIL) - 1 ->
- eresye:assert(restaurant, {room_ticket, N});
- true -> ok
- end,
- phil_spawn(N + 1).
-
-philosopher(N, init) -> new_seed(), philosopher(N, ok);
-philosopher(N, X) ->
- think(N),
- Ticket = eresye:wait_and_retract(restaurant,
- {room_ticket, '_'}),
- eresye:wait_and_retract(restaurant, {fork, N}),
- eresye:wait_and_retract(restaurant,
- {fork, (N + 1) rem (?N_PHIL)}),
- eat(N),
- eresye:assert(restaurant, {fork, N}),
- eresye:assert(restaurant,
- {fork, (N + 1) rem (?N_PHIL)}),
- eresye:assert(restaurant, Ticket),
- philosopher(N, X).
-
-think(N) ->
- io:format("~w: thinking ...~n", [N]),
- timer:sleep(random:uniform(10) * 1000).
-
-eat(N) ->
- io:format("~w: eating ...~n", [N]),
- timer:sleep(random:uniform(10) * 1000).
-
-new_seed() ->
- {_, _, X} = erlang:now(),
- {H, M, S} = time(),
- H1 = H * X rem 32767,
- M1 = M * X rem 32767,
- S1 = S * X rem 32767,
- put(random_seed, {H1, M1, S1}).
View
52 examples/eresye/prodcons.erl
@@ -1,52 +0,0 @@
-%%
-%%prodcons.erl
-%%
-%%-------------------------------------------------------------------------
-%%
-%% ERESYE, an ERlang Expert SYstem Engine
-%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com)
-%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it)
-%%
-%% This program is free software: you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation, either version 3 of the License, or
-%% (at your option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with this program. If not, see <http://www.gnu.org/licenses/>
-%%
--module(prodcons).
-
--compile(export_all).
-
-start() ->
- eresye:start(pc),
- spawn(prodcons, cons_1, [1]),
- spawn(prodcons, cons_1, [2]),
- spawn(prodcons, cons_1, [3]),
- spawn(prodcons, prod, [0]),
- ok.
-
-prod(20) -> ok;
-prod(Index) ->
- eresye:assert(pc, {item, Index}), prod(Index + 1).
-
-cons(20) -> ok;%eres:stop (pc);
-cons(Index) ->
- Fact = eresye:wait_and_retract(pc,
- {item, fun (X) -> X == Index end}),
- %%eres:retract (pc, Fact),
- io:format("Consumer ~p~n", [Fact]),
- cons(Index + 1).
-
-cons_1(N) ->
- Fact = eresye:wait_and_retract(pc, {item, '_'}),
- %%eres:retract (pc, Fact),
- io:format("~w: Consumer ~p~n", [N, Fact]),
- timer:sleep(random:uniform(500)),
- cons_1(N).
View
87 examples/eresye/relatives.erl
@@ -1,87 +0,0 @@
-%%
-%%relatives.erl
-%%
-%%-------------------------------------------------------------------------
-%%
-%% ERESYE, an ERlang Expert SYstem Engine
-%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com)
-%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it)
-%%
-%% This program is free software: you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation, either version 3 of the License, or
-%% (at your option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with this program. If not, see <http://www.gnu.org/licenses/>
-%%
--module(relatives).
-
--compile([export_all]).
-
-%%
-%% if (X is female) and (X is Y's parent) then (X is Y's mother)
-%%
-mother(Engine, {female, X}, {parent, X, Y}) ->
- eresye:assert(Engine, {mother, X, Y}).
-
-%%
-%% if (X is male) and (X is Y's parent) then (X is Y's father)
-%%
-father(Engine, {male, X}, {parent, X, Y}) ->
- eresye:assert(Engine, {father, X, Y}).
-
-%%
-%% if (Y and Z have the same parent X) and (Z is female)
-%% then (Z is Y's sister)
-%%
-sister(Engine, {parent, X, Y}, {parent, X, Z},
- {female, Z})
- when Y =/= Z ->
- eresye:assert(Engine, {sister, Z, Y}).
-
-%%
-%% if (Y and Z have the same parent X) and (Z is male)
-%% then (Z is Y's brother)
-%%
-brother(Engine, {parent, X, Y}, {parent, X, Z},
- {male, Z})
- when Y =/= Z ->
- eresye:assert(Engine, {brother, Z, Y}).
-
-%%
-%% if (X is Y's father) and (Y is Z's parent)
-%% then (X is Z's grandfather)
-%%
-grandfather(Engine, {father, X, Y}, {parent, Y, Z}) ->
- eresye:assert(Engine, {grandfather, X, Z}).
-
-%%
-%% if (X is Y's mother) and (Y is Z's parent)
-%% then (X is Z's grandmother)
-%%
-grandmother(Engine, {mother, X, Y}, {parent, Y, Z}) ->
- eresye:assert(Engine, {grandmother, X, Z}).
-
-start() ->
- eresye:start(relatives),
- lists:foreach(fun (X) ->
- eresye:add_rule(relatives, {?MODULE, X})
- end,
- [mother, father, brother, sister, grandfather,
- grandmother]),
- eresye:assert(relatives,
- [{male, bob}, {male, corrado}, {male, mark},
- {male, caesar}, {female, alice}, {female, sara},
- {female, jane}, {female, anna}, {parent, jane, bob},
- {parent, corrado, bob}, {parent, jane, mark},
- {parent, corrado, mark}, {parent, jane, alice},
- {parent, corrado, alice}, {parent, bob, caesar},
- {parent, bob, anna}, {parent, sara, casear},
- {parent, sara, anna}]),
- ok.
View
70 examples/eresye/sample.erl
@@ -1,70 +0,0 @@
-%%
-%%sample.erl
-%%
-%%-------------------------------------------------------------------------
-%%
-%% ERESYE, an ERlang Expert SYstem Engine
-%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com)
-%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it)
-%%
-%% This program is free software: you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation, either version 3 of the License, or
-%% (at your option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with this program. If not, see <http://www.gnu.org/licenses/>
-%%
--module(sample).
-
--export([rule/4, rule1/3, rule2/4, start/0, start1/0,
- start2/0]).
-
--include("sample.hrl").
-
-rule(Engine, {hello, world}, {ciao, X}, {X, 10}) ->
- io:format("Hit!\n"), ok.
-
-rule1(Engine, {hello, world}, {ciao, X} = F) ->
- io:format("Hit 1!\n"),
- eresye:assert(Engine, {test}),
- eresye:retract(Engine, F),
- ok;
-rule1(Engine, {hello, world}, {test}) ->
- io:format("Hit 2!\n"), ok.
-
-rule2(Engine, {hello, world}, #sample_record{a = Z} = X,
- {mondo, Z}) ->
- io:format("Hit 3! ~p\n", [X]), ok.
-
-start() ->
- eresye:start(myengine),
- %% Z = fun (Engine, Fact) ->
- %% io:format ("FUN!~p~n", [Fact])
- %% end,
- %% gen_server:call (myengine, {add_rule,
- %% {Z, 0},
- %% {["{ciao,mondo}"], []}}),
- eresye:add_rule(myengine, {sample, rule2}),
- eresye:assert(myengine, [{ciao, mondo}, {mondo, 20}]),
- eresye:assert(myengine, {hello, world}),
- eresye:assert(myengine, {ok, world}),
- eresye:assert(myengine, #sample_record{a = 10, b = 50}),
- %%eresye:add_rule (myengine, {sample, rule}),
- %%eresye:add_rule (myengine, {sample, rule1}),
- ok.
-
-%% spawn (sample, start2, []).
-
-start1() ->
- eresye:retract(myengine, {test}),
- eresye:assert(myengine, {test}).
-
-start2() ->
- F = eresye:wait(myengine, {ok, '_'}),
- io:format("Got it ~p~n", [F]).
View
53 examples/eresye/sieve.erl
@@ -1,53 +0,0 @@
-%%
-%%sieve.erl
-%%
-%%-------------------------------------------------------------------------
-%%
-%% ERESYE, an ERlang Expert SYstem Engine
-%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com)
-%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it)
-%%
-%% This program is free software: you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation, either version 3 of the License, or
-%% (at your option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with this program. If not, see <http://www.gnu.org/licenses/>
-%%
--module(sieve).
-
--compile([export_all]).
-
-remove_multiple(Engine, {X}, {Y})
- when (X rem Y == 0) and (X =/= Y) ->
- eresye:retract(Engine, {X}).
-
-final_rule(Engine, {is, started} = X)
- when not ["{is, finished}"]; true ->
- eresye:retract(Engine, X),
- eresye:assert(Engine, {is, finished}).
-
-start() ->
- eresye:start(sieve),
- eresye:assert(sieve, [{X} || X <- lists:seq(2, 100)]),
- eresye:assert(sieve, {is, started}),
- eresye:add_rule(sieve, {sieve, remove_multiple}, 2),
- eresye:add_rule(sieve, {sieve, final_rule}, 1),
- Start = now(),
- eresye:wait_and_retract(sieve, {is, finished}),
- End = now(),
- io:format("KB: ~p~n", [eresye:get_kb(sieve)]),
- io:format("Rules fired: ~p~n",
- [{ok, R} = eresye:get_rules_fired(sieve)]),
- D = timer:now_diff(End, Start),
- io:format("Time = ~p sec, ~p rules/sec, rule execution "
- "time ~p msec~n",
- [D / 1.0e+6, R / (D / 1.0e+6), D / 1.0e+3 / R]),
- eresye:stop(sieve),
- ok.
View
45 examples/eresye/wine.erl
@@ -1,45 +0,0 @@
--module(wine).
-
--include("wine.hrl").
-
--export([childof/1, is_a/2, is_class/1, redwine/1,
- wine/1]).
-
-is_class(wine_grape) -> true;
-is_class(wine) -> true;
-is_class(redwine) -> true;
-is_class(whitewine) -> true;
-is_class('Chianti') -> true;
-is_class(_) -> false.
-
-is_a(redwine, wine) -> true;
-is_a(whitewine, wine) -> true;
-is_a('Chianti', redwine) -> true;
-is_a('Chianti', wine) -> true;
-is_a(_, _) -> false.
-
-childof(wine_grape) -> [];
-childof(wine) -> [redwine, whitewine, 'Chianti'];
-childof(redwine) -> ['Chianti'];
-childof(whitewine) -> [];
-childof('Chianti') -> [];
-childof(_) -> exit(undef_class).
-
-wine(X = #redwine{}) ->
- #wine{name = X#redwine.name, body = X#redwine.body,
- color = X#redwine.color, flavor = X#redwine.flavor,
- grape = X#redwine.grape, sugar = X#redwine.sugar};
-wine(X = #whitewine{}) ->
- #wine{name = X#whitewine.name, body = X#whitewine.body,
- color = X#whitewine.color, flavor = X#whitewine.flavor,
- grape = X#whitewine.grape, sugar = X#whitewine.sugar};
-wine(X = #'Chianti'{}) ->
- #wine{name = X#'Chianti'.name, body = X#'Chianti'.body,
- color = X#'Chianti'.color, flavor = X#'Chianti'.flavor,
- grape = X#'Chianti'.grape, sugar = X#'Chianti'.sugar}.
-
-redwine(X = #'Chianti'{}) ->
- #redwine{name = X#'Chianti'.name,
- body = X#'Chianti'.body, color = X#'Chianti'.color,
- flavor = X#'Chianti'.flavor, grape = X#'Chianti'.grape,
- sugar = X#'Chianti'.sugar}.
View
42 examples/eresye/wine_sample.erl
@@ -1,42 +0,0 @@
-%%
-%%wine_sample.erl
-%%
-%%-------------------------------------------------------------------------
-%%
-%% ERESYE, an ERlang Expert SYstem Engine
-%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com)
-%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it)
-%%
-%% This program is free software: you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation, either version 3 of the License, or
-%% (at your option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with this program. If not, see <http://www.gnu.org/licenses/>
-%%
--module(wine_sample).
-
--compile(export_all).
-
--include("wine.hrl").
-
-start() ->
- eresye:start(wine, wine),
- eresye:add_rule(wine, {wine_sample, rule, 1}),
- %%eresye:assert (wine, #wine {name = "Vino"}),
- eresye:assert(wine, #'Chianti'{}),
- eresye:assert(wine, #wine_grape{}),
- ok.
-
-stop() -> eresye:stop(wine).
-
-%% rule (Engine, #wine{name = 'Vino'} = W) ->
-%% io:format ("~p~n", [W]);
-rule(Engine, #wine{} = W) -> io:format("~p~n", [W]);
-rule(Engine, W) -> io:format("~p~n", [W]).
View
4 rebar.config
@@ -2,5 +2,7 @@
%% {sub_dirs, ["examples/simple"]}.
%% {erl_opts, [{src_dirs, ["examples/simple"]}]}.
{erl_opts, [nowarn_unused_vars]}.
-{deps, [{misultin, "0.9-dev", {git, "https://github.com/gleber/misultin.git", "master"}}]}.
+{deps, [{misultin, "0.9-dev", {git, "https://github.com/gleber/misultin.git", "master"}},
+ {seresye, "0.0.4", {git, "https://github.com/gleber/seresye.git", "master"}}
+ ]}.
View
85 src/Makefile
@@ -1,85 +0,0 @@
-#
-# Makefile
-#
-
-EBIN=../ebin
-
-include ../Makefile.conf
-
-.SUFFIXES: .erl .beam
-
-OBJS=\
-ontology.beam \
-ontology_service.beam \
-fipa_ontology_sl_codec.beam \
-sl_parser.beam \
-sl.beam \
-mtp.beam \
-exat.beam \
-acl.beam \
-agent.beam \
-fipa_semantics_simple.beam \
-match_lib.beam \
-semantics.beam \
-envelope.beam \
-mtp.beam \
-exat_app.beam \
-exat_sup.beam \
-exat_server.beam \
-logger.beam \
-object.beam \
-eventmanager.beam \
-sync.beam \
-multisync.beam \
-ams.beam \
-pingagent.beam \
-pingeragent.beam \
-http_parser.beam \
-http_server.beam \
-media_type.beam \
-eresye_agenda.beam \
-eresye.beam \
-eresye_ontology_resolver.beam \
-eresye_tree_list.beam
-
-
-
-ERL_OBJS=$(foreach file, $(OBJS), $(EBIN)/$(file))
-
-OTHER_OBJS=
-FIND=find
-
-all: $(ERL_OBJS) $(OTHER_OBJS)
- cp exat.app $(EBIN)
-
-fipa_ontology_sl_codec.erl: $(EBIN)/ontology.beam ../priv/fipa_ontology.onto
- (cd ../priv; \
- erl -noshell -pa ../ebin -eval \
- 'ontology:compile ("fipa_ontology", [include, sl_codec]),halt ().'; \
- mv fipa_ontology.hrl ../include; \
- mv fipa_ontology_sl_codec.erl ../src; \
- cd ../src)
-# (cd ../priv; \
-# sh compile_fipa_ontology.sh fipa_ontology; \
-# mv fipa_ontology.hrl ../include; \
-# mv fipa_ontology_sl_codec.erl ../src; \
-# cd ../src)
-
-http_parser.erl: http_parser.yrl
- $(YRL) $<
-
-media_type.erl: media_type.yrl
- $(YRL) $<
-
-sl_parser.erl: sl_parser.yrl
- $(YRL) $<
-
-$(EBIN)/%.beam: %.erl
- $(BEAM) $<
-
-clean:
- @(cd $(EBIN); $(RM) -f *.beam)
-
-clearbak:
- @$(FIND) . -type f -name \*~ -exec rm {} \;
-
View
455 src/agent.erl
@@ -1,455 +0,0 @@
-%%
-%% agent.erl
-%%
-%% ----------------------------------------------------------------------
-%%
-%% eXAT, an erlang eXperimental Agent Tool
-%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it)
-%%
-%% This program is free software: you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation, either version 3 of the License, or
-%% (at your option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with this program. If not, see <http://www.gnu.org/licenses/>
-
--module(agent).
-
--behaviour(gen_server).
-
--include("object.hrl").
-
--include("acl.hrl").
-
--include("fipa_ontology.hrl").
-
--export([behave/2, get_acl_semantics/1, get_behaviour/1,
- get_message/1, get_mind/1, get_property/2, join/1, kill/1,
- match_message/2, new/2, send_message/4, set_behaviour/2,
- set_property/3, set_rational/3, stop/1]).
-
--export([init/1, code_change/3, handle_call/3, handle_cast/2,
- handle_info/2, terminate/2]).
-
--define(AGENT_BEHAVIOURS, '__AGENT_BEHAVIOURS').
-
--define(AGENT_DETACHED_BEHAVIOURS,
- '__AGENT_DETACHED_BEHAVIOURS').
-
-new(AgentName) ->
- gen_server:start({local, AgentName}, agent,
- [AgentName, [],
- dict:store(?AGENT_DETACHED_BEHAVIOURS, [], dict:new()),
- []],
- []),
- ok.
-
-new(AgentName, Parameters) ->
- new(AgentName),
- Rationality = prop(Parameters, rationality),
- Behaviour = prop(Parameters, behaviour),
- if Rationality =/= nil ->
- {Mind, Semantics} = Rationality,
- agent:set_rational(AgentName, Mind, Semantics);
- true -> nil
- end,
- if Behaviour =/= nil ->
- agent:set_behaviour(AgentName, Behaviour);
- true -> nil
- end,
- ok.
-
-prop([], _) -> nil;
-prop([{Key, Value} | T], Key) -> Value;
-prop([_ | T], Key) -> prop(T, Key).
-
-%%
-%% MAIN CALLS
-%%
-behave(AgentOrObject, Behaviour) ->
- Agent = extract_agent_identifier(AgentOrObject),
- CurrentBehaviour = get_behaviour(Agent),
- %% BehaviourObject = object:new(Behaviour),
- %% set_property(Agent, ?AGENT_BEHAVIOUR, BehaviourObject),
- %% object:bind(BehaviourObject, Agent),
- %% object:start(BehaviourObject),
- %% object:join(BehaviourObject),
- %% object:delete(BehaviourObject),
- set_behaviour(Agent, Behaviour),
- join(Agent),
- set_property(Agent, ?AGENT_BEHAVIOURS,
- CurrentBehaviour),
- ok.
-
-get_behaviour(Agent) ->
- get_property(Agent, ?AGENT_BEHAVIOURS).
-
-set_behaviour(Agent, Behaviours)
- when is_list(Behaviours) ->
- BehaviourObjectList = create_behaviours(Agent,
- Behaviours, []),
- set_property(Agent, ?AGENT_BEHAVIOURS,
- BehaviourObjectList),
- start_behaviours(BehaviourObjectList),
- ok;
-set_behaviour(Agent, Behaviour)
- when is_atom(Behaviour) ->
- set_behaviour(Agent, [Behaviour]).
-
-start_behaviours([]) -> ok;
-start_behaviours([{BehaviourObject, detached}
- | Tail]) ->
- object:start(BehaviourObject), start_behaviours(Tail);
-start_behaviours([BehaviourObject | Tail]) ->
- object:start(BehaviourObject), start_behaviours(Tail).
-
-create_behaviours(_, [], Acc) -> Acc;
-create_behaviours(Agent,
- [{BehaviourName, detached} | Tail], Acc) ->
- BehaviourObject = object:new(BehaviourName),
- object:bind(BehaviourObject, Agent),
- DetachedBehaviours = get_property(Agent,
- ?AGENT_DETACHED_BEHAVIOURS),
- set_property(Agent, ?AGENT_DETACHED_BEHAVIOURS,
- [BehaviourObject | DetachedBehaviours]),
- create_behaviours(Agent, Tail,
- [{BehaviourObject, detached} | Acc]);
-create_behaviours(Agent, [BehaviourName | Tail], Acc) ->
- BehaviourObject = object:new(BehaviourName),
- object:bind(BehaviourObject, Agent),
- create_behaviours(Agent, Tail, [BehaviourObject | Acc]).
-
-join(Agent) ->
- BehaviourObject = get_property(Agent,
- ?AGENT_BEHAVIOURS),
- join_list(BehaviourObject),
- set_property(Agent, ?AGENT_BEHAVIOURS, nil),
- ok.
-
-join_list(nil) -> ok;
-join_list([]) -> ok;
-join_list([{BehaviourObject, detached} | Tail]) ->
- join_list(Tail);
-join_list([BehaviourObject | Tail]) ->
- object:join(BehaviourObject),
- object:delete(BehaviourObject),
- join_list(Tail).
-
-set_property(Agent, Property, Value) ->
- gen_server:call(Agent, [set_property, Property, Value]).
-
-get_property(Agent, Property) ->
- gen_server:call(Agent, [get_property, Property]).
-
-get_message(Agent) ->
- gen_server:cast(Agent, [getmessage, self()]),
- receive X -> X end.
-
-match_message(Agent, Pattern) ->
- gen_server:cast(Agent,
- [match_message, Pattern, self()]),
- receive X -> X end.
-
-send_message(nil, ReceiverAgent, Mode, Message) ->
- gen_server:call(ReceiverAgent, [Mode, Message]), ok;
-send_message(SenderAgent, ReceiverAgent, Mode,
- Message) ->
- SenderAgentName = extract_agent_identifier(SenderAgent),
- %%io:format("name = ~w\n", [SenderAgentName]),
- R = agent:get_property(SenderAgentName, rationality),
- CanSend = if R == nil -> true;
- true ->
- [Engine, Semantics] = R,
- %%io:format("Semantics = ~w,~w,~w\n",
- %% [Engine, Semantics, SenderAgentName]),
- object:call(Semantics, is_feasible,
- [SenderAgentName, Engine, Message])
- end,
- %%io:format("Cansend = ~w\n", [CanSend]),
- if CanSend ->
- perform_message_sending(ReceiverAgent, [Mode, Message]),
- ok;
-%%% FIXME!!!! This is not for a distributed environment?????
- true -> error
- end.
-
-extract_agent_identifier(AgentOrObject)
- when is_record(AgentOrObject, 'agent-identifier') ->
- AgentOrObject#'agent-identifier'.name;
-extract_agent_identifier(AgentOrObject)
- when is_record(AgentOrObject, object) ->
- extract_agent_identifier(object:agentof(AgentOrObject));
-extract_agent_identifier(AgentOrObject) ->
- AgentOrObject.
-
-perform_message_sending(ReceiverAgent, [Mode, Message])
- when is_record(ReceiverAgent, 'agent-identifier') ->
- mtp:http_mtp_encode_and_send(Message);
-perform_message_sending(ReceiverAgent,
- [Mode, Message]) ->
- gen_server:call(ReceiverAgent, [Mode, Message]).
-
-set_rational(AgentOrObject, EngineName,
- SemanticsClass) ->
- SemanticsObject = object:new(SemanticsClass),
- %% io:format("Semantic Object = ~w\n", [SemanticsObject]),
- Agent = extract_agent_identifier(AgentOrObject),
- set_property(Agent, rationality,
- [EngineName, SemanticsObject]).
-
-get_mind(AgentOrObject) ->
- Agent = extract_agent_identifier(AgentOrObject),
- %%io:format("Agent = ~w\n", [Agent]),
- [EngineName, SemanticsObject] = get_property(Agent,
- rationality),
- EngineName.
-
-get_acl_semantics(AgentOrObject) ->
- Agent = extract_agent_identifier(AgentOrObject),
- Semantics = get_property(Agent, rationality),
- if Semantics == nil -> nil;
- true ->
- [EngineName, SemanticsObject] = get_property(Agent,
- rationality),
- SemanticsObject
- end.
-
-stop(Agent) ->
- agent:join(Agent),
- Semantics = get_acl_semantics(Agent),
- if Semantics =/= nil -> object:delete(Semantics);
- true -> nil
- end,
- gen_server:cast(Agent, stop),
- ok.
-
-kill(Agent) ->
- BehaviourObject = get_property(Agent,
- ?AGENT_BEHAVIOURS),
- kill_list(BehaviourObject),
- DetachedBehaviourObject = get_property(Agent,
- ?AGENT_DETACHED_BEHAVIOURS),
- kill_list(DetachedBehaviourObject),
- set_property(Agent, ?AGENT_BEHAVIOURS, nil),
- Semantics = get_acl_semantics(Agent),
- if Semantics =/= nil -> object:delete(Semantics);
- true -> nil
- end,
- gen_server:cast(Agent, stop),
- ok.
-
-kill_list(nil) -> ok;
-kill_list([]) -> ok;
-kill_list([{BehaviourObject, detached} | Tail]) ->
- object:delete(BehaviourObject), kill_list(Tail);
-kill_list([BehaviourObject | Tail]) ->
- object:delete(BehaviourObject), kill_list(Tail).
-
-%%
-%% CALLBACKS
-%%
-
-%%
-%% Initialize
-%%
-init(State) ->
- [AgentName | _] = State,
- ams:register_agent(AgentName),
- {ok, State}.
-
-%%
-%% Terminate
-%%
-terminate(normal, State) ->
- [AgentName | _] = State,
- ams:de_register_agent(AgentName),
- ok.
-
-%%
-%% Code Change
-%%
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-%%
-%% Gets a property from agent
-%%
-handle_call([get_property, PropertyName], From,
- [AgentName, AclQueue, AgentDict, ProcessQueue]) ->
- Value = a__get_prop(AgentDict, PropertyName),
- {reply, Value,
- [AgentName, AclQueue, AgentDict, ProcessQueue]};
-%%
-%% Sets a property
-%%
-handle_call([set_property, PropertyName, PropertyValue],
- From, [AgentName, AclQueue, AgentDict, ProcessQueue]) ->
- A1 = a__set_prop(AgentDict, PropertyName,
- PropertyValue),
- {reply, ok, [AgentName, AclQueue, A1, ProcessQueue]};
-%%
-%% Receives an ACL message in String format
-%%
-handle_call([acl, Acl], From,
- [AgentName, AclQueue, AgentDict, ProcessQueue]) ->
- %%io:format("[Agent] Received ACL=~s\n", [Acl]),
- case catch acl:parse_message(Acl) of
- {'EXIT', Reason} ->
- %%io:format("[Agent] Error in ACL parsing\n"),
- R = [AgentName, AclQueue, AgentDict, ProcessQueue];
- ParsedMessage ->
- %%io:format("[Agent] ACL parsed OK\n"),
- {AclQueue1, ProcessQueue1} = perform_re(AgentName,
- AgentDict, ParsedMessage,
- AclQueue, ProcessQueue),
- R = [AgentName, AclQueue1, AgentDict, ProcessQueue1]
- end,
- {reply, ok, R};
-%%
-%% Receives an ACL message in Erlang format
-%%
-handle_call([acl_erl_native, Acl], From,
- [AgentName, AclQueue, AgentDict, ProcessQueue]) ->
- %%io:format("[Agent] Received ACL=~w\n", [Acl]),
- {AclQueue1, ProcessQueue1} = perform_re(AgentName,
- AgentDict, Acl, AclQueue,
- ProcessQueue),
- {reply, ok,
- [AgentName, AclQueue1, AgentDict, ProcessQueue1]}.
-
-%%
-%% Retrieves a message from the queue(or waits for the message)
-%%
-handle_cast([getmessage, From],
- [AgentName, AclQueue, AgentDict, ProcessQueue]) ->
- if length(AclQueue) > 0 ->
- ProcessQueue1 = ProcessQueue,
- [Message | AclQueue1] = AclQueue,
- catch From ! Message;
- true ->
- ProcessQueue1 = ProcessQueue ++ [{nil, From}],
- AclQueue1 = AclQueue
- end,
- {noreply,
- [AgentName, AclQueue1, AgentDict, ProcessQueue1]};
-%%
-%% Retrieves a matching message from the queue
-%% (or waits for a matching message)
-%%
-handle_cast([match_message, Pattern, From],
- [AgentName, AclQueue, AgentDict, ProcessQueue]) ->
- {Sent, NewAclQueue} = find_matching_message(AclQueue,
- Pattern, From, []),
- if Sent ->
- AclQueue1 = NewAclQueue, ProcessQueue1 = ProcessQueue;
- true ->
- ProcessQueue1 = ProcessQueue ++ [{Pattern, From}],
- AclQueue1 = AclQueue
- end,
- %% if
- %% length(AclQueue) > 0 ->
- %% ProcessQueue1 = ProcessQueue,
- %% [Message | AclQueue1] = AclQueue,
- %% catch(From ! Message);
- %% true ->
- %% ProcessQueue1 = ProcessQueue ++ [{Pattern, From}],
- %% AclQueue1 = AclQueue
- %% end,
- {noreply,
- [AgentName, AclQueue1, AgentDict, ProcessQueue1]};
-%%
-%% Stops the agent process
-%%
-handle_cast(stop, State) -> {stop, normal, State}.
-
-%%
-%% Any message handler
-%%
-handle_info(Any, State) -> {stop, {unknown_info, Any}, State}.
-
-%%
-%% OTHER FUNCTIONS
-%%
-a__set_prop(AgentDict, Property, Value) ->
- dict:store(Property, Value, AgentDict).
-
-a__get_prop(AgentDict, Property) ->
- case dict:find(Property, AgentDict) of
- {ok, Value} -> Value;
- Other -> nil
- end.
-
-%%
-%% finds a matching message and sends it
-%%
-find_matching_message([], Pattern, Process, NewQueue) ->
- {false, lists:reverse(NewQueue)};
-find_matching_message([Message | MessageTail], Pattern,
- Process, NewQueue) ->
- Match = match_lib:match_acl(Pattern, Message),
- if Match ->
- catch Process ! Message,
- {true, lists:reverse(NewQueue) ++ MessageTail};
- true ->
- find_matching_message(MessageTail, Pattern, Process,
- [Message | NewQueue])
- end.
-
-%%
-%% forwards a message to the process requesting a match
-%%
-forward_to_maching_process(Message, [],
- NewProcessQueue) ->
- {false, lists:reverse(NewProcessQueue)};
-forward_to_maching_process(Message,
- [{nil, Process} | ProcessQueueTail],
- NewProcessQueue) ->
- catch Process ! Message,
- {true,
- lists:reverse(NewProcessQueue) ++ ProcessQueueTail};
-forward_to_maching_process(Message,
- [{Pattern, Process} | ProcessQueueTail],
- NewProcessQueue) ->
- Match = match_lib:match_acl(Pattern, Message),
- if Match ->
- catch Process ! Message,
- {true,
- lists:reverse(NewProcessQueue) ++ ProcessQueueTail};
- true ->
- forward_to_maching_process(Message, ProcessQueueTail,
- [{Pattern, Process} | NewProcessQueue])
- end.
-
-forward_or_enqueue(AclQueue, ProcessQueue, Message) ->
- {Forwarded, NewProcessQueue} =
- forward_to_maching_process(Message, ProcessQueue, []),
- if Forwarded ->
- {AclQueue1, ProcessQueue1} = {AclQueue,
- NewProcessQueue};
- true ->
- ProcessQueue1 = ProcessQueue,
- AclQueue1 = AclQueue ++ [Message]
- end,
- {AclQueue1, ProcessQueue1}.
-
-perform_re(Agent, AgentDict, Message, AclQueue,
- ProcessQueue) ->
- R = a__get_prop(AgentDict, rationality),
- CanEnqueue = if R == nil -> true;
- true ->
- [Engine, Semantics] = R,
- %% io:format("Semantics = ~w\n", [Semantics]),
- object:call(Semantics, rational_effect,
- [Agent, Engine, Message]),
- true
- end,
- if CanEnqueue ->
- forward_or_enqueue(AclQueue, ProcessQueue, Message);
- true -> {AclQueue, ProcessQueue}
- end.
View
84 src/ams.erl
@@ -35,51 +35,43 @@
-module(ams).
--export([action/2, event/2, extends/0, pattern/2,
- request_proc/4]).
-
-export([de_register_agent/1, get_registered_agents/0,
register_agent/1, start_link/0]).
--include("acl.hrl").
+-behaviour(simple_agent).
--include("fipa_ontology.hrl").
+-export([code_change/3, handle_acl/2, handle_call/3,
+ handle_cast/2, handle_info/2, init/2,
+ terminate/2]).
-extends() -> nil.
+-include_lib("exat/include/acl.hrl").
-pattern(Self, request) ->
- [#aclmessage{speechact = 'REQUEST',
- ontology = "FIPA-Agent-Management",
- protocol = "fipa-request"}].
+-include_lib("exat/include/fipa_ontology.hrl").
-event(Self, request_event) -> {acl, request}.
+-record(state, {}).
-action(Self, start) -> [{request_event, request_proc}].
+handle_acl(#aclmessage{speechact = 'REQUEST',
+ ontology = "FIPA-Agent-Management",
+ protocol = "fipa-request"} = Message,
+ State) ->
+ lists:foreach(fun(Content) ->
+ ContentReply = prepare_reply(Content),
+ spawn(fun () -> acl:reply(Message, 'INFORM', ContentReply) end)
+ end, Message#aclmessage.content),
-request_proc(Self, EventName, Message, ActionName) ->
- %%io:format("Received msg ~w\n", [Message]),
- Content = Message#aclmessage.content,
- %%io:format("Received from ~w -> ~w\n",
- %% [Message#aclmessage.sender, Content]),
- ContentReply = prepare_reply(Content),
- %%io:format("Reply ~w~n", [ContentReply]),
- acl:reply(Message, 'INFORM', ContentReply).
+ {noreply, State}.
-prepare_reply([Content = #action{'1' =
- #'get-description'{}}]) ->
+prepare_reply(Content = #action{'1' = #'get-description'{}}) ->
logger:log('AMS', "get-description"),
APService = #'ap-service'{name =
"fipa.mts.mtp.http.std",
type = "fipa.mts.mtp.http.std",
addresses = mtp:addresses()},
- APDescription = #'ap-description'{name =
- exat:current_platform(),
+ APDescription = #'ap-description'{'name' = exat:current_platform(),
'ap-services' = [APService]},
- Result = #result{'0' = Content, '1' = [APDescription]},
- [Result];
-prepare_reply([Content = #action{'1' =
- #search{'0' =
- #'ams-agent-description'{}}}]) ->
+ #result{'0' = Content, '1' = [APDescription]};
+
+prepare_reply(Content = #action{'1' = #search{'0' = #'ams-agent-description'{}}}) ->
logger:log('AMS', "search ams-agent-description"),
Agents = [#'agent-identifier'{name = X,
addresses = mtp:addresses()}
@@ -88,45 +80,57 @@ prepare_reply([Content = #action{'1' =
ownership = "NONE",
state = "active"}
|| X <- Agents],
- %%io:format("DS ~w~n", [Descriptions]),
- Result = #result{'0' = Content, '1' = Descriptions},
- [Result].
+ #result{'0' = Content, '1' = Descriptions}.
%%====================================================================
%% Func: start_link/0
%% Returns: {ok, Pid}.
%%====================================================================
start_link() ->
+ simple_agent:new(ams, ams, [{behaviour, ams}]).
+
+init(ams, Params) ->
logger:start('AMS'),
logger:log('AMS', "Staring AMS."),
ontology_service:register_codec("FIPA-Agent-Management",
fipa_ontology_sl_codec),
- agent:new(ams, [{behaviour, ams}]),
- [BehaviourObject] = agent:get_behaviour(ams),
- Pid = object:executorof(BehaviourObject),
- {ok, Pid}.
+ {ok, #state{}}.
+
+handle_call(Call, _From, State) ->
+ {reply, {error, unknown_call}, State}.
+
+handle_cast(_Call, State) ->
+ {reply, {error, unknown_cast}, State}.
+
+handle_info(Msg, State) ->
+ {noreply, State}.
+
+code_change(_, _, _) -> erlang:error(notimp).
+
+terminate(_Reason, _State) ->
+ ok.
%%====================================================================
%% Func: register_agent/1
%% Returns: ok.
%%====================================================================
register_agent(AgentName) ->
- eresye:assert(agent_registry, {agent, AgentName}).
+ seresye:assert(agent_registry, {agent, AgentName}).
%%====================================================================
%% Func: de_register_agent/1
%% Returns: ok.
%%====================================================================
de_register_agent(AgentName) ->
- eresye:retract(agent_registry, {agent, AgentName}).
+ seresye:retract(agent_registry, {agent, AgentName}).
%%====================================================================
%% Func: get_registered_agents/0
%% Returns: [string()].
%%====================================================================
get_registered_agents() ->
- AgentList = eresye:query_kb(agent_registry,
- {agent, '_'}),
+ AgentList = seresye:query_kb(agent_registry,
+ {agent, '_'}),
AgentLocalNames = [X || {_, X} <- AgentList],
PlatformName = exat:current_platform(),
[lists:flatten([atom_to_list(X), "@", PlatformName])
View
1,364 src/eresye.erl
@@ -1,1364 +0,0 @@
-%%
-%% eresye.erl
-%%
-%% ----------------------------------------------------------------------
-%%
-%% ERESYE, an ERlang Expert SYstem Engine
-%% Copyright (C) 2005-07 Francesca Gangemi (francesca@erlang-consulting.com)
-%% Copyright (C) 2005-07 Corrado Santoro (csanto@diit.unict.it)
-%%
-%% This program is free software: you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation, either version 3 of the License, or
-%% (at your option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with this program. If not, see <http://www.gnu.org/licenses/>
-%%
-%%
--module(eresye).
-
--behaviour(gen_server).
-
-%%====================================================================
-%% Include files
-%%====================================================================
-
-%%====================================================================
-%% External exports
-%%====================================================================
-
--export([add_rule/2, add_rule/3, assert/2, get_kb/1,
- get_ontology/1, get_rete/1, get_rules_fired/1,
- query_kb/2, remove_rule/2, retract/2, retract_match/2,
- retract_select/2, start/1, start/2, start_link/1,
- stop/1, wait/2, wait_and_retract/2]).
-
-%%====================================================================
-%% Internal exports
-%%====================================================================
-
--export([code_change/3, handle_call/3, handle_cast/2, handle_info/2,
- init/1, terminate/2]).
-
-%%====================================================================
-%% External functions
-%%====================================================================
-%%====================================================================
-%% Func: start/1
-%% Arguments: Engine Name
-%%====================================================================
-start(EngineName) ->
- gen_server:start({local, EngineName}, ?MODULE,
- [EngineName, nil], []).
-
-%%====================================================================
-%% Func: start/2
-%% Arguments: Engine Name, Ontology
-%%====================================================================
-start(EngineName, Ontology) ->
- gen_server:start({local, EngineName}, ?MODULE,
- [EngineName, Ontology], []).
-
-%%====================================================================
-%% Func: start_link/1
-%% Arguments: Engine Name
-%%====================================================================
-start_link(EngineName) ->
- gen_server:start_link({local, EngineName}, ?MODULE,
- [EngineName, nil], []).
-
-%%====================================================================
-%% Func: stop/1
-%% Arguments: Engine Name
-%%====================================================================
-stop(EngineName) -> gen_server:call(EngineName, {stop}).
-
-%%====================================================================
-%% Func: assert/2
-%% Arguments: EngineName, FactToAssert or FactList
-%%====================================================================
-assert(EngineName, Fact) when is_list(Fact) ->
- [assert(EngineName, F) || F <- Fact], ok;
-assert(EngineName, Fact) when is_tuple(Fact) ->
- gen_server:call(EngineName, {assert, Fact}).
-
-%%====================================================================
-%% Func: retract/2
-%% Arguments: EngineName, FactToRetract or FactList
-%%====================================================================
-retract(EngineName, Fact) when is_list(Fact) ->
- [retract(EngineName, F) || F <- Fact];
-retract(EngineName, Fact) when is_tuple(Fact) ->
- gen_server:call(EngineName, {retract, Fact}).
-
-retract_match(EngineName, MS) ->
- gen_server:call(EngineName, {retract_match, MS}).
-
-retract_select(EngineName, MS) ->
- gen_server:call(EngineName, {retract_select, MS}).
-
-%%====================================================================
-%% Func: add_rule/2
-%% Arguments: EngineName, Rule
-%%====================================================================
-add_rule(Name, Fun) -> add_rule(Name, Fun, 0).
-
-%%====================================================================
-%% Func: add_rule/3
-%% Arguments: EngineName, Rule, Salience
-%%====================================================================
-add_rule(Name, {Module, Fun, ClauseID}, Salience) ->
- add_rule(Name, {Module, Fun}, ClauseID, Salience);
-add_rule(Name, {Module, Fun}, Salience) ->
- add_rule(Name, {Module, Fun}, 0, Salience).
-
-add_rule(Name, Fun, ClauseID, Salience) ->
- Ontology = get_ontology(Name),
- case get_conds(Fun, Ontology, ClauseID) of
- error -> error;
- CondsList ->
- lists:foreach(fun (X) ->
- case X of
- {error, Msg} ->
- io:format(">> add_rule->get_conds error!!!~n~w:~s~n",
- [Fun, Msg]);
- {PConds, NConds} ->
- % io:format(">> PConds=~p~n",[PConds]),
- % io:format(">> NConds=~p~n",[NConds]),
- gen_server:call(Name,
- {add_rule,
- {Fun, Salience},
- {PConds, NConds}})
- end
- end,
- CondsList),
- ok
- end.
-
-%%====================================================================
-%% Func: remove_rule/2
-%% Arguments: EngineName, Rule
-%%====================================================================
-remove_rule(Name, Rule) ->
- gen_server:call(Name, {remove_rule, Rule}).
-
-%%====================================================================
-%% Func: wait/2
-%% Arguments: EngineName, PatternToMatch
-%%====================================================================
-wait(Name, Pattern) ->
- wait_retract(Name, Pattern, false).
-
-%%====================================================================
-%% Func: wait_and_retract/2
-%% Arguments: EngineName, PatternToMatch
-%%====================================================================
-wait_and_retract(Name, Pattern) ->
- wait_retract(Name, Pattern, true).
-
-wait_retract(Name, Pattern, NeedRetract)
- when is_tuple(Pattern) ->
- PList = tuple_to_list(Pattern),
- SList = [term_to_list(X) || X <- PList],
- FunList = [if is_function(X) -> X;
- true -> fun (_) -> true end
- end
- || X <- PList],
- %%io:format ("SList = ~p~n", [SList]),
- [_ | DList] = lists:foldl(fun (X, Sum) ->
- lists:concat([Sum, ",", X])
- end,
- [], SList),
- PidHash = erlang:phash2(self()),
- ClientCondition =
- lists:flatten(io_lib:format("{client, ~p, Pid, FunList}",
- [PidHash])),
- FinalPattern = [ClientCondition,
- lists:concat(["{", DList, "}"])],
- RetractString = if NeedRetract ->
- "eresye:retract (Engine, Pattern__),";
- true -> ""
- end,
- SFun =
- lists:flatten(io_lib:format("fun (Engine, {client, ~p, Pid, FunList} "
- "= X, Pattern__) -> FunPatPairs = lists:zip "
- "(FunList, tuple_to_list (Pattern__)), "
- "FunEval = [F(X) || {F, X} <- FunPatPairs], "
- "A = lists:foldr (fun (X,Y) -> X and "
- "Y end, true, FunEval), if A -> eresye:retract "
- "(Engine, X), ~s Pid ! Pattern__; "
- "true -> nil end end.",
- [PidHash, RetractString])),
- %%io:format ("Fun = ~p~n", [SFun]),
- %%io:format ("Pattern = ~p~n", [FinalPattern]),
- Fun = evaluate(SFun),
- gen_server:call(Name,
- {add_rule, {Fun, 0}, {FinalPattern, []}}),
- %%io:format ("Rete is ~p~n", [eresye:get_rete (Name)]),
- eresye:assert(Name, {client, PidHash, self(), FunList}),
- receive Pat -> Pat end,
- %% if
- %% NeedRetract -> eresye:retract (Name, Pat);
- %% true -> ok
- %% end,
- gen_server:call(Name, {remove_rule, Fun}),
- Pat.
-
-term_to_list(X) when is_integer(X) ->
- integer_to_list(X);