# Domain of a composite function

Consider the built-in function FunctionDomain to find a domain of a composite function f(f(x)) where f(x)=1/x.

f[x_]:=1/x
FunctionDomain[Composition[f, f][x], x]
FunctionDomain[1/(1/x), x]


The output is True in both cases.

Apparently Mathematica simplifies the argument before applying the FunctionDomain. That's why it gives mathematically incorrect output (x=0 should be excluded). Composition[f,f][x]=f(f(x)) = 1/(1/x)= x. And the domain of x is all real numbers. In case when Hold function is applied to 1/(1/x) the output is x < 0 || x > 0 as it should be.

FunctionDomain[Hold[1/(1/x)], x]


Output: x < 0 || x > 0

But when Hold is applied to Composition[f, f][x] The result is completely different. FunctionDomain[Hold[Composition[f, f][x]], x] returns the input as output.

Why doesn't it work? What am I missing?

One idea is to convert the Composition into a form that partially evaluates its arguments, something like:

freezeComposition[c_Composition] := Composition[
Apply@Hold,
ReplaceRepeated[#, Hold[x_]->x]&,
Apply@Defer,
Composition[Hold,Evaluate,#]&/@c
]


Then, we can do:

f[x_]:=1/x
FunctionDomain[freezeComposition[Composition[f,f]][x], x]


x<0||x>0

• @ CarlWoll the function that you have defined works perfectly! However I'm not able to understand the syntax as I am a beginner user of Mathematica. – roman465 Jan 18 '17 at 13:59
• I'm wondering if it's possible to achieve the same result using any of built-in Hold functions? I noticed that not only FunctionDomain but functions like Reduce and ReplaceAll return mathematically incorrect results. f[x_] := 1/x; {Reduce[1/(1/x) == 0, x, Reals],Reduce[f[f[x]] == 0, x, Reals],Solve[1/(1/x) == 0, x, Reals],Solve[1/(1/x) == 0, x, Reals],FunctionDomain[1/(1/x), x],FunctionDomain[f[f[x]], x],1/(1/x) /. x -> 0,f[f[x]] /. x -> 0} How can I prevent (partial) evaluation of the first argument? – roman465 Jan 18 '17 at 14:25
• @roman465. All of these simplifications occur because Mathematica always attempts to find a general solution to the problem while (sort of) ignoring special (or corner) cases. – march Jan 18 '17 at 16:21

You could use StrictFunctionDomain function from Domains package which evaluates given expression in special environment that prevents removal of removable singularities:

f // ClearAll
f[x_] := 1/x

StrictFunctionDomain[Composition[f, f][x], x]
(* x < 0 || x > 0 *)
StrictFunctionDomain[1/(1/x), x]
(* x < 0 || x > 0 *)
StrictFunctionDomain[Hold[1/(1/x)], x]
(* x < 0 || x > 0 *)
`