SHOW:
|
|
- or go back to the newest paste.
| 1 | - | ;; Backward Chaining |
| 1 | + | %% Backward chaining |
| 2 | ||
| 3 | - | (ns backward) |
| 3 | + | -module(backward). |
| 4 | - | (import '(java.util.concurrent Executors ExecutorCompletionService)) |
| 4 | + | -export([start/0,mainLoop/0,solveGoal/2,solveRule/2,collect/3]). |
| 5 | ||
| 6 | - | (declare start solve-goal solve-rule collect unify) |
| 6 | + | start() -> |
| 7 | %% Initialize KB | |
| 8 | - | ; Choose between using parallel collect or sequential collect. |
| 8 | + | ets:new(rules, [bag, named_table]), |
| 9 | - | (def use-parallel-collect true) |
| 9 | + | ets:insert(rules, {g,[d,e,f,h,i,j],1.0}),
|
| 10 | ets:insert(rules, {g,[a,b,c],1.1}),
| |
| 11 | - | (def completion-service (ExecutorCompletionService. |
| 11 | + | ets:insert(rules, {a,[],0.1}),
|
| 12 | - | (Executors/newCachedThreadPool))) |
| 12 | + | ets:insert(rules, {b,[],0.2}),
|
| 13 | ets:insert(rules, {c,[],0.3}),
| |
| 14 | - | (defn start [] |
| 14 | + | ets:insert(rules, {d,[],0.4}),
|
| 15 | - | (loop [] |
| 15 | + | ets:insert(rules, {e,[],0.5}),
|
| 16 | - | (print "Enter query: ") (flush) |
| 16 | + | ets:insert(rules, {f,[],0.6}),
|
| 17 | - | (let [query (read-line) |
| 17 | + | ets:insert(rules, {h,[],0.7}),
|
| 18 | - | truth (solve-goal (symbol query))] |
| 18 | + | ets:insert(rules, {i,[],0.8}),
|
| 19 | - | (printf "Answer is: %s\n" truth)) |
| 19 | + | ets:insert(rules, {j,[],0.9}),
|
| 20 | - | (recur))) |
| 20 | + | mainLoop(). |
| 21 | ||
| 22 | - | (defn fetch-rules [goal] |
| 22 | + | mainLoop() -> |
| 23 | - | (case goal |
| 23 | + | Query = io:read("Enter query: "),
|
| 24 | - | g '[[a,b,c],[d,e,f]] |
| 24 | + | solveGoal(element(2, Query), self()), |
| 25 | - | a '[[e,f]] |
| 25 | + | receive |
| 26 | - | b '[[c,d,e,f]] |
| 26 | + | {_, Truth} -> io:format("Answer is: ~w~n", [Truth])
|
| 27 | - | c '[[e,f]] |
| 27 | + | end, |
| 28 | - | d '[[e,f]] |
| 28 | + | mainLoop(). |
| 29 | - | e '[[]] |
| 29 | + | |
| 30 | - | f '[[]] |
| 30 | + | solveGoal(Goal, Caller) -> |
| 31 | - | true (throw (Exception. "No applicable rule")))) |
| 31 | + | %% Fetch rules... |
| 32 | ApplicableRules = ets:match(rules,{Goal, '$1', '$2'}),
| |
| 33 | - | (defn solve-goal [goal] |
| 33 | + | lists:foreach( |
| 34 | - | (let [rules (fetch-rules goal)] |
| 34 | + | fun([RuleBody,Truth]) -> |
| 35 | - | (if (some empty? rules) |
| 35 | + | if |
| 36 | - | 1.0 ; return a truth value |
| 36 | + | %% If RHS is null |
| 37 | - | (do |
| 37 | + | RuleBody == [] -> Caller ! {Goal, Truth};
|
| 38 | - | (doseq [rule rules] |
| 38 | + | %% If RHS contains subgoals |
| 39 | - | (.submit completion-service #(solve-rule rule))) |
| 39 | + | true -> spawn(backward, solveRule, [RuleBody, self()]) |
| 40 | - | (.get (.take completion-service)))))) |
| 40 | + | end end, |
| 41 | ApplicableRules), | |
| 42 | - | ; Move minimization logic here from collect. |
| 42 | + | receive |
| 43 | - | (defn solve-rule [rule-tail] |
| 43 | + | %% Each message is of the form {goal,truth}
|
| 44 | - | (let [truths (collect solve-goal rule-tail)] |
| 44 | + | %% Just accept the 1st answer |
| 45 | - | (apply + truths))) |
| 45 | + | {_, Truth} -> Caller ! {Goal, Truth}
|
| 46 | end. | |
| 47 | - | ; Accumulate results |
| 47 | + | |
| 48 | - | (def collect (if use-parallel-collect pmap map)) |
| 48 | + | solveRule(RuleTail, Caller) -> |
| 49 | N = length(RuleTail), | |
| 50 | Collector = spawn(backward, collect, [[], N, Caller]), | |
| 51 | %% For each subgoal in Rule | |
| 52 | %% Spawn a process to solve each subgoal | |
| 53 | lists:foreach( | |
| 54 | fun(Subgoal) -> spawn(backward, solveGoal, [Subgoal, Collector]) end, | |
| 55 | RuleTail). | |
| 56 | ||
| 57 | %% Accumulate results | |
| 58 | collect(Truths, N, Caller) -> | |
| 59 | %% If we have N messages send back the answer | |
| 60 | %% Answer = min of truth values, equivalent to fuzzy-logic AND | |
| 61 | if length(Truths) == N -> Caller ! {dont_care, lists:min(Truths)};
| |
| 62 | true -> true | |
| 63 | end, | |
| 64 | receive | |
| 65 | {_, Truth} -> collect([Truth | Truths], N, Caller)
| |
| 66 | end. |