so the output of:
MOI.get(Ipopt.Optimizer(), MOI.ListOfSupportedNonlinearOperators())
includes inv
, so I thought it should handle the inverse of a matrix. however, in my minimal example, it does not:
n = 5
model = Model(Ipopt.Optimizer)
#=
decision variables
=#
# the transition matrix
@variable(model, P[1:n, 1:n] .≥ 0)
# the stationary distn
@variable(model, π★[1:n] .≥ 0.0)
# the fundamental matrix
Z = @expression(model, inv(I(n) - (P - ones(n) * π★')))
giving an error MethodError: no method matching JuMP.NonlinearExpr(::JuMP.NonlinearExpr)
I saw your trick here to include Z
as a variable with a constraint, but this causes the solver not to converge. is this the only solution?
@variable(model, Z[1:n, 1:n])
@constraint(model, Z * (I(n) - (P - ones(n) * π★')) .== I(n))
I’ve actually had success with inv
by register
ing the function myself, via the legacy way. see below. so, it should be possible in principle, no? note: I’m trying to simplify my code but also add another variable, which is proving difficult to do by modifying my idleness_cost
function.
function idleness_cost(P_flat...)
# rebuild transition matrix
P = reshape(collect(P_flat), n, n)
# compute the fundamenatal matrix
Z = inv(I(n) - (P - ones(n) * π★'))
# first hitting times starting at arbitrary state to all other states
m₁ⱼ = [((1 == j ? 1.0 : 0.0) - Z[1, j] + Z[j, j]) / π★[j] for j = 1:n]
# return cost of idleness costs
return sum(m₁ⱼ[j] * ϕ[j] for j = 1:n)
end
model = Model(Ipopt.Optimizer)
register(model, :idleness_cost, n * n, idleness_cost, autodiff=true)
thanks!