Screamer provides a nondeterministic choice-point operator, a backtracking mechanism, and a forward propagation facility.
Screamer was originally written by Jeffrey Mark Siskind and David Allen McAllester.
The copy of Screamer this documentation refers to is maintained courtesy of Steel Bank Studio Ltd by Nikodemus Siivola.
The Google Group
http://groups.google.com/group/screamer/
exists for Screamer-related discussions.
Screamer is maintained in Git:
git clone git://github.com/nikodemus/screamer.git
will get you a local copy.
http://github.com/nikodemus/screamer
is the GitHub project page.
Following original publications by Siskind and McAllester form the basis of this manual:
Screaming Yellow Zonkers, 1991. Old Screamer manual, doesn't always hold true for Screamer 3.20 on which this “modern” Screamer is based, but still probably the most complete discussion of various operators and the overall design of Screamer outside of this manual.
Screamer: A Portable Efficient Implementation of Nondeterministic Common Lisp, 1993. A paper describing the fundamentals of Screamer.
Nondeterministic Lisp as a Substrate for Constraint Logic Programming, 1993. A paper describing the constaints propagation features of Screamer.
Screamer shadows defun, and a couple of other symbols.
Examples in this manual are expected to be entered in the package
SCREAMER-USER, which has the correct defun.
Packages using Screamer are best defined using
define-screamer-package, which is like defpackage
using CL and SCREAMER packages, but does the additional
shadowing imports.
This is however by no means necessary: you can also explicitly use
screamer::defun.
Screamer adds nondeterminism by providing the choice-point
operator either and the failure operator
fail.
A choice-point is a point in program where more than one thing can happen. When a choice-point is encountered, one of the possibilities occurs, and execution continues. Should a failure subsequently occur, the system backtracks to the last choice-point where multiple possibilities were still present, and tries again.
Backtracking is controlled by a form providing a nondeterministic
context, eg. all-values, one-value, or
for-effects.
(all-values
(let ((x (either 1 2 3 4)))
(if (oddp x)
x
(fail)))) ; => (1 3)
At first (either 1 2 3 4) evaluates to 1, which is oddp,
so all-values receives it and sets about producing the next
value. Now either returns 2, which isn't oddp. Hence
fail is called causing the system to backtrack.
Starting again from the choice-point 3 is produced, which is
oddp, and is received by all-values, which in turn
requests the next value. Now either returns 4, which again
causes fail to backtrack.
Since the only choice-point available cannot produce any more
alternatives, control passes back to all-values which returns
the collected values.
Had we wanted only one answer instead of an enumeration of all
possible answers we could have used one-value instead of
all-values.
If you're familiar with Prolog, all-values and one-value
are analogous to Prolog's bagof and cut primitives.
Given either and fail we can write functions returning
arbitrary sequences of nondeterministic values. Such functions are
called generators, and by convention have names starting with
a- or an-.
Consider for example an-integer-between:
;;; Screamer already provides an-integer-between, so we'll
;;; call this by a different name.
(defun an-int-between (min max)
(if (> min max)
(fail)
(either min (an-int-between (1+ min) max))))
(all-values (an-int-between 41 43)) ; => (41 42 43)
Called with two integers, this function produces nondeterministic values in the given range – finally backtracking to a previous choice-point when all possibilities have been exhausted.
Given an-integer-between and fail we can write eg. a
generator for square numbers:
;;; Square numbers are numbers produced by squaring an integer.
(defun a-square-number (min max)
(let* ((x (an-integer-between 0 max))
(square (* x x)))
(if (<= min square max)
square
(fail))))
(all-values (a-square-number 12 80)) ; => (16 25 36 49 64)
We're not restricted to numbers, of course. Writing a generator for potential comedy duos works just the same:
(defun a-comedic-actor ()
(list (either :tall :short) (either :thin :fat)))
(defun a-comedy-duo ()
(let ((a (a-comedic-actor))
(b (a-comedic-actor)))
(if (or (eq (first a) (first b))
(eq (second a) (second b)))
(fail)
(list a :and b))))
(one-value (a-comedy-duo)) ; => ((:TALL :THIN) :AND (:SHORT :FAT))
What should happen to side-effects when a nondeterministic function backtracks? It depends. Some side-effects should be retained, and some undone – and it is impossible for the system to know in general what is the right choice in a given case.
Screamer is able to undo effects of setf and setq
(including calls to user-defined setf-functions), but cannot undo
calls to other functions with side-effects such as set,
rplaca, or sort.
By default all side-effects are retained:
(let ((n 0))
(list :numbers
(all-values (let ((x (an-integer-between 0 3)))
(incf n)
x))
:n n)) ; => (:NUMBERS (0 1 2 3) :N 4)
Macros local and global can be used to turn
undoing of side-effects on and off lexically.
(let ((m 0)
(n 0))
(list :numbers
(all-values (let ((x (an-integer-between 0 3)))
(local
(incf n)
(global
(incf m)))
x))
:m m
:n n)) ; => (:NUMBERS (0 1 2 3) :M 4 :N 0)
In addition to nondeterminism via backtracking as discussed so far,
Screamer also provides for forward constraint propagation via
logic variables constructed using make-variable.
Screamer provides a variety of primitives for constraining variables.
By convention suffix v is used to denote operators that accept
(and potentially return) variables in addition to values. Any
foov is generally just like foo, except its arguments
can also be logic variables, and that it may assert facts about them
and will possibly return another variable.
The operator assert! is the primary tool about asserting facts
about variables.
Expression such as (foov myvar) typically returns another
variable depending on myvar, which can be constrained to be
true using assert!.
Operator bound? can be used to test if variable is bound to a
specific value, and value-of can be used to obtain its value.
;;; Make a variable
(defparameter *v* (make-variable "The Answer"))
;;; It is initially unconstrained.
*v* ; => ["The Answer"]
;;; Constrain it to be an integer.
(assert! (integerpv *v*))
*v* ; => ["The Answer" integer]
;;; Constrain 40 to be 2 less than *v*
(assert! (=v 40 (-v *v* 2)))
;;; And we have our answer.
*v* ; => 42
;;; However, there's a catch. Even though *v* printed as 42 above, *v*
;;; is still a variable. This is convenience for working in the REPL:
;;; unbound variables print using square brackets, bound ones print
;;; as their value.
(type-of *v*) ; => SCREAMER::VARIABLE
;;; To obtain its value:
(value-of *v*) ; => 42
Assertions – and constraint operators in general – can cause failure and backtracking, in which case constraints from the last attempt are undone.
This allows us to search the solution space using backtracking:
(defparameter *x* (make-variable "X"))
(defparameter *y* (make-variable "Y"))
(assert! (integerpv *x*))
(assert! (integerpv *y*))
(assert! (=v 0 (+v *x* *y* 42)))
(all-values (let ((x (an-integer-between -50 -30))
(y (an-integer-between 2 5)))
(assert! (=v *x* x))
(assert! (=v *y* y))
(list x y))) ; => ((-47 5) (-46 4) (-45 3) (-44 2))
A possibly less intuitive, but usually more efficient method is to assert range constraints as variables instead of nondeterministic values, and force a solution:
(assert! (=v *x* (an-integer-betweenv -50 -30)))
(assert! (=v *y* (an-integer-betweenv 2 5)))
(all-values
(solution (list *x* *y*)
(static-ordering #'linear-force)))
; => ((-47 5) (-46 4) (-45 3) (-44 2))
In this case backtracking occurs only inside solution, when
the system is trying to apply different solution to the given
constraints, whereas in the first one we backtracked over the entire
let.
Screamer is implemented using a code-walker, which does not unfortunately currently support the full ANSI Common Lisp.
Following special operators signal an error if they appear in code processed by the code walker:
Following special operators are accepted, but they cannot contain nondeterministic forms:
Additionally, functions defined using flet and labels
are not in nondeterministic context, even if the surrounding context
is nondeterministic.
Undoing side-effects via local is reliable only if the
setf and setq forms are lexically apparent:
(local (incf (foo)))
may or may not work as expected, depending on how foo is
implemented. If (incf (foo)) expands using eg. set-foo,
the code-walker will not notice the side-effect.
Undoing side-effects via local when there is no prior value
might not work as expected, depending on the implementation of the
place:
local will cause that to happen.
Example: assignment to an unbound variable inside local signals
an error.
nil) to be returned, undoing the side-effect means assigning
the marker object back to the place.
Example: undoing (setf gethash) of a previously unknown key
will cause nil to be stored in the table instead of removing
the new key and its value entirely via remhash.
Solving the “Einstein's Riddle” using nondeterministic features of Screamer, ie. backtracking search.
Solving the “The Zebra Puzzle”, using forward constraint propagation features of Screamer.
(This puzzle is virtually identical to “Einstein's Riddle”, but the solution is very different.)
Solving a sudoku puzzle using forward constraint propagation features of Screamer.
Nondeterministically evaluates and returns the value of one of its
alternatives.
eithertakes any number of arguments. With no arguments,(either)is equivalent to(fail)and is thus deterministic. With one argument, (EITHER X) is equivalent toxitself and is thus deterministic only whenxis deterministic. With two or more argument it is nondeterministic and can only appear in a nondeterministic context.It sets up a choice-point and evaluates the first
alternativereturning its values. When backtracking follows to this choice-point, the nextalternativeis evaluated and its values are returned. When no morealternativesremain, the current choice-point is removed and backtracking continues to the next most recent choice-point.
Backtracks to the most recent choice-point.
failis deterministic function and thus it is permissible to reference#'fail, and write(funcall #'fail)or(apply #'fail).Calling
failwhen there is no choice-point to backtrack to signals an error.
When called in non-deterministic context, adds
functionto the trail. Outside non-deterministic context does nothing.Functions on the trail are called when unwinding from a nondeterministic selection (due to either a normal return, or calling
fail.)
Evaluates
bodyas an implicitprognand returns a list of all of the nondeterministic values yielded by the it.These values are produced by repeatedly evaluating the body and backtracking to produce the next value, until the body fails and yields no further values.
Accordingly, local side effects performed by the body while producing each value are undone before attempting to produce subsequent values, and all local side effects performed by the body are undone upon exit from
all-values.Returns a list containing
nilifbodyis empty.An
all-valuesexpression can appear in both deterministic and nondeterministic contexts. Irrespective of what context theall-valuesappears in, thebodyis always in a nondeterministic context. Anall-valuesexpression itself is always deterministic.
all-valuesis analogous to the `bagof' primitive in Prolog.
Returns the first nondeterministic value yielded by
form.No further execution of
formis attempted after it successfully returns one value.If
formdoes not yield any nondeterministic values (i.e. it fails) thendefaultis evaluated and its value returned instead.defaultdefaults to(fail)if not present.Local side effects performed by
formare undone whenone-valuereturns, but local side effects performed bydefaultare not undone whenone-valuereturns.A
one-valueexpression can appear in both deterministic and nondeterministic contexts. Irrespective of what context theone-valueappears in,formis always in a nondeterministic context, whiledefaultis in whatever context theone-valueform appears.A
one-valueexpression is nondeterministic ifdefaultis present and is nondeterministic, otherwise it is deterministic.If
defaultis present and nondeterministic, and ifformfails, then it is possible to backtrack into thedefaultand for theone-valueform to nondeterministically return multiple times.one-valueis analogous to the cut primitive (`!') in Prolog.
Evaluates
bodyas an implicitprognin a nondeterministic context and returnsnil.The body is repeatedly backtracked to its first choice-point until the body fails.
Local side effects performed by
bodyare undone whenfor-effectsreturns.A
for-effectsexpression can appear in both deterministic and nondeterministic contexts. Irrespective of what context thefor-effectsappears in,bodyare always in a nondeterministic context. Afor-effectsexpression is is always deterministic.
Returns the Ith nondeterministic value yielded by
form.I must be an integer. The first nondeterministic value yielded by
formis numbered zero, the second one, etc. The Ith value is produced by repeatedly evaluatingform, backtracking through and discarding the first I values and deterministically returning the next value produced.No further execution of
formis attempted after it successfully yields the desired value.If
formfails before yielding both the I values to be discarded, as well as the desired Ith value, thendefaultis evaluated and its value returned instead.defaultdefaults to(fail)if not present.Local side effects performed by
formare undone whenith-valuereturns, but local side effects performed bydefaultand by I are not undone whenith-valuereturns.An
ith-valueexpression can appear in both deterministic and nondeterministic contexts. Irrespective of what context theith-valueappears in,formis always in a nondeterministic context, whiledefaultand I are in whatever context theith-valueappears in.An
ith-valueexpression is nondeterministic ifdefaultis present and is nondeterministic, or if I is nondeterministic. Otherwise it is deterministic.If
defaultis present and nondeterministic, and ifformfails, then it is possible to backtrack into thedefaultand for theith-valueexpression to nondeterministically return multiple times.If I is nondeterministic then the
ith-valueexpression operates nondeterministically on each value of I. In this case, backtracking for each value offormanddefaultis nested in, and restarted for, each backtrack of I.
Evaluates
bodyas an implicitprognand prints each of the nondeterministic values yielded by it usingAfter each value is printed, the user is queried as to whether or not further values are desired. These values are produced by repeatedly evaluating the body and backtracking to produce the next value, until either the user indicates that no further values are desired or until the body fails and yields no further values.
Returns the last value printed.
Accordingly, local side effects performed by the body while producing each value are undone after printing each value, before attempting to produce subsequent values, and all local side effects performed by the body are undone upon exit from
print-values, either because there are no further values or because the user declines to produce further values.A
print-valuesexpression can appear in both deterministic and nondeterministic contexts. Irrespective of what context theprint-valuesappears in, thebodyare always in a nondeterministic context. Aprint-valuesexpression itself is always deterministic.
print-valuesis analogous to the standard top-level user interface in Prolog.
Evaluates
bodyas an implicitprognin nondeterministic context, returning true if the body ever yields true.The body is repeatedly backtracked as long as it yields
nil. Returns the first true value yielded by the body, ornilif body fails before yielding true.Local side effects performed by the body are undone when
possibly? returns.A
possibly? expression can appear in both deterministic and nondeterministic contexts. Irrespective of what context thepossibly? appears in, its body is always in a nondeterministic context. Apossibly? expression is always deterministic.
Evaluates
bodyas an implicitprognin nondeterministic context, returning true if the body never yields false.The body is repeatedly backtracked as long as it yields true. Returns the last true value yielded by the body if it fails before yielding
nil, otherwise returnsnil.Local side effects performed by the body are undone when
necessarily? returns.A
necessarily? expression can appear in both deterministic and nondeterministic contexts. Irrespective of what context thenecessarily? appears in, its body is always in a nondeterministic context. Anecessarily? expression is always deterministic.
Evaluates
bodyin the same fashion asprognexcept that allsetfandsetqforms lexically nested in its body result in global side effects which are not undone upon backtracking.Note that this affects only side effects introduced explicitly via
setfandsetq. Side effects introduced by Common Lisp builtin functions such asrplacaare always global anyway.
localandglobalmay be nested inside one another. The nearest lexically surrounding one determines whether or not a givensetforsetqresults in a local or global side effect.Side effects default to be global when there is no surrounding
localorglobalexpression. Global side effects can appear both in deterministic as well as nondeterministic contexts. In nondeterministic contexts,globalas well assetfare treated as special forms rather than macros. This should be completely transparent to the user.
Evaluates
bodyin the same fashion asprognexcept that allsetfandsetqforms lexically nested in its body result in local side effects which are undone upon backtracking.This affects only side effects introduced explicitly via
setfandsetq. Side effects introduced by either user defined functions or builtin Common Lisp functions such asrplacaare always global.Behaviour of side effects introduced by macro-expansions such as
incfdepends on the exact macro-expansion. If(incf (foo))expands using eg.set-foo,localis unable to undo the side-effect.
localcannot distinguish between initially uninitialized and intialized places, such as unbound variables or hash-table keys with no prior values. As a result, an attempt to assign an unbound variable insidelocalwill signal an error due to the system's attempt to first read the variable. Similarly, undoing a(setf gethash)when the key did not previously exist in the table will insert anilinto the table instead of doing aremhash. Easiest way to work around this is by usingtrail.
localandglobalmay be nested inside one another. The nearest lexically surrounding one determines whether or not a givensetforsetqresults in a local or global side effect.Side effects default to be global when there is no surrounding
localorglobalexpression. Local side effects can appear both in deterministic as well as nondeterministic contexts though different techniques are used to implement the trailing of prior values for restoration upon backtracking. In nondeterministic contexts,localas well assetfare treated as special forms rather than macros. This should be completely transparent to the user.
Nondeterministically returns an element of
sequence. The elements are returned in the order that they appear insequence. Thesequencemust be either a list or a vector.
Generator yielding integers starting from
lowand continuing sequentially in increasing direction.
Generator yielding integers starting from
highand continuing sequentially in decreasing direction.
Nondeterministically returns an integer in the closed interval [
low,high]. The results are returned in ascending order. Bothlowandhighmust be integers. Fails if the interval does not contain any integers.
Analogous to the
cl:apply, exceptfunctioncan be either a nondeterministic function, or an ordinary deterministic function.You must use
apply-nondeterministicto apply a nondeterministic function. An error is signalled if a nondeterministic function object is used withcl:apply.You can use
apply-nondeterministicto apply either a deterministic or nondeterministic function, though even if all of theargumentsare deterministic andfunctionis a deterministic function object, the call expression will still be nondeterministic (with presumably a single value), since it is impossible to determine at compile time that a given call toapply-nondeterministicwill be passed only deterministic function objects for function.
Analogous to
cl:funcall, exceptfunctioncan be either a nondeterministic function, or an ordinary determinisitic function.You must use
funcall-nondeterministicto funcall a nondeterministic function. An error is signalled if you attempt to funcall a nondeterministic function object withcl:funcall.You can use
funcall-nondeterministicto funcall either a deterministic or nondeterministic function, though even if all of theargumentsare deterministic andfunctionis a deterministic function object, the call expression will still be nondeterministic (with presumably a single value), since it is impossible to determine at compile time that a given call tofuncall-nondeterministicwill be passed only deterministic function objects for function.
Analogous to the
cl:multiple-value-call, exceptfunction-formcan evaluate to either a nondeterministic function, or an ordinary deterministic function.You must use
multiple-value-call-nondeterministicto multiple-value-call a nondeterministic function. An error is signalled if a nondeterministic function object is used withcl:multiple-value-call.You can use
multiple-value-call-nondeterministicto call either a deterministic or nondeterministic function, though even if all of thevalues-formsare deterministic andfunction-formevaluates to a deterministic function object, the call expression will still be nondeterministic (with presumably a single value), since it is impossible to determine at compile time that a given call tomultiple-value-call-nondeterministicwill be passed only deterministic function objects for function.While
multiple-value-call-nondeterministicappears to be a function, it is really a special-operator implemented by the code-walkers processing nondeterministic source contexts.
Returns
tifxis a nondeterministic function andnilotherwise.
#'fooreturns a nondeterministic function object iff it is used in nondeterminisitc context andfoois either a nondeterministiclambdaform, or the name of a nondeterministic function defined usingscreamer::defun.Currently, if
foois a nondeterministic function defined usingscreamer::defun,#'fooand(symbol-function 'foo)in deterministic context will return an ordinary deterministic Common Lisp function, which will signal an error at runtime.
Whenever
failis called during execution ofbody, executesfailing-formsbefore unwinding.
Executes
bodykeeping track of the number of timesfailhas been called without unwinding frombody. Afterbodycompletes, reports the number of failures to*standard-output*before returning values frombody.
Creates and returns a new variable. Variables are assigned a name which is only used to identify the variable when it is printed. If the parameter
nameis given then it is assigned as the name of the variable. Otherwise, a unique name is assigned. The parameternamecan be any Lisp object.
Restricts
xtot. No meaningful result is returned. The argumentxcan be either a variable or a non-variable.This assertion may cause other assertions to be made due to noticers attached to
x.A call to
assert! fails ifxis known not to equaltprior to the assertion or if any of the assertions performed by the noticers result in failure.Except for the fact that one cannot write
#'assert!,assert! behaves like a function, even though it is implemented as a macro.The reason it is implemented as a macro is to allow a number of compile time optimizations. Expressions like
(assert! (notv x)),(assert! (numberpv x))and(assert! (notv (numberv x)))are transformed into calls to functions internal to Screamer which eliminate the need to create the boolean variable(s) normally returned by functions likenotvandnumberpv. Calls to the functionsnumberpv,realpv,integerpv,memberv,booleanpv,=v,<v,<=v,>v,>=v,/=v,notv,funcallv,applyvandequalvwhich appear directly nested in a call toassert!, or directly nested in a call tonotvwhich is in turn directly nested in a call toassert!, are similarly transformed.
Returns
xifxis not a variable. Ifxis a variable thenvalue-ofdereferencesxand returns the dereferenced value. Ifxis bound then the value returned will not be a variable. Ifxis unbound then the value returned will be a variable which may bexitself or another variable which is shared withx.
If
xis acons, or a variable whose value is acons, returns a freshly consed copy of the tree with all variables dereferenced. Otherwise returns the value ofx.
Returns
tifxis not a variable or ifxis a bound variable. Otherwise returnsnil.bound? is analogous to the extra-logical predicates `var' and `nonvar' typically available in Prolog.
The primitive
ground? is an extension of the primitivebound? which can recursively determine whether an entire aggregate object is bound. Returnstifxis bound and either the value ofxis atomic or aconstree where all atoms are bound.Otherwise returns nil.
fmust be a deterministic function. If all argumentsxare bound, returns the result of callingfon the dereferenced values of spread arguments.Otherwise returns a fresh variable
v, constrained to be equal to the result of callingfon the dereferenced values of arguments.Additionally, if all but one of
vand the argument variables become known, and the remaining variable has a finite domain, then that domain is further restricted to be consistent with other arguments.
fmust be a deterministic function. If all argumentsxare bound, returns the result of callingfon the dereferenced values of arguments.Otherwise returns a fresh variable
v, constrained to be equal to the result of callingfon the dereferenced values of arguments.Additionally, if all but one of
vand the argument variables become known, and the remaining variable has a finite domain, then that domain is further restricted to be consistent with other arguments.
Returns
tif the aggregate objectxis known to equal the aggregate objecty,nilif the aggregate objectxis known not to equal the aggregate objecty, and a new boolean variablevif it is not known whether or notxequalsywhenequalvis called.The values of
x,yandvare mutually constraints via noticers so thatvequalstif and only ifxis known to equalyandvequalsnilif and only ifxis known not to equaly.Noticers are attached to
vas well as to all variables nested in both inxandy. When the noticers attached to variables nested inxandydetect thatxis known to equalythey restrictvto equalt. Likewise, when the noticers attached to variables nested inxandydetect thatxis known not to equalythey restrictvto equalnil.Furthermore, if
vlater becomes known to equaltthenxandyare unified. Likewise, ifvlater becomes known to equalnilthenxandyare restricted to not be equal. This is accomplished by attaching noticers to the variables nested inxandywhich detect whenxbecomes equal toyand fail.The expression
(known? (equalv x y))is analogous to the extra-logical predicate `==' typically available in Prolog.The expression
(known? (notv (equalv x y)))is analogous to the extra-logical predicate `\=' typically available in Prolog.The expression
(assert! (equalv x y))is analogous to Prolog unification.The expression
(assert! (notv (equalv x y)))is analogous to the disunification operator available in Prolog-II.
Copies an aggregate object, replacing any symbol beginning with a question mark with a newly created variable.
If the same symbol appears more than once in
x, only one variable is created for that symbol, the same variable replacing any occurrences of that symbol. Thus(template '(a b (?c d ?e) ?e))has the same effect as:(LET ((?C (MAKE-VARIABLE)) (?E (MAKE-VARIABLE))) (LIST 'A 'B (LIST C 'D E) E)).This is useful for creating patterns to be unified with other structures.
Restricts
xto be a boolean. Ifxis equal totafter being restricted to be boolean, returnst. Ifxis equal tonilor if the value ofxis unknown returnsnil. The argumentxcan be either a variable or a non-variable.The initial restriction to boolean may cause other assertions to be made due to noticers attached to
x. A call toknown? fails ifxis known not to be boolean prior to the assertion or if any of the assertions performed by the noticers result in failure.Restricting
xto be boolean attaches a noticer onxso that any subsequent assertion which restrictsxto be non-boolean will fail.Except for the fact that one cannot write
#'known?,known? behaves like a function, even though it is implemented as a macro.The reason it is implemented as a macro is to allow a number of compile time optimizations. Expressions like
(known? (notv x)),(known? (numberpv x))and(known? (notv (numberpv x)))are transformed into calls to functions internal to Screamer which eliminate the need to create the boolean variable(s) normally returned by functions likenotvandnumberv. Calls to the functionsnumberpv,realpv,integerpv,memberv,booleanpv,=v,<v,<=v,v, >=v, /=v,notv,funcallv,applyvandequalvwhich appear directly nested in a call toknown?, or directly nested in a call tonotvwhich is in turn directly nested in a call toknown?, are similarly transformed.
Restricts
xto a be boolean. Afterxis restricted a nondeterministic choice is made. For one branch,xis restricted to equaltand(decide x)returnstas a result. For the other branch,xis restricted to equalniland(decide x)returnsnilas a result. The argumentxcan be either a variable or a non-variable.The initial restriction to boolean may cause other assertions to be made due to noticers attached to
x. A call todecideimmediately fails ifxis known not to be boolean prior to the assertion or if any of the assertions performed by the noticers result in failure.Restricting
xto be boolean attaches a noticer onxso that any subsequent assertion which restrictsxto be non-boolean will fail.Except for implementation optimizations
(decide x)is equivalent to:(EITHER (PROGN (ASSERT! X) T) (PROGN (ASSERT! (NOTV X)) NIL))Except for the fact that one cannot write
#'decide,decidebehaves like a function, even though it is implemented as a macro.The reason it is implemented as a macro is to allow a number of compile time optimizations. Expressions like
(decide (notv x)),(decide (numberpv x))and(decide (notv (numberpv x)))are transformed into calls to functions internal to Screamer which eliminate the need to create the boolean variable(s) normally returned by functions like notv and numberv. Calls to the functionsnumberpv,realpv,integerpv,memberpv,booleanpv,=v,<v,<=v,>v,>=v,/=v,notv,funcallv,applyvandequalvwhich appear directly nested in a call to decide, or directly nested in a call tonotvwhich is in turn directly nested in a call to decide, are similarly transformed.
Restricts
xto be a boolean.Returns
tif this restrictsxtonil, andtif this restrictsxtonil.Otherwise returns a new boolean variable
v.vandxare mutually constrained via noticers, so that if either is later known to equalt, the other is restricted to equalniland vice versa.Note that unlike
cl:notnotvdoes not accept arbitrary values as arguments: it fails if its argument is nott,nil, or variable that can be restricted to a boolean.
Restricts each argument to be boolean.
Returns
tif called with no arguments, or if all arguments are known to equaltafter being restricted to be boolean, and returnsnilif any argument is known to equalnilafter this restriction.Otherwise returns a boolean variable
v. The values of the arguments andvare mutually constrained:Note that unlike
- If any argument is later known to equal
nilvalue ofvbecomesnil.- If all arguments are later known to equal
t, value ofvbecomest.- If value of
vis later known to equalt, all arguments becomet.- If value of
vis later known to equalnil, and all but one argument is known to bet, the remaining argument becomesnil.cl:and,andvis a function and always evaluates all its arguments. Secondly, any non-boolean argument causes it to fail.
Restricts each argument to be boolean.
Returns
nilif called with no arguments, or if all arguments are known to equalnilafter being restructed to be boolean, and returnstif any argument is known to equaltafter this restriction.Otherwise returns a boolean variable
v. The values of arguments andvare mutually constrained:Note that unlike
- If any argument is later known to equal
t, value ofvbecomest.- If all arguments are later known to equal
nil, value ofvbecomesnil.- If value of
vis later known to equalnil, all arguments becomenil.- If value of
vis later known to equalt, and all but one argument is known to benil, the remaining argument becomest.cl:or,orvis a function and always evaluates all its arguments. Secondly, any non-boolean argument causes it to fail.
Constrains all its arguments to be boolean. If each argument is known, returns the number of
targuments. Otherwise returns a fresh constraint variablev.
vand arguments are mutually constrained:
- Lower bound of
vis the number arguments known to bet.- Upper bound of
vis the number arguments minus the number of arguments known to benil.- If lower bound of
vis constrained to be equal to number of arguments known to benil, all arguments not known to benilare constrained to bet.- If Upper bound of
vis constrained to be equal to number of arguments known to bet, all arguments not known to betare constrained to benil.
Returns a variable whose value is constrained to be one of
values.valuescan be either a vector or a list designator.
Returns
tifxis known to be a member ofsequence(using the Common Lisp functioneqlas a test function),nilifxis known not to be a member ofsequence, and otherwise returns a new boolean variablev.When a new variable is created, the values of
xandvare mutually constrained via noticers so thatvis equal totif and only ifxis known to be a member ofsequenceandvis equal tonilif and only ifxis known not to be a member ofsequence.The current implementation imposes two constraints on the parameter
- If
xlater becomes known to be a member ofsequence, a noticer attached toxrestricts v to equalt. Likewise, ifxlater becomes known not to be a member ofsequence, a noticer attached toxrestrictsvto equalnil.- If
vever becomes known to equaltthen a noticer attached tovrestrictsxto be a member ofsequence. Likewise, ifvever becomes known to equalnilthen a noticer attached tovrestrictsxnot to be a member ofsequence.sequence. First,sequencemust be bound whenmembervis called. Second,sequencemust not contain any unbound variables whenmembervis called.The value of parameter
sequencemust be a sequence, i.e. either a list or a vector.
Returns a real variable whose value is constrained to be greater than or equal to
low.
Returns a real variable whose value is constrained to be less than or equal to
high.
Returns a real variable whose value is constrained to be greater than or equal to low and less than or equal to high. If the resulting real variable is bound, its value is returned instead. Fails if it is known that low is greater than high at the time of call.
The expression
(a-real-betweenv low high)is an abbreviation for:(LET ((V (MAKE-VARIABLE))) (ASSERT! (REALPV V)) (ASSERT! (>=V V LOW)) (ASSERT! (<=V V HIGH)) (VALUE-OF V))
Returns an integer variable whose value is constrained to be greater than or equal to
low.
Returns an integer variable whose value is constrained to be less than or equal to
high.
Returns an integer variable whose value is constrained to be greater than or equal to
lowand less than or equal tohigh. If the resulting integer variable is bound, its value is returned instead. Fails if it is known that there is no integer betweenlowandhighat the time of call.The expression
(an-integer-betweenv low high)is an abbreviation for:(LET ((V (MAKE-VARIABLE))) (ASSERT! (INTEGERPV V)) (ASSERT! (>=V V LOW)) (ASSERT! (<=V V HIGH)) (VALUE-OF v))
Returns
tifxis known to be numeric,nilifxis known to be non-numeric, and otherwise returns a new boolean variablev.The values of
xandvare mutually constrained via noticers so thatvis equal totif and only ifxis known to be numeric andvis equal tonilif and only ifxis known to be non-numeric.
- If
xlater becomes known to be numeric, a noticer attached toxrestrictsvto equalt. Likewise, ifxlater becomes known to be non-numeric, a noticer attached toxrestrictsvto equalnil.- If
vever becomes known to equaltthen a noticer attached tovrestrictsxto be numeric. Likewise, ifvever becomes known to equalnilthen a noticer attached tovrestrictsxto be non-numeric.
Returns
tifxis known to be real,nilifxis known to be non-real, and otherwise returns a new boolean variablev.The values of
xandvare mutually constrained via noticers so thatvis equal totif and only ifxis known to be real andvis equal tonilif and only ifxis known to be non-real.
- If
xlater becomes known to be real, a noticer attached toxrestrictsvto equalt. Likewise, ifxlater becomes known to be non-real, a noticer attached toxrestrictsvto equalnil.- If
vever becomes known to equaltthen a noticer attached tovrestrictsxto be real. Likewise, ifvever becomes known to equalnilthen a noticer attached tovrestrictsxto be non-real.
Returns
tifxis known to be integer valued, andnilifxis known be non-integer value.If it is not known whether or not
xis integer valued whenintegerpvis called thenintegerpvcreates and returns a new boolean variablev.The values of
xandvare mutually constrained via noticers so thatvis equal totif and only ifxis known to be integer valued, andvis equal tonilif and only ifxis known to be non-integer valued.If
xlater becomes known to be integer valued, a noticer attached toxrestrictsvto equalt. Likewise, ifxlater becomes known to be non-integer valued, a noticer attached toxrestrictsvto equalnil.Furthermore, if
vever becomes known to equaltthen a noticer attached tovrestrictsxto be integer valued. Likewise, ifvever becomes known to equalnilthen a noticer attached tovrestrictsxto be non-integer valued.
Constrains its arguments to be real. If called with a single argument, returns its value. If called with multiple arguments, behaves as if a combination of two argument calls:
(MINV X1 X2 ... Xn) == (MINV (MINV X1 X2) ... Xn)If called with two arguments, and either is known to be less than or equal to the other, returns the value of that argument. Otherwise returns a real variable
v, mutually constrained with the arguments:
- Minimum of the values of X1 and X2 is constrained to equal
v. This includes constraining their bounds appropriately. If it becomes know that cannot be true.failis called.- If both arguments are integers,
vis constrained to be an integer.
Constrains its arguments to be real. If called with a single argument, returns its value. If called with multiple arguments, behaves as if a combination of two argument calls:
(MAXV X1 X2 ... Xn) == (MAXV (MAXV X1 X2) ... Xn)If called with two arguments, and either is known to be greater than or equal to the other, returns the value of that argument. Otherwise returns a real variable
v, mutually constrained with the arguments:
- Maximum of the values of X1 and X2 is constrained to equal
v. This includes constraining their bounds appropriately. If it becomes know that cannot be true.failis called.- If both arguments are integers,
vis constrained to be an integer.
Constrains its arguments to be numbers. Returns 0 if called with no arguments. If called with a single argument, returns its value. If called with more than two arguments, behaves as nested sequence of two-argument calls:
(+V X1 X2 ... Xn) = (+V X1 (+V X2 (+V ...)))When called with two arguments, if both arguments are bound, returns the sum of their values. If either argument is known to be zero, returns the value of the remaining argument. Otherwise returns number variable
v.Note: Numeric contagion rules of Common Lisp are not applied if either argument equals zero.
- Sum of X1 and X2 is constrained to equal
v. This includes constraining their bounds appropriately. If it becomes known that cannot be true,failis called.- If both arguments are known to be reals,
vis constrained to be real.- If both arguments are known to be integers,
vis constained to be integer.- If one argument is known to be a non-integer, and the other is known to be a real,
vis constrained to be a non-integer.- If one argument is known to be a non-real, and the other is known to be a real,
vis constrained to be non-real.
Constrains its arguments to be numbers. If called with a single argument, behaves as if the two argument call:
(-V 0 X)If called with more than two arguments, behaves as nested sequence of two-argument calls:
(-V X1 X2 ... Xn) = (-V X1 (-V X2 (-V ...)))When called with two arguments, if both arguments are bound, returns the difference of their values. If X2 is known to be zero, returns the value of X1. Otherwise returns number variable
v.Note: Numeric contagion rules of Common Lisp are not applied if X2 equals zero.
- Difference of X1 and X2 is constrained to equal
v. This includes constraining their bounds appropriately. If it becomes known that cannot be true,failis called.- If both arguments are known to be reals,
vis constrained to be real.- If both arguments are known to be integers,
vis constained to be integer.- If one argument is known to be a non-integer, and the other is known to be a real,
vis constrained to be a non-integer.- If one argument is known to be a non-real, and the other is known to be a real,
vis constrained to be non-real.
Constrains its arguments to be numbers. If called with no arugments, returns 1. If called with a single argument, returns its value. If called with more than two arguments, behaves as nested sequence of two-argument calls:
(*V X1 X2 ... Xn) = (*V X1 (*V X2 (*V ...)))When called with two arguments, if both arguments are bound, returns the product of their values. If either argument is known to equal zero, returns zero. If either argument is known to equal one, returns the value of the other. Otherwise returns number variable
v.Note: Numeric contagion rules of Common Lisp are not applied if either argument equals zero or one.
- Product of X1 and X2 is constrained to equal
v. This includes constraining their bounds appropriately. If it becomes known that cannot be true,failis called.- If both arguments are known to be reals,
vis constrained to be real.- If both arguments are known to be integers,
vis constained to be integer.- If
vis known to be an integer, and either X1 or X2 is known to be real, both X1 and X2 are constrained to be integers.- If
vis known to be an reals, and either X1 or X2 is known to be real, both X1 and X2 are constrained to be reals.
Constrains its arguments to be numbers. If called with a single argument, behaves as the two argument call:
(/V 1 X)If called with more than two arguments, behaves as nested sequence of two-argument calls:
(/V X1 X2 ... Xn) = (/V ... (/V (/V X1 X2) X3) ... Xn)When called with two arguments, if both arguments are bound, returns the division of their values. If X1 is known to equal zero, returns 0. If X2 is known to equal zero,
failis called. If X2 is known to equal one, returns the value of X1. Otherwise returns number variablev.Note: Numeric contagion rules of Common Lisp are not applied if X1 equals zero or X2 equals one.
- Division of X1 and X2 is constrained to equal
v. This includes constraining their bounds appropriately. If it becomes known that cannot be true,failis called.- If both arguments are known to be reals,
vis constrained to be real.- If both arguments are known to be integers,
vis constained to be integer.- If
vis known to be an integer, and either X1 or X2 is known to be real, both X1 and X2 are constrained to be integers.- If
vis known to be an reals, and either X1 or X2 is known to be real, both X1 and X2 are constrained to be reals.
Returns a boolean value which is constrained to be
tif each argument Xi is less than the following argument Xi+1 and constrained to benilif some argument Xi is greater than or equal to the following argument Xi+1.This function takes one or more arguments. All of the arguments are restricted to be real.
Returns
twhen called with one argument. A call such as(<v x1 x2 ... xn)with more than two arguments behaves like a conjunction of two argument calls:(ANDV (<V X1 X2) ... (<V Xi Xi+1 ) ... (<V Xn-1 Xn))When called with two arguments, returns
tif X1 is known to be less than X2 at the time of call,nilif X1 is known to be greater than or equal to X2 at the time of call, and otherwise a new boolean variablev.A real value X1 is known to be less than a real value X2 if X1 has an upper bound, X2 has a lower bound and the upper bound of X1 is less than the lower bound of X2.
A real value X1 is known to be greater than or equal to a real value X2 if X1 has a lower bound, X2 has an upper bound and the lower bound of X1 is greater than or equal to the upper bound of X2.
When a new variable is created, the values of X1, X2 and v are mutually constrained via noticers so that
vis equal totif and only if X1 is known to be less than X2 andvis equal tonilif and only if X1 is known to be greater than or equal to X2.Restricting a real value X1 to be less than a real value X2 is performed by attaching noticers to X1 and X2. The noticer attached to X1 continually restricts the lower bound of X2 to be no lower than the upper bound of X1 if X1 has an upper bound. The noticer attached to X2 continually restricts the upper bound of X1 to be no higher than the lower bound of X2 if X2 has a lower bound. Since these restrictions only guarantee that X1 be less than or equal to X2, the constraint that X1 be strictly less than X2 is enforced by having the noticers fail when both X1 and X2 become known to be equal.
- If it later becomes known that X1 is less than X2, noticers attached to X1 and X2 restrict
vto equalt. Likewise, if it later becomes known that X1 is greater than or equal to X2, noticers attached to X1 and X2 restrictvto equalnil.- If
vever becomes known to equaltthen a noticer attached tovrestricts X1 to be less than X2. Likewise, ifvever becomes known to equalnilthen a noticer attached tovrestricts X1 to be greater than or equal to X2.Restricting a real value X1 to be greater than or equal to a real value X2 is performed by an analogous set of noticers without this last equality check.
All arguments are constrained to be real. Returns
twhen called with one argument. A call such as(<=v x1 x2 ... xn)with more than two arguments behaves like a conjunction of two argument calls:(ANDV (<=V X1 X2) ... (<=V Xi Xi+1) ... (<=V Xn-1 Xn))When called with two arguments, returns
tif X1 is know to be less than or equal to X2 at the time of the call,nilif X1 is known to be greater than X2, and otherwise a new boolean variablev.Values of
v, X1, and X2 are mutually constrained:
vis equal totiff X1 is known to be less than or equal to X2.vis equal toniliff X2 is known to be greater than X2.- If
vis known to bet, X1 is constrained to be less than or equal to X2.- If
vis known to benil, X1 is constrained to be greater than X2.
Returns a boolean value which is constrained to be
tif all of the arguments are numerically equal, and constrained to benilif two or more of the arguments numerically differ.This function takes one or more arguments. All of the arguments are restricted to be numeric.
Returns
twhen called with one argument. A call such as(=v x1 x2 ... xn)with more than two arguments behaves like a conjunction of two argument calls:(ANDV (=V X1 X2) ... (=V Xi Xi+1) ... (=V Xn-1 Xn))When called with two arguments, returns
tif X1 is known to be equal to X2 at the time of call,nilif X1 is known not to be equal to X2 at the time of call, and a new boolean variablevif is not known if the two values are equal.Two numeric values are known to be equal only when they are both bound and equal according to the Common Lisp function
=.Two numeric values are known not to be equal when their domains are disjoint. Furthermore, two real values are known not to be equal when their ranges are disjoint, i.e. the upper bound of one is greater than the lower bound of the other.
When a new variable is created, the values of X1, X2, and
vare mutually constrained via noticers so thatvis equal totif and only if X1 is known to be equal to X2, andvis equal tonilif and only if X1 is known not to be equal to X2.Restricting two values x1 and x2 to be equal is performed by attaching noticers to x1 and x2. These noticers continually restrict the domains of x1 and x2 to be equivalent sets (using the Common Lisp function
- If it later becomes known that X1 is equal to X2 noticers attached to X1 and X2 restrict
vto equalt. Likewise if it later becomes known that X1 is not equal to X2 noticers attached to X1 and X2 restrictvto equalnil.- If
vever becomes known to equaltthen a noticer attached tovrestricts X1 to be equal to X2. Likewise ifvever becomes known to equalnilthen a noticer attached tovrestricts X1 not to be equal to X2.- If X1 is known to be real then the noticer attached to X2 continually restrict the upper bound of X1 to be no higher than the upper bound of X2 and the lower bound of X1 to be no lower than the lower bound of X2. Likewise for bounds of X1 if X2 is known to be real.
=as a test function) as their domains are restricted.Restricting two values X1 and X2 to not be equal is also performed by attaching noticers to X1 and X2. These noticers however do not restrict the domains or ranges of X1 or X2. They simply monitor their continually restrictions and fail when any assertion causes X1 to be known to be equal to X2.
All arguments are constrained to be real. Returns
twhen called with one argument. A call such as(>=v x1 x2 ... xn)with more than two arguments behaves like a conjunction of two argument calls:(ANDV (>=V X1 X2) ... (>=V Xi Xi+1) ... (>=V Xn-1 Xn))When called with two arguments, returns
tif X1 is know to be greater than or equal to X2 at the time of the call,nilif X1 is known to be less than X2, and otherwise a new boolean variablev.Values of
v, X1, and X2 are mutually constrained:
vis equal totiff X1 is known to be greater than or equal to X2.vis equal toniliff X2 is know to be less than X2.- If
vis known to bet, X1 is constrained to be greater than or equal to X2.- If
vis known to benil, X1 is constrained to be less than X2.
All arguments are constrained to be real. Returns
twhen called with one argument. A call such as(>v x1 x2 ... xn)with more than two arguments behaves like a conjunction of two argument calls:(ANDV (> X1 X2) ... (> Xi Xi+1) ... (> Xn-1 Xn))When called with two arguments, returns
tif X1 is know to be greater than X2 at the time of the call,nilif X1 is known to be less than or equal to X2, and otherwise a new boolean variablev.Values of
v, X1, and X2 are mutually constrained:
vis equal totiff X1 is known to be greater than X2.vis equal toniliff X2 is known to be less than or equal to X2.- If
vis known to bet, X1 is constrained to be greater than X2.- If
vis known to benil, X1 is constrained to be less than or equal to X2.
Returns a boolean value which is constrained to be
tif no two arguments are numerically equal, and constrained to benilif any two or more arguments are numerically equal.This function takes one or more arguments. All of the arguments are restricted to be numeric.
Returns
twhen called with one argument. A call such as(/=v x1 x2 ... xn)with more than two arguments behaves like a conjunction of two argument calls:(ANDV (/=V X1 X2) ... (/=V X1 Xn) (/=V X2 X3) ... (/=V X2 Xn) ... (/=V Xi Xi+1 ... (/=V Xi Xn) ... (/=V Xn-1 xn))When called with two arguments, returns
tif X1 is known not to be equal to X2 at the time of call,nilif X1 is known to be equal to X2 at the time of call, and otherwise a new boolean variablev.Two numeric values are known not to be equal when their domains are disjoint.
Two real values are known not to be equal when their ranges are disjoint, i.e. the upper bound of one is greater than the lower bound of the other.
Two numeric values are known to be equal only when they are both bound and equal according to the Common Lisp function
=.When a new variable is created, the values of X1, X2 and
vare mutually constrained via noticers so thatvis equal totif and only if X1 is known not to be equal to X2 andvis equal tonilif and only if X1 is known to be equal to X2.Restricting two values X1 and X2 to be equal is performed by attaching noticers to X1 and X2. These noticers continually restrict the domains of X1 and X2 to be equivalent sets (using the Common Lisp function
- If it later becomes known that X1 is not equal to X2, noticers attached to X1 and X2 restrict
vto equalt. Likewise, if it later becomes known that X1 is equal to X2, noticers attached to X1 and X2 restrictvto equalnil.- If
vever becomes known to equaltthen a noticer attached tovrestricts X1 to not be equal to X2. Likewise, ifvever becomes known to equalnilthen a noticer attached tovrestricts X1 to be equal to X2.=as a test function) as their domains are restricted. Furthermore, if X1 is known to be real then the noticer attached to X2 continually restrict the upper bound of X1 to be no higher than the upper bound of X2 and the lower bound of X1 to be no lower than the lower bound of X2. The noticer of X2 performs a symmetric restriction on the bounds of X1 if it is known to be real.Restricting two values X1 and X2 to not be equal is also performed by attaching noticers to X1 and X2. These noticers however, do not restrict the domains or ranges of X1 or X2. They simply monitor their continually restrictions and fail when any assertion causes X1 to be known to be equal to X2.
argumentsis a list of values. Typically it is a list of variables but it may also contain nonvariables.The specified
ordering-force-functionis used to force each of the variables in list to be bound.Returns a list of the values of the elements of list in the same order that they appear in list, irrespective of the forcing order imposed by the
ordering-force-function.The
ordering-force-functioncan be any function which takes a list of values as its single argument that is guaranteed to force all variables in that list to be bound upon its return. The returned value of theordering-force-functionis ignored.The user can construct her own
ordering-force-functionor use one of the following alternatives provided with Screamer:(STATIC-ORDERING #'LINEAR-FORCE), (STATIC-ORDERING #'DIVIDE-AND-CONQUER-FORCE), (REORDER COST-FUN TERMINATE-TEST ORDER #'LINEAR-FORCE) and (REORDER COST-FUN TERMINATE-TEST ORDER #'DIVIDE-AND-CONQUER-FORCE).Future implementation of Screamer may provide additional forcing and ordering functions.
Returns an ordering force function based on
force-function.The ordering force function which is returned is a nondeterministic function which takes a single argument
x. This argumentxcan be a list of values where each value may be either a variable or a non-variable. The ordering force function applies theforce-functionin turn to each of the variables inx, in the order that they appear, repeatedly applying theforce-functionto a given variable until it becomes bound before proceeding to the next variable. The ordering force function does not return any meaningful result.
force-functionis any (potentially nondeterministic) function which can be applied to a variable as its single argument with the stipulation that a finite number of repeated applications will force the variable to be bound. Theforce-functionneed not return any useful value.Screamer currently provides two convenient force-functions, namely
#'linear-forceand#'divide-and-conquer-forcethough future implementations may provide additional ones. (The defined Screamer protocol does not provide sufficient hooks for the user to define her own force functions.)
Returns an ordering force function based on arguments.
The
force-functionis any (potentially nondeterministic) function which can be applied to a variable as its single argument with the stipulation that a finite number of repeated applications will force the variable to be bound. Theforce-functionneed not return any useful value.The ordering force function which is returned is a nondeterministic function which takes a single argument
x. This argumentxcan be a list of values where each value may be either a variable or a non-variable.The ordering force function repeatedly selects a "best" variable using using
cost-functionandorder. Eg. using#'domain-sizeand#'<as thecost-functionandorder, then the variable with the smallest domain will be forced first.Function
terminate? is then called with the determined cost of that variable, and unless it returns true,force-functionis applied to that variable to force constrain it.Process then iterates until all variables become bound or
terminate? returns true.The ordering force function does not return any meaningful result.
Screamer currently provides two convenient force-functions, namely #'linear-force and #'divide-and-conquer-force though future implementations may provide additional ones. (The defined Screamer protocol does not provide sufficient hooks for the user to define her own force functions.)
Returns
xif it is not a variable. Ifxis a bound variable then returns its value.If
xis an unbound variable then it must be known to have a countable set of potential values. In this casexis nondeterministically restricted to be equal to one of the values in this countable set, thus forcingxto be bound. The dereferenced value ofxis then returned.An unbound variable is known to have a countable set of potential values either if it is known to have a finite domain or if it is known to be integer valued.
An error is signalled if
xis not known to have a finite domain and is not known to be integer valued.Upon backtracking
xwill be bound to each potential value in turn, failing when there remain no untried alternatives.Since the set of potential values is required only to be countable, not finite, the set of untried alternatives may never be exhausted and backtracking need not terminate. This can happen, for instance, when
xis known to be an integer but lacks either an upper of lower bound.The order in which the nondeterministic alternatives are tried is left unspecified to give future implementations leeway in incorporating heuristics in the process of determining a good search order.
Returns
xifxis not a variable. Ifxis a bound variable then returns its value. Otherwise implements a single binary-branching step of a divide-and-conquer search algorithm. There are always two alternatives, the second of which is tried upon backtracking.If it is known to have a finite domain
dthen this domain is split into two halves and the value ofxis nondeterministically restricted to be a member one of the halves. Ifxbecomes bound by this restriction then its value is returned. Otherwise,xitself is returned.If
xis not known to have a finite domain but is known to be real and to have both lower and upper bounds then nondeterministically either the lower or upper bound is restricted to the midpoint between the lower and upper bound. Ifxbecomes bound by this restriction then its dereferenced value is returned. Otherwise,xitself is returned.An error is signalled if
xis not known to be restricted to a finite domain and either is not known to be real or is not known to have both a lower and upper bound.When the set of potential values may be infinite, users of
divide-and-conquer-forcemay need to take care to fail when the range size of the variable becomes too small, unless other constraints on it are sufficient to guarentee failure.The method of splitting the domain into two halves is left unspecified to give future implementations leeway in incorporating heuristics in the process of determining a good search order. All that is specified is that if the domain size is even prior to splitting, the halves are of equal size, while if the domain size is odd, the halves differ in size by at most one.
Returns the domain size of
x.If
xis an integer variable with an upper and lower bound, its domain size is the one greater than the difference of its bounds. Eg. [integer 1:2] has domain size 2.If
xis a variable with an enumerated domain, its domain size is the size of that domain.If
xis acons, or a variable whose value is acons, its domain size is the product of the domain sizes of itscarandcdr.Other types of unbound variables have domain size
nil, whereas non-variables have domain size of 1.
Returns the range size of
x. Range size is the size of the range values ofxmay take.If
xis an integer or a bound variable whose value is an integer, it has the range size 0. Reals and bound variables whose values are reals have range size 0.0.Unbound variables known to be reals with an upper and lower bound have a range size the difference of their upper and lower bounds.
Other types of objects and variables have range size
nil.
Convenience wrapper around
defpackage. Passes its argument directly todefpackage, and automatically injects two additional options:(:shadowing-import-from :screamer :defun :multiple-value-bind :y-or-n-p) (:use :cl :screamer)
First evaluates
objective-form, which should evaluate to constraint variablev.Then repeatedly evaluates FORM1 in non-deterministic context till it fails. If previous round of evaluation produced an upper bound
bforv, the during the next round any change tovmust provide an upper bound higher thanb, or that that change fails.If the last successful evaluation of
formproduced an upper bound forv, returns a list of two elements: the the primary value of FORM1 from that round, and the upper bound ofv.Otherwise if FORM2 is provided, returns the result of evaluating it, or else calls fails.
Note: this documentation string is entirely reverse-engineered. Lacking information on just how
best-valuewas intended to work, it is hard to tell what is a bug, an accident of implementation, and what is a feature. If you have any insight intobest-value, please send email to nikodemus@random-state.net.
Returns the number of time a non-NIL value occurs in its arguments.
Removes any information about
function-namefrom Screamer's who-calls database.
deprecated.Calls all functions installed using
trail, and removes them from the trail.Using
unwind-trailis dangerous, astrailis used by Screamer internally to eg. undo effects of local assignments--hence users should never call it. It is provided at the moment only for backwards compatibility with classic Screamer.
Removes any information about all user defined functions from Screamer's who-calls database.
Set to
tto enable the dynamic extent optimization,nilto disable it. Default is platform dependent.
The version of Screamer which is loaded. This is currently still 3.20, while we're considering how to express versions for this copy of Screamer in the future.
Discretize integer variables whose range is not greater than this number. Discretize all integer variables if
nil. Must be an integer ornil.
Ignore propagations which reduce the range of a variable by less than this ratio.
Strategy to use for
funcallvandapplyv. Either:gfcfor Generalized Forward Checking, or:acfor Arc Consistency. Default is:gfc.
*v: Dictionary+v: Dictionary-v: Dictionary/=v: Dictionary/v: Dictionary<=v: Dictionary<v: Dictionary=v: Dictionary>=v: Dictionary>v: Dictionarya-boolean: Dictionarya-booleanv: Dictionarya-member-of: Dictionarya-member-ofv: Dictionarya-numberv: Dictionarya-real-abovev: Dictionarya-real-belowv: Dictionarya-real-betweenv: Dictionarya-realv: Dictionaryall-values: Dictionaryan-integer: Dictionaryan-integer-above: Dictionaryan-integer-abovev: Dictionaryan-integer-below: Dictionaryan-integer-belowv: Dictionaryan-integer-between: Dictionaryan-integer-betweenv: Dictionaryan-integerv: Dictionaryandv: Dictionaryapply-nondeterministic: Dictionaryapply-substitution: Dictionaryapplyv: Dictionaryassert!: Dictionarybest-value: Dictionarybooleanp: Dictionarybooleanpv: Dictionarybound?: Dictionarycount-failures: Dictionarycount-trues: Dictionarycount-truesv: Dictionarydecide: Dictionarydefine-screamer-package: Dictionarydivide-and-conquer-force: Dictionarydomain-size: Dictionaryeither: Dictionaryequalv: Dictionaryfail: Dictionaryfor-effects: Dictionaryfuncall-nondeterministic: Dictionaryfuncallv: Dictionaryglobal: Dictionaryground?: Dictionaryintegerpv: Dictionaryith-value: Dictionaryknown?: Dictionarylinear-force: Dictionarylocal: Dictionarymake-variable: Dictionarymaxv: Dictionarymemberv: Dictionaryminv: Dictionarymultiple-value-call-nondeterministic: Dictionarynecessarily?: Dictionarynondeterministic-function?: Dictionarynotv: Dictionarynumberpv: Dictionaryone-value: Dictionaryorv: Dictionarypossibly?: Dictionaryprint-values: Dictionarypurge: Dictionaryrange-size: Dictionaryrealpv: Dictionaryreorder: Dictionarysolution: Dictionarystatic-ordering: Dictionarytemplate: Dictionarytrail: Dictionaryunwedge-screamer: Dictionaryunwind-trail: Dictionaryvalue-of: Dictionarywhen-failing: Dictionary