## the premises and conclusions, being separate functions, don't actually
## have anything to do with each other as stated here; in particular,
## there's no reason to assume that the `b' argument to premise_1() will be
## the same value as the `b' argument to premise_2().
## However, the functions are combined and evaluated together in board.py,
## such that the same name in any given allotment always has the same value.
## The presentation here is a bit deceptive; what really happens is that
## values are assigned to the set of all formal argument names and
## then the functions are called with the names in the actual
## arguments matched to the placement in the formal arguments.
## This means that *what* names are used in the formal arguments matters, even
## though in ordinary contexts that would just be a matter of clarity.
## The same (or a similar) effect could be gotten by assigning strings
## to the premises and conclusions which would then be passed to eval(),
## but, uh, I did it this way, even though that way might have been
## clearer. Too bad I didn't think of it first.
## Basically one big function is created that tries to find some assignment of
## values to all the names present in all premise_n() and conclusion_n()
## functions such that:
##
## (premise_1(p1_names) and ... and premise_n(pn_names))
## and not
## (conclusion_1(c1_names) or ... or conclusion_n(cn_names))
##
## That is, since the names are used in determining what gets passed
## *to* the function, the same values are used for the same names in
## the *body* of the function as well.
def R(y, x):
return (x.isTetra() or y.isTetra()) and x.sameRow(y)
premise_1 = lambda a, b: R(a,b)
premise_2 = lambda b, c: R(b,c)
conclusion_1 = lambda a, c: R(a,c)
## The above, eg, essentially gets converted to:
## (exists x,y,z)(premise_1(x,y) & premise_2(y,z) & ~conclusion_1(x,z))
## and we try to find some assignment of values to (x,y,z) that makes
## it the case.
## Here, doing so happens to find a counterexample to R's being transitive.
## limit the domain to a 4x1 board on which all objects are small.
## `board' here is the board module; it's passed in because otherwise
## the name `SMALL' (and any other name one might want to access, like `LARGE'
## or `Tetrahedron') would be inaccessible.
def constraints(board):
return {'sizes':(board.SMALL,),
'rows':(1,),
'cols':(0,1,2,3)}
## valid constraint keys are the ones given above plus `shapes', a tuple
## of what shape classes to use.