# Relational operators

CQL has 6 relational operators:
relationmeaning
`<`less than
` ≤ `less than or equal to
` ≥ `greater than or equal to
`>`greater than
`≺`ancestor of
`≼`ancestor of or equal to
`≽`descendant of or equal to
`≽`descendant of or equal to
` == `equal to
` ≠ `not equal to

The `≠` filter is defined as an abbreviation for applying the not filter to the filter that results from replacing the `≠` with `==`:

```	       left ≠ right
≡
not { left == right }```

The four relational operators

`    ≺, ≼, ≻, ≽`

only allow position arguments. These four filters are discussed in more detail here: ancestor/descendant relation operators.

## matching the position

Each of these relational operators is its own filter. For example, the CQL expression
`      power A<power a`
is a `<` filter whose two arguments are the filters `power A` and `power a`.

Generally, if either or both of the two operands to a relational filter does not match the current position, then neither does the relational filter, except in two cases:

• If the filter is `==` and both operands are sets, then the filter is treated specially.
• The `≠` filter is treated as an abbreviation for `not ... == ...`

For example, consider the following filter, which is equal to the number of white pieces in the previous position:

`parent:#△`

If the current position is the initial position, then this parent filter would not match the position (since the initial position has not parent). Suppose the current position is the initial position.

`	5==parent:#△`

will be true only if the following two conditions are satisfied:

1. the current position is not the initial position
2. the previous position has exactly 5 white pieces in it.

Thus, if the current position is the initial position, each of the following three filters are always false (never match):

```	5 == parent:#△
5<parent:#△
5>parent:#△```

However,

`        5 != parent:#△`
always matches the initial position, because it is an abbreviation for
`	not {5 == parent:#△}`

## Conversions of set operands to numbers

If exactly one operand of a relation operator is a set filter and the other operand is a numeric filter, then the set represented by the set filter is converted into its cardinality.

Thus,

`△==3`
means the same thing as
`{#△}==3`
and is true when the current position has exactly 3 white pieces.

Similarly,

`	△→♚>1`
is converted into
`	#{△→♚}>1`
and matches the current position when the black king is in double check.

## Comparing positions with <, <=, >, and >=

If each operand of the two operands of a binary comparison operator is a position filter, the associated comparison is performed on the positionid of the operands. That is, if `X` and `Y` are positions, then
`	`X`<`Y``
is true exactly when the `positionid` of `X` is smaller than the `positionid` of `Y`.
`	{find check}<find ――=♘`
is equivalent to:
`	{find check} : positionid<{find ――=♘} : positionid`
In the above expression, the value of the `find check` filter isthe next position that is a check.

The value of the `find ――=♘` filter is the next position from which there is a knight underpromotion.

When these two positions are compared, their numeric positionid values are compared Thus, `{find check} : positionid` gives the positionid of the position of the next check, using the `:` operator to evaluate `positionid` using another current position. Likewise, `{find ――=♘} : positionid` is the positionid of the next position from which there is knight underpromotion.

Conversions of position operands are most commonly used in the body of the echo filter. Typically, an `echo` filter might begin something like this:

```	echo (source target) {
source<target
...
}```

This idiom can be used to ensure that the `target` position is a descendant of the `source` position (if `variations` is not set); or simply to make sure that the same pair of positions is only evaluated once in the body of the `echo`.

## comparing set filters using ==

If both operands of the `==` operator are set filters, then the operands are compared as sets: the filter matches only if the corresponding sets are identical. Likewise, if both operands of the `!=` filter are sets, then filter matches only if the corresponding sets are not identical. These rules apply even if the sets are empty.

For example, if `x` is a set variable, then

`	x==a-h1-8`
matches a position exactly when `x` is the all 64 squares. This expression has the same effect as the following, which is true if `x` contains 64 squares:
`	#x==64`
or, equivalently, by using the conversion of set operands to numbers to
`	x==64`
.

## The numeric value of a comparison operator

A comparison operator with numeric arguments is also a numeric filter. If a comparison operator matches the current position, then its value is the value of its first operand in the position. This applies to all the comparison operators except for `!=`, which has no numeric value by definition. It also does not apply for the numeric operator `==` when both its arguments are sets (since sets are compared with set equality).

For example, to check if the number of white pawns is between at least 4 and smaller than 7 in a position, we can use

`	4 ≤ (#♙<7)`

That is because, if the number of white pawns is ` ≥ 7`, then the `#♙<7` filter will not match, so neither neither will the `4 ≤ ...` filter (because relational filters do not match if one their arguments does not match).

On the other hand, if the number of white pawns is smaller than 7, then `#♙<7` will match and will have value equal to `#♙`. In this case, the whole filter will match if `4 ≤ #♙` matches, which is what we want.

In fact, because relational operators are right associative, and because sets compared with numbers are converted to their cardinality, the above filter is equivalent to the terse:

`      4 ≤ ♙<7`

Such ternary relational operator notation is common in mathematics, but many programming languages do not support the notation.

The numeric value of comparison operators is often exploited in echo filters that are sorted. Sometimes we want to sort an `echo` by the distance between the source and the target:

```	sort
echo (source target){
...
distance(source target) ≥ 5}```

The value of the body of the `echo` is equal to `distance(source target)` whenever that distance is at least 5 (and the other requirements of the `echo` body also match). If the distance is not at least 5, the body does not match.

When a named filter requires a numeric argument, the filter normally has higher precedence than the binary comparison operators. Thus,

`	abs x<3`
is parsed as
`	{abs x}<3`
rather than
`        abs {x<3}`

However, because sort can take a set filter as argument,

```
sort #△≥10
≡
sort (#△≥10)
≡
sort △ ≥ 10
≡
sort (△ ≥ 10)```
which sorts on the number of white pieces when that number is at least 10. Note that `△ ≥ 10` is converted into `(#△) ≥ 10` due to the conversion of set operands with relational operators.

# Relational operators with string arguments

Relational operators can have string filter arguments. Strings are compared in lexicographic order by the ASCII value of their characters, so that for example

```  "A">"a"
"Ab">"A"
""<"A"
```

Relational operators have string values just like the case for for numeric values. Therefore, they can be chained just like for numeric values.

Thus, to check that a character `X` is lowercase, one could use

```
"a" ≤ X ≤ "z"
```
(or more generally, `lowercase X==X`)

# Examples

Relational operators are used in most of the CQL examples, starting with the simplest example, QQqq.cql, which finds positions with the material of two queens against two queens, and no other pieces:
```♕==2
♛==2
◭==6```
Here, `♕==2` is converted (due to conversion of set operands discussed above) into `#♕==2`. That is, the filter is true if the number of white queens on the board is equal to 2.

Similarly, `♛==2` is true if the number of black queens on the board is equal to 2.

Finally, `◭==6` is true if the total number of white (`A`) and black (`a`) pieces is equal to 6. If so, the material must be `♔♕♕♚♛♛`.

This file finds the following position:

Elkies 1993, after 7. Qfg8! (zugzwang)
(found from CQL file: qqqq.cql)

In the position it is black to move, and because of this, black loses. If the position were white to move, black would draw. This position itself was found by computer; the study is the first ever composed using a six-piece tablebase.