Difference between f.is_number and bool(f.free_symbols)

55 views
Skip to first unread message

Paul Royik

unread,
Sep 13, 2021, 12:56:23 AM9/13/21
to sympy
Are there any cases when f.is_number != (not bool(f.free_symbols))?

If I have an arbitrary expression, what is the correct way to check whether it has variables?

Thank you.

Chris Smith

unread,
Sep 13, 2021, 8:00:15 AM9/13/21
to sympy
To confirm, if you mean that it is free from any Symbol (free or bound) then `not expr.has(Symbol)` will be best. But if you consider `Integral(x, (x, 1, 2))` as a number then you should use `is_number` or `free_symbols`, with `expr.is_number` failing sooner than `not expr.free_symbols` if the expression has a free symbol.  (So if you suspect the expression has free symbols then use `is_number`, else `free_symbols`).

`f.is_number != (not bool(f.free_symbols))` should be an invariant for Expr, but SymPy also deals with Booleans, so `S.true.is_number` is False and `S.true.free_symbols` is empty.

/c

Oscar Benjamin

unread,
Sep 13, 2021, 8:56:47 AM9/13/21
to sympy
Think about things that are literally not numbers:

In [9]: Interval(1, 2).is_number
Out[9]: False

In [10]: ImmutableMatrix([[1, 2], [3, 4]]).is_number
Out[10]: False


--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/9af46205-ce22-494c-a604-c27b6682fa96n%40googlegroups.com.

Paul Royik

unread,
Sep 13, 2021, 12:21:23 PM9/13/21
to sympy
Thanks to everybody!

Aaron Meurer

unread,
Sep 13, 2021, 1:10:50 PM9/13/21
to sympy
is_number means "can be evalf'ed". So for example, we have the following

>>> f = Function('f')
>>> f(0).is_number
False
>>> f(0).free_symbols
set()

So you should use is_number specifically if you are checking if you
can evaluate the expression to a literal number.

Aaron Meurer
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/8717be3c-0286-4741-900c-94e21573f3c5n%40googlegroups.com.

Chris Smith

unread,
Sep 13, 2021, 1:48:36 PM9/13/21
to sympy
> can be evalf'ed

That's a clear and good reminder.

/c

Aaron Meurer

unread,
Sep 13, 2021, 1:56:57 PM9/13/21
to sympy
This would be a good thing to have some standalone documentation on.
There are also some related things like the functionality that is used
by diff() to determine what can be used as a differentiation variable,
which is a little more complex than just free_symbols in general
because you can have things like derivatives with respect to indexed
expressions.

Aaron Meurer
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/69d8097b-b81b-4490-ae85-0dbb946346c1n%40googlegroups.com.

Oscar Benjamin

unread,
Sep 13, 2021, 2:14:36 PM9/13/21
to sympy
There is also is_Number vs is_number. There is also is_comparable which means can be evalf'd to a real number.

There should be a glossary of all the different attributes that are used throughout sympy:

In [1]: for name in dir(x):

   ...:     if name.startswith('is'):

   ...:         print(name)

   ...: 

is_Add

is_AlgebraicNumber

is_Atom

is_Boolean

is_Derivative

is_Dummy

is_Equality

is_Float

is_Function

is_Indexed

is_Integer

is_MatAdd

is_MatMul

is_Matrix

is_Mul

is_Not

is_Number

is_NumberSymbol

is_Order

is_Piecewise

is_Point

is_Poly

is_Pow

is_Rational

is_Relational

is_Symbol

is_Vector

is_Wild

is_algebraic

is_algebraic_expr

is_antihermitian

is_commutative

is_comparable

is_complex

is_composite

is_constant

is_even

is_extended_negative

is_extended_nonnegative

is_extended_nonpositive

is_extended_nonzero

is_extended_positive

is_extended_real

is_finite

is_hermitian

is_hypergeometric

is_imaginary

is_infinite

is_integer

is_irrational

is_meromorphic

is_negative

is_noninteger

is_nonnegative

is_nonpositive

is_nonzero

is_number

is_odd

is_polar

is_polynomial

is_positive

is_prime

is_rational

is_rational_function

is_real

is_scalar

is_symbol

is_transcendental

is_zero



Aaron Meurer

unread,
Sep 13, 2021, 2:22:38 PM9/13/21
to sympy
A glossary would be a great idea.

By the way, I am going to start writing a lot of documentation in
SymPy soon (see https://groups.google.com/g/sympy/c/vYsavewGj1w). If
anyone has things in SymPy that they wish were documented better,
particularly the sorts of things that would go in high-level
explanations and how-to guides, please reach out to me. We will likely
be running some sort of survey for the same so watch this space for
more information in the coming months.

On Mon, Sep 13, 2021 at 12:14 PM Oscar Benjamin
<oscar.j....@gmail.com> wrote:
>
> There is also is_Number vs is_number. There is also is_comparable which means can be evalf'd to a real number.

As an aside, I really wish we didn't have the is_Uppercase attributes.
They were implemented as a performance hack because attribute lookups
are slightly faster than isinstance(). But the cost they have had in
terms of user confusion greatly outweighs any performance gain they
have produced. We should consider deprecating them, or at the very
least, banning the creation of new ones on new classes. I think it's
also unfortunate that we have is_ methods that aren't actually part of
the assumptions system. But that's just something we'll just have to
document and live with.

Aaron Meurer
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CAHVvXxQeJ8eOdCpSKsiAXPjZKrd_jS2WRmfLdZS_Drjm377L5g%40mail.gmail.com.

Chris Smith

unread,
Sep 13, 2021, 8:40:12 PM9/13/21
to sympy
The varieties of `is_lowercase` don't bother me as much: some are easy to compute independently (like `is_number`) whereas others are more complicated and depend on other attributes (like `is_real`).

/c

Aaron Meurer

unread,
Sep 14, 2021, 3:49:16 PM9/14/21
to sympy
The problem is that is_lowercase looks like the assumptions system. So
people might become confused when the assumptions APIs don't actually
work. For instance

>>> Symbol('x', number=True).is_number
False

At least is_polynomial and is_rational_function are functions.

I think the fix here is to make the above emit a warning (see
https://github.com/sympy/sympy/pull/21417#issuecomment-856001694). And
everything should be documented as well.

Aaron Meurer
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/50f5774b-7835-470c-8a08-57617910ec4en%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages