Presentation on theme: "Database Manipulation Section 7.4. Prolog Knowledge Base n Knowledge base = database –set of facts/rules in the program n Can add/subtract facts and rules."— Presentation transcript:
Database Manipulation Section 7.4
Prolog Knowledge Base n Knowledge base = database –set of facts/rules in the program n Can add/subtract facts and rules at run time n Adding facts/rules –assert, asserta, assertz n Subtracting facts/rules –retract, retractall
Asserting a Fact n Just tell prolog that it’s so ?- raining. ERROR: Undefined procedure: raining/0 ?- assert(raining). Yes ?- raining. Yes n Prolog didn’t know about raining/0
Preparing Prolog for a Predicate n Need to tell Prolog that the predicate exists –helpful also to say that it may have rules added n Give a directive in the program file –a command to Prolog :- dynamic raining/0. n Says that raining/0 is a predicate –prevents the error message
Dynamic Predicates n Can be done during session ?- dynamic foggy/0. Yes ?- foggy. No n Note how we call goals in a file :- dynamic foggy/0. –can do that with any query
Asserting Rules n Just give rule instead of fact –use parentheses if rule is compound (to prevent confusion about the comma) ?- assert(raining). ?- assert(bad :- raining ; foggy). ?- assert(nice :- (sunshine, \+ cold)). ?- bad. Yes
Assertion Order n assert/1 puts the fact/rule in the database –order is implementation dependent –(SWI-Prolog puts it at the end) n asserta/1 puts fact/rule in front n assertz/1 puts fact/rule at end
Assertion Order ?- assert(num(1)). ?- assertz(num(2)). ?- asserta(num(0)). ?- assertz(num(3)). ?- num(X). X = 0 ; X = 1 ; X = 2 ; X = 3 Adds num(1) to database Adds num(2) to end of DB Adds num(0) to front of DB Adds num(3) to end of DB num(1). num(2). num(0). num(3).
Assertion Order Exercise ?- asserta(what(1)). ?- assertz(what(2)). ?- asserta(what(3)). ?- assertz(what(4)). ?- asserta(what(5)). ?- what(X). X = ? ;
Exercise n Write a predicate that asks the user for a person’s parents & asserts those facts ?- add_parents(mark). Who is mark’s father? bob. Who is mark’s mother? isabel. Yes ?- father(mark, Dad), mother(mark, Mom). Dad = bob, Mom = isabel
Retraction n Tell Prolog to remove a fact/rule ?- raining. Yes ?- retract(raining). Yes ?- raining. No
Retracting Rules n As for asserting rules –use parentheses if body is compound –body may be a variable/partly instantiated ?- retract(bad :- raining ; foggy). ?- retract(nice :- Body). Body = sunshine, \+ raining Yes
Retraction Order n From first to last ?- retract(num(N)), retract(num(M)). N = 0 M = 1 Yes n retract fails if no clause matches
Retracting All Clauses n rectractall/1 retracts multiple clauses –all clauses with head matching the argument ?- num(N). N = 0 ?- retractall(num(N)). Yes ?- num(N). No Note:also gets rules ?- assert(bad :- member(1,)). Yes ?- bad. Yes ?- retractall(bad). Yes ?- bad. No
Asserting and Retracting n Used for AI programs that learn –create a new rule & add it to the database –forget an old rule n Can also be used for efficiency –asserta solutions previously found –found before general code called
Naïve Fibonacci fib(1, 1). fib(2, 1). fib(N, F) :- N > 2, N1 is N – 1, fib(N1, F1), N2 is N – 2, fib(N2, F2), F is F1 + F2.
Trace fib(5,F) fib(5, F 0 ) fib(4, F 1 ) fib(3, F 2 ) fib(2, F 3 ) F 3 = 1 fib(1, F 4 ) F 4 = 1 fib(2, F 5 ) F 5 = 1 fib(3, F 2 ) fib(2, F 3 ) F 3 = 1 fib(1, F 4 ) F 4 = 1 fib(3, F) gets calculated again extra work done much worse as #s get bigger
Assertional Fibonacci (8.5.4) fib2(1, 1). fib2(2, 1). fib2(N, F) :- N > 2, N1 is N – 1, fib2(N1, F1), N2 is N – 2, fib2(N2, F2), F is F1 + F2, asserta( fib2(N, F) ).% remember the result % at the beginning
Trace fib2(5,F) fib2(5, F 0 ) fib2(4, F 1 ) fib2(3, F 2 ) fib2(2, F 3 ) F 3 = 1 fib2(1, F 4 ) F 4 = 1 asserta( fib2(3, 2) ) fib2(2, F 5 ) F 5 = 1 asserta( fib2(4, 3) ) fib2(3, F 6 ) F 6 = 2 asserta( fib2(5, 5) ) Saves work from calculating fib(3) Matches asserted fact – no need to recalculate
Problems for Asserting Solutions n Backtracking gives multiple solutions –saved solution found first –then solution re-calculated –and re-asserted: solution there twice, now –next time there’ll be three solutions n Adding a cut to the solution might help –asserta( fib2(F, N) :- ! ).
Generating Facts n Multiplication table make_table :- \+ (L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], member(X, L), member(Y, L), Z is X * Y, assert(product(X, Y, Z)), fail).
Using the Multiplication Table n Now have 100 multiplication facts ?- product(X, Y, 12). X = 2, Y = 6 ; X = 3, Y = 4 ; X = 4, Y = 3 ; X = 6, Y = 2 ; No
Asserts on Calls in Progress n Suppose assert or assertz a clause of a predicate that’s in progress –is that clause considered for that call? strange(N) :- assertz(strange(N)),fail. n Does strange(3) succeed or fail? –or throw an exception
Speed of Dynamic Predicates n Dynamic predicates may be slower than static (dynamic = can change, static = can’t) n Prolog may have a better way for remembering solutions –remember or record predicates to memorize –recall or recorded to recall –forget or erase to forget
Remembering Solutions n One clause (near front) to look for remembered solutions –cut if find one n Remember solution after it’s calculated
Remembering Fibonacci fib_mem(0, 1). fib_mem(1, 1). fib_mem(N, F) :- recorded(fibonacci, fib(N, F)), !. fib_mem(N, F) :- N > 1, succ(N1, N),fib_mem(N1, F1), succ(N2, N1),fib_mem(N2, F2), succ(N2, N1),fib_mem(N2, F2), F is F1 + F2,recorda(fibonacci, fib(N, F)). F is F1 + F2,recorda(fibonacci, fib(N, F)).
Recording n recorda/2, recordz/2 store 2 nd argument –use 1 st argument as a key –you can record same fact under multiple keys –key is integer or atom (or term – but no good) n recorded/2 retrieves fact –needs key – only retrieves facts under that key –matches fact – only those that match selected
Erasing/Forgetting n recorded/3 also gives a memory location n Can use the location to erase the record ?- recorded(fibonacci, fib(500,_), Mem), erase(Mem).Yes n Can only erase one item at a time –don’t erase anything more than once
Versions of Fibonacci n Vanilla version is very slow –and only works on a few numbers n Remembering version quite fast –even faster when asking a second time n Single recursion version very fast –but second time takes as long as first ?- time(fib(20, F)), time(fib2(20, F)), time(fib_mem(20, F)).
Looking at Code n Program can inspect its own code n clause/2 returns clauses of program –1 st argument is the head of the rule –2 nd argument is the body –at least one argument must be given
Clause/2 sibs(Sib1, Sib2) :-parent(Sib1, P), parent(Sib2, P), different(Sib1, Sib2). different(X, Y) :- X \= Y. ?- clause(sibs(_, _), Body). Body = parent(_1,_2), parent(_3,_2), different(_1,_3) ?- clause(Head, _A \= _B). Head = different(_1,_2) Note: this last one doesn’t seem to work in SWI-Prolog
Compound Bodies n Body is a term – a comma term ?- (a, b, c, d) = (X, Y). X = a Y = b, c, d n Needs to be in parentheses when 2 nd arg. ?- clause(sibs(_,_), (parent(_,_), _) ). Yes Is there a clause of sibs/2 with a body like parent(_,_), …
Bodies of Facts n Puts true/0 in for body of fact parent(mark, alex). parent(bob, mark). parent(X, brian) :- parent(X, mark). ?- clause(parent(X, Y), Body). X = mark, Y = alex, Body = true ; X = bob, Y = mark, Body = true ; X = _1, Y = brian, Body = parent(_1,mark)
Looking at Built-in Code n Some built-in predicates are available ?- clause(member(X,Y), Body). X = _1, Y = [_1|_2], Body = true ; X = _1, Y = [_2|_3], Body = member(_1, _3) n Others are hidden ?- clause(clause(A,B), Body). ERROR: No permission to access private_procedure `clause/2'
Modifying Code n Replace every rule of the form –H :- …, different(X,Y), … n with –H :- …, X \= Y, … n (where the other bits don’t change) n Maybe for efficiency –H should be specified (else errors ensue)
Method for Modifying Code n Find a rule with matching head –Note: predicate must be dynamic n If it has a different(X,Y) in it, –replace it with X \= Y –retract old rule –assert new rule
Modifying Code ?- modify_rule(sib(_,_), different(X,Y), X\=Y). before: sib(A, B) :- parent(A,C),parent(B,C),different(A,B). n Problem – only modifies one clause! after: sib(A, B) :- parent(A,C),parent(B,C), A \= B.
Modifying All Clauses n Prolog prints bindings –ask for another solution –Prolog backs up to clause/2 & gets another rule –then changes that rule n Keep asking for answers until all done –it works – will stop when no rule has Old in it –it’s sort of like a loop
“Failure Driven Loops” n Need to make a change, then fail –Prolog will try another clause n Have predicate make a change, then fail –it will change all the rules before saying No n Says No even tho’ it worked! –if we put \+ in front, it’ll say Yes instead! –that’s more intuitive for user
Modify All modify_all(Head, Old, New) :- \+ modify_and_fail(Head, Old, New). modify_and_fail(Head, Old, New) :- modify_rule(Head, Old, New), fail. OR Just modify_all(Head, Old, New) :- \+ (modify_rule(Head, Old, New), fail).
Remaining Problem n too_different/3 is not fully changed –replace_code only changes first Old to New –backtracking doesn’t pick up new clause n Try to fix by making replace_code change all –unexpected side-effect: all X\=Y made the same –too_different(A,A,A) :- A\=A, A\=A, A\=A. n Too complicated for us!