Finite Domains in the Constrained Lambda Calculus - Semantic Scholar

2 downloads 0 Views 159KB Size Report
SEND + MORE = MONEY and n-queens, are presented. keywords: ..... since disjunctive terms are evaluated from left to right and thus, if the guard Null(l) fails,.
Finite Domains in the Constrained Lambda Calculus∗ Mar´ıa Victoria Cengarle, Luis Mandel Institut f¨ ur Informatik Ludwig-Maximilians-Universit¨ at Leopoldstr. 11b, D-80802 M¨ unchen, Germany Tel: +49 89 2180 6317 Fax: +49 89 2180 6310 {cengarle,mandel}@informatik.uni-muenchen.de

Abstract In [4, 7] a calculus with constraints which extends the traditional lambda calculus was presented. Here an instantiation of that general framework with finite domains is presented. An operational semantics for this approach is given. The set of reduction rules is enlarged with an operational ∃-rule for logical variables, since inequality is decidable in finite domains. A reduction strategy has been introduced: the depth first search in order to deal with disjunctive terms; in this way, give a disjunction, the leftmost meaningful subterm is chosen. Backtracking points are set while testing constraints and new reduction rules are introduced for the manipulation of the backtracking. Finally three typical examples, namely electrical circuits, SEN D + M ORE = M ON EY and n-queens, are presented. keywords: λ-calculus, Constraints, Functional Programming, Finite Domains, Operational Semantics.

Introduction An extension to the traditional functional languages with constraints was presented in [7]. The constraint system is treated as a black box, permitting interaction between the functional and the constraint theory. The approach is based on the untyped lambda calculus, whose semantics is given in a denotational fashion. The semantic functional is monotonic and therefore the least fixed point is reached, i.e. the semantic function is welldefined. Among the properties demonstrated there we have that the calculus satisfies the Church-Rosser property and that the reduction rules are correct, that is, interconvertible terms have the same semantics. ∗

Research supported by the DFG-project Constraints.

1

In this work we present an instantiation of that language using finite domains. Such domains were also studied in the framework of logical programming; see [5]. Using this kind of domains one can ensure the computability of negation (i.e. inequality). Two new reduction rules are added to the cited calculus, that evaluate disjunctive terms using a depth-first strategy or DFS for short. In this way, a new operational semantics is given to the calculus. That means, the language we introduce is a logical-functional one, where the functional feature is β-reduction and the logical features are the logical variables –calculated by the constraint solver– and backtracking. The language is called constrained because there are constraints imposing conditions on variables. Constraints are used in both ways, passively and actively. The passive use is just like typing a variable. The active use permits the calculation of values for variables in the underlying constraint theory, and these values are then substituted for the corresponding variables in the target term. In section 1 we state the requirements to the constraint solver underlying the functional calculus. Therein we give some general definitions such as constraint domain and constraint language. Section 2 defines the syntax of the λ-calculus extended with constraints and disjunction. In section 3 the calculus itself is introduced, there we have reduction rules and other non-congruent (operational) rules for computing solutions. An instantiation of the calculus using the finite domain is given in 4 together with classical examples of calculations within this instantiation. Finally in 5 we give the conclusions to which we arrived during the development of this language and briefly discuss about ongoing work.

1

Constraints

The term constraint is intuitively defined as a relationship required to hold among certain entities. We can take for instance the set of natural numbers with addition, multiplication, equality and perhaps other functions and predicates. We assume we are given a constraint system, which we handle as a black box. In particular, we suppose defined the concepts of • constraint language, typically a first-order language with at least equality and conjunction, • constraint theory, a set of axiom schemes and inference rules over the language, and • constraint solver, a machine answering queries over the theory in finite time.1 In the case of finite domains, negation is decidable. 1

In other words, given a formula the constraint solver tests whether the formula is a theorem in the theory. Given that the set of theorems of any axiomatizable first-order theory is recursively enumerable, and in order to have decidability, the constraint solver could test for theoremhood only during a certain time and elapsed this the formula could be presumed false.

2

1.1

Constraint Logic

The constraint solver reacts in two different ways to the queries formulated, its answers are either fail or a substitution s making the query true. We write C ⊢ s(ϕ) if the the constraint solver C computes the substitution s for ϕ (that is, s(ϕ) is a theorem of the underlying constraint theory). We also write C ⊢ ϕ and C 6⊢ ϕ if the computed answer is the identity substitution id resp. if ϕ is unsatisfiable in C (i.e. if the query ϕ fails). If a computed solution is unique, and if it is computed one single term t for just one variable x, we also write C ⊢ (∃!x)ϕ ∧ (∀x)(ϕ → x = t). In general, however, there may be more than one solution for a query. The set of solutions may moreover be infinite; if it is finite we write C ⊢ ϕ[t1 /x] ∧ · · · ∧ ϕ[tn /x] ∧ ∀x.(ϕ → x = t1 ∨ · · · ∨ x = tn ) when focusing only on the variable x. We assume a monotonic logic in the underlying constraint system.

1.2

Types, Terms and Formulas

The constraint language defines a set of terms and a set of formulas, which we denote by CT and CF, respectively. The language may define typed terms, in which case we let Γ0 denote the set of constraint terms types; if the constraint language is untyped, then we can consider Γ0 a singleton. Moreover we suppose defined a notion of free variable and of substitution of terms for (free) variables in constraint terms and in constraint formulas. These will be denoted by FV resp. t[t′ /x] and ϕ[t′ /x].

2

Calculus: Syntax and Semantics

We define a λ-calculus core. In general, a constraint system is naturally typed, and therefore we prefer to limit ourselves to a typed λ-calculus. (For an untyped approach, the reader may consult [7].) The typing information is not explicit, that is, λ-terms are not annotated. The approach taken is the so-called lambda-calculus with type assignment; see [1]. Any basis Γ for typing derivation has to contain the initial basis Γ0 of constraint terms types.

3

2.1

Syntax of Terms

The peculiarity of the λ-terms of our calculus is that a constraint formula may restrict the universe of validity of a number of variables, and that we may have disjunctive terms. Disjunction arises from the active use of constraints, as introduced in section 3. A constraint may restrict a variable in such a way that just one value makes sense for the variable. And if e.g. more than one but finitely many values make sense for that variable, then we generate a disjunctive term. In order to handle contradiction, and to ensure the Church-Rosser property (see [7]), a distinctive constant fail is a term of the language. In our case, contrariwise, the fail constant is introduce in order to enforce backtracking; see subsection 3.2. Definition 2.1.1 (λ-Terms) Given a set X of variables, the set Λ of λ-terms is inductively defined by Λ ::= X | fail | CT | (Λ Λ) | (λ X . Λ) | ({CF}Λ) | (Λ [] Λ) | (∃ X . Λ) Terms in Λ are denoted by M , N , etc. Syntactical equality is denoted by ≡ . Application and disjunction associate to the left, that is (M1 M2 . . . Mn ) ≡ (((M1 M2 ) . . .) Mn ) and (M1 [] M2 [] · · · [] Mn ) ≡ (((M1 [] M2 ) [] . . .) [] Mn ). Outermost parentheses are omitted. A program is any term M ∈ Λ. We have the notions of free variable and of substitution of terms for free variables defined in the usual way plus the following equalities for the new terms introduced: FV({ϕ}M ) = FV(ϕ) ∪ FV(M ) FV(M1 [] M2 ) = FV(M1 ) ∪ FV(M2 ) FV(∃ y . M ) = FV(M ) \ {y}

({ϕ}M )[x := N ] ≡ {ϕ[N/x]}M [x := N ] (M1 [] M2 )[x := N ] ≡ M1 [x := N ] [] M2 [x := N ] (∃ y . M )[x := N ] ≡ ∃ y . M [x := N ].

We assume the variable convention of [2] and require that free and bound variables are named differently. Because of the variable convention, in the last item above defining substitution it is not necessary to make the proviso “x 6= y.” Notice that λ-terms enrich the constraint terms, since ({ϕ}M )[x := N ] ≡def {ϕ[N/x]}M [x := N ] that is, a term N is substituted for x in ϕ and so ϕ[N/x] becomes a formula of the underlying constraint language with possible occurrences of a term N . For this purpose we have to combine both the constraint terms and the λ-terms. That is, not only the constraint terms and formulas define λ-terms (cf. 2.1.1 where Λ ::= CT | ({CF}Λ)), also the λ-terms define constraint terms, and so both sets of terms are defined by mutual induction.2 2 From an operational point of view, if the variable x occurs in the constraint formula ϕ, then x must be of type σ ∈ Γ0 , that is, of initial (or constraint) type. Therefore also the term N is of constraint type. Nevertheless, N needs not be a constraint term, it may be e.g. a β-redex. One could then argue that N can be reduced before the substitution takes place. However, N can involve still uninstantiated variables

4

We therefore enlarge the constraint language with λ-terms. The constraint solver needs not assign values to variables of functional type. We can let the inference machine work on “the rest” of the query deriving variable instance(s) and ignoring variables that are to be computed by the functional theory. The constraint solver can nevertheless use these values in order to test further constraints or calculate values for logical variables. We give names to some ground λ-terms. Following [2] we have: true ≡ λ x . λ y . x Cons ≡ λ x . λ y . λ z . x y

false ≡ λ x . λ y . y Head ≡ λ x . x true

Tail ≡ λ x . x false

Similarly nil, Null, List, Append, etc., can be defined. The types to be assigned to terms include the set Γ0 of constraint types and are defined using the Curry typing approach; see [1]. Using the approximation rule A defined there, one can type the fixed point operator Y. For the sake of simplicity, however, we will use the traditional functional notation and write F ≡ (λ · · · F · · ·) when defining a recursive function F. The term {ϕ}M denotes the term M constrained by the formula ϕ. In terms of scoping, a term M constrained by a formula ϕ may have variables in common with ϕ; this is indeed the very use of constraints. Nevertheless, there may be variables free in ϕ that do not occur in M . If moreover {ϕ}M is in a context where one of such variables do occur free, then this variables are in fact constrained by ϕ. Take for example the term M ≡ f ({x < y}x, y). M has the same intuitive meaning as N ≡ {x < y}f (x, y). This allows the interaction of variables between different subterms. Therefore, a formula ϕ is not to be understood as a binder or quantifier. This job is done by ∃, which moreover provides an elegant way to combine the functional theory with the constraint theory (see section 3 and [7]), avoiding the confusion which otherwise would arise when one writes e.g. (λ x . {x = 0}M ) N . In this case different values for x can be computed, namely 0 and N . Such confusion can be excluded by introducing an explicit quantifier ∃. Intuitively the operator [] denotes the “or” of options. The disjunction of terms is motivated by the multiple solutions that may be calculated by the underlying constraint solver. That means, if we have a term {ϕ}M and under assumption ϕ a variable x may be only one of two values v1 and v2 , then that term is intuitively the same as ({ϕ}M )[x := v1 ] [] ({ϕ}M )[x := v2 ].

2.2

Semantics of Terms

The work in [7] gives a detailed account of the semantics of constrained λ-terms. The semantic function is, as usual, defined in a recursive fashion. In order to prove its wellof higher type, for instance N could be the term (y z) where y is of type (σ1 → σ2 ), z is of type σ1 , and σ2 ∈ Γ0 .

5



Incons  

  @

@ @

v1 v2 . . . vn . . .

Compat

H @ H@ H @ H



Undefd

Figure 1: 3-valued logic and semantic values definedness, the semantics of the constraint logic was defined to be a 3-valued one. These values may be explained to be false (denoted by Incons for inconsistent), true (denoted by Compat for compatible), and I (still) don’t know (denoted by Undefd for undefined). Moreover, these values are ordered as in figure 1. Motivation for this ordering is the fact that the more information we get the bigger is the risk of contradiction being introduced. In the same spirit, the semantics of terms can be any of three possibilities. Meaningful values are the ones in the interpretation of the underlying constraint domain (closed under functional abstraction, as usual). Otherwise, the semantics of a term can be ⊤ if contradiction was introduced, or ⊥ if there are variables or, in general, subterms whose values cannot be calculated in the context given. These values are also ordered, see figure 1. Sometimes we call ⊤ the overspecified, ⊥ the underspecified value. The semantics of a term depends not only on the values of variables in the context of the term (the environment, denoted by e), it also depends on the constraint formulas occurring in that context, denoted by c. Given the “global” nature of constraint formulas occurring around terms (see discussion about binding in the previous subsection), the context of constraint formulas is collected before calculating the semantics of a term; see [7]. The semantics of the constant fail is the overspecified value ⊤. A constrained term {ϕ}M has the semantics of M if the constraint formula ϕ is true in the given environment; if ϕ is only satisfiable then the semantics of {ϕ}M is ⊥, and if ϕ is contradictory then ⊤. Schematically, i.e. forgetting for a second environment and global constraint, [[fail]] = ⊤,

[[{ϕ}M ]] = if [[ϕ]] then [[M ]].

Disjunctive terms are interpreted in powerdomains in [7]. This is because a disjunction represents the collection of all the possibilities. In this work we deviate from that point of view and take a more operational approach. Given a disjunction, we do choose one of the possibilities, namely the leftmost meaningful interpretation, if any: [[M [] N ]] =

(

[[M ]] if [[M ]] 6= ⊤, [[N ]] otherwise.

If [[M ]] = ⊥, we still do not have enough information in order to approximate the semantics of M ; it may become a value v or become overspecified. Only in this latter case we 6

state [[M [] N ]] = [[N ]]. In this approach, disjunction is in general not commutative, i.e. [[M [] N ]] 6= [[N [] M ]]. This semantics is well defined since the functional is monotonic.

3

Calculus: Rules

In this section we present the rules relating λ-terms. There are two groups of rules. In the first one we have a functional and some structural ones, in the second rules for value inference and backtracking. As functional rule we have the call-by-value version of βreduction. The structural rules allow one to reshape a term in such a way that function application or value inference may take place. These rules define congruences in the sense that they apply in any context; see figure 2. Value inference is the active use of constraints. By its means and given a constraint, the value(s) for a logical value may be calculated; see figure 3. Further rules inspect disjunctive terms from left to right and choose the first possibility that does not lead to a contradiction. If the possibility being considered fails, then computation backtracks to the last choice point and the next term to the right is in its turn treated; see figure 5. Choice and backtracking rules prevent the whole set of rules from being congruences. From a procedural point of view we could say that the rules can be applied only at top level. The choice rule is motivated by the presence of disjunction, which is interpreted by take any possibility. This rule is inspired by logic programming and allows a more efficient implementation of the calculus. One of the possibilities is effectively chosen, and if the choice afterwards (notice the notion of time, absent in denotational approaches) turns out to be a bad one, then the selection is revised and the computation backtracks.

3.1

Functional and Structural Rules

In this section we define a set of reduction rules that permit calculation in the functional theory combined with the constraint theory. The function application or β-reduction we consider is the so-called call-by-value one. Let us motivate our choice. Suppose we define instead (β) (λ x . M ) N −→ M [x := N ] where N is any term. We have then the shared value problem. On the one hand, (λ x . x + x) (2 [] 3) −→β (2 [] 3) + (2 [] 3) and if we admit the intuitive semantics of disjunction to be any of the possible values involved, the term above would have the same meaning as the term 4 [] 5 [] 6. On the other hand, and given that x + x and 2 × x define the same function, (λ x . 2 × x) (2 [] 3) −→β 2 × (2 [] 3) 7

(A) {ϕ1 }{ϕ2 }M (PC ) {ϕ ∧ P (. . . , {ϕi }Mi , . . . , )}N (P∃) {ϕ ∧ P (. . . , ∃ xi . Mi , . . .)}N (C∃) {ϕ}∃ x . M (β) (λ x . M ) V ( [] 1) M [] M ( [] 2) (M1 [] M2 ) N ( [] 3) M (N1 [] N2) ( [] 4) {ϕ}(M1 [] M2 ) ( [] 5) ∃ x . (M1 [] M2 ) ( [] 6) {ϕ ∧ P (. . . , M1 [] M2 , . . .)}N

−→ −→ −→ −→ −→ −→ −→ −→ −→ −→ −→

(C1 ) (C2 ) (C3 ) (C4 ) (fail1 ) (fail2 ) (fail3 ) (fail4 ) (fail5 )

−→ −→ −→ −→ −→ −→ −→ −→ −→

M1 {ϕ}M2 ({ϕ}M1 ) M2 M1 ∃ x . M2 (∃ x . M1 ) M2 fail M λ x . fail {ϕ}M {ϕ}fail ∃ x . fail

{ϕ1 ∧ ϕ2 }M {ϕ ∧ ϕi ∧ P (. . . , Mi , . . .)}N ∃ xi . {ϕ ∧ P (. . . , Mi , . . .)}N ∃ x . {ϕ}M M [x := V ] where V is a value M (M1 N ) [] (M2 N ) (M N1 ) [] (M N2 ) ({ϕ}M1 ) [] ({ϕ}M2) (∃ x . M1 ) [] (∃ x . M2 ) ({ϕ ∧ P (. . . , M1 , . . .)}N ) [] ({ϕ ∧ P (. . . , M2 , . . .)}N ) {ϕ}(M1 M2 ) {ϕ}(M1 M2 ) ∃ x . (M1 M2 ) ∃ x . (M1 M2 ) fail fail fail if ϕ is contradictory fail fail

Figure 2: Functional and structural rules and this new term has the same meaning as 4 [] 6, that is, a semantics different to the one computed before. This problem was already considered in the literature, and a meanwhile standard solution is the call-by-value reduction strategy. A step of β-reduction is only performed when the parameter is a value. Values are typically abstractions, variables and in our case constraint terms. Definition 3.1.1 (Values) The set V ⊂ Λ of values is inductively defined by V ::= X | fail | CV | (λ X . Λ) where CV is the subset of constraint terms in CT whose λ-terms occurrences are values. Definition 3.1.2 (Basic Rules) Figure 2 shows the basic rules of the constrained λcalculus. These rules are not congruences, as is shown in the next subsection, because of the rules introduced there. Sometimes we index the arrow with the name of the rule employed. One would tend to write a rule λ x . (M1 [] M2 ) −→ (λ x . M1 ) [] (λ x . M2 ). Interpreting the [] -term constructor as disjunction, this rule generates unacceptable derivations. For example, λ x . (1 [] 2) −→ (λ x . 1) [] (λ x . 2). Intuitively, the left hand side represents 8

(∃d) C ⊢ ϕ[t1/x] ∧ · · · ∧ ϕ[tn /x] ∧ ∀x.(ϕ → x = t1 ∨ · · · ∨ x = tn ) implies ∃ x . {ϕ}M −→∃ ({ϕ}M )[x := t1 ] [] · · · [] ({ϕ}M )[x := tn ] (∃o) C ⊢ ϕ[t1/x] implies ∃ x . {ϕ}M −→∃ ({ϕ}M )[x := t1 ] [] ∃ x . {ϕ ∧ x 6= t1 }M

Figure 3: ∃-rules the set of functions which always return the value 1 or 2, whereas the right hand side is the constant function 1 union the constant function 2. With the choice rules of the next subsection, one could argue that the former is still a valid rule, since we choose the leftmost non-failed possibility. Interesting discussion about such a rule can be found in [8].

3.2

Value Inference and Backtracking

The binder ∃ makes the variable x “invisible” to the outside of the term ∃ x . M , and the value of x can only be calculated by the constraint solver and not by the functional theory (i.e. the β-reduction cannot substitute a value for x). Explicit scoping gives rise to two different reduction rules in connection with the constraint theory. Definition 3.2.1 (∃-Rules) Figure 3 shows further rules of the constrained λ-calculus. In the ∃-rules of figure 3, the computed answers are values, so those rules signify no shared-variable problem at all. The rule ∃d is called denotational and requires that the computed solutions be finite. The rule ∃o is called operational and permits denumerably many solutions. Note that in ∃o the addition of a constraint of the form x 6= t1 may result in a noncomputable constraint. However, negation is computable in finite domains, as this calculus is instantiated in the next section. (λ x . {ϕ}M ) N HH

H H β H

C ⊢ (∃!x)ϕ ∧ (∀x)(ϕ → x = N ) implies ∃ x . {ϕ}M

    ∃ H  j H 

({ϕ}M )[x := N ]

Figure 4: ∃ and β rules These rules are motivated by the Henkin theories. That is, those theories T for which, given any sentence ∃ x . M , there is a constant k in the language such that: T |= ∃ x . M ⊃ M [x := k]. In the presence of a unique solution, these reduction rules show similarities with the β-rule as shown in figure 4. For the β-reduction, the substitution is induced by 9

if M1 −→ M1′ and M1′ is not a value if M1 −→ V where V 6= fail if M1 −→ fail

(try) M1 [] · · · [] Mn −→ M1′ [] · · · [] Mn (sc) M1 [] · · · [] Mn −→ V (bt) M1 [] · · · [] Mn −→ M2 [] · · · [] Mn

Figure 5: Choice rules3 the presence of an actual parameter to the abstraction. In the case of the ∃-reduction, the value for the variable is calculated by the constraint solver as the only value valid for that variable in the constraint theory under the conditions in the constraint formula. Motivated by the usual situation in which a disjunction is such that any alternative can do the job, we introduce a rule that effectively chooses one option. The variant we adopt is to take the leftmost possibility. At the same time, a backtracking point is set, and if afterwards the computation fails, then the leftmost but one possibility is treated. And so on, from left to right. Definition 3.2.2 (Choice Rules) Figure 5 shows the choice rules of the constrained λcalculus. Hence the computation of a disjunctive term finishes when the first subterm of the disjunction does not fail. The choice rules themselves suggest a reduction strategy. Given a term M1 [] · · · [] Mn , it is somehow uninteresting if Mi −→ Ni , since it is also possible that Mj −→ Vj with j < i. Even if the top term isn’t a disjunction, e.g. if we have (M N ), it makes no sense to reduce the term N first, since it may be the case that M fails and therefore the whole term (M N ) fails. Therefore, given the syntactic (parse) tree of a term, redexes are searched for in a DFS fashion. The leftmost-outermost redex is reduced first. Having defined this reduction strategy, the Church-Rosser property is no longer an issue, since given any term just one reduction path is possible.

4

An Instantiation: Finite Domains

The constraint domain of finite subsets with associated properties is used in the present section to obtain an instantiation of the constrained λ-calculus. Finite domains allow the expression of range restrictions, and domain specific inference rules propagate domain restriction in such a way that the non-determinism of the computation is reduced. A finite domain is a collection of possible values for a variable. The collection of values may be included in a bigger and possibly infinite set. So for example one can take the 3

sc stands for “succeed” and bt for “backtrack.”

10

set of natural numbers and restrict every variable of the target term to be among a finite subset of natural numbers. Or the variables may be any value between the bounds of a chessboard, and so the subsets considered for the variables are the whole set which is itself finite. In the next subsections we collect a number of small computations in the constrained λcalculus defined above, and instantiated with the constraint theory of finite domains. In order to improve the readability we may write function calls as f (x) instead of (f x).

4.1

Crypto-arithmetic Puzzles

Consider the standard crypto-arithmetic puzzle SEND + MORE = MONEY . We require an injective assignment of digits 0, 1, . . . , 9 to the letters S, E, N, D, M, O, R, Y such the equation SEND + MORE = MONEY is satisfied. The solution of the problem is directly the specification of the problem. ∃SEN DM ORY . {S= 6 E, S 6= N, S 6= D, S 6= M, S 6= O, S 6= R, S 6= Y, E 6= N, E 6= D, E 6= M, E 6= O, E 6= R, E 6= Y, N 6= D, N 6= M, N 6= O, N 6= R, N 6= Y, D 6= M, D 6= O, D 6= R, D 6= Y, M 6= O, M 6= R, M 6= Y, O 6= R, O 6= Y, R 6= Y, S = 1 [] 2 [] 3 [] 4 [] 5 [] 6 [] 7 [] 8 [] 9, E = 0 [] 1 [] 2 [] 3 [] 4 [] 5 [] 6 [] 7 [] 8 [] 9, N = 0 [] 1 [] 2 [] 3 [] 4 [] 5 [] 6 [] 7 [] 8 [] 9, D = 0 [] 1 [] 2 [] 3 [] 4 [] 5 [] 6 [] 7 [] 8 [] 9, M = 1 [] 2 [] 3 [] 4 [] 5 [] 6 [] 7 [] 8 [] 9, O = 0 [] 1 [] 2 [] 3 [] 4 [] 5 [] 6 [] 7 [] 8 [] 9, R = 0 [] 1 [] 2 [] 3 [] 4 [] 5 [] 6 [] 7 [] 8 [] 9, Y = 0 [] 1 [] 2 [] 3 [] 4 [] 5 [] 6 [] 7 [] 8 [] 9, S × 1000 + E × 100 + N × 10 + D + M × 1000 + O × 100 + R × 10 + E = M × 10000 + O × 1000 + N × 100 + E × 10 + Y }List (S E N D M O R Y ) The evaluation of the term above generates a disjunctive term with the combination of all the available values for each letter. This term is evaluated from left to right using a DFS strategy. If the leftmost-outermost term reduces to fail then the computation backtracks to the last choice point.

4.2

Electrical Circuits

Let us construct a simple circuit4 of two resistors r1 and r2 in serie with a battery v. The resistors available for r1 are of values of 10Ω and 14Ω, and 27Ω and 60Ω for r2 . There are 4

This example is based on the one presented in [3].

11

also two batteries available of 10V and 20V . Let us suppose that the voltage over r2 must be between 14.5V and 16.5V . We would like to know which values of r1 , r2 and v should be taken in order to satisfy the constraint on r2 . battery b r A AA r

resistor1

b r AA A r

resistor2

The first two function definitions correspond to the Ohm law and the Kirchhoff law. ohm ≡ λ u r . u/r kirchhoff ≡ λ l . {Null(l)}0 [] {¬Null(l)}(Head(l) + kirchhoff(Tail(l))) The last function could also be written as λ l . {Null(l)}0 [] (Head(l) + kirchhoff(Tail(l))), since disjunctive terms are evaluated from left to right and thus, if the guard Null(l) fails, then the addition becomes the “else” of that guard. circuit is a function of five parameters, namely the values for the battery, for the resistor r1 , for r2 , and the lower and upper bounds for r2 . The subterm of the abstraction is an existentially quantified and constrained one, whose constraint formula specifies that the Ohm law and the Kirchhoff law be satisfied. circuit ≡ λ v r1 r2 lower upper . ∃ v1 v2 . {kirchhoff (List (v1 v2 − v)) = 0, kirchhoff (List (ohm (v1 r1 ) ohm (v2 r2 ))) = 0, v2 < upper, lower < v2 }List (v r1 r2 ) Finally we have a function call where we instantiate v, r1 and r2 with the disjunctive values they may assume, and lower and upper with the bounds of the voltage over r2 . circuit ((10 [] 20) (10 [] 14) (27 [] 60) 14 16.25) As circuit is called with a non-value, no β-reduction may take place. The parameters have to be reduced to values using the [] -rules circuit (10 (10 [] 14) (27 [] 60) 14 16.25) [] circuit (20 (10 [] 14) (27 [] 60) 14 16.25) and so on. After several applications of the same rule, we get the following disjunction: circuit circuit circuit circuit

(10 (10 (20 (20

10 14 10 14

27 27 27 27

14 14 14 14

16.25) 16.25) 16.25) 16.25)

[] circuit [] circuit [] circuit [] circuit

(10 (10 (20 (20

10 14 10 14

60 60 60 60

14 14 14 14

16.25) [] 16.25) [] 16.25) [] 16.25).

Now, as each function call passes values as parameters, we can reduce the β-redexes in a DFS-strategy. In the first case, and after some steps of β-reduction, we have ∃ v1 v2 . {v1 + v2 − 10 = 0, v1 /10 − v2 /27 = 0, v2 < 16.25, 14 < v2 }List (10 10 27) 12

The constraint solver can prove that the constraint is unsatisfiable, thus this term reduces to fail and the general term as follows: fail [] circuit (10 10 60 14 16.25) [] circuit (10 14 27 14 16.25) [] circuit (10 14 60 14 16.25) [] circuit (20 10 27 14 16.25) [] circuit (20 10 60 14 16.25) [] circuit (20 14 27 14 16.25) [] circuit (20 14 60 14 16.25). The first possibility is therefore discarded. In other words, the computation backtracks and evaluation continues with the following β-redex. ∃ v1 v2 .{v1 + v2 − 10 = 0, v1 /10 − v2 /60 = 0, v2 < 16.25, 14 < v2 }List (10 10 60) This term also fails, since the constraint is unsatisfiable, and the computation has to backtrack again. After iterating this process, we get a term that succeeds: List (20 10 27) [] circuit (20 10 60 14 16.25) [] circuit (20 14 27 14 16.25) [] circuit (20 14 60 14 16.25) −→ List (20 10 27) which is the final result, representing the values of the battery, the resistor r1 and the resistor r2 , respectively.

4.3

n-Queens

The problem we handle in this subsection is the so-called n-queens one. Given a chessboard of size n × n, we want to place n queens on it in such a way that they do not attack each other. The first function we define is one that generates the disjunction of values between 1 and n, where n is its formal parameter. We call this function dom. dom ≡ λ n . {n = 1}1 [] {n > 1}(dom(n − 1) [] n) The function we define next succeeds if the queens passed as parameter (given by their coordinates) attack each other. A queen attacks another one if they are in the same row, or in the same column, or in the same diagonal (this relation is of course symmetric). attack ≡ λ c d . {Head(c) = Head(d)}true [] {Second(c) = Second(d)}true [] {Abs(Head(c) − Head(d)) = Abs(Second(c) − Second(d))}true [] false (where Abs computes the absolute value of an integer number and Second abbreviates Head of Tail)

Now we define the function no-att which, given a pair of coordinates and a list of coordinates, succeeds if a queen placed in the coordinates does not attack any of the queens 13

placed in the coordinates listed. no-att ≡ λ c L . {Null(L)}true [] {attack(c Head(L))}false [] no-att(c Tail(L)) The following function nq has two parameters: the side n of the chessboard, and the number m of coordinates to be calculated. Given actual parameters, nq generates a list of m coordinates such that if a queen is placed on each one of them, they do not attack each other. The body of nq is a disjunction of two terms. The first one treats the base case where we want to generate just one coordinate, i.e. if m = 1. There are no other coordinates already generated, and therefore we have the whole chessboard at disposal. Thus, we let the ∃-rule generate the disjunction of the n × n coordinates on the chessboard. M ≡ {m = 1} ∃ c1 c2 . {c1 = dom(n), c2 = dom(n)} List (List (c1 c2 )) The second term in the disjunction treats the general case. There we call nq recursively, which delivers a list of m−1 coordinates, and afterwards generate one additional coordinate such that a queen placed on it does not attack a queen placed in any of the m − 1 other coordinates previously calculated. N ≡ {m > 1} ∃ c1 c2 L . {c1 = dom(n), c2 = dom(n), L = nq(n m − 1), no-att(List (c1 c2 ) L) } Cons(List (c1 c2 ) L) Thus the function nq simply is nq ≡ λ n m . (M [] N ). The function we are interested in has just one parameter, the side of the chessboard. n-queens ≡ λ n . nq(n n) If we instantiate the previous function assuming a chessboard of 4 × 4 squares, and after a series of reductions, we obtain: n-queens(4) −→∗ List (List (1 2) List (2 4) List (3 1) List (4 3))

5

Conclusions and Ongoing Work

We have presented a functional, logic and constraint-based programming language. The language is an instantiation of the general model already presented in [7] with finite domains. For this actual instance of the calculus, we have defined new ad-hoc reduction rules. In a longer version of this work we prove that these rules are correct (i.e. that they preserve the semantics of the terms in the relation), and moreover we plan to prove that the Church-Rosser property is verified. A new operational semantics has been defined, that induces a reduction strategy for disjunctive terms, and in general for any term. This strategy is the left-to-right, depth-first 14

one, which is the natural one in logic languages such as Prolog. Typical examples of constraint languages over finite domains, such as solution of electrical circuits, SEN D + M ORE = M ON EY and n-queens, were immediately programmed by following the specification of the problem in a declarative way. In any case the calculus provides an elegant means to combine functional and constraint-logic programming. The language is under implementation. First results where published in [6]. Also there is a parallel on-going work in Australia, at the Monash University, by the group of Prof. Crossley. We expect to have a full implementation of the language by the next winter. Acknowledgement: We would like to thank Hendrik Lock for fruitful discussions about the subject.

References [1] H. P. Barendregt. Lambda Calculi with Types. In S. Abramsky, D. M. Gabbay, and T. S. E. Maibaum, editors, Handbook of Logic in Computer Science, chapter 13, pages 117–309. Oxford University Press, 1992. [2] H. P. Barendregt and E. Barendsen. Introduction to Lambda Calculus. Technical report, Department of Computer Science, Catholic University of Nijmegen, Toernooiveld 1, 6525 ED Nijmegen, The Nederlands, July 1991. [3] A. Colmerauer. Opening the Prolog III universe. Byte Magazine, 12(9):177–182, August 1987. [4] J. N. Crossley, L. Mandel, and M. Wirsing. Una Extensi´on de Constraints al C´alculo Lambda. In Proceedings of the Segundo Congreso de Programaci´ on Declarativa, ProDe.93, Blanes, Girona Spain, September 29-30, October 1 1993. (In Spanish). [5] M. Dincbas, H. Simonis, and P. V. Hentenryck. Extending Equation Solving and Constraint Handling in Logic Programming. In MCC, Colloquium on Resolution of Equations in Algebraic Structures (CREAS), Austin, Texas USA, May 1987. [6] A. Knapp and L. Mandel. A Rewriting System with Explicit Substitutions for the First Order Constrained Lambda Calculus. Interne Reports der FG Programmiersysteme FR I-Passau-1994-094, FORWISS (Universit¨at Passau), 1994. [7] L. Mandel. Constrained Lambda Calculus. PhD thesis, Ludwig-Maximilians-Universit¨at M¨ unchen, Leopoldstraße 11b, 80802 M¨ unchen, Germany, Mar. 1995. 213 pages. [8] K. Sieber. Call-by-Value and Nondeterminism. In M. Benzen and J. F. Groote, editors, International Conference on Typed Lambda Calculi and Applications (TLCA ’93), pages 376–390, Mar. 1993. 31 pages.

15