\input texinfo   @c -*-texinfo-*-
@c %**start of header
@setfilename lparse.info
@settitle Lparse User Manual
@setchapternewpage off
@c %**end of header

@c Copyright (C) 1999-2000 Tommi Syrjänen <Tommi.Syrjanen@hut.fi>
@c  
@c Permission is granted to make and distribute verbatim copies of
@c this manual provided the copyright notice and this permission notice
@c are preserved on all copies.
@c  
@c Permission is granted to process this file through TeX and print the
@c results, provided the printed document carries copying permission
@c notice identical to this one except for the removal of this paragraph
@c (this paragraph not being relevant to the printed manual).
@c  
@c Permission is granted to copy and distribute modified versions of this
@c manual under the conditions for verbatim copying, provided that the
@c entire resulting derived work is distributed under the terms of a 
@c permission notice identical to this one.
@c  
@c Permission is granted to copy and distribute translations of this manual
@c into another language, under the above conditions for modified versions,
@c except that this permission notice may be stated in a translation
@c approved by the Free Software Foundation
@c  

@titlepage
@sp10 
@title Lparse User's Manual (Draft 0.9)
@subtitle for Version 1.0
@author Tommi Syrj@"anen
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1999 Tommi Syrj@"anen @email{tommi.syrjanen@@hut.fi}
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

@page


@end titlepage

@ifinfo

@node    Top,     Copying, , (dir)
@top lparse-0.99.47
 
Lparse is a front end of smodels, an implementation of the stable model
semantics for logic programs.

@end ifinfo

@menu
* Copying::
* Recent Changes::
* Introduction::
* Installation::
* Invoking Lparse::
* Theoretical Stuff::
* Language::
* Partial Models and Disjunctive Programs::
* Examples::
* Writing Smodels Programs::
* Future Development::
* Bugs::
* Concept Index::
@end menu


@ifinfo
@node    Copying, Recent Changes, Top, Top
@cindex Licence

Copyright @copyright{} 1999 Tommi Syrj@"anen @email{tommi.syrjanen@@hut.fi}
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

@end ifinfo

@node Recent Changes, Introduction, Copying, Top
@comment  node-name,  next,  previous,  up

@unnumbered Recent Changes

This section gives quick overview on recent changes that are made for
accepted language. The more detailed version notes are contained in file
NEWS in the distribution directory. 

Lparse 0.99.53 added a new keyword @samp{external} and a new command
line argument @code{-g @var{filename}}. Currently these features are
documented only in the @file{NEWS} file. 

Lparse 0.99.47 added a function API that allows the user-defined
functions to access also symbolic constants. @xref{Lparse API}.

Lparse version 0.99.43 changed the behavior of modular arithmetic to
correspond with usual mathematical semantics, that is, the modulo is now
always positive. 

Lparse version 0.99.42 allows the assignments in rule bodies to be in
any order as long as there are no cyles of the form: @samp{X=Y, Y=Z,
Z=X}. 

Lparse version 0.99.27 allows symbolic constants to be compared with
relational operators. It is now also possible to include
non-alphanumeric characters in constants by surrounding them with double
quotes. 

Lparse version 0.99.26 changed the behavior of weight definitions,
@xref{Declarations}, and global variables are now allowed within
conditions, @xref{Special Constructs}. 

Lparse version 0.99.24 added preliminary support for regular model
semantics. See NEWS file for short summary of the used translation.

Between lparse versions 0.99.21 and 0.99.22 the input language changed
in following three ways:

@enumerate
@item Four bitwise operations were added to internal functions: AND (&),
OR (|), XOR (^), and NOT (~). @ref{Internal Functions}.

@item The arity limits were removed, and now predicates and
functions may have unlimited number of arguments.

@item The prototypes for user-defined functions are now simplified. The
use of stdarg macros is no longer needed and the arguments are now
passed in an array of longs:

@code{long new_prototype(int num_arguments, long *arguments)}

@ref{User-Defined Functions}
@end enumerate

@page
@node Introduction, Installation, Recent Changes, Top
@chapter Introduction
@cindex Introduction

@emph{This manual is still in progress and there are some unfinished
parts in it.}

If you try to solve some problem using a traditional procedural
programming language (C, C++, Perl, and like), you do it by devising and
coding some clever algorithm that calculates the solution. The details
vary depending on the language of your choice, but in any case you have
to flesh out every step of the process.

Logic programming takes another approach to problem solving, that is, a
declarative approach. Instead of writing algorithms you just describe
the  problem in formal language and the underlying engine finds the
solution of the problem. The problem description is given in two parts:
the first part is a set of inference rules that tell how the problem
domain works, and the second is a set of facts that describe the actual
problem instance.

Of course, it is not possible to do everything with logic programming.
For example, writing declarative operating system kernels would be quite
difficult, but there are many problems that have nice and efficient
mappings to logic programs. For example, planning and configuration
problems have elegant and efficient logic program representations.
(@pxref{Examples}).

The stable model semantics is a fully declarative and intuitionally
clean semantics for logic programs. The stable models of a program may
be seen as a set of rational beliefs about the program. That is, if we
think that a program is a knowledge base encoding the relationships
between objects and a stable model is a set of those things in our
universe that we believe to be true, then our beliefs are consistent and
well-founded. Consistency means that we don't believe in two
contradictionary things and well-foundedness means that we have some
reason for our belief. We don't want to believe that Moon is made of
green cheese unless somebody gives a coherent theory that explains why
Moon is actually a big dairy product. For formal definition of stable
models see @ref{Stable Model Semantics}.

Smodels is an open-source implementation of the stable model semantics
that has been designed in the Laboratory for Theoretical Computer
Science in Helsinki University of Technology by Patrik Simons. Smodels
takes as its input a ground logical program (that is, a logic program
without variables) and it gives as its output the desired number of the
stable models of the program. While it is entirely possible to encode
the problems using only ground terms, it is very tedious. The language
will be much more expressive when the use of variables is allowed.

Lparse is a front end to smodels that allows the use of variables,
numerical functions, and numerous other things in logic programs. Lparse
takes as its input a logic program and transforms it to the form that
smodels understands. For each rule that has variables in it lparse
searches all possible values of the variables and outputs all possible
combinations of those values. This process is called grounding
(@xref{Grounding}).


The newest versions of lparse, smodels, and this document are available
at @*
@center @url{http://www.tcs.hut.fi/pub/smodels}. 


@menu
* Short Primer on Logic Programming::
* Stable Model Basics::
* Different Smodels Front-Ends::
@end menu

@node Short Primer on Logic Programming, Stable Model Basics, , Introduction
@comment  node-name,  next,  previous,  up
@section Short Primer on Logic Programming
@cindex Logic Programming Tutorial

This section has a really short primer on the subject of logic
programming in general. It is aimed for readers who have no prior
experience on logic programming. For an extensive treatment on the
traditional logic programming techniques you should consult @cite{The Art
of Prolog} by Sterling and Shapiro.

In logic programming languages there are basically four kinds of things,
atoms, constants, variables, and rules. They are presented here rather
informally. For formal stuff see @ref{Theoretical Stuff}.

@enumerate

@item Constants are the individual things that exists in the universe of
the problem domain. Constants are either numbers or symbolic constants.
In most logic programming languages the initial letter of a constant is
written in lower case. 

Few examples of constants: @code{a, 10, foo, bar}.

@item Variables are used to generalize things. Unlike traditional
programming language, you don't usually assign a value to a variable
directly. Instead, the underlying engine finds the correct values (or
@dfn{substitutes} constants in place of the variables) for them.

Variables start with a capital letter, like in: @code{X, Foo, Bar}.

@item An atom consists of a predicate symbol that is followed by a
parenthesised list of constants or variables. Atoms are used to express
relationships between constants. For example, atom @samp{parent(john,
jill)} might tell us that John is Jill's parent. An atom has two
possible truth values, @samp{true} and @samp{false}. 

@item Rules allow us to make inferences based on the predicates. For
example rule:

@example
sibling(X,Y) :- parent(Z,X), parent(Z,Y).
@end example

would tell us that if @samp{X} and @samp{Y} have the same parent
@samp{Z}, then they are siblings. Rules are composed of two parts, the
head (part to the left of @samp{:-}) and the body (right to @samp{:-}).
The idea here is that if every atom in the body (or tail as it is also
often called) is true, then the head must also be true. So if there is
some way to substitute constants for the variables @samp{X}, @samp{Y},
and @samp{Z} such that both @samp{parent(Z,X)} and @samp{parent(Z,Y)}
are true, then we can infer that @samp{sibling(X,Y)} is also true.

In classic logic programming languages (like Prolog) the inferences are
usually made top-down. That is, we give some atom as a query string, and
the system tries to find a way to infer it.

For example, if we were interested in finding out if Jack is Jill's
sibling we would issue a query @samp{sibling(jack, jill)?}. The system
would then scan through the rules until it finds some rule which has
predicate @code{sibling} as its head. After finding the rule that is
presented above the system would substitute @samp{jack} for variable
@samp{X} (denoted: @samp{X / jack}) and @samp{jill} for @samp{Y}
(@samp{Y / jill}).

Now the system has established that Jack and Jill are siblings if there
exists some @samp{Z} that is parent of both of them. Next the system
would issue a new query (called a subgoal) @samp{parent(Z, jack)?} in
order to find the parent of Jack. Let's say that Joan is Jack's mother.
Then the subgoal succeeds and the systems finds substitution @samp{Z /
joan}.

The system will then check whether Joan is also Jill's mother by issuing
the query @samp{parent(Joan, Jill)}. If the query succeeds, the system
answers @samp{yes} to our original question (@samp{sibling(jack,
jill)?}). If Joan is not Jill's mother the query fails, and the logic
programming engine backtracks and tries to find another substitution for
@samp{Z}. If no such substitutions can be found, the systems answers
@samp{no} to our question.

If there are more than one rule for a predicate, the rules are tried in
order. If one fails the next one is checked.
@end enumerate

Quite often the logic programs can be divided into two parts, a set of
inference rules and a database of facts for the rules to make inferences
with. 

For example, following program encodes a simple family database:

@example
sibling(X,Y) :- parent(Z,X), parent(Z,Y). 
mother(X,Y) :- parent(X,Y), female(X). 
uncle(X,Y) :- parent(Z, Y), sibling(Z,X), male(X). 
female(joan). female(jill). male(jack).  
parent(joan, jack). parent(joan, jill).
@end example

@node Stable Model Basics, Different Smodels Front-Ends, Short Primer on Logic Programming, Introduction
@comment  node-name,  next,  previous,  up
@section Stable Model Basics
@cindex Stable Model Basics

Traditional logic programming systems are query-driven. That is, you
enter a query and the system then tries to answer it. At any point only
those variables that are somehow involved in the query have values
binded to them. 

Smodels works in a different way. In the first phase all variables are
removed from the program by substituting all possible values for them in
all rules. This phase is called grounding (@pxref{Grounding}) and
it's the job that lparse does. In the next phase smodels computes the
stable models of the program. A model is a set of atoms such that it
makes every rule in the program @samp{true} when each atom that is in
the model is @samp{true} and each atom that is not in it is
@samp{false}. A model is stable when it meets some other requirements,
that are formalized in @ref{Stable Model Semantics}. Informally, a model is
stable if every atom in it has some ``reason'' to be there: for each
atom in the model there has to be some rule that has the atom as a head
and the rule body is @samp{true} in the model. 

As a simple example of what stable models are about consider the
following program segment that could represent a part of a PC
configuration system:

@example
ide_drive :- hard_drive, not scsi_drive. 
scsi_drive :- hard_drive, not ide_drive. 
scsi_controller :- scsi_drive. 
hard_drive.
@end example

Here the first rule says that if we have a @samp{hard_drive} in our
computer and we don't have a @samp{scsi_drive}, then we must have an
@samp{ide_drive} in it. The next rule says the same thing about
@samp{scsi_drive}: if we have a @samp{hard_drive} that is not an
@samp{ide_drive}, then it has to be a @samp{scsi_drive}. The third rule
says that if we have a @samp{scsi_drive} in the computer we must also
include a @samp{scsi_controller} in it. The last rule is a fact that
tells that our computer has a @samp{hard_drive} in it.

This program has two stable models. The first one is:

@example
@{ hard_drive, ide_drive @},
@end example

and the second one is:

@example
@{ hard_drive, scsi_drive, scsi_controller @}.
@end example

The first two rules represent a choice point: if we have a hard drive in
the computer we must choose between an ide drive or a scsi drive. 

If we add @samp{scsi_controller} into the first stable model the
resulting set of atoms is still a model of the program in propositional
logic, but it is no longer a stable model. That is because
@samp{scsi_controller} is needed only when @samp{scsi_drive} is present,
and when it is missing there is no reason to add @samp{scsi_controller}
in the model.

@node Different Smodels Front-Ends, , Stable Model Basics, Introduction
@comment  node-name,  next,  previous,  up
@section Different Smodels Front-Ends
@cindex Parse
@cindex PParse
@cindex Mcsmodels
@cindex Dlsmodels

Currently, there are a host of different front-ends to smodels:

@enumerate
@item lparse is the most feature-rich of the different parsers and front
ends, and it is the default one you should use when you are writing
smodels programs. 

@item parse is the original parser of smodels. It produces only smodels
1.x output, and is now outdated. 

@item pparse (``primitive parser'') is a simple parser that produces
smodels 2.x output, but it accepts only ground programs. It syntax for
extended rules is different from what is used in lparse. 

@item mcsmodels (``model checking smodels'') is a deadlock and
reachability checker that can be used to verify 1-safe Petri nets. It is
written by Keijo Heljanko and it is available at
@url{http://www.tcs.hut.fi/~kepa/tools/} 

@item dlsmodels is an older version of mcsmodels which only detects
deadlocks. It is available at same place as mcsmodels. 
@end enumerate

@node Installation, Invoking Lparse, Introduction, Top
@chapter Installation
@cindex Installation

Lparse comes now with an installation script @samp{configure} that
should make the installation easier. The procedure to follow is:
@enumerate
@item @samp{cd} to the directory containing lparse source code and type
@samp{./configure} to configure lparse for your system.
@item Type @samp{make} to compile the binaries.
@item Type @samp{make install} to install lparse.
@item If you want to remove the object files from the source code
directory you may type @samp{make clean} to do it.
@end enumerate

By default lparse and register are installed to directory
@file{/usr/local/bin} and the documentation to @file{/usr/local/info}.
You may change the directory by giving @samp{configure} the option
@samp{--prefix=@var{path}}.

There is a suite of smodels programs that can be used to check that
lparse is functioning correctly. Currently, it is not yet complete, but
I'll expand its functionality in forthcoming lparse releases.

The test programs are stored in directory @file{tests} and the expected
results are in directory @file{tests/results}. There is a perl script
@file{test_all} that performs all tests and reports any errors. The
tests can be also run with @samp{make check} command.

By default only info-version of this document is produced. To get a
version formatted for printing use @samp{make dvi}. 

@cindex Security 
As a security issue, you should newer run lparse with setuid bit set. It
is possible to call user-defined C/C++-functions from smodels programs
(@pxref{User-Defined Functions}) and if the setuid bit is on it a
malicious adversary can run basicly anything with the permissions of the
owner of lparse. 

@node Invoking Lparse , Theoretical Stuff, Installation, Top
@chapter Invoking Lparse
@cindex Invocation

@example
Usage: lparse [-1] [-c @var{const}=@var{number}] [-d all | facts | positive | none]
              [-D] [-i] [-n @var{number}] [-t] [-v] [-w @var{n}]
              [-W (no)all | (no)decl | (no)cons] @var{file1} @var{file2}@dots{}
@end example

Lparse is used as a front end to smodels. The usual way is to pipe the
output of lparse straightly to smodels:

@example
lparse @var{input_file1} @var{input_file2} | smodels
@end example

It is also possible to output the ground program in plain text, using
option @samp{-t}:

@example
lparse -t @var{input_file}
@end example

If the logic program has some varying integer parameter, its value can
be entered from command line with option @samp{-c}:

@example
lparse -c @var{parameter}=@var{value} @var{input_file}
@end example

By default the output file format is for smodels 2.x, but it is also
possible to output smodels 1.x format by using option @samp{-1}.

@menu
* Lparse Options::
* Smodels Options::
@end menu

@node     Lparse Options, Smodels Options, , Invoking Lparse
@comment  node-name,  next,  previous,  up
@section Lparse Options
@cindex Lparse Options
@cindex Options 

The available options are:
@itemize @bullet

@item @samp{-1} Use smodels 1.x output format.

@item @samp{-c @var{const}=@var{n}} @*
Define the identifier @var{const} to
be a numeric constant with value @var{n}.

@item @samp{-d all | facts | positive | none} @*
Control which domain predicates are emitted. The default is @samp{facts}
  @itemize @bullet 
  @item @samp{all} All domain literals are emitted. Rules with
unsatisfiable negative domain literals in their bodies are not removed.
  @item @samp{facts} All domain predicates in the rule bodies are
dropped.
  @item @samp{none} All domain literals are dropped.
  @item @samp{positive} All negative domain literals in the rule bodies
are dropped.
  @end itemize
@item @samp{-D} Debug lparse data structures. With this option lparse
creates really small internal hash tables, so that multiple rehashings
are forced.
@item @samp{-i} Disable the internal functions.
@item @samp{-n @var{n}} Set the desired number of models to @var{n}.
This overrides any @samp{compute}-statements in the program.
@item @samp{-r} Enable regular model extension. @xref{Regular Models}
@item @samp{-t} Print output as text.
@item @samp{-v} Print version information.
@item @samp{-w @var{n}} Set the default weight of literals to @var{n}.
If this option is not given the default weight will be @samp{1}.
@item @samp{-W all | arity | extended | library | unsat | weight |
syntax | typo | error }
Control the warnings emitted by lparse. For detailed explanation see
@ref{Parser Warnings}. 
@itemize @bullet
@item @samp{all} Enable all warnings.
@item @samp{arity} Check that a predicate symbol has same arity in all
places.
@item @samp{extended} Check general problems about extended rules.
@item @samp{library} Check problems with used-defined functions
(@ref{User-Defined Functions}).
@item @samp{similar} Check whether there are similarily named constants
and variables.
@item @samp{unsat} Warns if there are unsatisfiable predicate symbols in
the program.
@item @samp{weight} Warns if the default weight of literals is used
somewhere.
@item @samp{syntax} Defines @samp{arity}, @samp{extended}, and
@samp{weight}.
@item @samp{typo} Defines @samp{similar} and @samp{unsat}. 
@item @samp{error} Treat warnings as errors.
@end itemize
@item @samp{--dlp} Use disjunctive semantics for separator '|'. 
@end itemize



@node Smodels Options, , Lparse Options, Invoking Lparse
@comment  node-name,  next,  previous,  up
@cindex Smodels Options
@section Smodels Options

These options are current for smodels version 2.17.

@example
Usage: smodels [@var{number}] [-w] [-nolookahead] [-backjump]
               [-sloppy_heuristic] [-randomize] [-internal]
               [-tries @var{number}] [-conflicts @var{number}]
               [-seed @var{number}]
@end example

The first @var{number} determines the number of stable models computed.
A zero indicates all. 

@itemize @bullet
@item @samp{-nolookahead} do not use lookahead.
@item @samp{-backjump} does not always backtrack chronologically.
@item @samp{-sloppy_heuristic} doesn't compute the full heuristic after
lookahead
@item @samp{-randomize} does a randomized but complete search
@item @samp{-internal} prints a reduced program in internal form
@item @samp{-w} displays the well-founded model
@item @samp{-tries} tries to find a model stochastically a number of times
@item @samp{-conflicts} is the number of backtracks before the try fails
@item @samp{-seed} mixes the program
@end itemize

@node Theoretical Stuff, Language, Invoking Lparse, Top
@chapter Theoretical Stuff
@cindex Theoretical stuff

This chapter discusses the theoretical foundation of smodels and
lparse. The only thing in this chapter that is essential to know while
using lparse are the informal parts of sections about domain predicates
and strongly range restricted programs. You may well use
smodels and lparse without reading other parts of this chapter, but if
you want to understand why they work like they do you should read the
whole thing.

@menu
* Basic Terminology::
* Stable Model Semantics::
* Grounding::
* Domain Predicates::
* Strongly Range Restricted Programs::
* Regular Models::
@end menu

@node     Basic Terminology, Stable Model Semantics, , Theoretical Stuff
@comment  node-name,  next,  previous,  up
@section Basic Terminology
@cindex Terminology

@cindex Head
@cindex Body
@cindex Atom
@cindex Literal
@cindex Not-Atom
@cindex Negative Literal
@cindex Term
An @dfn{atom} is of the form @samp{p(a1, @dots{}, an)} where @samp{p} is
a @samp{n}-ary predicate symbol and @samp{a1}, @dots{}, @samp{an}
(@samp{n} >= 0) are terms. A @dfn{term} may be either a variable, a
constant or a function @samp{f(t1, @dots{}, tm)} where @samp{t1}, @dots{},
@samp{tm} are terms. An atom (or a function) with no variables is called
a @dfn{ground} atom (function). 

A @dfn{literal} is either an atom @samp{a} or its negation @samp{not a}.
Literals of the form @samp{not a} are called @dfn{not-atoms} or
@dfn{negative literals}.

@cindex Rule
A @dfn{rule} is of the form

@example
h :- l1, @dots{}, ln.
@end example

where the rule @dfn{head} is an atom and the rule @dfn{body} @samp{l1,
@dots{}, ln} (@samp{n} >= 0) are literals. If the rule body is empty
(@samp{n} = 0), the rule is called a @dfn{fact}. A general @dfn{logic
program} is a set of rules. In lparse there is also support for various
extended rules, in addition to basic rules. @xref{Rule Types}. 

@cindex Herbrand Universe
@cindex Herbrand Base
The @dfn{Herbrand universe} of a logic program is the set of all ground
terms that can be constructed using function symbols and constants in
that program. The @dfn{Herbrand base} of a logic program is the set of
all ground atoms that can be constructed using the predicates in the
program and terms in the Herbrand universe.

For example, in program:

@example
d(a). d(b). 
foo(X) :- not bar(X). 
bar(X) :- not foo(X).
@end example

the Herbrand universe is @samp{@{ a, b @}} (these two constants are the
only ground terms of the program), and the Herbrand base is
@code{@{ foo(a), foo(b), bar(a), bar(b) @}}.

@cindex Instance
@cindex Ground Instance
@cindex Herbrand Instantiation

An @dfn{instance} of an atom, a literal, a rule, or a function is
constructed by replacing all variables in it by ground terms. The
@dfn{Herbrand instantiation} of a program is the set of all ground
instances of the rules of the program that may be constructed using
terms in the Herbrand universe of the program. 

In the earlier example the Herbrand instantiation is

@example
@{ d(a). d(b). 
   foo(a) :- not bar(a). 
   foo(b) :- not bar(b). 
   bar(a) :- not foo(a). 
   bar(b) :- not foo(b). @}
@end example

@cindex Interpretation
@cindex Truth Valuation
@cindex Extension

An @dfn{interpretation} of a logic program is a subset of its Herbrand
base. An interpretation assigns a @dfn{truth valuation} to each element
of the base. If an atom is @samp{a} is in the interpretation, its
valuation is @dfn{true} in the interpretation, otherwise it is
@dfn{false}. An @dfn{extension} of a predicate @samp{p} is the set
@code{@{ a | a @r{is in the interpretation and its predicate symbol is}
p @}}.

@cindex Model
@cindex Herbrand Model
@cindex Satisfies

An atom @samp{a} is @dfn{satisfied} by an interpretation if its
valuation is true. A not-atom @samp{not a} is satisfied if the valuation
of @samp{a} is false. A rule is satisfied if either at least one of its
body literals is not satisfied by the interpretation or if its head is
satisfied. If an interpretation satisfies every rule of the Herbrand
instantiation of a program, it is a @dfn{(Herbrand) model} of the
program.

For example, the interpretation @code{@{ d(a), d(b), foo(a), bar(b)@}}
is a model of the earlier example program, because all the rules of the
Herbrand instantiation are satisfied:

Rules @code{d(a); d(b); foo(a) :- not bar(a);} and @code{bar(b) :- not
foo(b)} are satisfied because their rule heads are in the model. The
rule @code{foo(b) :- not bar(b)} is satisfied because @samp{not bar(b)}
is not satisfied. The last rule is satisfied for the same reason.

@cindex Knaster-Tarski Operator
@cindex Tp Operator
@cindex Minimal Model
A model is @dfn{minimal} if no proper subset of it is also a model. An
old theorem@footnote{M.H. van Emden and R.A. Kowalski: The semantics of
predicate logic as a programming language. JACM 23:733--742, 1976} says
that a logic program without negative 
literals has a unique minimal Herbrand model which is called the
@dfn{meaning} of the program. The minimal model @samp{M} of a program
@samp{P} can be found by using the Knaster-Tarski operator @samp{Tp}
where 

@example
Tp(M) = @{ h | h :- l1, @dots{}, ln @r{is a rule}
           @r{in the program}, and l1, @dots{}, ln @r{all}
           @r{belong to} M @}.
@end example

The minimal model can be found by starting with an empty set and
applying the Tp operator until a fixed point is found.

For example, if the Herbrand instantiation of a program is

@example
a. b. 
c :- a. 
d :- c, b. 
e :- f.
@end example

then the minimal model is found in following steps:
@enumerate
@item First @samp{M} is empty. Now @samp{c}, @samp{d}, and @samp{e}
cannot be added to model since their bodies are not in the partial
model. However, since the bodies of first two rules are empty, they may
be added to it to get a partial model @samp{M = @{ a, b @}}.

@item Now the body of the rule for @samp{c} is in the partial model, so
@samp{c} is added to the partial model, resulting in @samp{M = @{ a, b,
c @}}.

@item Because both @samp{c} and @samp{b} are in the partial model,
@samp{d} may be added to it also.

@item There are no more rules with true bodies that can be added to the
model, so the meaning of this program is @samp{M = @{ a, b, c, d @}}.
@end enumerate

@node Stable Model Semantics, Grounding, Basic Terminology , Theoretical Stuff
@comment  node-name,  next,  previous,  up
@section Stable Model Semantics
@cindex Stable Model Semantics
@cindex Reduct
@cindex Stable Model
@cindex Well-Founded
@cindex Reason

The concept of meaning defined in the prior section doesn't generalize
nicely to logic programs with negations and something else is needed. The
@dfn{stable model semantics} for a ground logic program @samp{P} is
defined in the following way:

Let @samp{M} be any set of atoms from @samp{P}. Then the @dfn{reduct}
@samp{Pm} of the program with respect to @samp{M} is obtained by
deleting from @samp{P}
@enumerate
@item each rule that has a negative literal @samp{not a} in its body
when @samp{a} belongs to @samp{M}.

@item all negative literals in the bodies of remaining rules.
@end enumerate

As @samp{Pm} is negation-free, it has a unique minimal Herbrand model.
If this model coincides with @samp{M}, then @samp{M} is a @dfn{stable
model} of the program @samp{P}. 

The intuitive explanation of the reduct is that if we believe that
@samp{M} is the set of all true ground atoms of the program, then any
rule that depends on a literal @samp{not b} when @samp{b} is true cannot
be used in deduction and may be discarded. Also, every literal @samp{not
b} is trivially satisfied if @samp{b} is not true and can be discarded.
If @samp{M} is the set of atoms that follow logically from @samp{Pm}
then we can say that our belief was consistent and ``rational''.

Example:

@example
a :- not b. 
b :- not a.
@end example

This program has two stable models, @samp{@{ a @}} and @samp{@{ b @}}. We
can see that @samp{@{ a @}} is a stable model by first taking the reduct
to get the program:

@example
a :-  .
@end example

As the only remaining rule has an empty body, the minimal model of the
program is @samp{@{ a @}} which is the same set that we started with. The
other stable model comes similarly.

In propositional logic this program has also third model, @code{@{ a, b
@}}, but this model is not stable, because its reduct is empty and thus
the minimal model of the reduct is also empty, not @code{@{ a, b @}}.

All stable models are @dfn{well-founded} as every atom that is in it has
to have some @dfn{reason} to be in there, that is, if an atom is in a
model there has to be a rule such that the atom occurs at the head of it
and all the body literals are satisfied. The third model in the above
example was not well-founded, because both of the rules had unsatisfied
bodies.

The set of stable models for a non-ground logic program is defined to be
the set of stable models of the Herbrand instantiation of the program. 

@node Grounding, Domain Predicates, Stable Model Semantics, Theoretical Stuff
@comment  node-name,  next,  previous,  up
@section Grounding
@cindex Grounding
@cindex Local Grounding

A @dfn{grounding} transforms a general logic program into an equivalent
ground logic program where the equivalence is defined as having the same
set of stable models. A @dfn{variable binding} is a substitution that
maps a subset of variables of a rule into ground terms. A grounding is
@dfn{local} if it is possible to do the grounding one rule at a time.

Above the set of stable models of a general program was defined to be
the set of stable models of its Herbrand instantiation. Why not use it
directly? The answer is that in practice it is not possible to generate
all Herbrand instances of a given logic program because the size of the
Herbrand instantiation is nearly always exponential with respect to the
size of the original problem.

Usually most of the rules in the Herbrand instantiation have
unsatisfiable bodies and they may be discarded without affecting the set
of stable models.

For example, the program:

@example
d(a). e(b). e(c). 
foo(X) :- d(X), not bar(X). 
bar(X) :- d(X), not foo(X).
@end example

has the Herbrand instantiation

@example
d(a). e(b). e(c). 
foo(a) :- d(a), not bar(a). 
foo(b) :- d(b), not bar(b). 
foo(c) :- d(c), not bar(c). 
bar(a) :- d(a), not foo(a). 
bar(b) :- d(b), not foo(b). 
bar(c) :- d(c), not foo(c).
@end example

It is not possible to deduce atoms @samp{d(b)} and @samp{d(c)} in the
above program, and any rule that depends on either of them cannot have
its body true. Those rules can be discarded without affecting stable
models. In effect, the program can be shortened to:

@example
d(a). e(b). e(c). 
foo(a) :- d(a), not bar(a). 
bar(a) :- d(a), not foo(a).
@end example

The crucial question now is, how do we know which rules can be dropped
out? Lparse does the job by dividing the predicates into two classes,
domain and non-domain predicates. The intuition is such that the
non-domain predicates are the ones that we are interested in, and domain
predicates just give all possible variable bindings. Informally domain
predicates are those predicates that are not defined recursively or in
terms of recursively defined predicates. 

In the example above predicates @samp{d} and @samp{e} are domain
predicates, while @samp{foo} and @samp{bar} are not since they depend
recursively on each other. In the next section there is a
longer discussion on domain predicates.

@node Domain Predicates, Strongly Range Restricted Programs, Grounding, Theoretical Stuff
@comment  node-name,  next,  previous,  up
@section Domain Predicates

In beginning of this section the notion of @dfn{domain predicates} is
introduced quite informally, the formal definitions are in
subsection @ref{Formal Domains}. There are also some tips on how to
construct domains using relational algebra in subsection
@ref{Constructing Domains}.

@menu
* Informal Domains::
* Constructing Domains::
* Formal Domains::
@end menu

@node Informal Domains, Constructing Domains, , Domain Predicates
@comment  node-name,  next,  previous,  up
@subsection Domains Informally
@cindex Domain Predicate - Informal

Lparse divides the predicate symbols of a logic program into two
classes, domain and non-domain predicates. The domain predicates are
used to find all possible variable bindings of rules.

For example, in program:

@example
d(a,b). d(b,c). d(c,a). 
foo(X,Y,Z) :- d(X,Y), d(Y,Z), not bar(X,Y,Z). 
bar(X,Y,Z) :- d(X,Y), d(Y,Z), not foo(X,Y,Z).
@end example

Predicate symbol @samp{d} is the only domain predicate. When grounding
the rules for @samp{foo} and @samp{bar} lparse gets the possible
variable bindings from literals @samp{d(X,Y)} and @samp{d(Y,Z)}.

In this program there are three possible variable bindings for the two
non-ground rules:
@enumerate
@item @samp{@{X=a, Y=b, Z=c@}}, from @samp{d(a,b)} and @samp{d(b,c)}.
@item @samp{@{X=b, Y=c, Z=a@}}, from @samp{d(b,c)} and @samp{d(c,a)}.
@item @samp{@{X=c, Y=a, Z=b@}}, from @samp{d(c,a)} and @samp{d(a,b)}.
@end enumerate

The resulting ground program will be:

@example
d(a,b). d(b,c). d(c,a). 
foo(a,b,c) :- d(a,b), d(b,c), not bar(a,b,c).
foo(b,c,a) :- d(b,c), d(c,a), not bar(b,c,a).
foo(b,c,a) :- d(b,c), d(c,a), not bar(c,a,b).
bar(a,b,c) :- d(a,b), d(b,c), not foo(a,b,c).
bar(b,c,a) :- d(b,c), d(c,a), not foo(b,c,a).
bar(b,c,a) :- d(b,c), d(c,a), not foo(c,a,b).
@end example

In practice, the non-domain predicates are the ``interesting''
predicates, and the domain predicates are just programmer's way to tell
precisely what instances of the ``interesting'' predicates we want to
consider.

After the grounding is done it is often possible to drop all
domain literals from the program. After all, we already know that they
will be true in every stable model of the program. Lparse command-line
argument @samp{-d none} (@pxref{Lparse Options}) drops all domain
literals from the program. 

We can use as a domain predicate (nearly) any predicate that has a fixed
extension in all stable models of the program. That is, if we know all
true ground instances of the predicate even before we ask smodels to
compute them, the predicate is a domain predicate.

For example, in program:

@example
p(X,Y) :- d1(X,Y), not q(X,Y). 
q(X,Y) :- d1(X,Y), not p(X,Y). 
d1(X,Y) :- d2(X), d3(Y), not d4(X). 
d2(a). d2(b). d3(c). d4(a).
@end example

Predicates @samp{d1}, @samp{d2}, @samp{d3}, and @samp{d4} are domain
predicates. All rules with @samp{d2}, @samp{d3}, or @samp{d4} as heads
are facts so the whole extensions of those predicates are given directly
in the program (@samp{@{ d2(a), d2(b) @}} for @samp{d2}, and @samp{@{
d3(c) @}} and @samp{@{ d4(a) @}} for @samp{d3} and @samp{d4}).

As the only rule for @samp{d1} has only domain literals in its body, we
also can calculate its extension with relational algebra by taking a
natural join over the extensions of @samp{d2}, @samp{d3}, and @samp{d4}.
The resulting extension is simply @samp{@{ d1(b, c) @}} (@samp{d1(a,c)}
is not in the extension because @samp{d4(a)} is always true and thus the
variable binding doesn't satisfy the literal @samp{not d4(X)}).

The extensions of predicates @samp{p} and @samp{q} can't be calculated
beforehand, since they depend on each other recursively. The program has
one choice point where either @samp{p(b,c)} is added to the model or
@samp{q(b,c)} is added to model, but not both. Thus the extension of
@samp{p} will be either @samp{@{ p(b,c) @}} or it will be empty,
depending on which atom got included in the model.

However, there are some cases where the extension of a predicate is
fully known at the beginning, but the predicate is not in fact a domain
predicate (the formal definition given in @ref{Formal Domains} also
excludes these predicates).

For example, in program:

@example
d(1). d(2). d(3). 
s(X+1) :- d(X), s(X). 
s(1).
@end example

The extension of @samp{s} is always @code{@{ s(1), s(2), s(3), s(4) @}}
but @samp{s} is not a domain predicate since it depends recursively on
itself.

Recursions that are formed exclusively by positive literals (like the
one above) don't insert any choice points into the program and in theory
they could be allowed also within domain predicates. The main reason why
they are excluded is that of efficiency. First, it would be
computationally difficult to find out whether a recursion is a ``legal''
one @footnote{If there are many predicates in a positive recursive
cycle, some of the predicates in it might be also a part of a negative
cycle.}. Second, the computation of the transitive closure of the
extensions is also quite difficult operation. The idea of local
grounding is that each rule needs to be processed only once. If the
cycles were allowed, we would have to process each rule in the cycle as
many times as there are atoms in the extensions.

There is one more complication about domain predicates: If a predicate
occurs as a head in an extended rule (@pxref{Rule Types}) it may not be
a domain predicate. The reason why choice rules are excluded is clear as
they implicitly add a choice point to the program. The reason why other
rules are also excluded is implementation specific, as extended rules
are processed after the domain generation. This will probably change in
a future release, but for the time being you cannot use a predicate as a
domain predicate if it occurs as a head in an extended rule.

@node Constructing Domains, Formal Domains, Informal Domains, Domain Predicates 
@comment  node-name,  next,  previous,  up
@subsection Constructing Domains
@cindex Constructing Domains
@cindex Relational Algebra

All basic relational algebra operations can be done on the extensions of
domain predicates and the result will still be a domain predicate. The
operations are:
@enumerate
@item Union of the extensions of @samp{P} and @samp{R}:

@example
U(X) :- P(X). 
U(X) :- R(X).
@end example

@item Intersection of the extensions:

@example
I(X) :- P(X), R(X).
@end example

@item Set difference of the extensions:

@example
D(X) :- P(X), not R(X).
@end example

@item Cartesian product:

@example
C(X,Y) :- P(X), R(Y).
@end example

@item Natural join:

@example
J(X,Y,Z) :- P(X,Y), R(Y,Z).
@end example

@item Symmetric difference:

@example
S(X) :- P(X), not R(X). 
S(X) :- R(X), not P(X).
@end example

@end enumerate

@node Formal Domains, , Constructing Domains, Domain Predicates
@comment  node-name,  next,  previous,  up
@subsection Formal Domains
@cindex Formal Domains
@cindex Dependency Graph
@cindex Depends

The @dfn{dependency graph} @samp{Gp(Vp, Ep)} of a logic program @samp{P}
is constructed as follows:
@enumerate
@item @code{Vp = @{ A | A @r{is a predicate symbol in} @samp{P}@}}

@item @samp{(a,b)} belongs to @samp{Ep} if and only if there exists a
rule in @samp{P} where @samp{a} is the predicate symbol in head and
@samp{b} is a predicate symbol in rule body.
@end enumerate

A predicate @samp{a} @dfn{depends} on a predicate @samp{b} if and only
if there exists a path from @samp{a} to @samp{b} in the dependency
graph.

A predicate @samp{p} of a logic program @samp{P} is a @dfn{domain
predicate} if and only if it holds that every path starting from node
@samp{p} in the dependency graph is cycle free.

@node Strongly Range Restricted Programs, Regular Models, Domain Predicates, Theoretical Stuff
@comment  node-name,  next,  previous,  up
@section Strongly Range Restricted Programs
@cindex Range Restricted
@cindex Strongly Range Restricted

A rule is @dfn{strongly range restricted} if it holds that if a variable
appears in the rule it also appears in a positive domain literal in the
body.

A logic program is @dfn{strongly range restricted program} if and only
if every rule in it is strongly range restricted.

For example. if @samp{d} is a domain predicate and there are two rules:

@example
p(X,Y) :- d(X,Y), not q(X,Y). 
q(X,Y) :- not d(X,Y), not q(X,Y).
@end example

then the first rule is strongly range restricted since both @samp{X} and
@samp{Y} occur in the domain literal @samp{d(X,Y)}. The second rule is
not range restricted, since the domain literal is negative, and not
positive.

The reason for including range restriction is that during grounding we
have to know exactly what ground instances of rules are needed. 

For example, if we tried to use rules of the following form:

@example
a(X) :- not b(X,Y).
@end example

We would have to generate a ground instance for each imaginable binding
of @samp{Y}. In effect, we would have to use every single constant that
appears somewhere in the program as a possible binding for @samp{Y} and
there may be hundreds of thousands of them. So the domain predicates are
used to ``restrict the range'' of variables.

The earlier smodels front-end, @code{parse}, allowed rules of the form:

@example
p(X,Y) :- q(X,Y), not r(X,Y).
@end example

where @samp{q} was any predicate symbol. Parse calculated the needed
ground instances by disregarding all negative literals and then
calculating a deductive closure of the rules. This method had the
weakness that the whole program had to be kept in memory during
grounding, which severely affected the performance of the system.

@node Regular Models, , Strongly Range Restricted Programs, Theoretical Stuff 
@comment  node-name,  next,  previous,  up
@section Regular Models
@cindex Regular Models

The support for regular model semantics is still really preliminary.
Current details can be found in NEWS file. 

@node Language, Partial Models and Disjunctive Programs, Theoretical Stuff, Top
@chapter Language
@cindex Language

This chapter describes the language that lparse accepts. The first
section gives a brief introduction about the most important things while
the rest of the chapter give detailed description of the language. 

@menu
* Basic Things::
* Terms::
* Rule Types::
* Declarations::
* Statements::
* Special Constructs::
* Functions::
* Keywords::
@end menu

@node     Basic Things,  Terms, , Language
@comment  node-name,  next,  previous,  up
@section Basic Things

The basic things needed with smodels and lparse are introduced here by
using node coloring problem as an example. In node coloring we are given
a set of nodes and a set of edges that connect the nodes. The problem is
to use some fixed number of colors to color each node so that two
adjacent nodes don't have same color. In this example we use three
colors, red, blue, and yellow.

As this example uses only basic rules it is quite long. In chapter
@ref{Examples} there is a version using extended rules (@pxref{Rule
Types}) that solves the general case of this problem and takes only
three lines of code.

@example
color(red). 
color(blue). 
color(yellow). 

col(X,red) :- node(X), not col(X, blue), not col(X,yellow). 
col(X,blue) :- node(X), not col(X, red), not col(X,yellow). 
col(X,yellow) :- node(X), not col(X, blue), not col(X,red). 
fail :- edge(X,Y), color(C), col(X,C), col(Y,C). 
node(a). node(b). 
node(c). node(d). 
edge(a,b). edge(b,c). 
edge(c,d). edge(d,a). 

compute 1 @{ not fail @}.
@end example

The first three lines,

@example
color(red). 
color(blue). 
color(yellow).
@end example

define the colors we are allowed to use. The predicate @samp{color} is
also defined in such way that it can be used as a domain predicate
(@pxref{Domain Predicates}) later in the program. 

The following rule,

@example
col(X,red) :- node(X), not col(X, blue), not col(X,yellow).
@end example

says that if a node is not blue and it is not yellow, then the node has
to be red. The next two rules are otherwise identical but they are for
colors blue and yellow.

Generally, the semantics of a basic rule matches that of logical
implication: if the body is true the head must also be true.

It is quite common to model choices by using recursive not-atoms of the
form:

@example
a :- not b. 
b :- not a.
@end example

If @samp{b} is not true, then @samp{a} must be true and the other way
round. However, this construction is not true exclusive or of the atoms,
since it is possible that some other part of the program forces both
@samp{a} and @samp{b} to be true. To get XOR one should add a rule of
the form:

@example
fail :- a, b.
@end example

to the program.

The next rule

@example
fail :- edge(X,Y), color(C), col(X,C), col(Y,C).
@end example

ensures that neighbouring nodes have different colors. Here the
predicate @samp{node} is not needed to give domain for node-variables
@samp{X} and @samp{Y} because @samp{edge} is also a domain predicate.

The @samp{fail} atom is used to signal that something is wrong with the
model, namely that two adjacent nodes have the same color. Later in the
program we demand that @samp{fail} may not be true in any stable model
of the program.

The same effect could be achieved by using construction:

@example
  :- edge(X,Y), color(C), col(X,C), col(Y,C).
@end example

Rules with empty heads work as constraints on the models of the program.
If a variable binding makes the the body of the rule true, then the
binding is discarded.

The next part of the program:

@example
node(a). node(b). 
node(c). node(d). 
edge(a,b). edge(b,c). 
edge(c,d). edge(d,a).
@end example

defines a simple graph with four nodes and four edges. Usually, the
graph is stored in another file so that we don't have to duplicate the
inference rules for each graph.

The last line of the program:

@example
compute 1 @{ not fail @}.
@end example

tells smodels that we want only one model and that the atom @samp{fail}
may not be in the model. This rules out all models where two adjacent
nodes have the same color.

The code of this example is stored in directory
@file{examples} as @file{color1.lp}. The example graph is
in the same directory as @file{graph1}.

The process of running this program through smodels would look like:

@example
% @kbd{lparse color1.lp graph1 | smodels} 
smodels version 2.10. Reading...done 
Answer: 1 
Stable Model: edge(d,a) edge(c,d) edge(a,b) edge(b,c) node(a) node(d) 
node(c) node(b) col(a,yellow) col(c,red) col(d,blue) col(b,blue) 
color(yellow) color(red) color(blue)   
True 
Duration: 0.030 
Number of choice points: 3 
Number of wrong choices: 0  
Number of atoms: 24 
Number of rules: 35 
Number of picked atoms: 45 
Number of forced atoms: 0  
Number of truth assignments: 152 
Size of searchspace (removed): 12 (0)
@end example

As the first line of output smodels prints its version information. The
next lines give the first model found. In the model nodes @samp{d} and
@samp{b} are colored blue, node @samp{a} is yellow and node @samp{c} is
red.

The word @samp{true} below the model tells that there may be also other
models, but smodels didn't calculate them @footnote{It is possible, that
there actually are no more models, but smodels reports @samp{true}
always if the whole search space is not explored.}. If there are no
models left, the line reads @samp{false}. @samp{false} is displayed also
if the program has no models at all.

The rest of the lines give some statistics about your program. The
duration tells how long the search took in seconds. (FIXME: more
explanations here)

@c The number of choice points tell how many times smodels had to guess a
@c truth value for a ground atom. This time smodels guessed the correct
@c value for each atom and thus it didn't have to backtrack. There were a
@c total of 24 atoms and 35 rules in the grounded program (the original had
@c four non-ground rules, 11 facts, and 12 atoms). In general, the number
@c of choice points is more important than the number of rules or atoms
@c when we want to compare complexities of problems.

@c The number of picked-atoms tell how many times smodels lookahead
@c heuristics managed to pick a truth value to an atom. (FIXME: tähän
@c tarvitaan lisää sepustusta).

It is often useful to be able to see what exactly is output from lparse.
This can be accomplished by using @samp{-t} command line argument:

@example
% @kbd{lparse -t color1.lp graph1} 
edge(d,a). 
edge(c,d). 
edge(a,b). 
edge(b,c). 
node(a). 
node(d). 
node(c). 
node(b). 
fail :- col(d,yellow), col(a,yellow). 
fail :- col(c,yellow), col(d,yellow).  
fail :- col(a,yellow), col(b,yellow). 
@r{ [24 output lines snipped] } 
compute 1 @{ not fail @}
@end example

At the beginning of this program the domain predicates are output just
like they were entered in the input program. The next three lines define
three cases where the constraints of the problem instance are broken.


@node       Terms, Rule Types, Basic Things, Language
@comment  node-name,  next,  previous,  up
@section Terms
@cindex Terms

There are three different types of terms: constants, variables and
functions.

@enumerate
@item Constant:
@cindex Constant

A constant is either a symbolic constant or a numeric constant. A
symbolic constant is a string of letters and numbers which may also
contain underscores @samp{_} starting with a lower case letter or a
sequence of characters that is enclosed within double quotes @samp{"}.

A numeric constant is an integer. Currently the allowed range for numbers
goes only from - 2^30 to 2^30. This limitation is due to seriously
limited implementation of constants and will be removed in some later
release. @xref{Future Development}.

Sample constants: @code{0, 1020, cons_tant, "quoted constant"}.

It is also possible to define a symbolic constant to act as an numeric
constant by adding a constant declaration (@pxref{Declarations}). If you
add the line @code{const @var{foo} = @var{number}} to your program, from
that point on every occurrence of the constant @var{foo} will be
substituted by @var{number}.

In general you may use an expression that evaluates to a constant value
everywhere where you can use constants, that is, it is legal to use
constructs like:

@code{const double = 2 * foo.}

@item Variables
@cindex Variable

A variable is a string of letters and numbers which may also contain
underscores @samp{_} starting with an upper case letter

Sample variables: @code{X, Time_1}.

@item Functions

A function is either a function symbol followed by a parenthesised
argument list or an builtin arithmetical expression. A function may be
either a numerical function that is actually used to compute something
or it is a symbolic function of the form @samp{foo(a)}, which basicly
just defines a new constant that gets the name @samp{foo(a)}.

A numerical function may be either built-in internal function or an user
specified C/C++-function, which is linked to lparse dynamically
(@pxref{User-Defined Functions}). The internal comparison functions
(@samp{eq}, @samp{neq}, @samp{lt}, @samp{le}, @samp{gt}, and @samp{ge}) can
be used with both numeric and symbolic constants, but other functions
allow only numeric arguments.  

The use of functions is explained more fully in Section @ref{Functions}. 


Sample functions: @code{X+1, times(X,5, plus(Y, 1))}.

@end enumerate

@node       Rule Types, Declarations, Terms, Language
@comment  node-name,  next,  previous,  up
@section Rule Types
@cindex Rule Types

There are four different rule types. Basic rules function like normal
logic programming rules while the extended rule types (constraint,
weight, and choice) rules add more expressivines to the language. 

@enumerate
@item Basic Rule
@cindex Basic Rule

@example
h(X) :- a1(X), a2(X), an(X), not b1(X), not b2(X), not bm(X).
@end example

If @samp{a1(X), @dots{}, an(X)} are in a stable model and @samp{b1(X),
@dots{}, bn(X)} are not, then @samp{h(X)} is also put in the model.

If there is no head, then all those models that make the whole body true
will be discarded. 

@item Constraint Rule
@cindex Constraint Rule

@example
h(X) :- @var{lower} @{ a1(X), a2(X), an(X), not b1(X),
                not b2(X), not bm(X) @} @var{upper}.
@end example

Here @var{lower} and @var{upper} are numeric constants or constant
valued expressions, and one of them may be left out. The semantics is
that if the number of true literals in the body is between @var{lower}
and @var{upper} (inclusive), then the head is put in the model.

If @var{lower} bound is missing '0' is substituted, and if @var{upper}
bound is missing any number of body literals may be true.

Each ground instance of a constraint rule will be transformed into three
distinct rules that are outputted, for example:

@example
h(a) :- 2 @{ d1(a), d2(a), d3(a), d4(a) @} 3.
@end example

will be instantiated as:

@example
h(a) :- int1(a), not int2(a). 
int1(a) :- 2 @{ d1(a), d2(a), d3(a), d4(a) @}. 
int2(a) :- 4 @{ d1(a), d2(a), d3(a), d4(a) @}.
@end example

Here @samp{int1} and @samp{int2} are new internal predicates.
The main reason for constructing a new rule also for @samp{int1} is that
it makes possible to combine many constraint rules into one rule, for
example:

@example
h(X) :- 1 @{ d(X), e(X) @}, 1 @{ f(X), g(X) @}.
@end example

@item Weight Rule
@cindex Weight Rule

@example
h(X) :- @var{lower} [ a1(X)=@var{wa1}, a2(X)=@var{wa2}, an(X)=@var{wan},
         not b1(X)=@var{wb1}, not b2(X)=@var{wb2}, not bm(X)=@var{wbm} ] @var{upper}.
@end example

A weight rule behaves otherwise just like a constraint rule, but each
literal may be given a different integral weight, and if the sum of the
weights of satisfied literals in the rule body is between @var{lower}
and @var{upper} (inclusive), then h(X) is put to the model. In addition,
if @var{lower} is missing '-infinity' is substituted. 

The weights @var{wa1}, @dots{}, @var{wbm} may be any expressions. If
there are variables in weight expressions, they must be strongly range
restricted.

The weights of the literals may be given in the rule body, or they may
be defined earlier by global weight declarations. The local values
override the global values. If there is neither global or local
declaration, the default value is used. The programwise default is
normally @samp{1}, but you can change it with command-line argument
@samp{-w}. @xref{Lparse Options}.

Negative weights are handled by inverting the literal (@samp{a} becomes
@samp{not a} and @samp{not a} becomes @samp{a}), changing the sign of
the weight and adding the absolute value of the weight to the bounds.

For example, 
@example
h :- @var{lower} [ a1=@var{wt1}, a2=@var{-wt2}, not a3=@var{wt3}, not a4=@var{-wt4} ].
@end example

becomes

@example
h :- @var{lower} + |@var{wt2}| + |@var{wt4}| [ a1=@var{wt1}, not a2=@var{wt2},
                            not a3=@var{wt3}, a4=@var{wt4} ].
@end example


@item Choice Rule
@cindex Choice Rule

@example
@var{lower} @{ h1(X), h2(X), hk(X) @} @var{upper} :- @var{body}.
@end example

If the @var{body} of a choice rule is true, then the number of
@samp{h1(X)}, @dots{}, @samp{hn(X)} that are true in the model will be
between @var{lower} and @var{upper} inclusive.

If both bounds are missing there may be any number of head atoms
included in a model. It is then said that the @var{body} gives the head
atoms a reason to be in a model, but it doesn't force them to be in
it.

There exists the notation

@example
h1(X) | @dots{} | hk(X) :- @var{body}.
@end example

which is a shorthand for

@example
1 @{ h1(X), @dots{}, hk(X) @} 1 :- @var{body}.
@end example

That is, using @samp{|} notation you get an exclusive or of the head
atoms. 

Internally, a choice rule with non-zero bounds will be translated
into three rules:

@example
@{ h1(X), @dots{}, hk(X) @} :- @var{body}.
  :- @var{upper} +1 @{ h1(X), @dots{}, hk(X) @}, @var{body}.
  :- @var{k} - @var{lower} +1 @{ not h1(X), @dots{}, not hk(X) @}, @var{body}.
@end example

where @var{body} is the rule body of the original rule. 

It is also possible to use weights in choice rules. The syntax for
weights is similar than that used in weight rules:

@example
@var{lower} [ h1(X)=@var{w1}, @dots{}, hk(X)=@var{wk} ] @var{upper} :- @var{body}.
@end example

This will be transformed into:

@example
@{ h1(X), @dots{}, hk(X) @} :- @var{body}.
  :- @var{upper} + 1 [ h1(X)=@var{w1}, @dots{}, hk(X)=@var{wk} ], @var{body}.
  :- @var{total} - @var{lower} +1 [ h1(X)=@var{w1}, @dots{}, hk(X)=@var{wk} ], @var{body}.
@end example

Here @var{total}=@var{w1}+@dots{}+@var{wk}.
@end enumerate

It is possible to combine many special rules into one rule. The only
restriction is that if there is a basic tail section in the rule (like
@samp{f, g} in the next example) it has to be at the end of the rule. 

For example, following rule is legal:

@example
1 @{ a, b, c @} :- 1 @{ d, e @}, 2 [ not d = 2, not e = 2 ], f, g.
@end example

This rule would be translated into following rules:

@example
@{ a, b, c @} :- int1, int2, f, g. 
:- 3 @{ not a, not b, not c @} :- int1, int2, f, g. 
int1 :- 1 @{ d, e @}. 
int2 :- 2 [ not d = 2, not e = 2 ].
@end example

Each rule has to be strongly range restricted (@pxref{Strongly Range
Restricted Programs}). In particular, the domain predicates should be in
the basic tail section of the rule. If there is some variable that gets
its range from a domain literal inside an extended rule, a new domain
predicate is added to the basic tail section to restrict the variable.
The extension of the new predicate will be the union of the extension of
all domain predicates in which the variable occurs.

For example, in rule

@example
a(X) :- 2 @{ d1(X), not d2(X), nd(X) @}, 1 @{ d3(X), d4(X) @}.
@end example

where @samp{d1}, @samp{d2}, @samp{d3}, and @samp{d4} are domain
predicates and @samp{nd} is not, the variable @samp{X} doesn't occur in
a domain predicate in the basic tail section. As a result, the rule will
be transformed into:

@example
a(X) :- 2 @{ d1(X), not d2(X), nd(X) @}, 1 @{ d3(X),d4(X) @}, int1(X). 
int1(X) :- d1(X). 
int1(X) :- d2(X). 
int1(X) :- d3(X). 
int1(X) :- d4(X).
@end example

where @samp{int1} is a new internal predicate.

@node     Declarations, Statements, Rule Types, Language
@comment  node-name,  next,  previous,  up
@section  Declarations
@cindex   Declarations

There are four kinds of declarations in the language: function
declarations, constant declarations, weight definitions and hide
declarations. The declarations may occur anywhere in the source code.
The only restriction is that you have to declare a constant or a
function before you use it.

@enumerate
@item Function declaration:
@cindex Function Declaration

@example
function @var{foo}.
@end example

This declares the identifier @var{foo} to be used as a numeric function
throughout the program. The used defined functions are described in more
detail in Section @ref{User-Defined Functions}.

@item Constant declaration:
@cindex Constant Declaration

@example
const @var{bar} = @var{expr}.
@end example

This declares the identifier @var{bar} as being a numeric constant with
value @var{expr}, which may be any constant valued expression. It is
also possible to define constants from command line by using switch
@samp{-c}. There are more about numeric constants in Section @ref{Terms}.

The syntax of constant declaration has been changed from previous
versions of lparse, namely, the '=' was not used before. 

@item Weight definition
@cindex Weight Definition

@example
weight @var{atom} = @var{expr}.
@end example

This declares the default weight of atom @var{atom} to be @var{expr}.
Any variables occuring in @var{expr} must also occur in @var{atom}. The
weights will then be instantiated during grounding.

When a weight is needed for a literal @samp{a} that doesn't have explicit weight
assigned to it lparse starts looking for weight definitions that it has
seen before the line in question. Lparse tries to unify @samp{a} with
each definition, and when a match is found it uses that weight. If no
weight definition matches for @samp{a}, the global default weight
(1, if not set with @samp{-w} option) is used.

For example, in program

@example
weight p(X,Y) = 1.
weight p(a,Y) = 2.
weight p(a,b) = 3.

a :- 2 [ p(a,b)=1, p(a,a), p(b,b) ].
@end example

the weight of @samp{p(a,a)} is @samp{1} because the explicit definition
overrides all global definitions. Lparse then starts looking for weight
of @samp{p(a,a)}. It first tries to unify @samp{p(a,a)} and
@samp{p(a,b)}, but fails because @samp{a != b}. Unifying with
@samp{p(a,Y)} succeeds, when variable @samp{Y} is binded with value
@samp{a}. Thus, the weight of @samp{p(a,a)} is @samp{2}. Using similar
process lparse determines that the weight of @samp{p(b,b)} is @samp{1}.

If the weight of a literal is defined more than once, only the latest
definition is used. For example:

@example
weight p(X) = X.
weight p(2) = 10.

a :- 2 [ p(1), p(2) ].  % weights: p(1) = 1, p(2) = 10

weight p(Y) = Y+5.

b :- 2 [ p(1), p(2) ].  % weights: p(1) = 6, p(2) = 7
@end example

Note that before lparse version 0.99.26 the weight of @samp{p(2)} would
have been also @samp{10}, but under the new semantics the weight
definition for @samp{p(Y)} shadows the earlier definition. 

@item Hide declaration
@cindex Hide
@cindex Hide declaration

@example
hide @var{p(X,Y)}.
@end example

Smodels 2.x offers a feature where some atoms may be hidden from the
printed models. The atoms still affect the model in normal way, but they
just are not printed. The internal predicates generated by lparse are
automatically hidden.

The hide declaration above marks all ground instances of 2-ary predicate
@var{p} to be hidden. The arguments of @var{p} are used only to distinct
predicates with different arities from each other.

For example, if program

@example
hide p(X).
p(1..2).
p(X,Y) :- p(X), p(Y).
@end example

is given to smodels as input, the output will be:

@example
smodels version 2.16. Reading...done
Answer: 1
Stable Model: p(1,1) p(2,1) p(1,2) p(2,2) 
True
@end example

@end enumerate

@node     Statements, Special Constructs, Declarations, Language
@comment  node-name,  next,  previous,  up
@section  Statements
@cindex Statements

The statements are used to specify desired properties of the models.
There are two kinds of statements, compute and optimize statements.

@enumerate
@item Compute statement:
@cindex Compute Statement

@example
compute @var{number} @{ a1, a2, an, not b1, not b2, not bm @}.
@end example

Only stable models containing a1, ..., an and not containing b1, ..., bm
are computed. The number of generated models is controlled by
@var{number}. If @var{number} is 0 or identifier @samp{all}, all
models are computed. The default number of models is 1.

@item Optimize statement:
@cindex Optimize Statement
@cindex Minimize Statement
@cindex Maximize Statement

@example
maximize @{ a1, a2, an, not b1, not b2, not bm @}. 
minimize @{ a1, a2, an, not b1, not b2, not bm @}.
@end example

When a optimize statement is given smodels tries to find models with as
many (or as few) of the given literals as possible. You may also use
weights with these literals, and then the model with maximal (or
minimal) weight is returned.

However, the behavior of smodels is not the one that would come to mind
first. Namely, smodels first searches a single model, and prints it.
After that smodels prints only ``better'' models. For example, if in the
first model includes three optimized atoms, only those models with four
or more are returned afterwards. 

If there are more than one optimize statement they are considered fixed
order, the last one being the strongest. When comparing two models M1
and M2, if the last optimize statement gives different values for both
models the rest of the statements are not evaluated at all. Only if M1
and M2 tie with respect to the last optimize statement the next one
before it is used, and so on.
@end enumerate

@node     Special Constructs, Functions , Statements, Language
@comment  node-name,  next,  previous,  up
@section Special Constructs
@cindex Special Constructs

There are a number of special constructs that may be used to shorten the
programs, namely ranges, multiple arguments, and conditions. 

@enumerate
@item Range:
@cindex Range

A range is of the form:

@example
@var{start} .. @var{end}
@end example

where @var{start} and @var{end} are constant valued expressions. A range
is a notational shortcut which is mainly used to define numerical
domains in a compact way. A range is expanded by defining a new domain
predicate, and adding all elements of the range to its extension. The
range is then replaced by a variable that gets its domain from the new
domain predicate.

For example, fact @samp{a(1..3).} is a shortcut for

@example
a(X) :- int1(X). 
int1(1). 
int1(2). 
int1(3).
@end example

Ranges can also be used in rule bodies with the same semantics. 

@example
b :- a(1..3).
@end example

expands to

@example
b :- a(X), int1(X).
int1(1). 
int1(2). 
int1(3).
@end example

Now @samp{b} is true if any of @samp{a(1)}, @samp{a(2)}, or @samp{a(3)}
is true. 
@item Multiple Arguments:
@cindex Multiple Arguments

Multiple arguments are of the form

@example
@var{arguments} ; @var{arguments}
@end example

where @var{arguments} are lists of terms that may occur as predicate
arguments. Multiple arguments are expanded by generating a new literal
for each argument list except in basic rule heads where a new rule is
generated for each set of arguments.

For example,

@example
foo(a ; b; c).
@end example

is expanded to

@example
foo(a). 
foo(b). 
foo(c).
@end example

and

@example
@{ a(X ; Y+1) @} :- d( X ; Y).
@end example

will be expanded to

@example
@{ a(X), a(Y+1) @} :- d(X), d(Y).
@end example

@item Condition
@cindex Condition

A condition is of the form:

@example
p(X) : q(X)
@end example

where @samp{p(X)} is any literal and @samp{q} is a domain predicate.
If the extension of @samp{q} is @samp{@{ q(a_1), q(a_2), @dots{},
q(a_n) @}}, then the above condition is semantically equivalent to
writing @samp{p(a_1), p(a_2), @dots{}, p(a_n)} in the place of
condition. For example, 

@example
q(1..2).
a :- 1 @{ p(X):q(X) @}.
@end example

will be grounded to give

@example
q(1). q(2).
a :- 1 @{ p(1), p(2) @}.
@end example

If the condition is empty, that is, if there are no ground atoms for
predicate @samp{q(X)}, the behavior depends on where the condition is
used. If the condition is in basic rule tail, the literal is satisfied.

@example
a :- b : c.
@end example

becomes

@example
a :- b.
@end example

if @samp{c} is true, and

@example
a.
@end example
if it is not.

Within extended rule sections the literals with empty conditions don't
count against rule bounds. This is to allow rules of the form

@example
foo :- 1 @{ chosen(X) : version(X) : X > 2 @}.
@end example

to have intuitive semantics. Atom @samp{foo} is true only if there is at
least one atom @samp{chosen(X)} where @samp{X} > 2. 

Semantically the expansion of conditions takes place after the global
variables of the rule are instantiated. For example in program

@example
d(1..2).
a(X) :- 1 @{ p(X,Y) : d(Y) @}, d(X).
@end example

variable @samp{X} will be first instantiated to give program 

@example
d(1). d(2).
a(1) :- 1 @{ p(1, Y) : d(Y) @}, d(1).
a(2) :- 1 @{ p(2, Y) : d(Y) @}, d(2).
@end example

In the next step the conditions are expanded to give

@example
d(1). d(2).
a(1) :- 1 @{ p(1, 1), p(1, 2) @}, d(1).
a(2) :- 1 @{ p(2, Y), p(2, 2) @}, d(2).
@end example

In practice the conditions are expanded as early as possible. If you
don't have any global variables in the conditions, they are expanded
before instantiating the rest of variables because it is computationally
a more efficient method.

It is also possible add many conditions to one literal. For example in
condition

@example
p(X,Y) : q1(X) : q2(Y)
@end example

domain predicate @samp{q1} gives values to @samp{X} and @samp{q2} gives
values to @samp{Y}. 

@end enumerate

@node Functions, Keywords, Special Constructs, Language
@comment  node-name,  next,  previous,  up
@section Functions
@cindex Functions
@cindex Symbolic Functions

There are two kinds of functions in lparse, numerical functions and
symbolic functions. The difference is that a numerical function is used
to compute something, but a symbolic function basicly just defines a new
constant that is the value of the function.

For example, in program:

@example
d(1 .. 2). e(a ; b). 
q(X+1) :- d(X). 
p(f(X)) :- e(X).
@end example

there are two functions, @samp{X+1} and @samp{f(X)}. Here @samp{X+1} is
a numerical function and its value is computed during grounding, while
@samp{f(X)} is a symbolic function and only thing that grounding does to
it is to instantiate @samp{X}. The grounded program is:

@example
d(1). d(2). e(a) e(b). 
q(2) :- d(1). 
q(3) :- d(2). 
p(f(a)) :- e(a). 
p(f(b)) :- e(b).
@end example

The functions @samp{f(a)} and @samp{f(b)} are treated just like
constants by smodels.

@menu
* Numerical Functions::
* Internal Functions::
* User-Defined Functions::
* Lparse API::
@end menu

@node Numerical Functions, Internal Functions, , Functions
@comment  node-name,  next,  previous,  up
@subsection Numerical Functions
@cindex Numerical Functions

Numerical functions can occur in two different roles in rules, either as
a term or as a literal.

As a term a numerical function gives a value to an argument of a
predicate. When grounding the rule with resolved variable bindings the
function is called and the return value is stored into the position.
Internally the function is replaced by a new variable and an assign
function in the rule body.

For example @code{p(X, Y, X+Y) :- d(X,Y)} becomes @code{p(X, Y, Z) :-
d(X,Y), Z = X+Y.} When grounding the above rule with variable binding
@code{@{X/1, Y/2@}} the ground rule becomes @code{p(1,2,3) :- d(1,2)}.

As a literal a function works as a constraint for possible variable
values. If the function returns @samp{false}, i.e. 0 when called with a
given variable binding that binding is discarded. If it returns
@samp{true}, i.e. any value other than 0, the ground rule corresponding to
the binding is printed. When printing a ground rule all functions
in its body are discarded. For example the program

@example
d(1). d(2). 
q(X,Y) :- d(X), d(Y), X < Y.
@end example

is grounded to give

@example
d(1). d(2). 
q(1,2) :- d(1), d(2).
@end example

@node Internal Functions, User-Defined Functions, Numerical Functions, Functions
@comment  node-name,  next,  previous,  up
@subsection Internal Functions
@cindex Internal Functions

There are 17 different arithmetical functions built in lparse. The
internal functions are automatically declared unless @samp{-i} command
line option is given.

There is an infix operator defined for each internal function. The
notations @samp{fun(X,Y)} and @samp{X op Y} are interchangeable. In fact,
the latter is converted internally into the former. All internal
functions accept many arguments, so you can call for example
@samp{plus(X,Y,Z,2)}.

The comparison functions are only functions that allow symbolic
constants as their arguments. The constants are then compared using
lexicographic, that is, phonebook ordering. 

@enumerate
@item plus(X,Y): X + Y
@item minus(X,Y): X - Y
@item times(X,Y): X * Y
@item div(X,Y): X / Y
@item mod(X,Y): X mod Y
@item lt(X,Y): X < Y
@item gt(X,Y): X  > Y
@item le(X,Y): X <= Y
@item ge(X,Y): X >= Y
@item eq(X,Y): X == Y
@item neq(X,Y): X != Y
@item assign(X,Y): X = Y
@item abs(X): | X |
@item and(X,Y): bitwise AND of X and Y
@item or(X,Y): bitwise OR of X and Y
@item xor(X,Y): bitwise XOR of X and Y
@item not(X): bitwise NOT of X 
@end enumerate

The operator precedence is following:

@example
- (unary) ; *, /, mod ; +, - ; ==, !=, <, >, <=, >= ; =
@end example

The @samp{assign} function returns always 1 when the assignment
succeeds, so the constructs like @samp{X = Y = 5} don't work like
they do in C.

@node User-Defined Functions, Lparse API, Internal Functions, Functions
@comment  node-name,  next,  previous,  up
@subsection User-Defined Functions
@cindex User-Defined Functions


It is possible to add a user-defined C or C++ function to lparse. In
earlier versions of lparse you had to use the perl script
@code{register} to link the functions statically to lparse binaries. The
new method allows dynamic linking of shared library files to lparse.

Just about every C/C++-function can be linked with lparse, but those
functions that meant to be directly called from logic programs should
have the prototypes:

@example
long foo(int num_args, long *args)
@end example

That is, lparse passes the arguments in an array of long integers with
an integer parameter telling the lenght of the array. The symbolic
constants are encoded as indices to the symbol table where the actual
strings are stored. The numeric constants can be handled using normal
functions and operators but the only way to handle symbolic constants is
to use the lparse API @pxref{Lparse API}.

Lparse uses the normal C convention or treating value 0 as false and
every other value as true. 

Before you can use your own function you have to add it to a shared
library and tell lparse where the library can be found.

@c As default lparse uses @file{libs/liblparse.so} if it exists. Lparse
@c searches additional libraries from directories defined in (in this
@c order):

@cindex Environmental Variables
@cindex .lparserc
@enumerate
@item Environmental variable @code{LPARSE_LIBRARY_PATH}.
@item In file @file{~/.lparserc}.
@item Environmental variable @code{LD_LIBRARY_PATH}. 
@end enumerate

The additional libraries should be defined using environmental variable 
@code{LPARSE_LIBRARIES} or in @file{.lparserc}.

An example @file{.lparserc} is:

@example
LPARSE_LIBRARY_PATH = /home/tss/lparse-libs 
LPARSE_LIBRARIES = libfoobar.so
@end example

If you have files @file{foo.c} and @file{bar.c} that you want to use
with lparse, you can create the shared library with following steps.
(These steps work with @file{gcc} on a linux system, if you use some
other system they may or may not work.)

@enumerate
@item Compile the files into object files using @samp{-fPIC}- option:

@code{gcc -fPIC -Wall -c foo.c}

@item Create the shared library. If your functions call some library
functions, it will be safest to link these to the library. Here we
suppose that @file{foo.c} uses some functions defined in standard math
library:

@code{gcc -shared -Wl,-soname,libfoobar.so -o libfoobar.so foo.o bar.o
-lm}

@item Move @file{libfoobar.so} to a suitable place and put a pointer to
it into @file{.lparserc}. 
@end enumerate

In @file{lib} directory of lparse distribution there is a makefile that
can be used as a model for generating your own libraries. 

@c In @file{lib} directory of lparse distribution there is a makefile that
@c generates @file{liblparse.so}. You may add there all object files you
@c want to be shared with all users. The makefile can also be used as a
@c skeleton for other libraries. 

The final step is to tell lparse that you want to use your own
functions. This is done by adding a function declaration

@code{function foo.}

to the program. When a function is declared lparse goes on and tries to
find the function symbol from the libraries. It will pick the first
match that it finds and display an error if no matches are found. If
lparse founds some other external symbol with the same name, for example
a character array, it will die horribly trying to jump at the symbol. If
you get a lot of segmentation faults while using your own, functions
this may be one reason.

@node Lparse API, ,User-Defined Functions , Functions
@comment  node-name,  next,  previous,  up
@subsection Lparse API
@cindex API

The lparse version 0.99.47 added a programming API that allows
user-defined functions to manipulate also symbolic constants. The API
functions are defined in the file @file{lparse.h} that is located in
@file{lib} directory of lparse distribution. 

The @file{lparse.h} contains declarations of seven functions that
provide the basic constant handling capabilities. The current version of
the API doesn't differentiate between symbolic constants and symbolic
functions. That is, a symbolic function is internally treated as a
oridinary constant that just happens to have a specific form.

The header file defines an enumeration @samp{lparse_constant_t} to hold
the possible types of lparse constants:

@center @code{typedef enum @{ LP_NUMERIC, LP_SYMBOLIC @} lparse_constant_t;}

The current API functions are:
@example
lparse_constant_t lparse_constant_type(long @var{constant})
int lparse_is_numeric(long @var{constant})
int lparse_is_symbolic(long @var{constant})
char *lparse_get_symbolic_constant_name(long @var{symbolic_constant})
long lparse_get_symbolic_constant_index(char *@var{symbolic_constant})
int lparse_symbol_exists(char *@var{symbolic_constant})
long lparse_create_new_symbolic_constant(char *@var{arg})
@end example

@table @code
@item lparse_constant_t lparse_constant_type(long @var{constant})
The function @code{lparse_constant_type} returns the type
(@code{LP_NUMERIC} or @code{LP_SYMBOLIC}) of the argument
@var{constant}. 

@item int lparse_is_numeric(long @var{constant})
Returns @var{true} if @var{constant} is a numeric constant, @var{false}
otherwise. 

@item int lparse_is_symbolic(long @var{constant})
Returns @var{true} if @var{constant} is a symbolic constant, @var{false}
otherwise.

@item char *lparse_get_symbolic_constant_name(long
@var{symbolic_constant})
Returns a pointer to the symbol table entry of @var{symbolic_constant}
or @code{NULL} if it is not defined. As the pointer is to the actual
symbol table, you should not mess with it.

@item long lparse_get_symbolic_constant_index(char
*@var{symbolic_constant})
Returns the lparse symbolic constant that corresponds to the character
string @var{symbolic_constant} or a special value
@code{LP_INVALID_CONSTANT} if the symbolic constant is not defined.

@item int lparse_symbol_exists(char *@var{symbolic_constant})
Returns @var{true} if @var{symbolic_constant} is defined as a symbolic
constant and @var{false} otherwise.

@item long lparse_create_new_symbolic_constant(char *@var{new_string})
The function @code{lparse_create_new_symbolic_constant(char *@var{new_string})}
stores its argument into the symbol table and returns its symbolic
constant value. It is safe to add same constant many times to the table
and all calls will return the same value.
@end table

For example, the following code can be used to identify whether a
constant is a symbolic function (this example can be found in the
@file{lib} directory of lparse distribution):
@example
/* apitest.c -- a small example how the lparse API can be used */

#include "lparse.h"
#include <string.h>

/* This function returns the symbolic constant 'true' if its first
   argument is a symbolic function, and 'false' otherwise */
long is_symbolic_function(int nargs, long *args)
@{
  char *st = 0;
  
  if (lparse_is_symbolic(args[0])) @{
    st = lparse_get_symbolic_constant_name(args[0]);

    /* supposes that there is a '(' in a constant only if it actually is
       a symbolic function */
    if (strstr(st, "(")) @{    
      return lparse_create_new_symbolic_constant("true");
    @}
  @}
  return lparse_create_new_symbolic_constant("false");
@}
@end example
Suppose that the above function was compiled and linked to
@file{liblparse.so}. Then, the following program
@example
function is_symbolic_function.
a(is_symbolic_function(1)).
b(is_symbolic_function(foo(1))).
c(is_symbolic_function(bar)).
@end example
gives the following output:
@example
smodels version 2.23. Reading...done
Answer: 1
Stable Model: c(false) b(true) a(false) 
True
@end example

@node Keywords, , Functions, Language
@comment  node-name,  next,  previous,  up
@section Keywords
@cindex Keywords
@cindex Internal Atoms
@cindex Internal Variables
@cindex Internal Predicates

The following identifiers are used as keywords by lparse:

@enumerate
@item compute
@item const
@item function
@item hide
@item maximize
@item minimize
@item mod
@item not
@item weight
@end enumerate

In addition to keywords lparse uses internal atoms, predicates, and
variables. The names of the internal predicates and atoms start with an
underscore (@samp{_}). The names of internal variables start with
@samp{I_}. You should avoid using the internal symbols in your programs,
or strange behavior may result. 

@node Partial Models and Disjunctive Programs, Examples,  Language, Top
@comment  node-name,  next,  previous,  up
@chapter Partial Models and Disjunctive Programs

Smodels and Lparse now include facilities to calculate stable and
partial models for disjunctive logic programs. However, this
functionality is still quite primitive. The theretical basis of these
features is presented in @cite{Unfolding Partiality and Disjunctions in
Stable Model Semantics} by Janhunen, Niemel@"a, Simons, and You. This
paper appears in Proceedings of the 7th International Conference on
Principles of Knowledge Representation and Reasoning and it's available
for download at @url{http://www.tcs.hut.fi/~ttj/publications.html}.

@menu
* Partial Models::
* Disjunctive Programs::
@end menu

@node Partial Models, Disjunctive Programs, , Partial Models and Disjunctive Programs 
@comment  node-name,  next,  previous,  up
@section Partial Models
@cindex Partial Models
@cindex Partial Interpretation

As we saw in @ref{Basic Terminology}, an interpretation of a logic
program assigns a truth value to atoms in the Herbrand base of the
program. Each atom is either @samp{true} or @samp{false} in the
interpretation. A @dfn{partial interpretation} @samp{I} is an
interpretation that assigns a definite truth value to only some atoms of
the base and the rest of the atoms are said to have @samp{unknown} truth
value.

@cindex Partial Model
A @dfn{partial model} is a partial interpretation that satisfies all
rules of the program. However, the concept of satisfaction has to be
redefined to take into accord the fact that there are now three
different truth values. We impose an order on truth values so that

@center @samp{false} < @samp{unknown} < @samp{true}.

The truth value @samp{I(B)} of the body of a rule is obtained by taking
minimum of the truth values of the literals in the body and the truth
value @samp{I(H)} of the head is the maximum of the truth values of the
head atoms. A rule is satisfied when @samp(I(H)) >= @samp{I(B)}.

For example, suppose that we have a partial interpretation @samp{I(a) =
unknown}, @samp{I(b) = true}, @samp{I(c) = unknown}, @samp{I(d) =
false}. Suppose further that we have two rules:
@example
a | d :- b, not c.
d :- a. 
@end example
Now the first rule is satisfied since @samp{I(H) = unknown} >=
@samp{I(B) = unknown}. The second rule is not satisfied as @samp{I(H) =
false} < @samp{I(B) = unknown}. 

@node Disjunctive Programs, , Partial Models, Partial Models and Disjunctive Programs 
@comment  node-name,  next,  previous,  up
@section Disjunctive Programs
@cindex Disjunctive Programs



@node Examples, Writing Smodels Programs , Partial Models and Disjunctive Programs, Top
@chapter Examples
@cindex Examples

The source code of all examples in this chapter is included in the
@file{examples} directory of lparse tarball. More examples can be found
from @file{lparse-demo.tgz} which is available at

@center @uref{http://www.tcs.hut.fi/pub/smodels/lparse/}.

@menu
* Node Coloring::
* Planning::
@end menu

@node Node Coloring, Planning, , Examples
@comment  node-name,  next,  previous,  up
@cindex Node Coloring
@section Node Coloring

@example
% Node coloring problem by Tommi Syrj@"anen. 
% Given a graph given as a set of nodes and edges 
% find a way to color the nodes with 'n' colors such that 
% two adjacent nodes are not colored with the same color.  

const n=3. % this can be changed with command line argument '-c'.

color(1..n).

% Each node should have exactly one color:
1 @{ node_color(N, C) : color(C) @} 1 :- node(N).

% Two adjacent nodes have to have different colors: 
 :- node_color(X, C), node_color(Y,C), edge(X,Y), color(C). 
 
% Typical command line 
% lparse -d none -c n=3 color2.lp graph | smodels
@end example

@c @node Schur Numbers, Planning, Node Coloring, Examples
@c @comment  node-name,  next,  previous,  up
@c @cindex Schur Numbers
@c @section Schur Numbers
@c 
@c @example
@c % Schur problem by Ilkka Niemel@"a 
@c % Put the integers N=@{1,2,...,n@} to b boxes such 
@c % that for any X,Y in N  
@c % (i) X and 2X are in different boxes and  
@c % (ii) if X and Y are in the same box then X+Y is in a different box.  
@c % pos(X,B): integer X is in a box B.  
 
@c pos(X,B) :- n(X), b(B), not negpos(X,B).  
@c negpos(X,B) :- n(X), b(B), not pos(X,B).  
 
@c % X is in at most one box  
@c :- n(X), b(B), b(B1), pos(X,B), pos(X,B1), B != B1.  
@c % X is in at least one box  
@c :- n(X), not has_box(X).  
@c has_box(X) :- n(X), b(B), pos(X,B). 
 
@c % Condition (i)  
@c :- n(X),  Y = 2*X,  b(B), pos(X,B), pos(Y,B). 
@c % Condition (ii)  
@c :- n(X), n(Y), b(B), pos(X,B), pos(Y,B), Z=X+Y, pos(Z,B). 
 
@c n(1..n).  
@c b(1..b).  
 
@c % let's remove symmetries by taking always the lowest free box. 
@c :- n(X), b(B), pos(X,B), b(B1), B1 < B, not occupied(X,B1).  
@c % occupied(X,B) iff there is a number Y < X in B  
@c occupied(X,B) :- n(X), b(B), n(Y), Y < X, pos(Y,B).  
 
@c % Typical command line  
@c % lparse -d none -c n=13 -c b=3 schur.lp | smodels
@c @end example

@node Planning, , Node Coloring, Examples
@comment  node-name,  next,  previous,  up
@cindex Planning
@section Planning

The largest example program in @file{example} directory is
@file{logistics.lp} which shows a way to encode planning problems as
smodels programs. The program is too big to be included in this manual,
but here are some selected bits.

In planning problem we are given a descriptions of the initial state of
the world and the desired goal state. In addition, we are given a set of
actions that can be used to change the state of world.

In logistics domain we have an action @code{load_truck(Object, Truck)}
which is used, naturaly enough, to load packages into trucks. The
precondition for this operation is that the object and truck are at the
same place and the effect is that the package will be inside the truck.

The first step in converting the action to smodels rules is to add a
third argument to it, namely time, to it. Thus we'll use predicate
@code{load_truck(Object, Truck, Time)} to model the loading.

A natural way to encode actions is to use choice rules, in form:

@example
@{ action @} :- preconditions.
@end example

According to the semantics of choice rules, if the body is true in a
model then the head may be true in the model, but it doesn't have to be
true in it. Thus, when the preconditions are fulfilled we can either
perform the action or decide to do some other action.

The effects of an action are implied by the action:

@example
effects :- action.
@end example

The blocking of conflicting actions is done by adding a constraint 
that says that if an action doesn't change its own precondition, 
then the precondition has to hold also at the next instant: 

@example
precondition(I+1) :- action, precondition(I).
@end example

Using these guidelines we can encode @samp{load_truck} with following
rules: 

@example
load_truck(Obj, Tr, I) @} :- 
    at(Obj, Loc, I), 
    at(Tr, Loc, I), 
    object(Obj), 
    truck(Tr), 
    location(Loc), 
    time(I). 

%Effects: 
in(Obj, Tr, I+1) :- 
    load_truck(Obj, Tr, I), 
    truck(Tr), 
    object(Obj), 
    time(I). 

changes(Obj, I) :- 
    load_truck(Obj, Tr, I), 
    truck(Tr), 
    object(Obj), 
    time(I). 

% As one of the preconditions for load_truck(Obj, Tr, I) is 
% at(Tr, Loc, I) and the operator doesn't change it, the truck has to 
% be at the same place at the next instant.  

at(Tr, Loc, I+1) :- 
    load_truck(Obj, Tr, I), 
    at(Tr, Loc, I), 
    location(Loc), 
    truck(Tr), 
    object(Obj), 
    time(I).
@end example

In addition to operators we also need a set of frame axioms that take
care of those parts of the world that doesn't change at an time step and
that keep the system in consistent state:

@example
%% FRAME AXIOMS 
 
% Everything stays at the same place where it is unless some action 
% moves it. 
 
at(Obj, Loc, I+1) :- 
    at(Obj, Loc, I), 
    not changes(Obj, I), 
    object(Obj), 
    location(Loc), 
    time(I). 

% An object may not be in two places at the same time 
 
 :- 2 @{ at(Obj, Loc, I) : location(Loc), 
        in(Obj, Cont, I) : container(Cont) @}, 
    object(Obj), 
    end_time(I).
@end example

@node Writing Smodels Programs,  Future Development, Examples, Top
@chapter Writing Smodels Programs

This section contains some miscellaneous topics on writing programs for
smodels. First the operation of an Emacs major-mode for writing smodels
code is described. The two following subsections contain some tips for
debugging logic programs and using parser warnings. 

@menu
* Emacs Major-Mode for Smodels::
* Debugging Smodels Programs::
* Parser Warnings::
@end menu

@node Emacs Major-Mode for Smodels, Debugging Smodels Programs, ,Writing Smodels Programs
@section Editing Smodels Programs with Emacs
@cindex Emacs
@cindex smodels-mode.el

There is a major-mode for writing smodels programs with Emacs. It is
defined in file @file{smodels-mode.el} which is located int the
@file{src} directory of lparse distribution.

To use the mode you have to copy @file{smodels-mode.el} into some
directory that is mentioned in your @samp{load-path} Emacs variable and
add a command to load the mode when needed.

For example, suppose that
you want to use directory @file{~/.elisp} for all your Emacs Lisp files.
Then you could copy @file{smodels-mode.el} to that directory and add the
following commands to your @file{.emacs} startup file:

@example
;; First set the load path
(setq load-path (cons "~/.elisp" load-path))

;; Load smodels-mode automatically when needed.
(autoload 'smodels-mode "smodels-mode" "Smodels Editing Mode" t)

;; Use smodels-mode for all files that end with `.lp'. 
(setq auto-mode-alist (cons '("\\.lp$" . smodels-mode)
                             auto-mode-alist))

;; Turn syntax highlighting on automatically
(add-hook 'smodels-mode-hook 'turn-on-font-lock)
@end example

Smodels-mode knows how to indent smodels programs and performs some
syntax highlighting. All keywords are printed with
@samp{font-lock-keyword-face} font, built-in functions with
@samp{font-lock-builtin-face}, and variables with
@samp{font-lock-variable-face}.

You can also run lparse and smodels processes under Emacs with
smodels-mode. You can choose what parser to use with command @samp{M-x
smodels-set-parser}. By default @samp{lparse} is used. The actual
smodels version that is used to compute the models can be set with
@samp{M-x smodels-set-program}. By default, @samp{smodels} is used.
You can set command line arguments with @samp{M-x
smodels-set-parser-arguments} and @samp{M-x
smodels-set-program-arguments}. 

There are four different commands that can be used to start smodels
processes: 
@itemize @bullet
@item @samp{M-x smodels-compute-buffer} grounds the current buffer with
chosen parser, sents the results to a smodels process, and prints the
stable models in buffer @samp{*smodels*}.

@item @samp{M-x smodels-compute-files} works otherwise like
@samp{smodels-compute-buffer}, but it allows you to process programs
that are stored in multiple files. When you use this function the first
time it asks what files you want to include with the run. If you want to
change the file list later, you can do it with command @samp{M-x
smodels-set-file-list}.

@item @samp{M-x smodels-parse-buffer} sends the current buffer to the
parser and displays the output in buffer @samp{*smodels*}. By default,
@samp{smodels-parse-buffer} displays its output in plain text format,
but if you include a argument (i.e. if you invoke it with @samp{C-u M-x 
smodels-parse-buffer}) the output is in smodels internal format. 

@item @samp{M-x smodels-parse-files} grounds many files. 
@end itemize

The smodels-mode keymap binds above functions to following keys:
@itemize @bullet
@item @samp{C-c C-b} is binded to @samp{smodels-parse-buffer}
@item @samp{C-c C-f} is binded to @samp{smodels-parse-files}
@item @samp{C-t C-b} is binded to @samp{smodels-compute-buffer}
@item @samp{C-t C-f} is binded to @samp{smodels-compute-files}
@end itemize

@node Debugging Smodels Programs, , Emacs Major-Mode for Smodels , Writing Smodels Programs
@comment  node-name,  next,  previous,  up
@section Debugging Smodels Programs
@cindex Debugging

So now you have written a large logic program, but only thing that
smodels gives as answer is @samp{False}. Finding problems within logic
programs may be tedious and frustrating since a small typo may ruin the
whole program. It is not possible to give a debugging procedure that
works every time, but here are some things that I have found helpful.

@enumerate

@item Make sure that all constants begin with a lower case letter and
that all variables begin with an upper case letter. I once spent a
couple of hours searching for a mysterious bug in a planning model that
seemed to come and go. The cause for the bug was that in one rule I had
written @samp{at(tr, Loc, I)} instead of @samp{at(Tr, Loc, I)}. When
there was only one truck (namely @samp{tr}) in the model everything
worked well, but when there were more trucks a plan couldn't be found
because only one of the trucks could move.

@item Comment rules out one at a time to see which rule causes the
contradiction. Of course, if the problem is that some needed rule is
missing you cannot find it this way. It is also possible that the rule
commented out works correctly, but some other incorrect rule conflicts
with it. 

@item Make the domains as small as possible. If your program works well
when there is only one item of some type and it fails when there are
more of them, there is probably some rule demanding that if something is
true for one item, then is true for all of them. For example, once I
tried to split predicate @samp{drive_truck(Tr, From, To, I)} into three
smaller predicates @samp{drives(Tr, I)}, @samp{moves_from(Tr, From, I)},
and @samp{moves_to(Tr, To, I)}. The rule that I wrote for
@samp{moves_to} was of the form:

@example
moves_to(Tr, To, I) :-
    truck(Tr),
    location(To),
    time(I),
    drives(Tr, I).
@end example

Grounding transformed this rule into form:

@example
moves_to(tr, a, 1) :- drives(tr, 1).
moves_to(tr, b, 1) :- drives(tr, 1).
@end example

That is, the rule demanded that if a truck drives somewhere at all, it
must at the same time drive to each possible location. 

@item Use @code{compute} statements to test what combination of atoms
cause contradictions. Start with an empty @code{compute} statement and
if smodels finds a model continue by adding some atoms that should be in
the model to see where the things go wrong.

For example, when debugging my planning encoding I used @code{compute}
statements of the form:

@example
compute 1 @{ load_truck(pct, tr, 1), drive_truck(tr, a, b, 2),
            unload_truck(pct, tr, 3), at(pct, b, 4) @}.
@end example

after adding each operator to check that the program could find at least
some legal plan.

@item Use @samp{-t} argument to see what exactly lparse does to your
program. Because the ground programs are often quite big you should
comment out everything that in your opinion is not related to the bug. 

@end enumerate

@node Parser Warnings, , , Writing Smodels Programs
@comment  node-name,  next,  previous,  up
@cindex Warnings
@section Parser Warnings

Lparse can detect some possible errors from its input. The checks are
mostly aimed to detect constructs that have caused prior
trouble@footnote{If you are sometimes bitten badly by something you
think lparse should detect automatically, please send me an email about
it and I'll try to incorporate a new warning for it in later releases.}.
Most of the constructs are sometimes useful, but in wrong places they
have caused a lot of debugging. If you want to use the warnings
effectively, you should know what causes warnings and why.

@itemize @bullet
@item @samp{-W arity} detects cases when a predicate symbol has two
different arities in same program. This warning is mainly intended for
catching bugs where you forgot an argument from a predicate. For example

@example
p(a).
p(a,a).
@end example

emits warning 

@example
2: Warning: predicate 'p' is used with 2 arguments at line 2,
   while it is also used with 1 argument at line 1.
@end example

There are cases when when it is useful to have many different arities
for same predicate. For example, you could want to say something like

@example
goal :- goal(I), time(I).
@end example

to say that it doesn't matter when the goal is found. Of course, in many
of these cases it would be better to use different predicate symbols.

@item @samp{-W extended} detects general problems with extended
rules. This is a warning that should be enabled nearly always, at least
I haven't found any legitimate use for the constructs that trigger this
warning.

Currently, @samp{extended} warns about cases where you haveexplicitly
defined weights in places where they don't have any effect. Most often
this happens because you have used curly braces instead of brackets. For
example:

@example
a :- 2 @{ b = 3, not c = 2 @}.
@end example

gives warning

@example
1: Warning: weight defined for literal 'b' in a constraint rule.
1: Warning: weight defined for literal 'not c' in a constraint rule.
@end example

Here the fix is to replace @samp{@{} and @samp{@}} with @samp{[} and
@samp{]}. 

@item @samp{-W library} emits a warning in two cases: if you have
defined a library file that doesn't exist in @samp{.lparserc} or if you
declare a function two times.

@item @samp{-W similar} detects cases where you might have misspelled
the initial letter of a constant or variable. For example, in program

@example
a(1..5).
b(3..7).
c(I) :- a(I), b(i).
@end example

the variable @samp{I} was misspelled in literal @samp{b(i)}, and as the
result the domain of predicate @samp{c(X)} is empty instead of
@samp{c(3..5)} as intended. If warning @samp{similar} is enabled, lparse
outputs:

@example
3: Warning: constant 'i' is similar to variable 'I'
   (other occurrences of 'i' are not checked)
@end example

Lparse warns only the first possible typo that it sees. 

This warning is quite often a false alarm, since there are many reasons
why a program would have similar names for constants and variables.
However, enabling this warning cathces some of the most annoying bugs in
logic programs. 

@item @samp{-W unsat} is another option that can catch hard-to-find
typos. Given this option lparse warns if there is some predicate symbol
that can't be satisfied because it doesn't occur in a head of any rule.
This option is mainly intended to find out cases where you have
misspelled a predicate. For example, in program

@example
const max_time = 10.
time(1 .. max_time).
@{ action(I) @} :- preconition(I), time(I).
precondition(I) :- time(I). 
@end example 

the first non-trivial rule is probably trying to say that an
@samp{action} is possible only if its @samp{precondition} is true, but
the predicate was misspelled. Sometimes these errors are truly a pain to
find and correct. Using warning @samp{unsat} lparse outputs:

@example
3: Warning: predicate 'preconition' doesn't occur in any rule head.
@end example

This option is similar to the one above in that there are many cases
where it is not an error to have some unsatisfiable predicate in the
program. For example in program,

@example
a :- not b, enable_a.
b :- not a. 
@end example

we want that @samp{a} is not in any model unless we specifically allow
it by adding @samp{enable_a} as a fact into the program. 

@item @samp{-W weight} outputs a warning if you use the default weight
of a literal in some weight rule. Default weights are often useful, but
if you want to define weight explicitly for each literal you can set
this option to catch typos in global weight definitions. For example,
you might have program

@example
e(1..3). 
weight c(1) = 10.
weight c(2) = 15.
weight d(3) = 20.
a :- 30 [ c(X) : e(X) ]. 
@end example

Here the idea is, that @samp{a} should be true if the total weight of
true @samp{c(X)} atoms is more than @samp{30}. However, the last weight
definition was misspelled so that the weight of @samp{c(3)} is default
@samp{1} instead of @samp{20}.

Given option @samp{-W weight} lparse warns:

@example
5: Warning: default weight used for literal 'c(3)'
@end example

@item @samp{-W error} causes lparse to treat all warnings as errors. 

@end itemize

There are three options that can be used to set more than one warning
flag at a time:

@itemize @bullet

@item @samp{-W all} enables all warnings.
@item @samp{-W syntax} sets @samp{arity}, @samp{extended}, and
@samp{weight}.
@item @samp{-W typo} sets @samp{similar} and @samp{unsat}.
@end itemize

@node Future Development, Bugs, Writing Smodels Programs, Top
@comment  node-name,  next,  previous,  up
@chapter Future Development
@cindex Future Development

I have a couple of ideas that will probably be included in lparse some
day. They include:

@enumerate

@item Extended support for data types. I vision system like one that is
used in programming language Scheme, that is, user may freely mix normal
integers, floating point numbers and bignums and the system takes care
of rest. However, as this requires rewriting of quite large parts of
lparse code this will not happen very soon.

@item Some sort of unified method for setting attributes for predicates,
like marking them hidden, setting weights, and like. This feature would
prevent ``keyword-pollution'', that has been threatening lparse lately.
The feature will be implemented in such way that it will be easy to
convert current programs into new format automatically.

@item A new declaration that would allow one to define implicit domain
predicates for variables. For example, it would be possible to say
something like this: ``in each rule variable @samp{I} will have domain
@samp{time(I)}''.

@item Possibility of using predicates that occur as head of a special
rule as domain predicates. 

@end enumerate

If you have some suggestions or if you found a bug in lparse, please
send email it for me (@email{tommi.syrjanen@@hut.fi}). 


@node Bugs, Concept Index, Future Development, Top
@comment  node-name,  next,  previous,  up

@section Bugs
@cindex Bugs

Right now there are no known bugs in lparse.

@node Concept Index, , Bugs, Top
@page
@unnumbered Index

@printindex cp
@contents
@bye
