<<TeXUtilities`

Get[NotebookDirectory[]<>"dan_procedure.m"];

(*TeX Formatting*)Format[a[i_],TraditionalForm]:=Subscript[a,i]
Format[Inf,TeXForm]:=TeXCommand["infty"]

myFold[f_,l_List]:=Fold[f,l[[1]],l[[2;;All]]]

myTeXList[l_List]:=TeXForm[TeXVerbatim[myFold[#1<>", "<>#2&,ToString[TeXForm[#]]&/@l]]]

Format[cri[l_List],TeXForm]:=TeXVerbatim[myFold[#1<>" "<>#2&,ToString[TeXForm[#]]&/@l]]

Format[IIi[inds_List,args_List],TeXForm]:=TeXVerbatim["I_{"<>ToString[myTeXList[inds]]<>"}("<>ToString[myTeXList[args]]<>")"]

Format[H[a0_,alist_List,x_,alast_],TeXForm]:=TeXVerbatim["H("<>ToString[TeXForm[a0]]<>" \\mid "<>ToString[myTeXList[alist]]<>" \\dblslash "<>ToString[TeXForm[x]]<>" \\mid "<>ToString[TeXForm[alast]]<>")"];

(*manipulate and LaTeX results*)

gatherIntegrals[expr_]:=((If[Head[expr]===Plus,List@@expr,{expr}])//GatherBy[#,indices[#]&]&)//Reverse;
gatherIntegrals[expr_,function_]:=((If[Head[expr]===Plus,List@@expr,{expr}])//GatherBy[#,function]&)//Reverse;

countIntegrals[expr_]:=({Length[#],#}&/@expr)//ColumnForm//Print

texCountIntegrals[expr_]:="Integral & Number in expression"<>Fold[#1<>" \\\\ \n"<>#2&,"",{"$ I_"<>ToString[indices[#[[1]]]]<>" $ & "<>ToString[Length[#]]}&/@expr]<>" \\\\ \nTotal & "<>ToString[Total[Length/@expr]];

texCountIntegrals[expr_,function_]:="Type & Number in expression"<>Fold[#1<>" \\\\ \n"<>#2&,"",{Fold[#1<>" "<>#2&,ToString/@function[#[[1]]]]<>" $ & "<>ToString[Length[#]]}&/@expr]<>" \\\\ \nTotal & "<>ToString[Total[Length/@expr]];

texIntegralsSingleLine[expr_]:="I_{"<>StringCases[#,"I_{"~~index:Shortest[___]~~"}":>index][[1]]<>"}( "<>StringReplace[#,{"I_{"~~Shortest[___]~~"}"->"","("->"[",")"->"]"}]<>" )"&@(StringReplace[expr,{")-"->") \n - ",")+"->") \n + "}]);

texJoinIntegrals[expr_]:=Fold[#1<>" + {} \\\\ \n & {} + "<>#2&,expr]

texIntegralsWithFracGath[expr_]:=texJoinIntegrals[texIntegralsSingleLine/@ToString/@TeXForm/@(expr/.{Rational[a_,b_]:>Sign[a/b] HoldForm[Evaluate[Abs[Divide[a,b]]]]})]
texIntegralsWithFrac[expr_]:=texIntegralsWithFracGath[Total/@gatherIntegrals[expr]];

texIntegralsGath[expr_List]:=texJoinIntegrals[texIntegralsSingleLine/@ToString/@TeXForm/@(expr)]
texIntegralsGath[expr_List,scaling_]:=texJoinIntegrals[(If[#[[2]]≠1,ToString[TeXForm[1/#[[2]]]]<>" ",""]<>#[[1]])&/@MapThread[List,{texIntegralsSingleLine/@ToString/@TeXForm/@(scaling*expr//Expand),scaling}]]

texIntegralsByCoeff[expr_]:=Block[{gath=gatherIntegrals[expr,{indices[#],denominator[#]}&]},texIntegralsGath[Total/@gath,denominator/@gath[[All,1]]]];
texIntegrals[expr_]:=Block[{gath=gatherIntegrals[expr]},texIntegralsGath[Total/@gath]];

(*Using a pattern to make a pattern not a pattern!?*)
lhsRule[RuleDelayed[lhs_,rhs_]]:=lhs/.HoldPattern[w_Pattern]:>w[[1]]
rhsRule[RuleDelayed[lhs_,rhs_]]:=Expand[rhs]

ruleToIdentity[expr_]:=lhsRule[expr]-rhsRule[expr]//Expand;

texRule[expr_]:=Block[{gath=gatherIntegrals[Expand@rhsRule[expr]]},ToString[TeXForm[lhsRule[expr]]]<>" & {} = "<>texIntegralsGath[Total/@gath]];
texRuleWithFrac[expr_]:=Block[{gath=gatherIntegrals[Expand@rhsRule[expr]]},ToString[TeXForm[lhsRule[expr]]]<>" & {} = "<>texIntegralsWithFracGath[Total/@gath]];
texRuleByCoeff[expr_]:=Block[{gath=gatherIntegrals[Expand@rhsRule[expr],{indices[#],denominator[#]}&]},ToString[TeXForm[lhsRule[expr]]]<>" & {} = "<>texIntegralsGath[Total/@gath,denominator/@gath[[All,1]]]];
texRuleByCR[expr_]:=Block[{gath=Reverse@gatherIntegrals[Expand@rhsRule[expr],{indices[#],denominator[#],args[#]//Length,(Union@@(args[#][[All,1]]))//Length}&]},ToString[TeXForm[lhsRule[expr]]]<>" & {} = "<>texIntegralsGath[Total/@gath,denominator/@gath[[All,1]]]];

(* Load precomputed results to check later *)
Get[NotebookDirectory[]<>"wt4_dan_precomputed.m"];

(* ------ *)

wt4VarsToABC = {a[i_]:>{a,b,c,d,e,f}[[i+1]], x->Inf};
canonicalCR = {cri[{a_,b_,c_,d_}]:>cri[crOrbit[{a,b,c,d}]]};

in4Dan = Asymb[4,1,2]/.wt4VarsToABC//TeXForm

in4Polylog = iToCcr@hToI@hCrSimp[Asymb[4,1,2]]/.wt4VarsToABC;
%//TeXForm

out4AllN = iToCcr@hToI@hCrSimp@Expand@reduceAll[4]/.wt4VarsToABC//Expand;

out4AllNLower = Select[out4AllN, Position[#, a]≠{}&]/.canonicalCR;

out4AllN - (out4AllNLower - (out4AllNLower/.a->f))/.canonicalCR//Expand

wt4DanAllNPrecomputed == (in4Polylog - (out4AllNLower - (out4AllNLower/.a->f))/.{a->0,f->1}/.canonicalCR//Expand)

out4AllNLowerGathered = gatherIntegrals[out4AllNLower];

countIntegrals[out4AllNLowerGathered]

texCountIntegrals[out4AllNLowerGathered]

texIntegrals[2*out4AllNLower//Expand]

texIntegralsByCoeff[out4AllNLower//Expand]

texIntegralsWithFrac[out4AllNLower//Expand]

(* Now we use some identities to write everything in terms of I31 and I4 *)

Get[NotebookDirectory[]<>"wt4_rules_to_i31_i4.m"];

texRuleByCoeff[rule13to31]

texRuleByCoeff[rule22to13and31]

texRuleByCoeff[rule31to22]

(* Apply these rules to write I11111 as I311, I32 and I5 *)

out4AllNLoweras31and4= out4AllNLower/.rule22to13and31/.rule13to31/.canonicalCR//Expand;

wt4DanAllNLoweras31and4Precomputed == out4AllNLoweras31and4

out4AllNLoweras31and4gathered = gatherIntegrals[out4AllNLoweras31and4];

Length[out4AllNLoweras31and4]

wt4DanAllNas31and4Precomputed  == (in4Polylog - (out4AllNLoweras31and4 - (out4AllNLoweras31and4/.a->f))/.{a->0,f->1}/.canonicalCR//Expand)

countIntegrals[out4AllNLoweras31and4gathered]

texCountIntegrals[out4AllNLoweras31and4gathered]

texIntegralsByCoeff[2*out4AllNLoweras31and4//Expand]

(* convert to I22 and I4 *)

Get[NotebookDirectory[]<>"wt4_rules_to_i31_i4.m"];

texRuleByCoeff[rule13to31]

texRuleByCoeff[rule22to13and31]

texRuleByCoeff[rule31to22]

(* Apply these rules to write I11111 as I311, I32 and I5 *)

out4AllNLoweras22and4= out4AllNLower/.rule22to13and31/.rule13to31/.rule31to22/.canonicalCR//Expand;

out4AllNLoweras22and4gathered = gatherIntegrals[out4AllNLoweras22and4];

Length[out4AllNLoweras22and4]

wt4DanAllNas22and4Precomputed  == (in4Polylog - (out4AllNLoweras22and4 - (out4AllNLoweras22and4/.a->f))/.{a->0,f->1}/.canonicalCR//Expand)

countIntegrals[out4AllNLoweras22and4gathered]

texCountIntegrals[out4AllNLoweras22and4gathered]

texIntegralsByCoeff[4*out4AllNLoweras22and4//Expand]