# Writting a Hessian for an arbitrary number of variables or for a arbitrary vectorial function

The following code calculate the Hessian --- with simplification --- for a transcendental function.

fu[x_, y_, z_] :=  x^α y^β z^γ
hes = D[#1[#2, #3, #4], {{#2, #3, #4}}, {{#2, #3, #4}}] &
hescd = hes[fu, x, y,
z] /. {x_^(α_ - 2) y_^β_ z_^γ_ -> U/x^2,
x_^(α_ - 1) y_^(β_ - 1) z_^γ_ -> U/(x y)};
hescd // MatrixForm


I would like

1) to generalize it for a vector of arbitrary dimension

2) It obviously works for any algebraic function but not for all the transcendental functions for which there is a simplification. How to rewrite it to include directly in hes the simplification?

• – Jens Jan 15 '17 at 20:15
• I'm probably being dense here, but what is U? – Chris K Jan 16 '17 at 2:58
• @ChrisK It seems to stand for the entire function. It's an odd sort of simplification for programming, but common enough in papers – Michael E2 Jan 16 '17 at 4:00
• To be fair, the OP neglected to mention that U was supposed to be a stand-in for the entire function. – J. M.'s technical difficulties Jan 16 '17 at 17:05

This seems to work for the Cobb-Douglass function with arbitrary number of variables:

ClearAll[fu2, hess2]
fu2[x : {__}, p : {__}] := Times @@ (x^p)

hess2[fn_, x : {__}, p : {__}] := ReleaseHold[D[fn[x, p], {x, 2}] /.
Power[w_, Plus[k_Integer, a_]] :>  HoldForm[Power[w, k]] Power[w, a] /. fn[x, p] :> U]

hess2[fu2, {v, w, x, y, z}, {a, b, c, d, e}] // MatrixForm


In version 10 and later versions you can use Inactive and Activate combination instead of HoldForm and ReleaseHold, that is,

hess2[fn_, x : {__}, p : {__}] := Activate[D[fn[x, p], {x, 2}] /.
Power[w_, Plus[k_Integer, a_]] :>  Inactive[Power[w, k]] Power[w, a] /. fn[x, p] :> U]


Maybe you want the following:

hess[fn_, varList__] := Simplify[D[fn @@ {varList}, {{varList}, 2}]]


The first argument is the function, and the remaining arguments are referred to by varList__. Its length is arbitrary, and the function is applied to it by @@.

I added Simplify to address your point 2). It could be replaced by FullSimplify or some other, more customized commands that depend on the specific application.

Edit

I initially only went by the title of the question. The more specific replacement in the question can be built into my original answer by adding the following rule:

hess[fn_, varList__] := U ( D[fn @@ #, {#, 2}] /. Thread[# -> 1])/
KroneckerProduct[#, #] &[#] &@{varList}


This maintains the calling syntax given in the question, and works for arbitrary dimensions:

fu[w_, x_, y_, z_] := w^a x^b y^c z^d

hess[fu, w, x, y, z] // MatrixForm


The output is the same as in @MichaelE2's answer.

• Jens it works and it does not work. It works because it do the trick. But it does not work since the simplification is not done. My problem is to do the suggested simplification for a fonction of any length --- not only x^α y^β z^γ but also x^[Alpha] y^[Beta] z^[Gamma] v^[Epsilon] and so on – cyrille.piatecki Jan 15 '17 at 20:40
• @cyrille.piatecki OK, I added your specific simplification. – Jens Jan 16 '17 at 4:27

The Hessian is pretty straightforward, as pointed out by Jens. Using patterns instead of basic algebra makes the "simplification" trickier than necessary.

ClearAll[a, b, c, d, w, x, y, z, f];

f[x_List, p_List] := Inner[Power, x, p, Times];

vars = {w, x, y, z};
powers = {a, b, c, d};

D[f[vars, powers], {vars, 2}] * U/f[vars, powers] // MatrixForm