# Bug in connective constraints?

39 views

### denis.be...@gmail.com

Nov 12, 2022, 11:53:45 AM11/12/22
to CLIPSESG
According to the basic manual:

"§5.4.1.4 Connective Constraints

The ~ constraint has highest precedence, followed by the & constraint, followed by the | constraint. Otherwise, evaluation of multiple constraints can be considered to occur from left to right.

There is one exception to the precedence rules that applies to the binding occurrence of a variable. If the first constraint is a variable followed by an & connective constraint, then the first constraint is treated as a separate constraint which also must be satisified. Thus the constraint ?x&red|blue is treated like ?x&(red|blue) rather than (?x&red)|blue as the normal precedence rules would indicate."

However (in both versions 63x and 64x):

(deftemplate relation (slot size (type INTEGER)) (multislot elements))

(defrule test

(relation (size 4) (elements ?z1 ?z2 ?z3 ?z4))

(middle ?zi2&?z2|?z3)

(middle ?zi3&?z2|?z3&:(< ?zi2 ?zi3))

=>

(printout t ?z1 ?z2 ?z3 ?z4 crlf)

)

(reset)

(assert

(relation (size 4) (elements 1 2 3 4))

(middle 2)

(middle 3)

)

(facts)

f-0     (initial-fact)

f-1     (relation (size 4) (elements 1 2 3 4))

f-2     (middle 2)

f-3     (middle 3)

(watch rules)

(run)

FIRE    1 test: f-1,f-3,f-2 ;;; shouldn't fire

1234

FIRE    2 test: f-1,f-2,f-3

1234

FIRE    3 test: f-1,f-2,f-2 ;;; shouldn't fire

1234

### CLIPS Support

Nov 12, 2022, 6:06:29 PM11/12/22
to CLIPSESG
The constraint for the second pattern is

?zi2 and (?z2 or ?z3)

Since ?zi2 is not previously bound, that portion of the constraint is satisfied and ?zi2 will be bound to whatever matches the remaining constraint. From the only relation fact, ?z2 and ?z3 are bound to the values 2 and 3 respectively, so both f-2 and f-3 will satisfy this constraint with ?zi2 bound to either 2 or 3.

The constraint for the third pattern is

?zi3 and (?z2 or (?z3 and (< ?zi2 ?zi3)))

Since ?zi3 is not previously bound, that portion of the constraint is satisfied and ?zi3 will be bound to whatever matches the remaining constraint. Since ?z2 is 2, the remaining constraint will be satisfied when matching f-2. This will place the activations with f-1,f-2,f-2 and f-1,f-3,f-2 on the agenda. Otherwise since ?z3 is 3, the remaining constraint can only be matched for f-3, but only if the constraint (< ?zi2 ?zi3) is satisfied, and this can only occur if the second pattern matches f-2. This will place the activation f-1,f-2,f-3 on the agenda.

### denis.be...@gmail.com

Nov 12, 2022, 11:30:30 PM11/12/22
to CLIPSESG
You say:
"The constraint for the third pattern is
?zi3 and (?z2 or (?z3 and (< ?zi2 ?zi3)))
Since ?zi3 is not previously bound, that portion of the constraint is satisfied and ?zi3 will be bound to whatever matches the remaining constraint. Since ?z2 is 2, the remaining constraint will be satisfied when matching f-2. This will place the activations with f-1,f-2,f-2 and f-1,f-3,f-2 on the agenda. Otherwise since ?z3 is 3, the remaining constraint can only be matched for f-3, but only if the constraint (< ?zi2 ?zi3) is satisfied, and this can only occur if the second pattern matches f-2. This will place the activation f-1,f-2,f-3 on the agenda."

But this interpretation [i.e.  (?zi3 and (?z2 or (?z3 and (< ?zi2 ?zi3)))] seems to be in contradiction with the basic manual.
According to the exception mentioned in the basic manual, since ?zi3 is not previously bound, the constraint for the third pattern should be interpreted as:
?zi3 and  (or (eq ?zi3 ?z2) or  (eq ?zi3 ?z3)) and (< ?zi2 ?zi3)))

As a result, the rule should fire once (for ?zi2=2 and ?zi3=3), not thrice.

### CLIPS Support

Nov 13, 2022, 1:32:51 PM11/13/22
to CLIPSESG
The phrase "the first constraint is treated as a separate constraint which also must be satisfied" means that

A & B | C & D

is treated as

A & (B | C & D)

when A is a binding occurrence of a variable. When you then apply the ~/&/| precedence, you get

A & (B | (C & D))

The exception only modifies the precedence of the & immediately following the binding occurrence. It doesn't modify the precedence of all subsequent occurrences of & which would give you

A & (B | C) & D

### denis.be...@gmail.com

Nov 13, 2022, 11:37:27 PM11/13/22
to CLIPSESG
Sorry, Gary, but your new example is impossible to understand.
You use the word "constraint" with three different meanings:
- logical connective: "Three connective constraints are available for connecting individual constraints and variables to each other. These are the & (and), | (or), and ~ (not) connective constraints."
-  connected constraint:: "The & constraint is satisfied if the two adjoining constraints are satisfied."
- variable binding: "If the first term of a connective constraint is the first occurrence of a variable name"

So, when you write "the first constraint" (here and in the manual) nobody can know what you're talking about.
The example in the manual:
"the constraint ?x&red|blue  [1st meaning] is treated like ?x&(red|blue) rather than (?x&red)|blue as the normal precedence rules would indicate"

Now, how should one understand ?x&(red|blue) when x is a binding occurrence ? Obviously as ?x&(?x=red| or ?x=blue) ; i.e. ?x is a binding occurrence and ?x must be red or blue
This makes perfect sense for a special case: one wants to introduce a new variable and to immediately reduce its possible values. The interpretation ?x&red or blue would make no sense (in particular variable ?x bound in the first case or not in the other).
Of course, the same should work with ?x&red|blue|green, i.e. it should be interpreted as ?x&(?x=red| or ?x=blue or ?x=green), regardless of what's after.

There is a reason why logicians use parentheses. For the same reason, you should allow parentheses in "connectED constraints".
BTW, in  order to reduce ambiguities:
- the  title of section 5.4.1.4 should be "ConnectED Constraints"
- the first sentence should be: Three LOGICAL connectives are available for connecting individual constraints and variables to each other: & (and), | (or), and ~ (not). They allow to define respectively the & connected constraint (satisfied if the two adjoining constraints are satisfied), the | connected constraint (satisfied if either of the two adjoining constraints is satisfied) and the ~ connected constraint (satisfied if the following constraint is not satisfied).

Priorities and left to right parsing may be contradictory; so that parentheses should be allowed.

The exception part of the first paragraph should also be re-written, but I'm still unable to understand what you mean, so I currently don't have any alternative to propose.

Anyway, I think the real problem is, parentheses are not allowed: (defrule test (foo ?x&(red|blue)) => ) is a syntax error.
Allowing the use of parentheses would avoid all the current ambiguities/inconsistencies.

### CLIPS Support

Nov 15, 2022, 1:26:49 AM11/15/22
to CLIPSESG

One other way you can think of it is in terms of operators and operands. For an arithmetic expression such as

-1 * 3 + 2 * 4

if you apply the default precedence used by C, this will evaluate the expression as

(-1 * 3) + (2 * 4)

Now add an exception to the precedence. If the first operand is negative and followed by the * operator, then give that operator a lower precedence than the rest of the operators in the expression. With that exception the original expression is converted to

-1 * (3 + 2 * 4)

Then applying the default precedence you get

-1 * (3 + (2 * 4))

So instead of using constraint, I'll use operand and instead of using connective constraint, I'll use operator. Replacing the operators and operands in the original expression with CLIPS equivalents gives

?zi3 & ?z2 | ?z3 & :(< ?zi2 ?zi3)

and with the default precedence for the & and | operators gives

(?zi3 & ?z2) | (?z3 & :(< ?zi2 ?zi3))

Now add an exception to the precedence. If the first operand is a variable and followed by the & operator, then give that operator a lower precedence than the rest of the operators in the expression. With that exception the original expression is converted to

?zi3 & (?z2 | ?z3 & :(< ?zi2 ?zi3))

and then the default precedence gives

?zi3 & (?z2 | (?z3 & :(< ?zi2 ?zi3)))

The ART syntax used in CLIPS for pattern matching was designed by Paul Haley and Chuck Williams so back in 1985 I was also in the position of learning the semantics of something designed by someone else.

In ART, there were three completely different mechanisms that implemented "and" behavior: "and" conditional elements, & connective constraints, and an "and" function. In addition, there was a "logical" conditional element. I didn't hang on to any of the old ART documentation, but I did look through a copy of the 1990 ART-IM tutorial a few years back. Much as I remember from the original ART documentation, you could tell how things worked from context, but terminology was not consistently used. A lot of the CLIPS terminology evolved over time because there were different writers making separate decisions as to how to explain the syntax.

In retrospect, it would have been better if we had changed the names of the and/or/not conditional elements to all/any/none a long time. That would have been extremely simple to change. A lot of users confuse the and/or/not conditional elements with the and/or/not functions and that wasn't apparent until I saw code being posted to question forums. But at this point I think it would just cause more confusion.

I understand your confusion regarding constraints. There is some commonality in terminology between CLIPS and Jess (which also uses some ART syntax) and Drools (another open source tool which does not use ART syntax). [I haven't used any commercial tools recently so The term conditional element means the same thing in all three languages and the term constraint (something that must be true in order for a fact/object to match a pattern) is the same. Constraints include the syntax for matching specific values in a fact/object (such as with variables and literals) in addition to the connective constraints such as & and | which tie other constraints together but don't match against a specific value in a fact/object. But if you see something that's referring to the first, second, etc. constraint in a group, it's most likely not including the connective constraints in the count. The move away from using logical to describe anything other than something associated with the logical conditional element happened three decades ago. Not everything with and/or/not needs to be described as logical. In C there's a bitwise 'and' operator, &, a bitwise 'and' assignment operator, &=, but only the logical 'and' operator, &&, is referred to actually using logical. I think the and/or/not functions in CLIPS would be the appropriate thing for the logical label, but for a number of rule languages these are referred to as predicate functions.

### denis.berthier

Nov 15, 2022, 3:40:38 AM11/15/22

Ever since the early development of formal logic more than a century ago, or/and/not have been called logical connectives. I don’t know why AI should invent new confusing terms for this.
Their interpretation in AI differs from  their logical interpretation in only the sense that, for obvious practical reasons, not is interpreted as absence (same as in databases).

Section 5.4.1.4 is named « connective constraints » and you use this expression in the informal discussion but in the formal syntax you speak of « connectED  constraints ».

I agree that, with some reading of the sentence « If the first constraint is a variable followed by an & connective constraint, then the first constraint is treated as a separate constraint which also must be satisified. Thus the constraint ?x&red|blue is treated like ?x&(red|blue) rather than (?x&red)|blue as the normal precedence rules would indicate. »
the expression ?zi3&?z2|?z3&:(< ?zi2 ?zi3)
is interpreted as: (?zi3 & ?z2) | (?z3 &:(< ?zi2 ?zi3)) in the default order
and as: ?zi3 & (?z2 | (?z3 &:(< ?zi2 ?zi3)) in the special order.
The overly simple example in the manual ?x&red|blue merely lacks additional constraints to make this clear.

I understand  that you can’t change this for compatibility issues - though I wouldn’t care too much about JESS (which hasn't been updated for years).
But this exception looks totally arbitrary: it guarantees that ?zi3 is bound, but that’s all.

The problem remains that connected constraints as of now don’t allow the expression of all the boolean constraints.
In particular, without parentheses, there’s no way to express what I wanted to express, i.e; ?zi3 & (?z2|?z3) & (< ?zi2 ?zi3) - a very natural constraint (where ?zi3 is also guaranteed to be bound.
Of course, there’s still the possibility of using the full syntax &:(and (or (eq ?zi3 ?z2)  (eq ?zi3 ?z3))   (< (?zi2 ?zi3)) but this defeats the idea of having connected constraints and it  turns out to be particularly verbose when you want to deal with larger choices: &:(and (or (eq ?zi3 ?z2)  (eq ?zi3 ?z3)  (eq ?zi3 ?z4)  (eq ?zi3 ?z5)  (eq ?zi3 ?z6)  (eq ?zi3 ?z7))  …& (< ?zi3 ...

My conclusion: parentheses should be allowed in connected constraints.

--
You received this message because you are subscribed to the Google Groups "CLIPSESG" group.
To post to this group, send email to CLIP...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/CLIPSESG?hl=en

--> IF YOU NO LONGER WANT TO RECEIVE EMAIL <--
Click on "Edit my membership" link.
Select the "No Email" radio button.
Click the "Save these settings" button.

--> IF YOU WANT TO UNSUBSCRIBE <--
Click on "Edit my membership" link.
Click the "Unsubscribe" button.
Note: This appears to be the most reliable way to unsubscribe

Alternately, send email to CLIPSESG-u...@googlegroups.com. You will receive an email which you must respond to as well to unsubscribe. Clicking the link mentioned in the unsubscribe reply does not appear to work reliably.
---
You received this message because you are subscribed to the Google Groups "CLIPSESG" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clipsesg+u...@googlegroups.com.