dwavesystems / dwavesystems/dwave-optimization

`Square(x)` with a zero straddling range bypasses the `divide` zero denominator guard

Open
#554 2 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
C++
Stars
31
Forks
36
Avg merge
16h 55m
Merged PRs (30d)
8

Description

### Summary

When a decision variable `x` has a range that crosses zero (e.g. `lower_bound=-3, upper_bound=2`),
`Square(x)` incorrectly reports that its minimum value is positive.
This fools the `divide` operator's safety check into accepting it as a denominator,
even though `Square(x)` can actually be zero (when `x = 0`).
The model builds without error, but at runtime the division silently returns `inf`.

---

### Expected behaviour

```python
x = model.integer(lower_bound=-3, upper_bound=2) # range includes 0
model.constant(10) / Square(x)
# Should raise ValueError — Square(x) can be 0
```

`divide` documents that it raises `ValueError` if the denominator can ever be zero.
Since `x` can be `0`, `Square(x)` can be `0`, so a `ValueError` should be raised at model-build time.

---

### Actual behaviour

No error is raised at model-build time. When `x = 0` during solving, the result is `inf` with no warning.

```python
from dwave.optimization.model import Model
from dwave.optimization.symbols import Square

model = Model()
x = model.integer(lower_bound=-3, upper_bound=2)
sq = Square(x)
ratio = model.constant(10) / sq # ← no error raised (should raise)

with model.lock():
model.states.resize(1)
x.set_state(0, 0)
print(ratio.state(0)) # prints: [inf] ← silent wrong result
```

---

### Workaround

Avoid using `Square(x)` as a divisor when `x` can be zero.
Either constrain the variable to be strictly positive/negative before squaring,
or use `safe_divide` if zero-denominator should map to zero rather than `inf`.

```python
# Option 1: restrict x away from zero first
x = model.integer(lower_bound=1, upper_bound=5) # strictly positive
model.constant(10) / Square(x) # safe

# Option 2: use safe_divide (returns 0 on division by zero)
from dwave.optimization.mathematical import safe_divide
safe_divide(model.constant(10), Square(x))
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.