I am giving it a try with some Julia code too:
g = [8, 12, 16, 20, 24, 36, 40] # Available gears.
r = [] # Initialize an array of gear ratios.
for g1 in g # Fill in the array of gear ratios with values.
for g2 in g
if g1 > g2 # If nonnegativity constraints on the xᵢ variables are to be imposed below, remove the condition;
push!(r, g1/g2) # otherwise only gear ratios > 1 can be achieved.
end
end
end
a = log.(r)
n = length(a) # Number of (types of) gear ratios.
d = 45/28 # Required gear ratio.
b = log(d)
using JuMP
using LinearAlgebra
using Juniper
using Ipopt
optimizer = Juniper.Optimizer
nl_solver = optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0)
optimizer = Juniper.Optimizer
model = Model(optimizer_with_attributes(optimizer, "nl_solver"=>nl_solver))
@variable(model, x[1:n]>=0,Int) # If assumed nonnegative, only gear ratios >=1 can be obtained.
#@variable(model, x[1:n],Int) # But currently fails if the nonnegativity constraint is removed. Dunno why.
γ = 0.001 # Regularization coefficient (if small, it does not try to minimize the number of gears ratios)
@NLexpression(model,expr,(sum(a[i]*x[i] for i = 1:n)-b)^2 + γ*sum(abs(x[i]) for i=1:n))
@NLobjective(model, Min, expr)
print(model)
optimize!(model)
It finally (originally I reported troubles here) seems doing what I expected:
julia> println(JuMP.value.(x))
[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
julia> println(JuMP.objective_value(model))
0.0020198412370350254
julia> println(JuMP.termination_status(model))
Let’s compare the achieved gear ratio with the demanded one:
julia> r[3]*r[10]
1.5999999999999999
julia> d
1.6071428571428572
Sort of…
Is this satisfactory, @pepijndevos ?