Skip to main content

Python call to chgCoef yields attribute error for __cindex__

Answered

Comments

15 comments

  • Eli Towle
    Gurobi Staff Gurobi Staff

    Hi Jonathan,

    Can you try calling grbModel.update() before changing the coefficient? You can read more about this in the "Lazy Updates" section here. Essentially, if you want to immediately access a variable/constraint attribute or change some part of the model, you should first update the model.

    If this doesn't work, could you post a small working code example that reproduces the problem? Thanks!

    Eli

    0
  • Jonathan Eckstein
    Gurobi-versary
    First Comment
    First Question

    Yes, I did update the model first.  I'll try to post a self-contained example soon.

    0
  • Jonathan Eckstein
    Gurobi-versary
    First Comment
    First Question

    Here is a 12-line program that produces the same error.  Possibly I am doing something really dumb, but it is my first time with this API.  Optimizing the model instead of updating doesn't change the error.

    Thanks!  -- Jonatha

     

    import numpy
    import gurobipy as gp
    from gurobipy import GRB

    n = 10

    m = gp.Model()
    grbx = m.addMVar(shape=n, lb=-1.0, ub=1.0, vtype=GRB.CONTINUOUS, name="grbx")
    randomMatrix = numpy.random.rand(20,10)
    Q = numpy.transpose(randomMatrix) @ randomMatrix
    m.setObjective(0.5*(grbx @ Q @ grbx))
    constr = m.addConstr(grbx[0] + grbx[1] + grbx[2] <= 1.0)
    m.update()

    m.chgCoeff(constr,grbx[1],-2.0)

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Hi Jonathan,

    Ah, yes, you're right that this is because you are passing an \( \texttt{MVar} \) object instead of a \( \texttt{Var} \) object. I missed that in my first (hasty) reading of your post. I don't believe there is an analogous method for \( \texttt{MVar} \) objects. I'll look into this and get back to you.

    Thanks,

    Eli

    0
  • Jonathan Eckstein
    Gurobi-versary
    First Comment
    First Question

    OK, thanks!  Please let me know what you find out.

    Setting up my objective function with only scalar variables would be hellish.  I suppose that I could make big pile of scalar variables, each with an equality constraint to an element of the matrix variable.  That would not be pretty.  Or I guess I could simply delete all my constraints and then add in new ones. 

    I have to solve a bunch of QP problems, each of which some different variable bounds and linear constraint coefficients.

    0
  • Robert Luce
    Gurobi Staff Gurobi Staff

    Hello Jonathan,

    as written by Eli there currently is no way to change coefficents w.r.t. an Mvar object, but I have registered this in our backlog of future improvements to the matrix-friendly API.  Your suggestion to delete the old constraints, modify the coefficients on the ndarray level, and add them back to the model seems to be the most practical workaround to me.

    Robert

    0
  • Jonathan Eckstein
    Gurobi-versary
    First Comment
    First Question

    OK, thanks for checking.  I will just delete the constraints and add back modified ones.  I suspect that will be slow, but this is a prototype, proof-of-concept implementation, so its speed is not absolutely critical.

    0
  • cg
    Gurobi-versary
    Conversationalist

    Dear Robert and Eli,

    does this feature (change coefficients w.r.t. an Mvar object) already exist in the latest version of Gurobi (9.1)?

    Thank you!

    Chris.

    0
  • Eli Towle
    Gurobi Staff Gurobi Staff

    Unfortunately not. However, there is an easy workaround available in Gurobi 9.1. Namely, you can use MVar.tolist() to convert MVar objects to Var objects for use in Model.chgCoeff(). Similarly, you can convert MConstr objects to Constr objects with MConstr.tolist(). For example:

    import numpy as np
    import gurobipy as gp


    m = gp.Model()
    x = m.addMVar(shape=(3,), name='x')
    a = np.array([1.0, 2.0, 3.0])

    # Add constraint x[0] + 2 x[1] + 3 x[2] <= 1
    c = m.addConstr(a @ x <= 1)
    m.write('model1.lp')

    # Change to 5 x[0] + 2 x[1] + 3 x[2] <= 1
    m.chgCoeff(c.tolist()[0], x.tolist()[0], 5)
    m.write('model2.lp')
    0
  • Robert Luce
    Gurobi Staff Gurobi Staff

    That said, the workaround should no longer be necessary starting in the next feature release after 9.1, where you will be able to just do

    m.chgCoeff(c[0], x[0], 5)

    This works because indexing an MVar/MConstr will yield a Var/Constr object instead of a (1,) slice.

    0
  • cg
    Gurobi-versary
    Conversationalist

    Thank you both! I am looking forward to the new release but for the time being Eli's suggested work-around will do it too.

    0
  • Maliheh Aramon
    Gurobi Staff Gurobi Staff

    Hi Chris, 

    Gurobi 9.5 was recently released. Included in this release is a new feature where indexing an MVar/MConstr returns a Var/Constr object. 

    We hope this fix works well for you. Please let us know if you see any other issues using this.

    Best regards,

    Maliheh

    0
  • Satender .
    Gurobi-versary
    First Question
    First Comment

    Hi Maliheh Aramon,

    I am still getting the same error as discussed above with gurobi 10.0. Is the update you mentioned still intact? 

    Regards,

    Satender

    0
  • Maliheh Aramon
    Gurobi Staff Gurobi Staff

    Hi Satender, 

    Yes, sorry about this. The Python Matrix API went through an overhaul in the latest Gurobi version 10.0. You can check out our recent webinar on this. 

    In Gurobi 10.0, indexing an MVar/MConstr returns a 0-dim object of the same type. To access a Var/Constr object from an MVar/MConstr, you need to call the method MVar.item()/MConstr.item(). As an example:

    m.chgCoeff(c.item(), x[0].item(), 5)

    Best regards,

    Maliheh

    0
  • Satender .
    Gurobi-versary
    First Question
    First Comment

    Thank you Maliheh Aramon.

    0

Please sign in to leave a comment.