/*-------------------------------------------------------------*/
/*    An NCL program for recognition of geometric figures      */
/*    (C) 1993 Zdravko Markov, II-BAS                          */
/*-------------------------------------------------------------*/
/*
DESCRIPTION:
-----------
   This program illustrates the use of NCL for recognition of
simple geometric figures. The edges of the figures are
represented by free nodes in the following form:

   edge(Vertex1,Vertex2,Slope,Length)

The shared variables among the free nodes represent the common
vertices and the geometric constraints (equal lengths and slopes
of some edges). The spreading activation nodes represent the
classes of figures. The variables, included in the spreading
activation nodes represent the connections between vertices and
classes of figures they belong to. The program is executed by
specifying the edges of instances of geometric figures as goals
in NCL/Prolog queries. The corresponding class is obtained
through a goal in these queries which unifies the free node
"figure".

Besides the concept nodes representing the classes of figures,
a spreading activation node for calculating perpendicularity is
also included. This node makes the net-clause look like a
connectionist network. Its purpose is to split the geometric
figures into two classes - perpendicular (square and rectangle)
and non-perpendicular (rhombus and parallelogram). The node is
activated when net-variables S1 and S2 (representing the slopes
of the corresponding edges) are bound. If the condition for
perpendicularity is present, then procedure "perp" binds
net-variable P, thus activating the perpendicular classes and
suppressing the non-perpendicular ones (through the inhibitory
connection ~P).

REFERENCE:
----------
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.

/*-------------------------------------------------------------*/
/* Edges of geometric figures */
edge(A,B,S1,L1):
edge(B,C,S2,L1):
edge(C,D,S1,L1):
edge(D,A,S2,L1):
edge(B,E,S2,L2):
edge(E,F,S1,L1):
edge(F,A,S2,L2):
edge(E,G,S3,L3):
edge(G,A,S4,L4):

/* For storing the name of the recognized figure */
figure(Fig):

/* General case of a four-side figure */
node(A,B,E,G,4,figure(four_side_figure)):

/* Splitting figure into two classes */
node(S1,S2,2,perp(S1,S2,P)):

/* Non-perpendicular figures */
node(A,B,E,F,~P,4,figure(parallelogram)):
node(A,B,C,D,~P,4,figure(rhombus)):

/* Perpendicular figures */
node(A,B,E,F,P,5,figure(rectangular)):
node(A,B,C,D,P,5,figure(square)).

/* A Prolog procedure for calculating perpendicularity */
perp(X,Y,true):-0 is (X-Y) mod 90,!.
perp(_,_,_).

/*-------------------------------------------------------------*/
/*  EXAMPLES:                                                  */
/*-------------------------------------------------------------*/
/* Instances  of figures */
f1:-edge(1,2,0,20),edge(2,3,45,30),edge(3,4,0,20),edge(4,1,45,30).
f2:-edge(1,2,0,20),edge(2,3,90,20),edge(3,4,0,20),edge(4,1,90,20).
f3:-edge(1,2,0,20),edge(2,3,50,20),edge(3,4,0,20),edge(4,1,50,20).
f4:-edge(1,2,0,20),edge(2,3,90,30),edge(3,4,0,20),edge(4,1,90,30).
f5:-edge(1,2,10,20),edge(2,3,30,40),edge(3,4,50,60),edge(4,1,70,80).

/* Example queries:

?- f1,figure(X).
X=parallelogram

All-solution queries deliver the corresponding class and all
superclasses too. For example:

?- setof(X,(f1,figure(X)),L).
X=_1
L=[parallelogram,four_side_figure]

?- setof(X,(f2,figure(X)),L).
X=_1
L=[square,rectangular,four_side_figure,rhombus]

*/
