vermaseren / form

The FORM project for symbolic manipulation of very big expressions
GNU General Public License v3.0
982 stars 118 forks source link

Inside of firstbracket_ #312

Open pschicho opened 5 years ago

pschicho commented 5 years ago

It would be very convenient to not only get the outside of the first bracket. Which is currently possible with firstbracket_. Maybe one of you knows a work around for this? All I could think of was using the "collect" command after bracketing accordingly. But if one could get hold of this content of the first bracket simpler this would be very appreciated.

jodavies commented 5 years ago

If I understand correctly, something like

Symbol a,b,c,d;                         

Local test = a*b + a*c + d*b;           

Bracket b;                              
Print +s;                               
.sort                                   

Local test2 = test[firstbracket_(test)];

Print +s;                               
.end                                    

achieves this?

Thanks, Josh.

pschicho commented 5 years ago

Thanks Josh, this was big help! Solved almost all my problems. Is there a similar way to get something like lastterm analogous to fristterm?

tueda commented 5 years ago

If your problem is very simple such that everything is represented only by symbols, then changing the sort type does the job:

On lowfirst;  * default
S a,b,c,d;
L F = (1+a+b+c+d)^2;
P;
.sort

On highfirst;  * the reverse ordering
Skip;
L G = F;
.sort

On lowfirst;  * switch back to the default
Skip;
L F1 = firstterm_(F);  * first term
L G1 = firstterm_(G);  * last term
P;
.end
   F =
      1 + 2*d + d^2 + 2*c + 2*c*d + c^2 + 2*b + 2*b*d + 2*b*c + b^2 + 2*a + 2*
      a*d + 2*a*c + 2*a*b + a^2;

   F1 =
      1;

   G1 =
      a^2;
pschicho commented 5 years ago

Sorry I should have been more specific as polynomials of symbols can be treated via lowfirst and highfirst ordering. The simplest example of my problem are terms that have integer numbers as arguments. Here form orders them internally with increasing values over the arguments. One could potentially flip the signs and use firstterm_ again but for a large number of terms I thought that maybe this could be troublesome and maybe done simpler.

On lowfirst;
CF f;
L F = f(1,2,3,4,5) + f(5,4,3,2,1);
P;
.sort

On highfirst;  * the reverse ordering
Skip;
L G = F;
.sort

On lowfirst;  * switch back to the default
Skip;
L F1 = firstterm_(F);  * first term
L G1 = firstterm_(G);  * last term
P;
.end
   F =
      f(1,2,3,4,5) + f(5,4,3,2,1);

   F1 =
      f(1,2,3,4,5);

   G1 =
      f(1,2,3,4,5);
jodavies commented 5 years ago

Something with dollar variables also works

#-                                                      
CFunction f,g;                                          

Local test = f(1,2,3,4,5) + f(5,4,3,2,1) + f(3,2,1,4,5);
.sort                                                   

#$idx = -1;                                             
$idx = $idx + 1;                                        
Multiply g($idx);                                       
Bracket g;                                              
.sort                                                   

Local first = test[g(0)];                          
Local last = test[g(`$idx')];                          

Print +s;                                               
.end                                                    
tueda commented 5 years ago

Similar to Josh's answer, but only for the last term:

CF f;
L F = f(1,2,3,4,5) + f(5,4,3,2,1) + f(3,2,1,4,5);
P;
.sort

* Scan all terms.
Skip;
NSkip F;
#$last = 0;
$last = term_;
ModuleOption noparallel;
.sort

Skip;
L First = firstterm_(F);
L Last = $last;
P;
.end
   F =
      f(1,2,3,4,5) + f(3,2,1,4,5) + f(5,4,3,2,1);

   First =
      f(1,2,3,4,5);

   Last =
      f(5,4,3,2,1);
vermaseren commented 5 years ago

Things like ‘lastterm’ or ‘lastbracket’ are rather complicated to obtain in a direct way. A Form expression is a sequence of terms of which in principle only a pointer to the first term is available. To get at the last term one has to traverse the whole expression. This is essentially what the last solution of Takahiro does.

It is of course possible to store in the datastruct for expressions the offset of the last term when this term is written, but that is way too specific programming, at the same time carrying an overhead. Hence such a thing would only be done if several important algorithms were to be sped up considerably by it. This I do not see currently.

I hope this clarifies things a bit.

Jos

On 27 Mar 2019, at 09:54, Takahiro Ueda notifications@github.com wrote:

Similar to Josh's answer, but only for the last term:

CF f; L F = f(1,2,3,4,5) + f(5,4,3,2,1) + f(3,2,1,4,5); P; .sort

  • Scan all terms. Skip; NSkip F;

    $last = 0;

    $last = term_; ModuleOption noparallel; .sort

Skip; L First = firstterm_(F); L Last = $last; P; .end F = f(1,2,3,4,5) + f(3,2,1,4,5) + f(5,4,3,2,1);

First = f(1,2,3,4,5);

Last = f(5,4,3,2,1); — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/vermaseren/form/issues/312#issuecomment-477044870, or mute the thread https://github.com/notifications/unsubscribe-auth/AFLxEh4EP1XOn9Zdms1ZPZh7Y30qGsaoks5vazHIgaJpZM4cLs-O.

pschicho commented 5 years ago

Thanks for the prompt and very thorough answers. A sweep over all terms seemed unavoidable but works quite well with dollars. This will perfectly do.

Thanks, Philipp