write dynamic model in python (coming from ampl)

Skip to first unread message

Hanna Schenk

Aug 10, 2022, 11:16:20 AM8/10/22
to Artelys Knitro forum
Dear all,
I have been using ampl to solve nonlinear optimisation problems with many variables from dynamic models.
in ampl it is easy to write something like this

var x1 {t in 0..T} >= 0
var x2 {t in 0..T} >= 0
var g1 {t in 0..T} = r * x1[t] * (1 - x1[t]/k)
var g2 {t in 0..T} = a * x1[t] * x2[t]
maximise: sum {t in 0..T} ( g2[t] - y[t] )
subject to c1 {t in 0..T}: x2[t+1] = (1 - b) * x2[t] + y[t];
subject to c2 {t in 0..T-1}: x1[t+1] = x1[t] + g1[t] - g2[t];

(a, r, b, k are constants) and solve it with knitro. I have been looking at the python examples and the knitro documentation.
The number of variables in my model depends on T, so I can not write the problem as in the examples/documentation.

Maybe someone can help and tell me whether it is possible (and if so how) to implement this type of problem in python and solve it using knitro


Julien Côté-Massicotte

Aug 11, 2022, 10:23:58 AM8/11/22
to Artelys Knitro forum
Hi Hanna,
Here is an example on how it could be written in Python. It is not complete, but that should give you a good start.
You can pass T, a, r, b and k as userParams to define obj and c.

#*     FUNCTION EVALUATION CALLBACKS                                *

def callbackEvalObj (kc, cb, evalRequest, evalResult, userParams):
    Tvar = userParams.T
    if evalRequest.type != KN_RC_EVALFC:
        print ("*** callbackEvalObj incorrectly called with eval type %d" % evalRequest.type)
        return -1
    x = evalRequest.x
    for ind in range(Tvar):
        g1[ind] = userParams.r * x[ind] * (1-x[ind]/userParams.k)
        g2[ind] = userParams.a * x[ind] * x[Tvar+ind]
    # Evaluate nonlinear term in objective
    for ind in range(Tvar)
         evalResult.obj += g2[ind] - y[ind]     #multiple ways to write this function
    for ind in range(Tvar-1):
        evalResult.c[ind]= (1-userParams.b)*x[Tvar+ind]+ y[ind] - x[Tvar+1+ind]
        evalResult.c[Tvar+ind]=x[ind] + g1[ind] - g2[ind] - x[ind+1]
    evalResult.c[2*Tvar-1]=... (last constraint for c1, but I'm not sure it exist because x2[t+1] doesn't exist for ind=T)

    return 0

class UserEvalType:
    def __init__ (self, T, a, r, b, k):
        self.T = T
        self.a = a
        self.r = r
        self.b = b
        self.k = k

# Create a new Knitro solver instance.
    kc = KN_new ()
    print ("Failed to find a valid license.")
    quit ()
xIndices = KN_add_vars (kc, 2*T)
cIndices = KN_add_cons (kc, 2*T-1)
for x in xIndices:
    KN_set_var_lobnds (kc, x, 0.0)
for c in cIndices:
    KN_set_con_eqbnds (kc, c, 0.0)    #added the left terms to evalResult.c and made it equal to 0.

KN_set_obj_goal (kc, KN_OBJGOAL_MAXIMIZE)

userEval = UserEvalType (T, a, r, b, k)

cbObj = KN_add_eval_callback (kc, evalObj = True, funcCallback = callbackEvalObj)

KN_set_cb_user_params (kc, cbObj, userEval)

Hope this helps!

Best regards,

Julien Côté-Massicotte

Reply all
Reply to author
0 new messages