Hi GPN,
Thanks for sharing your doubts and ideas. I found your solution very useful, and it inspired me to try a different approach.
My solutions uses the algorithm isolate from the library manip, so the notebook starts like:
import cdb.core.manip as manip
Then, I modify your approach (in particular the notation of the inverse, and taking care of the space between the operators A and G):
\partial{#}::PartialDerivative.
ex := \partial{A} + B + A (G**(-1) \partial{G}) + C.
sort_product(ex);
The algorithm sort_product will ensure the same order of the factors (the usefulness wuold be seen shortly.
Then, I define the contracted expression
contracted := G**(-1) \partial{(G A)};
and the expanded one. Following your idea, I manipulate the expanded expression and define a substitution rule
expanded := @(contracted);
product_rule(expanded)
distribute(expanded)
collect_factors(expanded)
sort_product(expanded)
contraction_rule := @(expanded) = @(contracted);
Note the appearance of sort_product again. Since the desired expression to substitute is not isolated on the left-hand-side of the substitution rule, we use isolate to isolate it:
manip.isolate(contraction_rule, $A \partial{G} G**(-1)$);
And finally we use the contraction_rule on the original expression ex:
substitute(ex, contraction_rule);
Hope you find this aproach useful!
Dox.