A proposal for the use of procedures in logic programming using Notation 3
Author: Guido Naudts E-mail:naudts_vannoten@yahoo.com
The proposal intends to introduce procedures with variable replacement in logic
programming while at the same time enhancing the efficiency of inferencing
and the modularity of the programming.
Syntax
The namespace proc: used is defined as:
@prefix proc: <proctest#>.
Syntax of procedure declaration:
<myproc> proc:variables (?x1 ?x2 ... ?xn);
proc:proc {a_tripleset}; proc:query {a_tripleset}.
Syntax of procedure call:
<myproc> proc:call (?a ?b ... ?q).
The intention is that the proc:call variables list is substituted in sequence for the
proc:variables list in the procedure declaration. Then the query is used together with the
initial substitution for inferencing with the tripleset defined after proc:proc.
The result (there can be more than one) is a list of substitutions or a failure (could be
indicated by an empty list).
The examples will clarify the intended result.
This definition is such that as well backward as forward reasoning can be used.
This could be indicated by a parameter eg proc:method "backward".
The proc:query could be omitted but only with forward reasoning; this is why I did not select
this.
Examples:
1)
Procedure:
:cube proc:variables (?a ?b);
proc:proc { {(?a ?a) math:product ?b1} => {[:result ?b1]}};
proc:query {[:result ?b]}.
Procedure call:
# ?z should become "16".
:cube proc:call ("4" ?z).
2)
Procedure:
# calculate ax + b
:line proc:variables (?a ?b ?x ?z);
proc:proc {
{(?a ?x) math:product _:y.
(_:y ?b) math:sum ?z1.} => {[:result ?z1]}};
proc:query {[:result ?z]}.
Procedure call:
# following should return "13" for ?z.
:line proc:call ("2" "3" "5" ?z).
In a rule (example, not implemented):
{[:displacement ?b].:line proc:call ("2" "3" ?b ?z). ?z math:greaterThan "20".} =>
{[:alert "The maximum value has been reached."]}.
3)An example with a recurrent call
Procedure:
# calculate n! res must be "1" when called
:factorial proc:variables (?n ?res);
proc:proc {
{ ?n math:greaterThan "1".
(?n "-1") math:sum ?y.
:factorial proc:call (?y ?z).
(?z ?n) math:product ?res}
=> {[:result ?res]}.
{?n math:equalTo "1"} => {[:result "1"] }};
proc:query {[:result ?res]}.
Procedure call:
# following should return 24 = 4! for ?result.
:factorial proc:call ("4" ?result).
Advantages:
* inferencing on small sets of data and rules
* procedures with variable replacement
* modularity
* ease of use
* still logical programming (neverwhere any order (sequence) of triples)
* together with proc:semantics a library of modules containing
many procedures can be made.
Caveat
The procedure variables must be global variables within the procedure, but
unknown outside the procedure. If two rules within the same procedure use the same variable
the name of that variable should not become different in the two rules because
of variable renumbering. I use the variable prefix "_:" for that.
Feasability
A demonstration of the above three testcases can be found on:
eulermoz.sourceforge.net/eulermoz/rdftest/
An explanation of the program is found in mozengine.html.
Double click on testInf.xul and then select testcases proctest, proctest2 and proctest3.
Correctness
The procedure call is really a subinferencing process with exactly the same characteristics as
the main process (same definition of input, same definition of output). In fact the same modules
are used (JsEngine.js and Forward.js) so the logic characteristics are identical.