Skip to content

Conversation

smichr
Copy link
Member

@smichr smichr commented Apr 10, 2021

References to other Issues or PRs

fixes #21269

Brief description of what is fixed or changed

Other comments

  • to return or to raise

Symbolic Range is tricky because you can't assume that it isn't EmptSet when making queries like .inf, e.g. neither Range(x,y,z).inf nor Range(x,y,z)[0] can return x unless we know that (y - x)*z > 0

And, technically, even Range(x, x + 2, 1)[0] should not return x unless we know that it is an integer.

  • this now raises an error
  • the relational form

cf #21285 For better protection, a two more Mods could be added to give: And(Eq(Mod(x,1),a%s), Eq(Mod(a,1),0), Eq(Mod(s,1),0)) where a is a representative point in the Range that is not infinite, s is the step and x is the relational variable. We should also make sure that there is not a clash between the symbols of the Range and the relational variable as in Range(x, x + 5, 2).as_relational(x).

  • this is done but the user can clash symbols if they want to
>>> var('x')
x
>>> Range(x, x + 3, 2).as_relational(x)
(x >= x) & Eq(Mod(x, 1), 0) & (x <= x + 2)
>>> var('x',real=True)
x
>>> Range(x, x + 3, 2).as_relational(x)
Eq(Mod(x, 1), 0)
>>> var('x',integer=1)
x
>>> Range(x, x + 3, 2).as_relational(x)
True

>>> var('x')
x
>>> Range(1, 1+ 2*x, x).as_relational(x)
Eq(Mod(-1, x), 0) & Eq(Mod(x, 1), 0) & (((x >= 1) & (x <= x + 1)) | ((x <= -1) &
 (x <= 1) & (x >= x + 1)))
>>> var('x',real=1)
x
>>> Range(1, 1+ 2*x, x).as_relational(x)
(x >= 1) & Eq(Mod(-1, x), 0) & Eq(Mod(x, 1), 0)
>>> var('x',integer=1)
x
>>> Range(1, 1+ 2*x, x).as_relational(x)
(x >= 1) & Eq(Mod(-1, x), 0)

Release Notes

  • sets
    • Range involving symbols will be made more canonical (correcting a bug in calculation of sup) and errors will be raised when trying to compute attributes that are not known due to limitations of assumptions on the arguments.

@sympy-bot
Copy link

sympy-bot commented Apr 10, 2021

Hi, I am the SymPy bot (v161). I'm here to help you write a release notes entry. Please read the guide on how to write release notes.

Your release notes are in good order.

Here is what the release notes will look like:

  • sets
    • Range involving symbols will be made more canonical (correcting a bug in calculation of sup) and errors will be raised when trying to compute attributes that are not known due to limitations of assumptions on the arguments. (#21286 by @smichr)

This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.9.

Click here to see the pull request description that was parsed.
<!-- Your title above should be a short description of what
was changed. Do not include the issue number in the title. -->

#### References to other Issues or PRs

fixes #21269 

#### Brief description of what is fixed or changed


#### Other comments

* to return or to raise

Symbolic Range is tricky because you can't assume that it isn't EmptSet when making queries like `.inf`, e.g. neither `Range(x,y,z).inf` nor Range(x,y,z)[0] can return `x` unless we know that (y - x)*z > 0

And, technically, even `Range(x, x + 2, 1)[0]` should not return `x` unless we know that it is an integer.

- [x] this now raises an error

* the relational form

cf #21285 For better protection, a two more Mods could be added to give: `And(Eq(Mod(x,1),a%s), Eq(Mod(a,1),0), Eq(Mod(s,1),0))` where `a` is a representative point in the Range that is not infinite, `s` is the step and `x` is the relational variable. We should also make sure that there is not a clash between the symbols of the Range and the relational variable as in `Range(x, x + 5, 2).as_relational(x)`.

- [x] this is done but the user can clash symbols if they want to
```python
>>> var('x')
x
>>> Range(x, x + 3, 2).as_relational(x)
(x >= x) & Eq(Mod(x, 1), 0) & (x <= x + 2)
>>> var('x',real=True)
x
>>> Range(x, x + 3, 2).as_relational(x)
Eq(Mod(x, 1), 0)
>>> var('x',integer=1)
x
>>> Range(x, x + 3, 2).as_relational(x)
True

>>> var('x')
x
>>> Range(1, 1+ 2*x, x).as_relational(x)
Eq(Mod(-1, x), 0) & Eq(Mod(x, 1), 0) & (((x >= 1) & (x <= x + 1)) | ((x <= -1) &
 (x <= 1) & (x >= x + 1)))
>>> var('x',real=1)
x
>>> Range(1, 1+ 2*x, x).as_relational(x)
(x >= 1) & Eq(Mod(-1, x), 0) & Eq(Mod(x, 1), 0)
>>> var('x',integer=1)
x
>>> Range(1, 1+ 2*x, x).as_relational(x)
(x >= 1) & Eq(Mod(-1, x), 0)
```
#### Release Notes

<!-- BEGIN RELEASE NOTES -->
* sets
  * Range involving symbols will be made more canonical (correcting a bug in calculation of `sup`) and errors will be raised when trying to compute attributes that are not known due to limitations of assumptions on the arguments.
<!-- END RELEASE NOTES -->

Update

The release notes on the wiki have been updated.

@smichr smichr force-pushed the Range branch 2 times, most recently from 4f7c453 to 4e01170 Compare April 12, 2021 22:00
@smichr smichr requested a review from czgdp1807 April 12, 2021 22:10
@smichr smichr changed the title [WIP] canonical Range corrections for symbolic Range Apr 12, 2021
@czgdp1807
Copy link
Member

Thanks for the correction. LGTM.

@smichr
Copy link
Member Author

smichr commented Apr 13, 2021

nominal coverage is 100%; ready to commit when tests pass

Range tries to be as lenient as possible in accepting symbolic limits
but must then be careful to make no assumptions when being asked
for elements of that Range.

e.g. Range(x,x+5)[0] is not x unless we know that x is an integer;
we also do not know that the size is 5 unless we know if x is an
integer. If x == oo then this would be a null range.
@smichr
Copy link
Member Author

smichr commented Apr 13, 2021

ping @Sagar231 (if you want to take a look)

@smichr smichr merged commit 5d14794 into sympy:master Apr 13, 2021
@smichr smichr deleted the Range branch April 13, 2021 22:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

make symbolic Range more canonical
5 participants