Anyway to get rid of `math.floor` for positive odd integers with `sympy.simplify`?

Question:

I’m trying to simplify some expressions of positive odd integers with sympy. But sympy refuses to expand `floor`, making the simplification hard to proceed.

To be specific, `x` is a positive odd integer (actually in my particular use case, the constraint is even stricter. But sympy can only do odd and positive, which is fine). `x // 2` should be always equal to `(x - 1) / 2`. Example code here:

``````from sympy import Symbol, simplify

x = Symbol('x', odd=True, positive=True)
expr = x // 2 - (x - 1) / 2
print(simplify(expr))
``````

prints `-x/2 + floor(x/2) + 1/2`. Ideally it should print `0`.

What I’ve tried so far:

1. Simplify `(x - 1) // 2 - (x - 1) / 2`. Turns out to be 0.
2. Multiply the whole thing by 2: `2 * (x // 2 - (x - 1) / 2)`. Gives me: `-x + 2*floor(x/2) + 1`.
3. Try to put more weights on the `FLOOR` op by customizing the `measure`. No luck.
4. Use `sympy.core.evaluate(False)` context when creating the expression. Nuh.
5. Tune other parameters like `ratio`, `rational`, and play with other function like `expand`, `factor`, `collect`. Doesn’t work either.

EDIT: Wolfram alpha can do this.

I tried to look like the assumptions of `x` along with some expressions. It surprises me that `(x - 1) / 2).is_integer` returns None, which means unknown.

I’m running out of clues. I’m even looking for alternativese of sympy. Any ideas guys?

I fail to see why sympy can’t simplify that.

But, on another hand, I’ve discovered the existence of `odd` parameter just now, with your question.

What I would have done, without the knowledge of `odd` is

``````k = Symbol('k', positive=True, integer=True)
x = 2*k-1
expr = x // 2 - (x - 1) / 2
``````

Then, expr is 0, without even the need to simplify.
So, can’t say why you way doesn’t work (and why that `odd` parameter exists if it is not used correctly to guess that `x-1` is even, and therefore `(x-1)/2` integer). But, in the meantime, my way of defining an odd integer `x` works.

There is some reluctance to make too much automatic in SymPy, but this seems like a case that could be addressed (since `(x-1)/2` is simpler than `floor(x/2)`. Until then, however, you can run a replacement on your expression which makes this transformation for you.

Let’s define a preferred version of `floor`:

``````def _floor(x):
n, d = x.as_numer_denom()
if d == 2:
if n.is_odd:
return (n - 1)/2
if n.is_even:
return n/2
return floor(x)
``````

When you have an expression with `floor` that you want to evaluate, replace `floor` with `_floor`:

``````>>> x = Symbol('x', odd=True)
>>> eq=x // 2 - (x - 1) / 2
>>> eq.replace(floor, _floor)
0
``````
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.