FeynCalc / feyncalc

Mathematica package for algebraic calculations in elementary particle physics.
https://feyncalc.github.io
GNU General Public License v3.0
309 stars 87 forks source link

FCUseCache[] uses stale cache even after FCClearScalarProducts[] #151

Closed j824h closed 2 years ago

j824h commented 2 years ago

It is empty.

FCClearScalarProducts[]; DiracTrick[DiracGamma[Momentum[p2+p3]].DiracGamma[Momentum[p1]].DiracGamma[Momentum[p2+p3]]]

FCClearCache[FeynCalcPackageFCFastContract]; DiracTrick[DiracGamma[Momentum[p2+p3]].DiracGamma[Momentum[p1]].DiracGamma[Momentum[p2+p3]]]



After clearing the scalar products (2nd output), I would expect the evaluation should be free of the Pair DownValues `s2` or `s3`.
However, it seems I get the same result as the 1st output, not free of `s2` and `s3`.
Only after manually calling ```FCClearCache[FeynCalc`Package`FCFastContract]```, I get the fresh result I expect. (3rd output)

As documented in the definition of `FCUseCache[]`, `FCUseCache[]` should know that `Pair[]` DownValues were cleared, but apparently that is not happening, causing `DiracTrick[]` to give the unexpected result.
j824h commented 2 years ago

Additional information

Inspection of FeynCalc`CacheManagement`Private`cachedToString[]

https://github.com/FeynCalc/feyncalc/blob/596858b200f1770621911744a1d8f3c39b4a639c/FeynCalc/Shared/CacheManagement.m

Looking at the source code above, the dependency is filtered as https://github.com/FeynCalc/feyncalc/blob/596858b200f1770621911744a1d8f3c39b4a639c/FeynCalc/Shared/CacheManagement.m#L83 before included in the caching version. https://github.com/FeynCalc/feyncalc/blob/596858b200f1770621911744a1d8f3c39b4a639c/FeynCalc/Shared/CacheManagement.m#L98

What I note is that, due to HoldAll attribute: https://github.com/FeynCalc/feyncalc/blob/596858b200f1770621911744a1d8f3c39b4a639c/FeynCalc/Shared/CacheManagement.m#L51 the first evaluation of cachedToString[standardSet]: https://github.com/FeynCalc/feyncalc/blob/596858b200f1770621911744a1d8f3c39b4a639c/FeynCalc/Shared/CacheManagement.m#L109 sets the rule from cachedToString[standardSet] (standardSet as a symbol, not evalulated as the list) to the returned string of ToString[standardSet].

This could be confirmed by evaluating: DownValues[FeynCalc`CacheManagement`Private`cachedToString]

Later evaluations of cachedToString[standardSet], regardless of the value of standardSet, returns the same string as the first evaluation of cachedToString[standardSet] did. This seems to break the intended design that FCUseCache[] should reflect the current value of DownValues of Pair[], etc.

DiracTrick[] internal trace

In DiracTrick[], it could be traced where FCUseCache[] is called to retrieve the stale cache. https://github.com/FeynCalc/feyncalc/blob/596858b200f1770621911744a1d8f3c39b4a639c/FeynCalc/Dirac/DiracTrick.m#L792

Example directly using FCUseCache[]

exp=Pair[Momentum[p1],Momentum[p2+p3]];
f=ExpandScalarProduct;

SP[p1,p2]=s2;
SP[p1,p3]=s3;

FCUseCache[f,{exp},{}]
f[exp]
FCClearScalarProducts[];
FCUseCache[f,{exp},{}]
f[exp]
FCClearCache[f];
FCUseCache[f,{exp},{}]
f[exp]
FCClearCache[f];

Mathematica versions

I could reproduce with some other versions of Mathematica in the same system. 12.1.1 for Linux x86 (64-bit) (June 19, 2020) 12.3.0 for Linux x86 (64-bit) (May 10, 2021)

vsht commented 2 years ago

Thanks for the bug report.

Unfortunately, when cachedToString works as intended, the performance gain from memoization (especially for small expressions) is often lost and one can easily construct cases, where calling ToString thousands of times (inside FCUseCache) makes things slower than using no memoization at all.

Having thought about this in more details, I think that using the built-in Hash function should be the easiest solution. The theoretical risk of hash collisions is of course there, but given that, to my understanding, Mma also uses hashing internally

https://mathematica.stackexchange.com/questions/68954/default-behaviour-of-hashexpr-and-hashing-in-different-versions-of-mathematica https://stackoverflow.com/questions/4039538/what-is-the-default-hash-code-that-mathematica-uses

I don't think that it is realistic to encounter such a collision in a typical calculation.

Using Associations would be another possibility (also to cross check for hash collisions), but for that one would need to drop Mma 8 and Mma 9 support first. This will also occur, but probably for FC 11.

vsht commented 2 years ago

I added an extra check against hash collisions for Mma versions newer than 9, since key lookups for associations is super fast. This should be a good compromise between safety and performance.

vsht commented 2 years ago

Since there have been no further comments, I'm assuming that this issue is now fixed.