<table cellspacing="0" cellpadding="0" border="0" ><tr><td valign="top" style="font: inherit;">All,<br><br>I have written a class to solve the problem.&nbsp; I expect to post it here in the next day or two.&nbsp; Because I need to parse each expression anew every time it occurs, it is slow to generate printable C++ code, but it does work, and the code compiles and executes very fast.&nbsp; (Slow is relative, of course.&nbsp; On my problem, for which GiNaC generates 50MB of code, this new class takes 5 minutes.&nbsp; The result is about 700K of code.)<br><br>The parsing would be sped up significantly if there was a unique identifier for nodes in a GiNaC expression tree.&nbsp; Just to see how fast, I pretended ex::gethash() was unique.&nbsp; Run time was reduced from 5 minutes to well under 1 second.<br><br>Is there a method other than this list where I can request that a serial number be added to expression tree
 nodes?<br><br>Thanks,<br>Doug<br><br><br>Support NPR 20 seconds at a time.  www.twentysecondsatatime.org<br><br>--- On <b>Mon, 5/24/10, jros <i>&lt;jros@unavarra.es&gt;</i></b> wrote:<br><blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px;"><br>From: jros &lt;jros@unavarra.es&gt;<br>Subject: Re: [GiNaC-list] Term ordering and compiling C++ code<br>To: "GiNaC discussion list" &lt;ginac-list@ginac.de&gt;<br>Date: Monday, May 24, 2010, 2:17 AM<br><br><div id="yiv1134827212">


  
  
On Sat, 2010-05-22 at 23:19 +0200, Richard B. Kreckel wrote:
<blockquote type="CITE">
<pre>Hi!<br><br>jros wrote:<br>&gt; Although I don't have a solution for your problem, as I'm myself<br>&gt; addressing similar problems<br>&gt; matching common subexpressions to variables, in down top manner, I think<br>&gt; that such a functionality<br>&gt; is implicitly implemented in GiNaC.<br>&gt; <br>&gt; If I understand GiNaC internal structure correctly, subexpressions<br>&gt; common to two expresions,<br>&gt; are frequently  shared internally, to save memory.<br><br>This is entirely correct, but...<br><br>&gt; So it must be possible to write a print algorithm that goes trough<br>&gt; an/some expression/s tree, and that replaces<br>&gt; every shared subexpression (let say sum product) with a variable, that<br>&gt; again is assigned a expression that would be printed<br>&gt; in the same way using recursion.  <br><br>...first, this sharing is entirely transparent for the user...<br></pre>
</blockquote>
You mean that we can not look to the smart ptr of a expression, or some of <br>
its subexpressions like add and mul to see if there are referenced by more than one<br>
expression.<br>
<br>
The idea would be: if an element of a subexpression is referenced more than once we can<br>
call it atom, and printout (for C code) the expression using the atom (avoiding expansion of the subexpression),<br>
and also print atom definition (for C code).<br>
<br>
It would be nice to be able to print expresions in GiNaC to see th level of sharing that it is using.<br>
<br>
Is sharing also enforced when solving linear equations?. I think this is a really important place for optimization if done.
<blockquote type="CITE">
<pre>&gt; Probably allowing/disallowing some kind automatic simplifications (so<br>&gt; that subexpression sharing expected value increases) can probably help<br>&gt; to obtain improved results.<br><br>...and second, sharing is currently not pursued aggressively! Rather, it <br>is exploited whenever it is trivial to do so. (The product rule of <br>differentiation is an example where exactly the same terms pop up again <br>and again so exploiting sharing comes at no cost.)<br></pre>
</blockquote>
It would be nice if sharing aggressiveness could be changed at runtime. without affecting performance for<br>
at least for the level of aggressiveness of the actual implementation.<br>
<br>
In this example<br>
<br>
e1=a+b<br>
e2=a+b+c<br>
<br>
I suppose that no sharing is implied like e2=e1+c, that would be computationally expensive. But, if instead<br>
<br>
e2=e1+c<br>
<br>
then e1 is referenced by e2?? (I suppose yes).<br>
<br>
If this is the case I consider that the level of sharing is respectably good :) . I mean, just defining the<br>
expresions with care would give good results.<br>
<br>
The sharing of expressions when diff is really nice.<br>
<br>
If parenthesization is kept to a maximum (no expansions made if they are not needed), as I think is the case,<br>
the sharing structure is kept as long as possible, and that is very good also.<br>
<br>
So, in my opinion using, what I understand is, the current level of sharing, I mean no changes at all, would allow<br>
to print C output code in a very optimized way.<br>
<br>
<br>
<blockquote type="CITE">
<pre>&gt; I wonder what do the developers think about this.<br><br>Well, I think that if the size of generated code is so prohibitively <br>large and compiler CSE doesn't help you may be better off writing your <br>own algorithm collecting similar terms in an associative array. You <br>could then artificially introduce temporaries, in order to help the <br>compiler. This would boil down to a more aggressive variant of GiNaC's <br>subexpression sharing. What do you think?<br></pre>
</blockquote>
<br>
I suppose you refer to <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Associative_array">http://en.wikipedia.org/wiki/Associative_array</a> (I'm not familiar with this).<br>
What would be the "key" and the "value"??.<br>
<br>
I think that you propose to go beyond the level of sharing of GiNaC, trying to find common expresions that are not shared by GiNaC. Do you?<br>
<br>
So you start traversing the structure and you push in the Associative array whatever subexpression you find,<br>
the "key" will be the subexpression and the "value" a new defined symbol for the atom (and may be the number of references to this atom),&nbsp; then you substitute the subexpression in the expression with the new atom.<br>
If the subexpression&nbsp; was already in the array, then no new insertion is made and the subexpression is substituted for the matching atom (the value).<br>
<br>
I suppose that to push a subexpression, you first (recursively) apply recursively the previous recipe to it (so it gets atomized before pushing).<br>
<br>
I suppose that a important issue is to decide when a expression should be consider atomized, and I think that this is dependent of the internal structure of GiNaC, for example:<br>
<br>
If a - b *( c +d +e) *f is a expression.<br>
<br>
atom1= c + d + e<br>
<br>
atom2=-b*atom1*f<br>
<br>
atom3=a + atom2<br>
<br>
I suppose that after this, if the expression<br>
<br>
b *( c +d +e) *f<br>
<br>
is atomized, a new atom will appear<br>
<br>
atom4=b*atom1*f<br>
<br>
Instead of avoiding the creation of an atom having into account b *( c +d +e) *f=-atom2<br>
<br>
I suppose that this would need things like, inserting the subexpression, only if it or its negative are not in the array.<br>
<br>
Nevertheless it seems to me that sharing in GiNaC automatically deals with this (or almost).<br>
<br>
Fine grained atomization like,<br>
<br>
atom1=c+d<br>
atom2=atom1+e<br>
<br>
seems more difficult and inefficient to implement, due to the internal expression representation.<br>
<br>
In my particular implementation, each time a operation is done the result is atomized, and all the expresions are kept atomized.<br>
To that end I define the special type atom (descent of symbol), that have a pointer to my equivalent (although less optimal) implementation of the associative array.<br>
<br>
This special type allows things like implementing making diff print to work flawlessly with atomized expresions (as if they were not). As I dare not&nbsp; overloading all the GiNaC operators, I only overloading the operators of a matrix class in which all the operations that I need are made.<br>
<br>
This implementation (certainly improvable), is optimal in some senses (single representation, maximum sharing an minimum memory, low cost of atomization), nevertheless<br>
fine tunning needs a deep knowledge of the internals of GiNaC.<br>
<br>
Thank you very much,<br>
<br>
Javier<br>
<br>
<br>
<br>
<br>
<blockquote type="CITE">
<pre>Bye<br>   -richy.<br></pre>
</blockquote>
 
</div><br>-----Inline Attachment Follows-----<br><br><div class="plainMail">_______________________________________________<br>GiNaC-list mailing list<br><a ymailto="mailto:GiNaC-list@ginac.de" href="/mc/compose?to=GiNaC-list@ginac.de">GiNaC-list@ginac.de</a><br><a href="https://www.cebix.net/mailman/listinfo/ginac-list" target="_blank">https://www.cebix.net/mailman/listinfo/ginac-list</a><br></div></blockquote></td></tr></table><br>