Skip to main content

About Divisor must be a constant in iteration

Ongoing

Comments

10 comments

  • Official comment
    Simranjit Kaur
    • Gurobi Staff Gurobi Staff
    This post is more than three years old. Some information may not be up to date. For current information, please check the Gurobi Documentation or Knowledge Base. If you need more help, please create a new post in the community forum. Or why not try our AI Gurobot?.
  • Eli Towle
    • Gurobi Staff Gurobi Staff

    Can you try printing out the value of \( \texttt{dc[k, j]} \) immediately before the line where the error occurs? I would guess that you receive this error because \( \texttt{dc[k, j]} \) is \( 0 \), which can't be used as a divisor.

    0
  • Yanbo Fan
    • Gurobi-versary
    • Investigator
    • Thought Leader

    Hi Eli Towle, 

    First of all, thank you for your reply. I originally thought it was possible that 0 was in the denominator during the iteration. But, by outputting the dc in each optimization process, I find that the dc in the wrong iteration is not the item of 0. This is the error message and the dc of the iteration where the error occurred. dc is [[524,524...], ...].

    Yanbo

    0
  • Eli Towle
    • Gurobi Staff Gurobi Staff

    I haven't been able to reproduce the error with your code. Could you please try adding the following print statement immediately before the line where you set \( \texttt{term2[k, j]} \) equal to \( \texttt{-1 * (l[k, j] * l[k, j]) / ((dc[k, j] ** 3) * dc[k, j])} \), then post the output you see when the error is thrown?

    print(f'dc[{k},{j}]={dc[k,j]} {type(dc[k,j])}')

    Also, did you cut off part of the error message? It would be helpful to see the full error traceback (the red text), which should be longer than the three lines you posted.

    Two comments about the code:

    • \( \texttt{term2} \) does not need to be defined as a set of model variables. It is only used in the code to temporarily store a QuadExpr object.
    • Consider a \( \texttt{dc} \) value of \( 524 \). Your objective includes the quadratic coefficient \( 1 / 524^4 \), which is approximately \( 10^{-11} \). This is much smaller than Gurobi's default feasibility tolerance of \( 10^{-6} \). As a result, Gurobi may not handle such small coefficients the way you expect.
    0
  • Yanbo Fan
    • Gurobi-versary
    • Investigator
    • Thought Leader

    Hi Eli Towle, 

    I'm very moved to see your detailed reply. I'm sorry for the error message I can't describe clearly before.

    First of all, this is the code that can show my complete error message. You can try it again.

    def gurobi_demo(qc):
    model = grb.Model('')
    s = np.array([[-250, -250, 0], [-250, 250, 0], [250, -250, 0], [250, 250, 0]])
    q = model.addVars(4, 3, lb=-500, vtype=GRB.CONTINUOUS, name='q')
    term2 = model.addVars(4, 4, vtype=GRB.CONTINUOUS, name='term2')
    l = model.addVars(4, 4, vtype=GRB.CONTINUOUS, name='l')
    dc = np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]])
    for k in range(4):
    for j in range(4):
    dc[k, j] = np.linalg.norm(qc[j] - s[k])

    model.update()
    sum = LinExpr()

    for k in range(4):
    for j in range(4):
    print(f'dc[{k},{j}]={dc[k, j]} {type(dc[k, j])}')
    term2[k, j] = -1 * (l[k, j] * l[k, j]) / ((dc[k, j] ** 3) * dc[k, j])
    sum += term2[k, j]
    model.setObjective(sum, sense=GRB.MAXIMIZE)

    for k in range(4):
    model.addConstr(q[k, 2] == 100)
    # model.addConstr(q[k, 2] <= 300)
    model.addConstr(q[k, 0] <= 500)
    model.addConstr(q[k, 0] >= -500)
    model.addConstr(q[k, 1] <= 500)
    model.addConstr(q[k, 1] >= -500)

    # np.linalg.norm(q[j] - s[k])
    for k in range(4):
    for j in range(4):
    rhs = QuadExpr()
    for i in range(3):
    rhs += q[j, i] * q[j, i] - 2 * s[k][i] * q[j, i]

    model.addConstr(l[k, j] * l[k, j] == rhs + s[k][0] ** 2 + s[k][1] ** 2 + s[k][2] ** 2)
    model.setParam('NonConvex', 2)
    model.optimize()
    for v in model.getVars():
    print('var name is {}, var value is {}'.format(v.VarName, v.X))
    return [[q[i, j].X for j in range(3)] for i in range(4)]

    def main():
    qc = [[[0 for j in range(3)] for i in range(4)]]
    while True:
    qc.append(gurobi_demo(qc[-1]))
    print(qc)

    What' s more, This is the complete error message (the red text).

    This is the output I see when solver throws an error after adding 

    print(f'dc[{k},{j}]={dc[k,j]} {type(dc[k,j])}')

    The last, about the problem which the dc is much smaller than Gurobi's default feasibility tolerance of 106. If the actual problem is that dc needs to be such a small value, how will this problem be solved? I don't know how to deal with such a problem when using gurobi.

    Best regards,

    Yanbo

     

     

    0
  • Eli Towle
    • Gurobi Staff Gurobi Staff

    I could reproduce this on a Windows machine. The error is related to the \( \texttt{numpy.int32} \) data type. 32-bit integers can only store values up to ~2 billion:

    >>> np.iinfo(np.int32)
    iinfo(min=-2147483648, max=2147483647, dtype=int32)

    You will get strange results when trying to store numbers larger than this with a \( \texttt{numpy.int32} \) data type. This is where the \( \texttt{ZeroDivisionError} \) comes from:

    >>> np.int32(256)**4
    0

    >>> np.int32(512)**4
    0

    To resolve the issue, you could try using 64-bit integers to represent the numbers stored in \( \texttt{dc} \):

    dc = np.array(..., dtype=np.int64)

    But because your objective function contains such small coefficients, you may still get some unexpected results from the solver. If this happens, you could try reformulating the model so it does not include such small objective coefficients. Alternatively, try using the ObjScale parameter to scale the objective function differently.

    0
  • Yanbo Fan
    • Gurobi-versary
    • Investigator
    • Thought Leader

    Hi Eli Towle,

    After reading the introduction of tolerance, I think it is the reason why dc * * 4 can not obtain the model solution because it exceeds gurobi or machine accuracy in the calculation process. So I enlarged the calculation of dc by adding the following code. 

    dc[k, j] = np.linalg.norm(qc[j] - s[k]) / 100

    Although I changed the original model, I found the optimal solution. Do you think changing only constants has a great impact on the actual meaning of the model or the whole optimization problem?

    Best regards,

    Yanbo

    0
  • Eli Towle
    • Gurobi Staff Gurobi Staff

    When you divide each \( \texttt{dc} \) value by \( 100 \), you are effectively multiplying the entire objective function by \( 10^8 \). Such a scaling does not change the optimal solution(s), though it may affect how reliably solvers like Gurobi can solve the model.

    0
  • Yanbo Fan
    • Gurobi-versary
    • Investigator
    • Thought Leader

    Hi Eli Towle,

    Okey, I understand your explanation. The last problem, In the calculation, I calculate log (1 + A)A is controlled by the decision variable, and the value of A is bigger than zero and far less than 1, in other words, 0 < a < < 1.

    Then, Gurobi will judge as 1 + A == 1. Facing this problem, how can I ensure the computational performance and obtain the optimal solution. The values corresponding to the relevant codes and variables are as follows.

    #Term3 is much less than 1
    model.addConstr(term3[k] >= grb.quicksum(zs[k, j] for j in range(K) if j != k))
    model.addConstr(term4[k] == term3[k] + 1)
    #In fact, term4 is not equal to 1
    model.addGenConstrLogA(term4[k], lv[k], 2, "log2")
    0
  • Yanbo Fan
    • Gurobi-versary
    • Investigator
    • Thought Leader

    Hi Eli Towle,

    When I set the parameter NumericFocus to 2, the above problem can be solved accurately. Maybe it only has some impact on the computational performance. 

    Best regards,

    Yanbo

    0

Post is closed for comments.