EXCEPTION - Ungrounded Variable

# Error Code: `EXCEPTION` - Ungrounded Variable

This guide explains why an ungrounded variable error may occur and describes how to fix it.

In Rel, a variable is grounded when it can be instantiated to a specific, finite set of values.

For instance, in the expression `x: range(1, 100, 1, x)`, the variable `x` is instantiated with the values `1, 2, ..., 100`.

By contrast, a variable is not grounded or is ungrounded if the system is unable to determine a way to instantiate a finite set of values.

## Example: Infinite Possibilities

For example, in `x: minimum(1, x, 1)`, there are infinitely many values of `x` for which `minimum(1, x, 1)` is `true`. In fact, this is the case in many relations defined in Rel Libraries, such as in the example above with `minimum`.

Consider another example that returns an ungrounded variable error:

``````def my_string = substring["abcd", -2]
def output = my_string`````` The example above defines the relation `my_string` as a substring of the `"abcd"` string, using the built-in `substring` relation. This returns an `EXCEPTION` error thrown by the query optimizer.

Because this third argument is allowed to be larger than the length of the string, the number of valid values is infinite. To fix this problem, you need to provide another argument to `substring` that states where the substring should end. For example, the substring could end after the second character:

``````// read query

def my_string = substring["abcd", -2, 2]
def output = my_string``````

## Example: Nonlinear Dependencies

Another reason an ungrounded variable error can occur is when nonlinear mathematical dependencies need to be resolved. In general, no closed form solutions (opens in a new tab) exist for these nonlinear dependencies, making it impossible for the system to determine all valid values.

For example:

``````def output(x, y) {
x = 4
and y^2 = x
}`````` The code above leads to an ungrounded variable error because the equation `y^2=x` is nonlinear. In this case, the valid values for `y` are known to be `2` and `-2`, yet the system can’t resolve this due to the nonlinear nature of the equation.

One solution is to rewrite the equation such that it’s linear in `y` (if possible):

``````// read query

def output(x, y) {
x = 4
and (y = sqrt[x] or y = -sqrt[x])
}``````

Or you can provide an explicit finite domain for `y`:

``````// read query

def D = range[-10, 10, 1]

def output(x, y in D) {
x = 4
and y^2 = x
}``````

In this way, the mathematical equation turns into a filter and only keeps `(x, y)` pairs that fulfill the equation.

See Grounded Variables in the Rel Language Reference manual and Rel Primer: Advanced Syntax for more details.