3
$\begingroup$

Is there any built-in function for decomposing a many-variables function as sum of products of single-variable functions? (I usually call this procedure Schmidt decomposition, but I'm not 100% that it is the correct name, and it is in some way analogous to the singular value decomposition in linear algebra)

$f(x,y)=\sum_k g_k u_k(x) v_k(y)$

where the functions u and v should be orthonormal.

Here a few examples of what I mean:

If the function is: $f(x,y)=\exp(-x^2-y^2)$ the output should be:

$g_1=1$

$u_1=\exp(-x^2)$

$v_1=\exp(-y^2)$

If the function is: $f(x,y)=\exp(-x^2-y^2)(x-y)$ the output should be:

$g_1=\frac{1}{\sqrt{2}}$

$u_1=\exp(-x^2)\ x$

$v_1=\exp(-y^2)$

$g_2=\frac{1}{\sqrt{2}}$

$u_2=\exp(-x^2)$

$v_2=-\exp(-y^2)\ y$

$\endgroup$
4
  • $\begingroup$ Why aren't $g_1$ and $g_2$ just 1 in the second example? $\endgroup$
    – Carl Woll
    Jul 11, 2017 at 16:36
  • $\begingroup$ that's not really crucial: the important thing is that the scaling is the same. $1/\sqrt{2}$ derives from the normalization of the coefficients: $\sum_k |g_k|^2 =1$ $\endgroup$
    – Fraccalo
    Jul 11, 2017 at 19:01
  • $\begingroup$ Well, your expected outputs don't satisfy your equation $f(x,y)=\sum_k g_k u_k(x) v_k(y)$, hence my question. $\endgroup$
    – Carl Woll
    Jul 11, 2017 at 19:08
  • $\begingroup$ yes you are right, I put those weight because I'm used to use those objects after having normalised them, but that's a step further :) $\endgroup$
    – Fraccalo
    Jul 12, 2017 at 8:16

1 Answer 1

5
$\begingroup$

Here is a variant of @LeonidShifrin's answer to How can I separate a separable function:

separate[f_, vars_:Automatic] := Module[{v, res, other, free},
    v = Replace[vars,
        {
        Automatic->Reduce`FreeVariables[f],
        Except[_List]->{vars}
        }
    ];
    res = Exp @ MapThread[
        Integrate,
        {Simplify @ D[Log@f,{v}], v}
    ];
    other = Activate @ Thread[Inactive[DeleteCases][Alternatives @@ v, v]];
    res = Replace[res Boole@MapThread[FreeQ,{res, other}], 0->1, {1}];
    Prepend[res, Simplify[f / Times@@res]]
]

Examples:

separate[Exp[-x^2-y^2-z^2](x+x^2)Sin[y]]
separate[Expand[(x (y+1))^5]]

{1, E^-x^2 x (1 + x), E^-y^2 Sin[y], E^-z^2}

{1, x^5, (1 + y)^5}

For your application, I think you can use the following function:

decompose[expr_] := Module[{terms},
    terms = Replace[Expand[expr],
        {
        a_Plus :> List @@ a,
        a_ :> {a}
        }
    ];
    separate /@ terms
]           

For your examples:

decompose[Exp[-x^2-y^2]]
decompose[Exp[-x^2-y^2](x-y)]

{{1, E^-x^2, E^-y^2}}

{{1, E^-x^2 x, E^-y^2}, {-1, E^-x^2, E^-y^2 y}}

Note that the constant terms are different from what you expected.

$\endgroup$
1
  • $\begingroup$ Thank you very much, it works perfectly! $\endgroup$
    – Fraccalo
    Jul 12, 2017 at 8:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.