# Reconstructing a function from its gradients

I have a list of the components of the gradients, $$\partial f/\partial x_i$$, of a function $$f(x_1,x_2,\cdots)$$. Is there some neat way to reconstruct the function $$f$$?

One approach to doing this would be treat this as a system of PDEs and use DSolve. However, Mathematica is unable to solve PDEs with more than 3 variables – see, for instance here.

Another approach is to integrate the gradients $$\int (\partial f/\partial x_i) dx_i$$ and then take the Union of the terms from all the integrals. This isn't quite a robust way of doing things as it fails if the expressions for the integrals are not simple enough (ExpandAll does not help). A code for doing this is the following : Table[act[m]=ExpandAll[Integrate[gradient[m],Subscript[x, m]],{m,1,NN}]; f=Fold[Union,act[1],Table[act[m],{m,2,NN}]];

Any better ideas?

Problems with code often require the code (or "All unhappy codes are unhappy in their own way"), but here's a somewhat complicated example that works:

vars = {w, x, y, z};
vf = Grad[(Log[w]^2 Sqrt[1 + x^3 y] + y^5 ArcTan[z^7])/Log[1 + x z], vars];
Fold[
#1 + Integrate[First[#2] - D[#1, Last[#2]], Last[#2],
Assumptions -> vars \[Element] Reals] &,
0, Transpose@{vf, vars}]
(*  (y^5 ArcTan[z^7])/Log[1 + x z] + (Sqrt[1 + x^3 y] Log[w]^2)/Log[1 + x z]  *)


Note: Fold[#1 + Integrate @@ #2 - #1 &, 0, Transpose@{F, vars}] is shorter, but the integrals are more complicated.

Of course I've seen Integrate fail on very complicated expressions, but I don't know what one could expect to work better than it, other than perhaps DSolve which sometimes takes a different route in edge cases.

Alternate method of integration:

Here's a way to use DSolve, which ends with a constant of integration C[5] that is omitted in the Integrate method:

iter[F_, {dF_, vars_, c_}] :=
F /. First@DSolve[D[F, First@vars] == dF, c @@ vars, vars];
Fold[
iter,
C[1] @@ vars,
Transpose@{
vf,
NestList[Rest, vars, Length@vars - 1],
Array[C, Length@vars]}
]


Use FoldList instead of Fold and you see the process mentioned in a comment below:

{C[1][w, x, y, z],
(Sqrt[1 + x^3 y] Log[w]^2)/
Log[1 + x z] + C[2][x, y, z],
(y^5 ArcTan[z^7])/Log[1 + x z] + (Sqrt[1 + x^3 y] Log[w]^2)/
Log[1 + x z] + C[3][y, z],
(y^5 ArcTan[z^7])/Log[1 + x z] + (Sqrt[1 + x^3 y] Log[w]^2)/
Log[1 + x z] + C[4][z],
(y^5 ArcTan[z^7])/Log[1 + x z] + (Sqrt[1 + x^3 y] Log[w]^2)/
Log[1 + x z] + C[5]}


Update: Error check

iter::nxact = "The vector field is not conservative: the derivative of  with respect to  minus  depends on .";
iter[F_, {dF_, v_, c_}] := F /. First@ DSolve[
If[InternalDependsOnQ[#, Complement[vars, v]],
Message[iter::nxact, F, First@v, dF, Complement[vars, v]];
Throw[$Failed], # ] &@ Simplify[D[F, First@v] - dF] == 0, c @@ v, v]; Catch@ Fold[ iter, C[1] @@ vars, Transpose@{ vf, NestList[Rest, vars, Length@vars - 1], Array[C, Length@vars]} ]  • Thanks a lot! This works like a charm for the case I have, in which the gradients are multivariate polynomials in the vars. May I ask what is the logic you are using here: it is iterated integrals and subtracting out something? – TheTwistedSector Jul 30 '19 at 19:07 • @TheTwistedSector It's how I teach it in Multivariable/Diff Eq. Basically, to find an$F$such that$\nabla F$equals a given$\nabla f$, alternate integrating and differentiating w.r.t the variables. First integrate the$w$component$F=\int f_w\,dw+g(x,y,z)=F^{(1)}+g$; then differentiate w.r.t.$x$:$F^{(1)}_x+g_x=f_x$. Then integrate$g=\int(f_x-F^{(1)}_x)\,dx+h(y,z)=F^{(2)}+h$. And so forth. One should check the integration constants$g,h,\dots$are free of any dependency on$(w),\,(w,x),\dots$, respectively. The code above does not do that. The answer is$F=F^{(1)}+F^{(2)}+\cdots\$. – Michael E2 Jul 30 '19 at 19:44
• One advantage is that the integrations get easier as you go along because of cancelation. You also can tell when the vector field is not conservative/closed/exact. – Michael E2 Jul 30 '19 at 19:44

It is worth pointing out that as of V12.2, DSolve can solve the example in my other answer:

vars = {w, x, y, z};
vf = Grad[(Log[w]^2 Sqrt[1 + x^3 y] + y^5 ArcTan[z^7])/Log[1 + x z],
vars];

DSolve[
Grad[f @@ vars, vars] == vf,
f, vars]
(*
{{f -> Function[{w, x, y, z},
C[1] + (y^5 ArcTan[z^7])/Log[1 + x z] + (
Sqrt[1 + x^3 y] Log[w]^2)/Log[1 + x z]]}}
*)

• Looks like some progress is happening on this front! Does DSolve` also work with the examples here? I would have tested this out by myself, but do not have v12.2 yet. – TheTwistedSector Feb 14 at 12:34
• @TheTwistedSector Yes, it works. I added an answer. – Michael E2 Feb 14 at 15:16