================================================================= Net-Clause Prolog Interpreter V2.0 (Standard Prolog + NCL) ================================================================= This document contains a short reference manual of the Net-Clause Language (NCL) interpreter. The following items are included: I. NCL overview II. The Prolog built-in procedures related to NCL III. The standard Prolog built-in procedures IV. List of publications related to NCL V. How to install and use the NCL/Prolog interpreter VI. Address for further information ================================================================= I. NCL overview ================================================================= The Net-Clause language is embedded in standard Prolog. Its syn- tax can be expressed in Prolog syntax as shown below: ::= : ::= [] | : ::= | | ::= ::= node(,,) ::= | ~ | , | ,~ ::= ::= ::= default(,) | default(,,) ::= => . ::= | : ----------------------------------------------------------------- 1. Net-Clauses ----------------------------------------------------------------- A net-clause can be seen as a network built out of free nodes, spreading activation nodes and default nodes. The variables oc- curring within a net-clause, the net-variables, are global logi- cal variables. They can be shared among the net-clause nodes thus playing the role of network connections linking the nodes. All types of net-clause nodes are generally accessible by the stan- dard Prolog database mechanism (e.g. by "assert", "retract", "clause", "listing" etc.). 1.1. Free Nodes --------------- The free nodes are just Prolog facts that can share variables in the scope of a net-clause. For example: a(X):b(Y):c(X+Y). /* A net-clauses built out of free nodes */ ?- a(1),b(2),c(X). /* An NCL/Prolog query accessing the nodes */ X=1+2 /* The answer of the NCL/Prolog interpreter */ The free node variables can be used for storing and accessing in- termediate results from different places in a NCL/Prolog program. Here is an illustration of using open-ended lists for that pur- pose: res(R):[]. /* One-node net-clause */ ?- res(X),member(a,X),member(b,X). X=[a,b|_1] 1.2. Spreading activation nodes ------------------------------- Consider the following node: node(X1,...,Xn,T,Goal) Depending on the form in which each Xi (i=1,...n) occurs, the threshold T is increased or decreased when Xi is bound to a non- variable term. Namely: - when Xi occurring as Xi is bound then T:=T-1; - when Xi occurring as ~Xi is bound then T:=T+1. The Goal is executed when the condition T=<0 becomes true. (Thus node(~X,~1,Goal) and node(X,1,Goal) are equivalent.) The follow- ing query illustrates this process: a(X): b(Y): c(Z): node(X,~Y,Z,1,(write(X-Y-Z),nl)). ?-a(a),node(_,_,_,M,_),b(b),node(_,_,_,N,_),c(c),node(_,_,_,K,_). a - _1 - _2 a - b - c M=0 N=1 K=0 1.3. Backtracking ----------------- If a procedure in a spreading activation node fails, the goals which have bound the variables contributing to its execution also fail. This is a way of ensuring the consistency between the bind- ings of the variables occurring in a spreading activation node and its procedure. Here is an example of using backtracking for sorting three numbers (the node procedures define the condition X>Y>Z, which is ensured by backtracking among the goals in the query and the free nodes in the net-clause): /* The Net-clause */ n(X): n(Y): n(Z): node(X,Y,2,X>Y): node(Y,Z,2,Y>Z). /* A query activating the net-clause and delivering the result */ ?- n(2),n(1),n(3),bagof(X,n(X),L). X=_1 L=[3,2,1] 1.4. Modes of backtracking -------------------------- The built-in procedure "netmode(Mode)" defines the current mode of backtracking, where: Mode=0 - No node procedures are executed; Mode=1 - Node procedures are executed without backtracking (no matter whether they succeed or fail). Mode=2 - For successful binding of a net-variable AT LEAST ONE of the node procedures activated by this bind- ing should succeed. Mode=3 - For successful binding of a net-variable ALL of the (DEFAULT) node procedures activated by this binding should succeed. 1.5. Breadth-first spreading activation --------------------------------------- Consider the following semantic net and its implementation as a net-clause. b / \ q / \ r / p \ s a ------ c ------ d /* A net-clause */ a(A): b(B): c(C): d(D): node(A,1,p(c([p(a,c)|A]))): node(A,1,p(b([q(a,b)|A]))): node(B,1,p(c([r(b,c)|B]))): node(C,1,p(d([s(c,d)|C]))). /* Prolog definition of the node procedure */ p(P):-P. /* Call the neighboring node */ p(P):-P=..[F,A],Q=..[F,B],Q, /* Indicate that markers meet */ write(A-and-B-'meet at'-F),nl. This net-clause implements a "marker passing" algorithm, where the marker is a list containing the path which it has passed through the network. Furthermore the node procedures can indicate when two markers meet. For example: ?- a([]),d(X). [p(a,c)] - and - [r(b,c),q(a,b)] - meet at - c X=d([s(c,d),r(b,c),q(a,b)]) Note that this path (in reverse order) is not the shortest one between "a" and "d". This is because in Mode=3 (the default mode) the spreading activation process works in a depth-first fashion (the procedures of the activated nodes are executed immediately after the activation). A breadth-first mode (all procedures of the active nodes are ex- ecuted before to proceed to the nodes activated by their execu- tion) of the spreading activation scheme is also available. Con- sider the following example: ?- netmode(0). /* Switch off the depth-first mode */ ?- top(T),a([]),spread(T),d(X). [r(b,c),q(a,b)] - and - [p(a,c)] - meet at - c X=d([s(c,d),p(a,c)]) Now we obtain the shortest path between "a" and "d". The breadth-first mode is implemented by the built-in procedure "spread(Level)", where its argument is a level in the stack of active goals. Thus by the conjunction "top(Level),, spread(Level)" we define the scope where the breadth-first spreading activation takes place. This means that all nodes ac- tivated by net-variables bound by work in a breadth-first mode. (All the other nodes activated by the latter nodes work in the same mode too.) 1.6. Default nodes ------------------ The default nodes specify the default control mechanism in NCL - a control scheme based on net-variable sharing (unifying two cur- rently free net-variables). We shall illustrate this by an ex- ample: a(X): d(X): b(Y): c(Z): default(X,Y,(integer(Z),Y=Z)): default(Y,0). The default mechanism is activated when an attempt to unify a currently free net-variable with another free net-variable, i.e. this is a request for information, currently not available. Con- sider net-variable X and the following ways to get its value: 1. ?- b(def_val),a(V). V=def_val The default value Y is supplied by calling node "b". Then the default mechanism unifies X with the binding of Y. 2. ?- c(10),a(V). V=10 The variable Z is bound by calling node "c". Then since Y is free it obtains its value by executing the default node procedure "integer(Z),Y=Z" (it terminates successfully). 3. ?- c(abc),a(V). V=0 4. ?- a(V). V=0 The default node procedure fails (because "integer(abc)" fails or in query 4 because Z is free and so, "integer(Z)" fails too). Then since Y is free its default value 0 is taken and passed to X. This is actually a default hierarchy, X <- Y <- 0. 5. ?- a(V),d(new_val),a(NewV). V=0 NewV=newval The obtained default value is overridden by a new value entered directly through a shared variable by calling node "d". The above examples show the priorities of the different sources of obtaining default values - decreasing form 1 to 4. Note that in all these cases the net-variable X is used just as a channel to propagate a default value to the NCL/Prolog query, but it remains unbound. Thus it can later be bound. This is illustrated by the last query (5), which shows the non-monotonicity of the default activation mechanism in NCL. 1.7. Pattern generalization --------------------------- NCL provides a built-in mechanism for generalization of ground terms, called pattern generalization. This operation is defined as follows: Let P be an expression, E - a ground expression and s = {X1/t1, X2/t2, ...,Xn/tn} - a substitution, such that Ps=E. Pattern generalization of E w.r.t. P, denoted by EgP, is the ex- pression Pr, where r is a variable-pure substitution r={Xi/Xj, for all i>j, such that ti=tj}. The expression P is called pattern for generalization and r - specialization substitution. For example, let E=f(a,b,g(a,b)), P=f(A,B,C), Q=f(A,B,g(C,D)). Then EgP=f(A,B,C) and EgQ=f(A,B,g(A,B)), i.e. the patterns P and Q specify which sub-terms within E are subject to generalization. The above definition actually describes a procedure for building a generalization of an expression. In this respect it relates to the inverse substitution, which instead of a pattern uses places to select the arguments to be replaced by variables. The pattern generalization allows for ordering of ground expres- sions based on comparing their generalizations w.r.t. a common pattern, defined as follows: Let E1 and E2 are ground expressions both unifiable with expression P. Then E1 is more general than E2 w.r.t. P, denoted by E1 >P> E2, if E1gP > E2gP (">" means more general in the usual sense, i.e. there exists a substitution s, such that (E1gP)s = E2gP ). It can be proven that E1 >P> E2 iff there exists a substitution s such that E2=(E1gP)s. For example, the expressions E1=f(1,2),f(2,3),f(3,4) is more general than E2=f(a,b),f(b,c),f(c,a) w.r.t. P=f(U,V),f(W,X),f(Y,Z), i.e. an open path of three edges in a graph is more general than a closed one (E1gP=f(U,V),f(W,X),f(Y,Z), s={U/a,V/b, W/b,X/c,Y/c,Z/a}). The basic idea of the implementation of pattern generalization is the following. All Prolog implementations support a special stack for storing the variable bindings. We use this stack to access the variables to be shared (applying the specialization substitution). The net-clause plays the role of the pattern for generalization (P), and the expression being generalized (E) is a conjunction of Prolog goals, unifying free nodes in the net- clause. The substitution s is determined by the set of variable bindings, obtained by unification of E with P. To define this set NCL provides two built-in procedures: "top(Marker)" and "gen(Marker)". Procedure "top" returns a marker to the current top of the stack and "gen" applies the specialization substitu- tion (r) to the variables whose bindings are stored in the stack beginning with the marker (the variables occurring in the domain of the substitution s). The result of the generalization is the modified net-clause, i.e. P becomes EgP. Here are examples of comparing the two ground expressions men- tioned above. /*---------------- Check for E1 >P> E2 -------------------*/ f(U,V): /* P is the current net-clause */ f(W,X): f(Y,Z). ?- top(M),f(1,2),f(2,3),f(3,4),gen(M). /* E1gP */ ?- net(X). /* Show the current net-clause */ X=f(_1,_2) : f(_2,_3) : f(_3,_4) ?- f(a,b),f(b,c),f(c,a). /* find s, such that E2=(E1gP)s */ yes /* s exists => E1 >P> E2 */ ?- /*---------------- Check for E2 >P> E1 -------------------*/ f(U,V): /* P is the current net-clause */ f(W,X): f(Y,Z). ?- top(M),f(a,b),f(b,c),f(c,a),gen(M). /* E2gP */ ?- net(X). /* Show the current net-clause */ X=f(_1,_2) : f(_2,_3) : f(_3,_1) ?- f(1,2),f(2,3),f(3,4). /* find s, such that E1=(E2gP)s */ no /* s does not exist => E1 >P> E2 is not true */ ?- The pattern generalization operation in NCL can be used to create connections in a net-clause or between different net-clauses. The following NCL program illustrates an approach to learning from examples in the domain of geometric figures. /* Unconnected segments for building geometric figures */ s(Vertex1,Vertex2,Length):[]. s(Vertex1,Vertex2,Length):[]. ... /* More free segments */ ... /* Concept nodes for geometric figures */ node(A,B,C,D,4,fig(parallelogram)):[]. node(A,B,C,D,4,fig(rhombus)):[]. ... /* Further concept nodes */ ... fig(X):[]. /* Training instance for a rhombus */ ?- top(T),s(a,b,5),s(b,c,5),s(c,d,5),s(d,a,5), node(a,b,c,d,_,fig(rhombus)),gen(T). ... /* Further training instances */ ... /* Recognition of an unknown geometric figure */ ?- s(1,2,99),s(2,3,99),s(3,4,99),s(4,1,99),fig(X). X=rhombus ----------------------------------------------------------------- 2. DD-Rules ----------------------------------------------------------------- The declarative semantics of the DD-rules is directly connected with the Horn clause semantics. A DD-rule is equivalent to a program clause in the Horn clause logic as shown below. A1:A2:...:An => B <--> B <- A1,A2,...,An. Prolog is also based on the Horn clause declarative semantics. However, while it implements the SLD-resolution strategy, the DD-rules execution mechanism implements the unit-resulting resolution (UR-resolution) strategy. The later is sound and com- plete. (Theoretically the SLD-resolution is also complete. However its practical implementations in the majority of the Prolog systems is not complete.) The DD-rule execution mechanism is similar to that of the spreading activation node. A DD-rule defines a condition for execution of the Prolog goal, specified at the right-hand side of the rule. This condition is based on availability and consistency of data. There are two types of data processed by DD-rules - dynamic and static. The dynamic data for a DD-rule are all Prolog goals unifiable with the free nodes in its left-hand side. Thus dynamic data can be specified in two ways - by goals in the NCL/Prolog query and by procedures of DD- rules. The static data are specified as Prolog facts. The main difference between dynamic and static data is that only dynamic data initiate the computation, i.e. activate DD-rules. Another difference is that the static data are permanent (as long as Prolog facts are permanent) and the dynamic ones exist until the DD-rules are active (i.e. until they are collecting and process- ing data). All dynamic data are stored in local databases. The free nodes in the left-hand side of a DD-rule play the role of communication gates to access these databases. Using these nodes the DD-rule collects data and checks for their consistency through the shared variables appearing in its left-hand side. A set of data is con- sistent for a DD-rule if the data unify simultaneously all free nodes in the left-hand side of the rule. The procedure in the right-hand side of the rule is executed for all consistent sets of data (both dynamic and static). Thus a DD-rule program genera- tes all solutions. The following example shows two ways of transforming a Horn clause program into a DD-rule one. /* A Horn clause program */ p(a,b) <- p(c,b) <- p(X,Z) <- p(X,Y),p(Y,Z) p(X,Y) <- p(Y,X) <- p(X,Y) /* DD-rule Program - Version 1 */ p(X,Y):p(Y,Z) => p(X,Z). p(X,Y) => p(Y,X). p(X,Y) => write(p(X,Y)),nl. /* Dynamic data, specified as an NCL/Prolog query */ ?- p(a,b),p(c,b). /* DD-rule Program - Version 2 */ s:p(X,Y):p(Y,Z) => p(X,Z). s:p(X,Y) => p(Y,X). s:p(X,Y) => write(p(X,Y)),nl. /* Static Data, specified as Prolog facts */ p(a,b). p(c,b). /* Dynamic data, specified as an NCL/Prolog query */ ?- s. Both versions of the program produce the following output: p(a,b) p(c,b) p(b,a) p(b,c) p(b,b) p(a,c) p(a,a) p(c,c) p(c,a) It is worth noting that this output is the complete semantics of the Horn clause program. This output however cannot be produced by a standard Prolog interpreter. This is because of the fixed computation and search rules used in the practical implementa- tions of the SLD-resolution, which makes the Prolog systems in- complete. 2.1. Local databases -------------------- A local database is a dynamic data structure existing until the DD-rules are active. It is defined implicitly by the free nodes appearing in the left-hand side of the DD-rules. The access to such a database is uniform - storing and retrieving data is based only on unification. The data are retrieved on successful unification. If a data item fails to match any of the records in the database, then it is stored in it. An important consequence of this access mechanism is that all data items stored in a local database are different. Here is an example of how a local database works: a(Key,Data) => true. ?- a(1,data1),a(2,data2),a(3,data3), /* Storing data */ a(2,X),a(1,Y). /* Accessing data */ X=data2 Y=data1 The contents of all local databases in a program can be deleted by using the built-in procedure "dellazy". (This procedure is also used in the lop level loop of the NCL/Prolog interpreter to initialize the local databases when a new query is processed.) 2.2. DD-rule parallel model (DD-rule = process) ----------------------------------------------- In contrast to the traditional parallel logic programming lan- guages (such as PARLOG for example) where the basic connection is "goal = process", in our model each DD-rule is a process. A DD- rule program can be viewed as a network of parallel "agents" (processes) which communicate through the local databases. In logic programming parallelism is discussed mostly as a concurrent execution of conjunctive goals (AND-parallelism) and a concurrent application of several clauses that match a goal (OR- parallelism). Both types of parallelism are "goal-oriented", while the DD-rule parallelism is "data-oriented". This means that each data item, newly stored in a local database, is processed simultaneously by all DD-rules connected to this local database. Though the DD-rules are data-oriented they can be used to imple- ment some types of classical Prolog parallelism. For example, consider the classical illustration of the stream AND-parallelism - the "sumtree" program. sumtree(T,N) <- flatten(T,P),sum(P,N). flatten(t(t(X,Y,Z),U,V),P) <- flatten(t(X,Y,t(Z,U,V)),P). flatten(t(e,N,Y),[N|P]) <- flatten(Y,P). flatten(e,[]). sum(Z,N) <- sigma(Z,0,N). sigma([N|P],M,S) <- plus(N,M,M1),sigma(P,M1,S). sigma([],N,N). In the stream AND parallel model this program works as follows. The goals "flatten(T,P)" and "sum(P,N)" incrementally communicate through the shared variable P. The "flatten" goal is a producer, which gradually creates a list of the labels of the tree T. When a new label is generated, the "sum" goal (the consumer) processes it immediately, not waiting for the whole list to be completed. In PARLOG for example, the process of producer-consumer synchronization is determined by mode declarations for the vari- able types (input or output) of the corresponding predicates. The DD-rule version of the "sumtree" program is the following: flatten(t(t(X,Y,Z),U,V),P) => flatten(t(X,Y,t(Z,U,V)),P). /* 1 */ flatten(t(e,N,Y),P) => flatten(Y,[N|P]). /* 2 */ flatten(_,[N|T]):sum(T,S) => S1 is S+N,sum([N|T],S1). /* 3 */ sum(P,S) => write(P-S),nl. /* 4 */ sum([],0). The "flatten" predicate is rewritten in a DD-rule manner, so that given a tree as a dynamic data item, it can generate a list of its labels. While this list is generated the local database "flatten(_,_)" is available for the other DD-rules. Thus the "sum" rule (3), working in parallel, uses each newly generated label and adds it to the previously calculated sum. The initial value for the sum is specified by a static data item - "sum([],0)". Rule 4 is used to keep track of the process, print- ing all currently available solutions, as shown by the following NCL/Prolog query: ?- flatten(t(t(e,2,t(e,3,e)),4,t(e,7,e)),[]). [2] - 2 [3,2] - 5 [4,3,2] - 9 [7,4,3,2] - 16 The whole process can be seen as an incremental communication} between rules 1,2 and 3 through local database "flatten(_,_)". It is important to note that no explicit (defined by the programmer) distinction between the producer and the consumer is needed. 2.3. Recursion in the left-hand side of the DD-rules ---------------------------------------------------- Consider the Horn clause program, implementing multiplication of numbers, represented as recursive terms. /* The Horn clause program */ a(0,N,N). a(s(X),Y,s(Z)):-a(X,Y,Z). m(0,M,0). m(s(M),N,P):-m(M,N,Q),a(Q,N,P). /* The DD-rule program */ s: m(M,N,Q):a(Q,N,P) => m(s(M),N,P). /* 1 */ m(0,M,0). s: a(X,Y,Z) => a(s(X),Y,s(Z)). /* 2 */ a(0,N,N). g(X,Y,Z): m(X,Y,Z) => write(X-Y-Z),abort. /* 3 */ ?- g(s(s(0)),s(s(0)),X),s. s(s(0)) - s(s(0)) - s(s(s(s(0)))) ?- DD-rules 1 and 2 are working in parallel until they generate a dynamic data item consistent with the goal. The consistency is checked by rule 3, which in case of success prints the solution and terminates the whole process. Consider now the following example: g(X):a(X,X1):a(X1,X2):a(X2,X3) => write(X),nl. a(a(0,N,N),_). a(a(s(X),Y,s(Z)),a(X,Y,Z)). This program is another implementation of the "adder" from the previous example. Here some examples of its work: ?- g(a(s(0),s(0),X)). (1) a(s(0),s(0),s(0)) a(s(0),s(0),s(0)) ?- g(a(s(s(0)),s(0),X)). (2) a(s(s(0)),s(0),s(s(s(0)))) ?- g(a(s(s(s(0))),s(0),X)). (3) a(s(s(0)),s(0),s(s(s(_)))) Note that this implementation of the "adder" is not recursive, i.e. the recursion is unfolded (defined by several "a" nodes). However this program adds only restricted range of numbers, as it is shown by query 3. So, the general case of this predicate should have infinite number of "a" nodes: g(X):a(X,X1): ... a(Xn-1,Xn):a(Xn,Xn+1): ... => write(X),nl. For such cases NCL offers a special syntax for the DD-rules, al- lowing recursion among the free nodes in a DD-rule. Thus the above program can be rewritten in the following way: g(X):a(X,Y):Y=X => write(X),nl. a(a(0,N,N),nil). a(a(s(X),Y,s(Z)),a(X,Y,Z)). The special procedure Y=X can appear in an arbitrary place in the left-hand side of a DD-rule. Its purpose is to unify the two net-variables which are from two different instances of the DD- rule. This means that when appear this procedure causes a new in- stance of the DD-rule to be generated (Y is from the current copy of the rule and X is from the new one). Note that a special term "nil" is used in the first data item "a". This term when binds variable Y in the procedure Y=X causes no more copies of the DD- rule to be generated, i.e. it acts as a termination condition for the recursion. ================================================================= II. Prolog built-in procedures related to NCL ================================================================= net(NetClause), net(NetClause,Functor/Arity) -------------------------------------------- Unifies its argument to all net-clauses currently in the database. When a second argument is used, only the nodes with the specified functor and arity are accessed. For example: a(X):[]. a(X,Y,Z): b(Y):node(X,1,ok). ?- net(X). X=a(_1):a(_2,_3,_4):b(_3):node(_2,1,ok) ?- net(X,node/3). X=node(_1,1,ok) ?- net(X,a/_). X=a(_1):a(_2,_3,_4) ?- net(X,_/3). X=a(_1,_2,_3):node(_1,1,ok) netmode(Mode) ------------ Defines the spreading activation mode (0 to 3). Called with a free variable it returns the current mode. See item 1.4 for more explanations. netnode(Functor,Node) --------------------- Unifies its arguments with the functor and whole structure of an existing in the database net-clause node. The following example illustrates a way of listing all net-clause nodes in the database ("curpred" returns the functors of the predicates currently in the database). a(X):[]. a(X,Y,Z): b(Y):node(X,1,ok). ?- curpred(P),netnode(P,Node),write(Node),nl,fail. a(_1) a(_1,_2,_3) b(_1) node(_1,1,ok) no ?- Note that this query prints the current net-clause similarly to "net", however without showing the shared variables. top(Top_of_stack) ----------------- Unifies its argument with the top of the stack of active goals. gen(Level) ---------- The purpose of this procedure is to share the variables which have been bound to unifiable ground terms by goals stored in the stack above a specified level. Doing so it performs the pattern generalization operation described in item 1.7. Actually this procedure only marks the variables to be shared and the actual sharing is performed when the variables are freed (after ter- minating the query or in case on failure). The following example illustartes how to share net-variables and use them in a same query. /* Procedure for performing pattern generalization */ patgen(Goals):-top(Top),no_backtrack_call(Goals),gen(Top),fail. patgen(_). no_backtrack_call(Goals):-call(Goals),!. a(X):b(Y). /* A net-clause with two unique net-variables */ ?- patgen((a(ok),b(ok))),a(new),b(X). X=new trail(Level,List_of_bindings) ----------------------------- Unifies its second argument with the list of the bindings of the net-variables bound by goals above the specified level in the stack. For example: a(X):b(Y):node(X,1,b(ok)). ?- top(Level),a(start),trail(Level,List). List=[ok,start] nproc(Level,List_of_procedures) ------------------------------- Similar to "trail", however the list contains the procedures of the nodes activated by binding the corresponding net-variables. For example: a(X):b(Y):node(X,1,b(ok)). ?- top(Level),a(start),trail(Level,List). List=[b(ok)] spread(Level) ------------- Activates the process of breadth-first spreading activation. See item 1.5 for more details. dellazy ------- This procedure clears the contents of all local databases in a program. (It is used in the lop level loop of the NCL/Prolog in- terpreter to initialize the local databases when a new query is processed.) ================================================================= III. The standard Prolog built-in procedures ================================================================= ----------------------------------------------------------------- 1. Control language ----------------------------------------------------------------- ! Freezes the choice of the current clause. call() Activates the specified term as a goal. abort Interrupts the execution and transfers the control to the top level. end Exits the NCL/Prolog interpreter. fail Always fails. true Always succeeds. repeat Can be always resatisfied. ----------------------------------------------------------------- 2. Term manipulation ----------------------------------------------------------------- = Succeeds iff the two terms are unified. == Succeeds iff the two terms are equal. \== Succeeds iff the two terms are different. \= Succeeds iff the two terms are not unifiable. =.. [|] The "univ" predicate. atom() Succeeds iff the term is an atom. arg(,,) Unifies an argument of a structure. functor(,,) Unifies a structure with a specified functor and number of arguments. integer() Succeeds iff the term is an integer number. name(,) Succeeds iff the list is unified with the ascii-codes of the atom characters. nonvar() Succeeds iff the term is not an uninstantiated variable. op(,,) Defines an operator. var() Succeeds iff the term is an uninstantiated variable. ----------------------------------------------------------------- 3. Database access ----------------------------------------------------------------- assert(,) Adds before in the procedure. asserta() Adds in the beginning of the procedure. assertz() Adds a clause at the end of the procedure. clause(,) Unifies a clause in the database specified by its head. clause(,,) Unifies a clause in the database specified by its functor (head and body could be unbound). curpred() Unifies its argument with the functor of a procedure in the database. Scans all procedures on backtracking. delete() Retracts from the database all procedures with the specified functor. learn Interactive mode for asserting clauses in the database ("q." for quit). listall Lists all existing clauses in the database. listing() Lists all clauses in the database with the specified functor. retract() Removes the specified clause form the database. ---------------------------------------------------------------- 4. Arithmetic (allowed operations: +,-,/,*,mod,~(unary minus)) ---------------------------------------------------------------- < Succeeds iff the value of expression1 is less than the value of expression2. > Succeeds iff the value of expression1 is greater than the value of expression2. =< Succeeds iff the value of expression1 is less than or equal to the value of expression2. >= Succeeds iff the value of expression1 is greater than or equal to the value of expression2. is Succeeds if the term is unified with the value of the expression. ----------------------------------------------------------------- 5. Input/Output ----------------------------------------------------------------- get0() Reads a character from the keyboard. list Switches on the listing mode (the input line is printed on the console). nl Sends a new line to the output stream. nolist Switches off the listing mode. put() Sends a character to the output stream. read() Reads a term from the keyboard. write() Prints a term to the output stream. def(,) Defines the character class for a particular character to be used by the term parser (read). Classes are: 0 - lower case letter; 1 - upper case letter; 2 - special character; 3 - space (ignored by read); 4 - illegal character; 5 - "end of term" (usually "."). ----------------------------------------------------------------- 6. Text files ----------------------------------------------------------------- close Closes the currently open text file and redirects the output to the console. consult() Adds to the database all clauses stored in a text file. dprog() Retracts all clauses whose functors appear as clause names in the file. open() Opens a file for output and redirects all successive output to the file. reconsult() Equivalent to the conjunction "dprog(X),consult(X)". save() Writes all clauses in the database on a file. [,...,] Equivalent to "consult(),...,consult()". [~,...,~] Equivalent to "reconsult(),...,reconsult()". ----------------------------------------------------------------- 7. List Processing ----------------------------------------------------------------- length(,) Unifies with the number of elements of the list. member(,) Succeeds if the element is a member of the list. append(,,) Appends to and unifies the result with . ----------------------------------------------------------------- 8. Program debugging ----------------------------------------------------------------- trace Switches on the trace mode. notrace Switches off the trace mode. debug Switches on the debug mode (more information on failure, and tracing built-in predicates if trace mode is on). nodebug Switches off the debug mode. step Switches on the step mode. Stops at each CALL port. nostep Switches off the step mode. top() Unifies its argument with the top of the stack of active goals. ----------------------------------------------------------------- 9. System predicates ----------------------------------------------------------------- shell() Executes a command by calling the operating system shell. edit( ----------- Invokes a text editor (usually vi) and passes to it a file to be edited. On exit performs "reconsult(". ----------------------------------------------------------------- 10. Extralogical ----------------------------------------------------------------- bagof(,, Stores in the list all instances of the term for all alternatives of the goal. setof(,, Same as "bagof", but excluding the repetitions in the list. ================================================================= IV. List of publications related to NCL ================================================================= 1. Markov, Z., C. Dichev & L. Sinapova. The Net-Clause Language - a tool for describing network models. In: Proceedings of the Eighth Canadian Conference on AI, Ottawa, 23-25 May, 1990, pp.33-39. 2. Markov, Z. & Ch. Dichev. Logical inference in a network en- vironment. In: Ph. Jorrand & V. Sgurev (eds.), Proceedings of AIMSA'90, Artificial Intelligence IV, North-Holland, 1990, 169- 178 3. Markov, Z., L. Sinapova & Ch. Dichev. Default reasoning in a network environment. In: Proceedings of ECAI-90, August 6-10, 1990, Stockholm, Sweden, 431-436. 4. Markov, Z. & Ch. Dichev. The Net-Clause Language - A Tool for Data-Driven Inference, In: Logics in AI, Proceedings of European Workshop JELIA'90, Amsterdam, The Netherlands, September 1990, LNCS, Vol.478, Springer-Verlag, 366-385. 5. Markov, Z. An Approach to Data-Driven Learning. In: Proceed- ings of the International Workshop on Fundamentals of Artificial Intelligence Research (FAIR'91), September 8-12, 1991, Smolenice, Czechoslovakia, LNCS, Vol.535, Springer-Verlag, 127-140. 6. Markov, Z. & Ch. Dichev. Distributed Logic Programming, in: G. Wiggins, C. Mellish and T. Duncan (eds.) Proceedings of the 3rd UK Annual Conference of Logic Programming, Edinburgh, Scotland, 1991, Workshops in Computing, Springer-Verlag, 36-55. 7. Markov, Z. A tool for building connectionist-like networks based on term unification. In: M. Richter and H. Boley (eds.), Proceedings of PDK'91, LNCS Vol.567, Springer-Verlag, 119-203. 8. Markov, Z. An Approach to Concept Learning Based on Term Generalization. In: Proceedings of the Ninth International Machine Learning Conference (ML92), San Mateo, CA, 1992, Morgan- Kaufmann, 310-315. 9. Sinapova, L. & Z. Markov. Grammar Representation and Parsing in a Data-Driven Logic Programming Environment. In: B. du Boulay & V. Sgurev (eds.), Proceedings of AIMSA'92, Artificial Intel- ligence V, North-Holland, 151-159. 10. Markov, Z. Inductive Inference in Networks of Relations, in: Proceedings of the Third International Workshop on Inductive Logic Programming (ILP'93), April 1-3, Bled, Slovenia, 256-277. 11. Sinapova, L. A network parsing scheme. In: Ph. Jorrand and V. Sgurev (eds.), Proceedings of AIMSA'90, Artificial Intel- ligence IV, North-Holland, 1990, 383-392. ================================================================= V. How to install and use the NCL/Prolog interpreter ================================================================= 1. Compile the file "NCL.C". 2. Make sure that the file "NCL.LIB" is on the default directory. This file contains library definitions for NCL/Prolog. 3. There are some pre-set parameters used by the NCL/Prolog. They are defined as constants in the beginning of the C-code. The most important among them are: Parameter (Error No. issued when violated) C-constant Value ----------------------------------------------------------------- Max. number of active goals (14) MaxFrames 10000 Max. number of variables in active goals (17) LocSize 50000 Max. space for atom and var characters (2,30) StringSpace 30000 Max. number of characters in all atoms (2,30) AtomLimit 29000 ----------------------------------------------------------------- These values (and all the others) can be changed when necessary (taking into account the memory they require). 4. When an NCL/Prolog program is interrupted (pressing a BREAK character) the following message appears: Abort, Trace(T), Debug(D), Step(S), topLevel ? where T, D and S are either 1 or 0, indicating correspondingly whether the "trace", "debug" and "step" modes are on or off. The system waits for a letter (or a sequence of letters, upper or lower case) followed by , and takes the following actions: T - alternates "trace" and "notrace" mode. D - alternates "debug" and "nodebug" mode. S - alternates "step" and "nostep" mode. A - aborts the execution and resumes the NCL/Prolog top level. L - invokes the debug top level (indicated by ??- ), which is similar to the usual top level, however preserving the current status of the interrupted program ("end" resumes its execution). - resumes the execution without any change. ================================================================= VI. Address for further information ================================================================= Zdravko Markov Institute of Informatics, Bulgarian Academy of Sciences Acad.G.Bonchev Street, Block 29A, 1113 Sofia, Bulgaria Tel: +359-2-707586 Fax: +359-2-720166 Email: markov@iinf.bg