Skip to content

Commit

Permalink
Replaced ToString-based caching function with the
Browse files Browse the repository at this point in the history
standard Hash (thanks to J. Park aka j824h for reporting
issue #151)
  • Loading branch information
vsht committed Feb 12, 2022
1 parent d5daa37 commit 5b0d820
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 38 deletions.
97 changes: 60 additions & 37 deletions FeynCalc/Shared/CacheManagement.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,67 +6,76 @@

(*
This software is covered by the GNU General Public License 3.
Copyright (C) 1990-2020 Rolf Mertig
Copyright (C) 1997-2020 Frederik Orellana
Copyright (C) 2014-2020 Vladyslav Shtabovenko
Copyright (C) 1990-2021 Rolf Mertig
Copyright (C) 1997-2021 Frederik Orellana
Copyright (C) 2014-2021 Vladyslav Shtabovenko
*)

(* :Summary: Functions for managing memoization in FeynCalc *)

(* ------------------------------------------------------------------------ *)

FCUseCache::usage=
"FCUseCache[func,{arg1,...},{opt1...}] evaluates \
func[arg1,...,opt1,...] and caches the result such that the \
next evaluation of same expressions occurs almost immediately. \
This caching also takes into account DownValues and global variables \
that enter into evaluation of func. For example, ExpandScalarProduct \
can't be naively cached, because it's result depends on the DownValues \
of Pair and ScalarProduct, which may be changed multiple times during \
the session by setting and erasing values of scalar products. With \
FCUseCache, however, caching will work properly, as FCUseCache knows \
the dependence on ExpandScalarProduct on those DownValues. \
\
For all this to work, a function should be explicitly whitelisted in FCUseCache.";
"FCUseCache[func,{arg1,...},{opt1...}] evaluates func[arg1,...,opt1,...] and
caches the result such that the next evaluation of same expressions occurs
almost immediately. This caching also takes into account DownValues and global
variables that enter into evaluation of func.
For example, ExpandScalarProduct can't be naively cached, because its result
depends on the DownValues of Pair and ScalarProduct, which may be changed
multiple times during the session by setting and erasing values of scalar
products. With FCUseCache, however, caching will work properly, as FCUseCache
knows the dependence on ExpandScalarProduct on those DownValues. For all this
to work, a function should be explicitly white-listed in FCUseCache.";

FCShowCache::usage =
"FCShowCache[func] shows existing cached values for the function func, that \
were introduced by FCUseCache";
"FCShowCache[func] shows existing cached values for the function func, that
were introduced by FCUseCache.";

FCClearCache::usage =
"FCClearCache[func] removes existing cached values for the function func, that \
were introduced by FCUseCache";
"FCClearCache[func] removes existing cached values for the function func that
were introduced by FCUseCache.
To remove all existing cache values use FCClearCache[All].";

FCUseCache::blacklist=
"The function `1` is not whitelisted for FCUseCache. Evaluation aborted!"
"The function `1` is not whitelisted for FCUseCache. Evaluation aborted!";

FCUseCache::fail=
"Error! FCUseCache has encountered a fatal problem and must abort the computation. \
The problem reads: `1`";


Begin["`Package`"]
Begin["`Package`"];
End[]
(* ------------------------------------------------------------------------ *)

Begin["`CacheManagement`Private`"]


SetAttributes[cachedToString, HoldAll]

Begin["`CacheManagement`Private`"];

whiteListNames = {
ExpandScalarProduct,
PairContract,
FCFastContract,
FeynCalc`NPointTo4Point`Private`getDet,
FeynCalc`SimplifyPolyLog`Private`simplifyArgument,
FeynCalc`FCApart`Private`pfracRaw
FeynCalc`FCApart`Private`pfracRaw,
FeynCalc`Package`momentumRoutingDenner
};

standardSetAssociation = {};

If[ $VersionNumber >= 10. ,
standardSetAssociation = Association[{}];
];

FCUseCache[fcFunc_, args_List, opts_List: {}] :=
Block[{fullOpts, cachedHead,depArgs, standardSet},
Block[{fullOpts, cachedHead,depArgs, standardSet, savedStandardSet},
fullOpts = Sort[Flatten[Join[opts, FilterRules[Options[fcFunc], Except[opts]]]]];
cachedHead=ToExpression["cacheFunc"<>ToString[fcFunc]];

If[ MemberQ[whiteListNames,fcFunc],
cachedHead[arg_, cargs_String, ops_] :=

cachedHead[arg_, cargs_, ops_] :=
MemSet[cachedHead[arg, cargs, ops], fcFunc[Sequence @@ arg, ops]],
Message[FCUseCache::blacklist,fcFunc];
Abort[]
Expand All @@ -80,21 +89,35 @@

Which[
fcFunc === ExpandScalarProduct,
depArgs = cachedToString[standardSet],
depArgs = Hash[standardSet],
fcFunc === PairContract,
depArgs = cachedToString[standardSet],
depArgs = Hash[standardSet],
fcFunc === FCFastContract,
depArgs = cachedToString[standardSet],
depArgs = Hash[standardSet],
fcFunc === FeynCalc`NPointTo4Point`Private`getDet,
depArgs = cachedToString[standardSet],
depArgs = Hash[standardSet],
fcFunc === FeynCalc`SimplifyPolyLog`Private`simplifyArgument,
depArgs = cachedToString[standardSet],
depArgs = Hash[standardSet],
fcFunc === FeynCalc`FCApart`Private`pfracRaw,
depArgs = cachedToString[standardSet],
depArgs = Hash[standardSet],
fcFunc === FeynCalc`Package`momentumRoutingDenner,
depArgs = Hash[standardSet],
True,
Message[FCUseCache::blacklist,fcFunc];
Abort[]
];

If[ $VersionNumber >= 10. ,
savedStandardSet = Key[depArgs][standardSetAssociation];
If[ MissingQ[savedStandardSet],
standardSetAssociation = Append[standardSetAssociation,{depArgs -> standardSet}],
If[ savedStandardSet=!=standardSet,
Message[FCUseCache::fail,"Hash collision detected."];
Abort[]
];
];
];

cachedHead[args,depArgs,fullOpts]
];

Expand All @@ -105,8 +128,8 @@
With[{i = ToExpression["cacheFunc" <> ToString[fcFunc]]},DownValues[i] = {};];


cachedToString[x_] :=
cachedToString[x] = ToString[x];
FCClearCache[All]:=
FCClearCache /@ whiteListNames;


FCPrint[1,"CacheManagement.m loaded"];
Expand Down
11 changes: 10 additions & 1 deletion Tests/Dirac/DiracTrick.test
Original file line number Diff line number Diff line change
Expand Up @@ -1129,7 +1129,16 @@ Momentum[p1, D], 0, 1] + Spinor[Momentum[p3, D], m, 1].GAD[Lor4].GSD[p3].GAD[Lor
{"fcstDiracTrickCoreProperties-ID122",
"FCSetDiracGammaScheme[\"NDR\"]\n DiracTrick[GAD[mu].(cc1 + cc2 GA[5]).(GSD[p] + m).GAD[rho], FCE -> True]", "cc1 GAD[mu].(m + GSD[p]).GAD[rho] + cc2 GAD[mu].(-m + GSD[p]).GAD[rho].GA[5]"},
{"fcstDiracTrickCoreProperties-ID123",
"DiracTrick[GAD[mu].DiracGamma[ExplicitLorentzIndex[i, D], D].GAD[mu]]", "(2 - D) DiracGamma[ExplicitLorentzIndex[i, D], D]"}
"DiracTrick[GAD[mu].DiracGamma[ExplicitLorentzIndex[i, D], D].GAD[mu]]", "(2 - D) DiracGamma[ExplicitLorentzIndex[i, D], D]"},
{"fcstDiracTrickCoreProperties-ID124",
"FCClearScalarProducts[]; SP[p1, p2] = s2;
SP[p1, p3] = s3; DiracTrick[
DiracGamma[Momentum[p2 + p3]] . DiracGamma[Momentum[p1]] .
DiracGamma[Momentum[p2 + p3]], FCE -> True]", "2*(s2 + s3)*GS[p2 + p3] - GS[p1]*(SP[p2, p2] + 2*SP[p2, p3] + SP[p3, p3])"},
{"fcstDiracTrickCoreProperties-ID125",
"FCClearScalarProducts[]; DiracTrick[
DiracGamma[Momentum[p2 + p3]] . DiracGamma[Momentum[p1]] .
DiracGamma[Momentum[p2 + p3]], FCE -> True]", "2*GS[p2 + p3]*SP[p1, p2 + p3] - GS[p1]*(SP[p2, p2] + 2*SP[p2, p3] + SP[p3, p3])"}
});

Tests`Dirac`fcstDiracTrick = {
Expand Down

0 comments on commit 5b0d820

Please sign in to comment.