vermaseren / form

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

Broken topologies_ #474

Open tueda opened 4 months ago

tueda commented 4 months ago

The 5.0.0-beta reference manual says

In version 4.3 there existed also the topologies_ and the phi_ functions to just generate topologies. This was before a complete implementation was made. For backward compatibility we have kept these functions, ...

but this is not the case and the test cases Diagrams_1, ..., Diagrams_4 in check/example.frm fail. For example, Diagrams_1 is

Vectors Q1,Q2,p1,...,p8;
Set QQ:Q1,Q2;
Set PP:p1,...,p8;
#define LOOPS "2"
Local F = topologies_(`LOOPS',2,{3,},QQ,PP);
Print +f +s;
.end

and should give, as in the manual,

   F =
       + node_(0,-Q1)*node_(1,-Q2)*node_(2,Q1,-p1,-p2)*node_(3,Q2,p1,-p3)*
      node_(4,p2,-p4,-p5)*node_(5,p3,p4,p5)
       + node_(0,-Q1)*node_(1,-Q2)*node_(2,Q1,-p1,-p2)*node_(3,p1,-p3,-p4)*
      node_(4,p2,p3,-p5)*node_(5,Q2,p4,p5)
      ;

but it suffers from memory bugs:

==465138== Conditional jump or move depends on uninitialised value(s)
==465138==    at 0x142CDF: ProcessTopology(EGraph*, void*) (diawrap.cc:537)
==465138==    by 0x174419: MGraph::newGraph(MNodeClass*) (grcc.cc:4883)
==465138==    by 0x174575: MGraph::connectClass(MNodeClass*) (grcc.cc:4524)
==465138==    by 0x17476B: MGraph::connectNode(int, int, MNodeClass*) (grcc.cc:4543)
==465138==    by 0x1747F8: MGraph::connectLeg(int, int, int, int, MNodeClass*) (grcc.cc:4591)
==465138==    by 0x17475E: MGraph::connectNode(int, int, MNodeClass*) (grcc.cc:4552)
==465138==    by 0x1747F8: MGraph::connectLeg(int, int, int, int, MNodeClass*) (grcc.cc:4591)
==465138==    by 0x174B3D: MGraph::connectLeg(int, int, int, int, MNodeClass*) (grcc.cc:4715)
==465138==    by 0x17475E: MGraph::connectNode(int, int, MNodeClass*) (grcc.cc:4552)
==465138==    by 0x1745A7: MGraph::connectClass(MNodeClass*) (grcc.cc:4528)
==465138==    by 0x17476B: MGraph::connectNode(int, int, MNodeClass*) (grcc.cc:4543)
==465138==    by 0x1747F8: MGraph::connectLeg(int, int, int, int, MNodeClass*) (grcc.cc:4591)
==465138==
==465138== Use of uninitialised value of size 8
==465138==    at 0x142D2C: ProcessTopology(EGraph*, void*) (diawrap.cc:543)
==465138==    by 0x174419: MGraph::newGraph(MNodeClass*) (grcc.cc:4883)
==465138==    by 0x174575: MGraph::connectClass(MNodeClass*) (grcc.cc:4524)
==465138==    by 0x17476B: MGraph::connectNode(int, int, MNodeClass*) (grcc.cc:4543)
==465138==    by 0x1747F8: MGraph::connectLeg(int, int, int, int, MNodeClass*) (grcc.cc:4591)
==465138==    by 0x17475E: MGraph::connectNode(int, int, MNodeClass*) (grcc.cc:4552)
==465138==    by 0x1747F8: MGraph::connectLeg(int, int, int, int, MNodeClass*) (grcc.cc:4591)
==465138==    by 0x174B3D: MGraph::connectLeg(int, int, int, int, MNodeClass*) (grcc.cc:4715)
==465138==    by 0x17475E: MGraph::connectNode(int, int, MNodeClass*) (grcc.cc:4552)
==465138==    by 0x1745A7: MGraph::connectClass(MNodeClass*) (grcc.cc:4528)
==465138==    by 0x17476B: MGraph::connectNode(int, int, MNodeClass*) (grcc.cc:4543)
==465138==    by 0x1747F8: MGraph::connectLeg(int, int, int, int, MNodeClass*) (grcc.cc:4591)
==465138==
==465138== Invalid read of size 4
==465138==    at 0x142D30: ProcessTopology(EGraph*, void*) (diawrap.cc:543)
==465138==    by 0x174419: MGraph::newGraph(MNodeClass*) (grcc.cc:4883)
==465138==    by 0x174575: MGraph::connectClass(MNodeClass*) (grcc.cc:4524)
==465138==    by 0x17476B: MGraph::connectNode(int, int, MNodeClass*) (grcc.cc:4543)
==465138==    by 0x1747F8: MGraph::connectLeg(int, int, int, int, MNodeClass*) (grcc.cc:4591)
==465138==    by 0x17475E: MGraph::connectNode(int, int, MNodeClass*) (grcc.cc:4552)
==465138==    by 0x1747F8: MGraph::connectLeg(int, int, int, int, MNodeClass*) (grcc.cc:4591)
==465138==    by 0x174B3D: MGraph::connectLeg(int, int, int, int, MNodeClass*) (grcc.cc:4715)
==465138==    by 0x17475E: MGraph::connectNode(int, int, MNodeClass*) (grcc.cc:4552)
==465138==    by 0x1745A7: MGraph::connectClass(MNodeClass*) (grcc.cc:4528)
==465138==    by 0x17476B: MGraph::connectNode(int, int, MNodeClass*) (grcc.cc:4543)
==465138==    by 0x1747F8: MGraph::connectLeg(int, int, int, int, MNodeClass*) (grcc.cc:4591)
==465138==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==465138==
jodavies commented 3 months ago

https://github.com/jodavies/form/commit/b356d5fcf681aca635cd9f2d1c9cae9daf35ab30

This sorts out the valgrind error, but that is not the cause of the test errors.

To me that looks like a change of convention (adding topo_ functions for enumeration) but also a bug: I would not expect the factor of 1/4.

jodavies commented 3 months ago

To remove the coefficients, you only need to comment out the symmetry factor code at the end of ProcessTopology. Probably this was just a copy-and-paste from ProcessDiagram and this bit was not removed. Commenting the "Topology counter" lines removes the topo_ tags (but here someone needs to decide if this should stay, and lose true backward compatibility with 4.3.1).

Then the only difference with the test output I think, is the node numbers start at 1 instead of 0.

jodavies commented 3 months ago

Diagrams_3 fails for a different reason. There it crashes in the print routine because it gets bad input:

#0  0x0000555555591c89 in FindVector (num=800000213) at dict.c:293
#1  0x0000555555668ac7 in WriteArgument (t=t@entry=0x7fffede60130) at sch.c:1485
#2  0x000055555566b309 in WriteSubTerm (sterm=sterm@entry=0x7fffede6010c, first=<optimised out>, first@entry=0) at sch.c:1941
#3  0x000055555566b7c6 in WriteInnerTerm (term=<optimised out>, first=0) at sch.c:2130

In the failing term, there is a -10 (MINVECTOR) followed by 3, so FindVector tries to access the names array at 3-AM.OffsetVector which is 800000213.

jodavies commented 3 months ago

Diagrams_3 fails for a different reason. There it crashes in the print routine because it gets bad input:

#0  0x0000555555591c89 in FindVector (num=800000213) at dict.c:293
#1  0x0000555555668ac7 in WriteArgument (t=t@entry=0x7fffede60130) at sch.c:1485
#2  0x000055555566b309 in WriteSubTerm (sterm=sterm@entry=0x7fffede6010c, first=<optimised out>, first@entry=0) at sch.c:1941
#3  0x000055555566b7c6 in WriteInnerTerm (term=<optimised out>, first=0) at sch.c:2130

In the failing term, there is a -10 (MINVECTOR) followed by 3, so FindVector tries to access the names array at 3-AM.OffsetVector which is 800000213.

The problem here is that not enough external vectors are defined. Here https://github.com/vermaseren/form/blob/9637b9a8ba584fa9b10fef38b0939972e13357f6/sources/diawrap.cc#L568 it tries to access (for "Diagrams_3") the 9th element (at index 8) of the set, which only has 8 elements. So it lands on the "3" of the implicitly declared {3,4} set (if you swap this to {4,3} you get 4 back).

So somewhere needs to be a proper check of the number of internal lines, against the size of the set.

But the more major issue is that the number of topologies returned doesn't agree with the manual. There it claims there should be 9 topologies (or 8 in the case of external line symmetry). Now we get 6 in both cases.

jodavies commented 2 weeks ago

Even if the plan is to now remove the topologies_ function, we still need a good set of tests for diagrams_. To that end I started with something simple: comparing the number of diagrams generated by qgraf and FORM for a simple phi3 model. Already for a 1-loop propagator, there is a difference that I don't understand: qgraf generates two diagrams with its "default" options: the 1l propagator, and a tadpole. FORM does not generate the tadpole, though I do not specify NoTadpoles_.

If I tell both qgraf and form not to generate tadpoles, then the diagram counts agree.