SymPy – 24 – manipolazione avanzata di espressioni – 2

Continuo da qui, copio qui.

Ricorsione attraverso l’albero delle espressioni
Now that you know how expression trees work in SymPy, let’s look at how to dig our way through an expression tree. Every object in SymPy has two very important attributes, func, and args.

func is the head of the object. For example, (x*y).func is Mul. Usually it is the same as the class of the object (though there are exceptions to this rule).

Two notes about func. First, the class of an object need not be the same as the one used to create it. For example

We created Add(x, x), so we might expect expr.func to be Add, but instead we got Mul. Why is that? Let’s take a closer look at expr.

Add(x, x), i.e., x + x, was automatically converted into Mul(2, x), i.e., 2*x, which is a Mul. SymPy classes make heavy use of the __new__ class constructor, which, unlike __init__, allows a different class to be returned from the constructor.

Second, some classes are special-cased, usually for efficiency reasons [note 3].

Note 3: Classes like One and Zero are singletonized, meaning that only one object is ever created, no matter how many times the class is called. This is done for space efficiency, as these classes are very common. For example, Zero might occur very often in a sparse matrix represented densely. As we have seen, NegativeOne occurs any time we have -x or 1/x. It is also done for speed efficiency because singletonized objects can be compared by is. The unique objects for each singletonized class can be accessed from the S object.

For the most part, these issues will not bother us. The special classes Zero, One, NegativeOne, and so on are subclasses of Integer, so as long as you use isinstance, it will not be an issue.

args are the top-level arguments of the object. (x*y).args would be (x, y). Let’s look at some examples

From this, we can see that expr == Mul(3, y**2, x). In fact, we can see that we can completely reconstruct expr from its func and its args.

Note that although we entered 3*y**2*x, the args are (3, x, y**2). In a Mul, the Rational coefficient will come first in the args, but other than that, the order of everything else follows no special pattern. To be sure, though, there is an order.

Mul’s args are sorted, so that the same Mul will have the same args. But the sorting is based on some criteria designed to make the sorting unique and efficient that has no mathematical significance.

The srepr form of our expr is Mul(3, x, Pow(y, 2)). What if we want to get at the args of Pow(y, 2). Notice that the y**2 is in the third slot of expr.args, i.e., expr.args[2].

So to get the args of this, we call expr.args[2].args.

Now what if we try to go deeper. What are the args of y. Or 2. Let’s see.

They both have empty args. In SymPy, empty args signal that we have hit a leaf of the expression tree.

So there are two possibilities for a SymPy expression. Either it has empty args, in which case it is a leaf node in any expression tree, or it has args, in which case, it is a branch node of any expression tree. When it has args, it can be completely rebuilt from its func and its args. This is expressed in the key invariant.

Key invariant
Every well-formed SymPy expression must either have empty args or satisfy expr == expr.func(*expr.args).

(Recall that in Python if a is a tuple, then f(*a) means to call f with arguments from the elements of a, e.g., f(*(1, 2, 3)) is the same as f(1, 2, 3).)

This key invariant allows us to write simple algorithms that walk expression trees, change them, and rebuild them into new expressions. Tutto questo nel prossimo post.


Posta un commento o usa questo indirizzo per il trackback.



Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di

Stai commentando usando il tuo account Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: