# Range

The **Range** constraint enforces that for all rows, the value of one of the columns is bounded by the values in the other two columns.

## Constraint API

Create a `Range` constraint.

* (required) `low_column_name`: The name of the column that contains the lowest value. This must be a numerical or datetime column.
* (required) `middle_column_name`: The name of the column that must be between the low and the high columns. This must be a numerical or datetime column.
* (required) `high_column_name`: The name of the column that contains the highest value. This must be a numerical or datetime column.
* `strict_boundaries`: Whether the boundaries between each of the comparisons are strict
  * (default) `True`: The middle column must be strictly greater than the low column and strictly less than the high column.
  * `False`: The middle column must be greater than *or equal to* the low column and less than *or equal to* the high column
* `table_name`: A string with the name of the table to apply this to. Required if you have a multi-table dataset.

```python
from sdv.cag import Range

my_constraint = Range(
    low_column_name='child_age',
    middle_column_name='parent_age',
    high_column_name='grandparent_age',
    strict_bounadires=True
)
```

## Usage

Apply the constraint to any SDV synthesizer. Then fit and sample as usual.

```python
synthesizer = GaussianCopulaSynthesizer(metadata)
synthesizer.add_constraints([my_constraint])

synthesizer.fit(data)
synthetic_data = synthesizer.sample()
```

For more information about using predefined constraints, please see the [**Constraint-Augmented Generation tutorial**](https://colab.research.google.com/drive/1WCMQujfVKL5giULZXOPPIBoMfzR9Zj68?usp=sharing).

## ❖ Auto-Detection

{% hint style="info" %}
❖ **SDV Enterprise Bundle**. This feature is available as part of the **CAG Bundle**, an optional add-on to SDV Enterprise. For more information, please visit the [CAG Bundle](https://docs.sdv.dev/sdv/explore/sdv-bundles/cag) page.
{% endhint %}

Auto-detection is allowed for this constraint but it is not enabled by default. We recommend auto-detecting the [ChainedInequality](https://docs.sdv.dev/sdv/concepts/constraint-augmented-generation-cag/predefined-constraints/chainedinequality) constraint instead, as it covers all the logic of this constraint and more!

If you'd like to auto-detect this constraint specifically, you can supply it in the auto-detection parameters. This will detect all instances of the constraint throughout the dataset.

```python
constraints = synthesizer.detect_constraints(
    data,
    constraint_classes=['Range']
)
```

**Detection Parameters**: By default, SDV detects this constraint for `datetime` columns only. Use the the `sdtypes` parameter to update this. Provide a list of sdtypes to detect (`datetime`, `numerical`, or both).

```python
constraints = synthesizer.detect_constraints(
    data,
    constraint_classes=['Range'],
    detection_params={
        'Range': { 'sdtypes': [ 'numerical', 'datetime' ] }
    }
)
```

## FAQs

<details>

<summary>What happens to missing values?</summary>

This constraint ignores missing values. The constraint considered is valid as long as the numerical values (non-missing values) follow the logic.

</details>

<details>

<summary>What if I want to compare a column to fixed values?</summary>

Many of our SDV synthesizers are already designed to learned the min/max values in every column and replicate the ranges in the synthetic data. This parameter is often called `enforce_min_max_values` and it applies to all numerical/datetime columns. For more information, check your [synthesizer's API guide](https://docs.sdv.dev/sdv/single-table-data/modeling/synthesizers).

You can also control the enforcement on a per-column basis. Turn on/off the enforcement on individual columns by accessing and updating the transformers. For more information, see the [Preprocessing guide](https://docs.sdv.dev/sdv/single-table-data/modeling/customizations/preprocessing).

Both of these options will allow you to fix the range (as observed in the real data) or expand it (by not enforcing it). If you'd like to further *restrict* the range, we encourage you to model the data as-is and use [conditional sampling](https://docs.sdv.dev/sdv/single-table-data/sampling/conditional-sampling) to get the range you need.

</details>
