# Converting a multivariate function to a single variate function

I want to convert a multivariate function into a single variable function. Aka to perform partial differentiation. While my attempt works but it is such an ugly kludge. Is there a better way of doing this?

``````func1(x,y) = 3.0*x + 7.0*y^2.0

function create1Dfunction(func::Function,vector::Vector,varnum::Int64)
len = length(vector)
if 1 <= varnum <= len
codestring = "("
for i in 1:len
if i == varnum
codestring = codestring * "x"
else
codestring = codestring * string(vector[i])
end
if i < len
codestring = codestring * ", "
end
end
codestring = codestring * ")"
# println(codestring)
subexpr = Meta.parse(codestring)
expr = :( x -> \$func(\$subexpr...) )
# println(expr)
local OneDimensionalFunc = eval(expr)
return OneDimensionalFunc
else
println("Error, parameter number \$(varnum) does not exists")
end
end

# We want to convert func1(x,y) to g(x) = x -> func1(3.1,x)
println("func1(3.1,7.8) = ",func1(3.1,7.8))
g = create1Dfunction(func1,[3.1,7.8],2)
println("g(7.8) = ",g(7.8))
``````

Output

``````Starting Julia...
_
_       _ _(_)_     |  Documentation: https://docs.julialang.org
(_)     | (_) (_)    |
_ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _  |  |
| | |_| | | | (_| |  |  Version 1.0.3 (2018-12-18)
_/ |\__ _|_|_|\__ _|  |  Official https://julialang.org/ release
|__/                   |

func1(3.1,7.8) = 435.18
g(7.8) = 435.18
``````

``````julia> func1(x, y) = 3.0*x + 7.0*y^2.0
func1 (generic function with 1 method)

julia> g(x) = func1(3.1, x)
g (generic function with 1 method)

julia> func1(3.1, 7.8)
435.18

julia> g(7.8)
435.18
``````
1 Like

What if my function have 26 variables and I want to convert it to a single variable function on variable number 21? And fill the rest with the value [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26] and I don’t want to do it by hand. And I don’t know the value of the vector of numbers to replace them with at compile time but only at runtime.

Ah, I see. Here’s an option without dynamic code generation:

``````oned(f, args, pos) = x -> f(ntuple(i -> i == pos ? x : args[i], length(args))...)

f(x, y) = 3.0*x + 7.0*y^2

g = oned(f, [3.1, 7.8], 2)
``````

And now:

``````julia> f(3.1, 7.8)
435.18

julia> g(7.8)
435.18
``````
3 Likes

Thank you very much. That worked and is a lot shorter

``````function oned(f::Function, args::Vector, pos::Int64)
return x -> f(ntuple(i -> i == pos ? x : args[i], length(args))...)
end
h = oned(func1,[3.1,7.8],2)
println("h(7.8) = ",h(7.8))
``````

Output

``````Starting Julia...
_
_       _ _(_)_     |  Documentation: https://docs.julialang.org
(_)     | (_) (_)    |
_ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _  |  |
| | |_| | | | (_| |  |  Version 1.0.3 (2018-12-18)
_/ |\__ _|_|_|\__ _|  |  Official https://julialang.org/ release
|__/                   |

func1(3.1,7.8) = 435.18
g(7.8) = 435.18
h(7.8) = 435.18
``````

Please check my final version of the program

``````func1(x,y) = 3.0 * x    + 7.0 * y    ^ 2.0
func2(X)   = 3.0 * X + 7.0 * X ^ 2.0

function create1Dfunction(func::Function,args::Vector,pos::Int64;FuncType::String="MultiParameters")
if 1 <= pos <= length(args)
if FuncType == "MultiParameters"
return x -> func( ntuple(i -> i == pos ? x : args[i], length(args))... )
else
return x -> func( ntuple(i -> i == pos ? x : args[i], length(args)) )
end
else
println("Error! Parameter number \$(pos) does not exists")
return x -> Nothing
end
end

# We want to convert func(x,y) to g(x) = x -> func1(3.1,x)
println("func1(3.1,7.8) = ",func1(3.1,7.8))
g = create1Dfunction(func1,[3.1,7.8],2)
println("g(7.8) = ",g(7.8))
h = create1Dfunction(func2,[3.1,7.8],2,FuncType="VectorParameters")
println("h(7.8) = ",h(7.8))
``````

Output

``````func1(3.1,7.8) = 435.18
g(7.8) = 435.18
h(7.8) = 435.18
``````