Suppose we have a real function $f:\mathbb R^2 \rightarrow \mathbb R$ and we would like to know if this function factorizes into $f(x,y)=f_1(x)f_2(y)$ for some real functions $f_1,f_2$. Is there an easy way of doing this in mathematica ? The program would return a set $f_1,f_2$ that does the job if they exist and would say it is not possible if such $f_1,f_2$ do not exist. I've been playing around with the "Collect" command, but I haven't figured out a way to get what I want.

Example: $f(x,y)=xy^2 - 4y^2 - xy+4y+x-4$ can be factorized into $(x-4)(y^2-y+1)$, so the program would return $f_1(x)=x-4, f_2(y)=y^2-y+1$. But $f(x,y) = xy+1$ cannot be factorized, so it would return impossible.

EDIT: I do not suppose that $f$ is separable, I would like to find out if it is, and in that case, get the factors $f_1,f_2$.

EDIT2: If I want to check the separability of a function using the proposed technique below, here is what I get:

Let's take a function that is NOT seperable:

ftest[t_, s_] := (s (t - T[1]) (s t - t T[1] + (T[1] - T[2]) T[2]))/Sqrt[s t (s - T[1]) (t - T[1]) (s - T[2]) (t - T[2]) (s - T[1] + T[2]) (t - T[1] +T[2])] 

Checking separability using the proposed code by taking the product of $f_1$ by $f_2$:

Simplify[getGX[ftest[x, y], x, y]*getHY[ftest[x, y], x, y] - ftest[x, y]] == 0

This returns true, although ftest is not separable.

  • 1
    $\begingroup$ Include a practical example of what you are working with, and the result you expect. $\endgroup$
    – MarcoB
    Commented Feb 16, 2021 at 16:00
  • $\begingroup$ If this does not suit your needs, edit your question to explain why. $\endgroup$ Commented Feb 16, 2021 at 16:08
  • 1
    $\begingroup$ Your factorization of $x y^2-4y^2-xy+4y+x-1$ doesn't appear to be correct: expanding $ (x-4)(y^2-y-1) $ yields $ x y^2-4 y^2 -x y +4 y +x -4 $. $\endgroup$
    – Pillsy
    Commented Feb 16, 2021 at 17:06
  • 2
    $\begingroup$ The Q&A @J.M. linked works for me. Leonid's solution does not assume $f$ is separable. You just have to check getGX evaluated (does not return with Head the same as getGX). $\endgroup$
    – Michael E2
    Commented Feb 16, 2021 at 17:32
  • 1
    $\begingroup$ With[{gx = getGX[ftest[x, y], x, y]}, FreeQ[gx, getGX] && Simplify[gx*getHY[ftest[x, y], x, y] - ftest[x, y]] == 0] returns False. (Check the result of getGX.) $\endgroup$
    – Michael E2
    Commented Feb 16, 2021 at 18:47

3 Answers 3


(too long for comment).

It does not, I explained why

Both answers in the link given by J. M.'s ennui work for me.

How can I separate a separable function

If you show an example of why it does not work and how, that will help.

Here is an example from one of the answers there

getGX[expr_, xvar_, yvar_] := 
  With[{dlogg = D[Log[expr], xvar] // FullSimplify}, 
   Exp[Integrate[dlogg, xvar]] /; FreeQ[dlogg, yvar]];
getHY[expr_, xvar_, yvar_] := FullSimplify[(#/getGX[#, xvar, yvar]) &[expr]]

And now do

f = x*y^2 - 4*y^2 - x*y + 4*y + x - 4;
getGX[f, x, y]
getHY[f, x, y] // Expand

gives the factors

enter image description here

If it can't factor it, the function returns unevaluated. So you treat that as the "impossible" case.

enter image description here

So why exactly the above not work for you?


I edited my question with more details about that code

You are not using the code in the answers quite correctly. Need to check if it fails or not, by checking if the result returns unevaluated or not. I would start with getGX first, and check if that evaluates or not. Then if it does, now call getHY.

One way could be

sep[f_, x_, y_] := Module[{fx, fy},
   fx = getGX[f, x, y];
   If[Head[fx] === getGX,
    Return["impossible", Module];
   fy = getHY[f, x, y];
   {fx, fy}

And now

ftest[t_, s_] := (s (t - T[1]) (s t - t T[1] + (T[1] - T[2]) T[2]))/
  Sqrt[s t (s - T[1]) (t - T[1]) (s - T[2]) (t - T[2]) (s - T[1] + 
      T[2]) (t - T[1] + T[2])];
sep[ftest[x, y], x, y]




sep[x*y^2 - 4*y^2 - x*y + 4*y + x - 4, x, y]


{-4 + x, 1 + (-1 + y) y}
  • 1
    $\begingroup$ I edited my question with more details about that code $\endgroup$
    – W. Volante
    Commented Feb 16, 2021 at 18:37

It is easy to show that your function is not separable by substituting specific values

ftest[t_, s_] := (s (t - T[1]) (s t - t T[1] + (T[1] - T[2]) T[2]))/
  Sqrt[s t (s - T[1]) (t - T[1]) (s - T[2]) (t - T[2]) (s - T[1] + 
  T[2]) (t - T[1] + T[2])]

For example

M = Table[ftest[i, j], {i, 1, 4}, {j, 1, 4}] /. T[i_] -> 3 i^2 + 7 i + 4;

(* 2 *)

Since the rank is greater than 1, it cannot be written as the sum of less than 2 separable terms.


Here's a similar post.

decompose[expr_, vars_?(ListQ[#] && Length[#] >= 2 &)] := 
 If[VectorQ[Keys[#], k |-> Length[k] <= 1], 
    Times @@@ Apply[Power, #, {2}], Indeterminate] &@
  GroupBy[FactorList[expr], vars \[Intersection] Level[#[[1]], {-1}] &]
decompose[(Log[x] + (x - 1)/Sqrt[x]) (y^2 + Sqrt[y] + y) // 
  Expand, {x, y}]

On page 411 of this book, there is a similar exercise proof:

enter image description here

In short, if $u(x,y)$ can be decomposed into the product of two monomials, then the second mixed partial derivative of $\ln u(x,y)$ should be 0.

For the function ftest[t, s], we find the second partial derivative of Log[ftest[t, s]]:

D[Log[ftest[t, s]], t, s] // FullSimplify

It can be seen that only when T[1] = T[2] or T[2]=0, its second mixed partial derivative is 0, so only when T[1] = T[2] or T[2]=0, ftest[t, s] can be decomposed.


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