View difference between Paste ID: CCsZgZvf and G9QhADgm
SHOW: | | - or go back to the newest paste.
1
%% Backward chaining
2
3
-module(backward).
4
-export([start/0,mainLoop/0,solveGoal/2,solveRule/2,collect/3]).
5
6
start() ->
7
	%% Initialize KB
8
	ets:new(rules, [bag, named_table]),
9
	ets:insert(rules, {g,[d,e,f,h,i,j],1.0}),
10
	ets:insert(rules, {g,[a,b,c],1.1}),
11
	ets:insert(rules, {a,[],0.1}),
12
	ets:insert(rules, {b,[],0.2}),
13
	ets:insert(rules, {c,[],0.3}),
14
	ets:insert(rules, {d,[],0.4}),
15
	ets:insert(rules, {e,[],0.5}),
16
	ets:insert(rules, {f,[],0.6}),
17
	ets:insert(rules, {h,[],0.7}),
18
	ets:insert(rules, {i,[],0.8}),
19
	ets:insert(rules, {j,[],0.9}),
20
	mainLoop().
21
22
mainLoop() ->
23
	Query = io:read("Enter query: "),
24-
	solveGoal(element(2, Query), self()),
24+
	if
25
		Query == {ok, x} -> exit(normal);
26-
		{_, Truth} -> io:format("Answer is: ~w~n", [Truth])
26+
		true -> ok
27
	end,
28
	Daddy = spawn(backward, solveGoal, [element(2, Query), self()]),
29
	receive
30
		{_, Truth} -> io:format("Answer is: ~w~n", [Truth]),
31
					  exit(Daddy, ok)
32
	end,
33
	mainLoop().
34
35
solveGoal(Goal, Caller) ->
36
    %% Fetch rules...
37
	ApplicableRules = ets:match(rules,{Goal, '$1', '$2'}),
38
	lists:foreach(
39-
			true -> spawn(backward, solveRule, [RuleBody, self()])
39+
40
		if 
41
			%% If RHS is null
42
			RuleBody == [] -> Caller ! {Goal, Truth};
43
			%% If RHS contains subgoals
44
			true -> spawn_link(backward, solveRule, [RuleBody, self()])
45-
		{_, Truth} -> Caller ! {Goal, Truth}
45+
46
		ApplicableRules),
47
	receive
48
		%% Each message is of the form {goal,truth}
49
		%% Just accept the 1st answer
50-
	Collector = spawn(backward, collect, [[], N, Caller]),
50+
		{_, Truth} -> Caller ! {Goal, Truth}		  
51
	end.
52
53
solveRule(RuleTail, Caller) ->
54-
		fun(Subgoal) -> spawn(backward, solveGoal, [Subgoal, Collector]) end,
54+
55
	Collector = spawn_link(backward, collect, [[], N, Caller]),
56
	%% For each subgoal in Rule
57
	%% Spawn a process to solve each subgoal
58
	lists:foreach(
59
		fun(Subgoal) -> spawn_link(backward, solveGoal, [Subgoal, Collector]) end,
60
		RuleTail).
61-
	if length(Truths) == N -> Caller ! {dont_care, lists:min(Truths)};
61+
62
%% Accumulate results
63
collect(Truths, N, Caller) ->
64
	%% If we have N messages send back the answer
65
	%% Answer = min of truth values, equivalent to fuzzy-logic AND
66
	if length(Truths) == N -> Caller ! {dont_care, lists:sum(Truths)};
67
	   true -> true
68
	end,
69
	receive
70
		{_, Truth} -> collect([Truth | Truths], N, Caller)
71
	end.