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
How about just this:
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[1] + 7.0 * X[2] ^ 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