# Set operands

Set operands are created either by creating set variables (which are the simplest set operands) or by using operand properties that produce set operands.

#### Examples of Set Operands

The simplest set operands, set variables, can be created using `Mixin#set_var`.

```# Creates a set var with greatest lower bound {0} and least upper bound
# {0, 1, 2}.
set_operand = set_var(0, 0..2)
```

A couple of examples of properties that produce set operands include the `SetOperand#union` property, which produces a new set operand representing the union of two set operands:

```new_set_operand = set_operand1.union set_operand2
```

The `SetEnumOperand#union` property produces a new set operand representing the union of all the set operands in an enumeration:

```new_set_operand = set_enum.union
```

## Constraints

Generated from `SetConstraintReceiver`.

### `==`

`==(constant_set, options = {})`

Constrains the set operand to have a domain equal to `constant_set`.

##### Examples
```# +set+ must equal [1,2,5]
set.must == [1,2,5]

# +set+ must not equal 1..67
set.must_not == 1..67

# +set+ must equal the singleton set 0. The constraint is reified with
# the boolean operand +is_singleton_zero+.
set.must.equal(0, :reify => is_singleton_zero)
```

`==(set_operand, options = {})`

Constrains the set operand to equal `set_operand`.

##### Examples
```# +set1+ must equal +set2+
set1.must == set2

# +set1+ must equal +set2+. Reify the constraint with the
# boolean operand +bool+.
set1.must.equal(set2, :reify => bool)
```

### `subset`

`subset(constant_set, options = {})`

Constrains the set operand to be a subset of `constant_set`.

##### Examples
```# +set+ must be a subset of [1,2,5]
set.must_be.subset_of [1,2,5]

# +set+ must be a subset of 1..67
set.must_be.subset_of 1..67

# +set+ must not be a subset of [0].
set.must_not_be.subset_of 0

# +set+ must be a subset of [1,3,5,7]. The constraint is reified with
# the boolean operand +bool+.
set.must_be.subset_of([1.3.5.7], :reify => bool)
```

`subset(set_operand, options = {})`

Constrains the set operand to be a subeset of `set_operand`.

##### Examples
```# +set1+ must be a subset of +set2+
set1.must_be.subset_of == set2

# +set1+ must be a subset of +set2+. Reify the constraint
# with the boolean operand +bool+.
set1.must_be.subset(set2, :reify => bool)
```

### `superset`

`superset(constant_set, options = {})`

Constrains the set operand to be a superset of `constant_set`.

##### Examples
```# +set+ must be a superset of [1,2,5]
set.must_be.superset_of [1,2,5]

# +set+ must be a superset of 1..67
set.must_be.superset_of 1..67

# +set+ must not be a superset of [0].
set.must_not_be.superset_of 0

# +set+ must be a superset of [1,3,5,7]. The constraint is reified with
# the boolean operand +bool+.
set.must_be.superset_of([1.3.5.7], :reify => bool)
```

`superset(set_operand, options = {})`

Constrains the set operand to be a superset of `set_operand`.

##### Examples
```# +set1+ must be a superset of +set2+
set1.must_be.superset_of set2

# +set1+ must be a superset of +set2+. Reify the constraint
# with the boolean operand +bool+.
set1.must_be.superset(set2, :reify => bool)
```

### `disjoint`

`disjoint(constant_set, options = {})`

Constrains the set operand to be disjoint with `constant_set`.

##### Examples
```# +set+ must be disjoint with [1,2,5]
set.must_be.disjoint_with [1,2,5]

# +set+ must be disjoint with 1..67
set.must_be.disjoint_with 1..67

# +set+ must not be disjoint with [0].
set.must_not_be.disjoint_with 0

# +set+ must be disjoint with [1,3,5,7]. The constraint is reified with
# the boolean operand +bool+.
set.must_be.disjoint_with([1.3.5.7], :reify => bool)
```

`disjoint(set_operand, options = {})`

Constrains the set operand to be disjoint with `set_operand`.

##### Examples
```# +set1+ must be disjoint with +set2+
set1.must_be.disjoint_with set2

# +set1+ must be disjoint with +set2+. Reify the constraint
# with the boolean operand +bool+.
set1.must_be.disjoint(set2, :reify => bool)
```

### `channel`

`channel(bool_enum, options = {})`

Constrains this set to channel `bool_enum`. The set is constrained to include value i exactly when the operand at index i in the boolean enumeration is true.

Neither reification nor negation is supported. The boolean enum and set can be interchanged.

##### Examples
```# Constrains the enumeration of boolean operands called +bools+ to at
# least have the first and third operands set to true
set.must_be.superset_of [0, 2]
set.must.channel bools

# An alternative way of writing the above.
set.must_be.superset_of [0, 2]
bools.must.channel set
```

### `complement`

`complement(constant_set, options = {})`

Constrains the set operand to be the complement of `constant_set`.

##### Examples
```# +set+ must be the complement of [1,2,5]
set.must_be.complement_of [1,2,5]

# +set+ must be the complement of 1..67
set.must_be.complement_of 1..67

# +set+ must not be the complement of [0].
set.must_not_be.complement_of 0

# +set+ must be the complement of [1,3,5,7]. The constraint is
# reified with the boolean operand +bool+.
set.must_be.complement_of([1.3.5.7], :reify => bool)
```

`complement(set_operand, options = {})`

Constrains the set operand to be the complement of `set_operand`.

##### Examples
```# +set1+ must be the complement of +set2+
set1.must_be.complement_of set2

# +set1+ must be the complement of +set2+. Reify the constraint
# with the boolean operand +bool+.
set1.must_be.complement(set2, :reify => bool)
```

### `include`

`include(int_enum)`

Constrains this set to include the values of `int_enum`.

The constraint has the side effect of sorting the integer operands in a non-descending order. It does not support reification nor negation.

##### Examples
```# Constrain +set+ to include the values of all operands in
# +int_enum+.
set.must.include int_enum
```

## Properties

Generated from `SetOperand`.

### `union`

`union(set_operand_or_constant_set)`

Produces a new SetOperand representing the union between this operand and `set_operand_or_constant_set`.

##### Examples
```# The union between +set1+ and +set2+.
set1.union set2

# The union between +set+ and {1, 3, 5}.
set.union [1,3,5]
```

### `intersection`

`intersection(set_operand_or_constant_set)`

Produces a new SetOperand representing the intersection between this operand and `set_operand_or_constant_set`.

##### Examples
```# The intersection between +set1+ and +set2+.
set1.intersection set2

# The intersection between +set+ and {1, 3, 5}.
set.intersection [1,3,5]
```

### `minus`

`minus(set_operand_or_constant_set)`

Produces a new SetOperand representing this operand minus `set_operand_or_constant_set`.

##### Examples
```# +set1+ minus +set2+.
set1.minus set2

# +set+ minus {1, 3, 5}.
set.minus [1,3,5]
```

### `size`

`size()`

Produces an IntOperand representing the size of the set.

##### Examples
```# The size of +set+.
set.size
```

### `sum`

`sum(options = {:weights => weights = Hash.new(1)})`

Produces an IntOperand representing the sum of the values in the set. One of the following options may also be given:

:weights
Produces the weighted sum using the specified hash of weights. The hash should map each value to that value’s weight.
:substitutions
Produces the sum of the set with all elements replaced according to the hash.

Elements not included in the weights or substitutions hash are removed from the upper bound of the set.

##### Examples
```# The sum of +set+.
set.sum

# The sum of +set+ with primes < 10 given twice the weight.
set.sum(:weights => {2 => 2, 3 => 2, 5 => 2, 7 => 2})

# The sum of +set+ with odd values in [1,6] being counted as 1.
set.sum(:substitutions => {1 => 1, 3 => 1, 5 => 1})
```

### `max`

`max()`

Produces an IntOperand representing the maximum of the set.

##### Examples
```# The maximum of +set+.
set.max
```

### `min`

`min()`

Produces an IntOperand representing the minimum of the set.

##### Examples
```# The minimum of +set+.
set.min
```

### `elements`

`elements()`

Produces a SetElementsOperand on which relation constraints can be placed that constrain all elements in the set.

##### Examples
```# The elements of +set+.
set.elements
```

### `disjoint_union`

`disjoint_union(set_operand_or_constant_set)`

Produces a new SetOperand representing the disjoint union between this operand and `set_operand_or_constant_set`. The disjoint union is the union of the disjoint parts of the sets.

##### Examples
```# The disjoint union between +set1+ and +set2+.
set1.disjoint_union set2

# The disjoint union between +set+ and {1, 3, 5}.
set.disjoint_union [1,3,5]
```