メインコンテンツへスキップ

Creating complex constraint with Python API

回答済み

コメント

3件のコメント

  • 正式なコメント
    Simranjit Kaur
    • 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

    There is a typo in the definition of \( \texttt{shapes} \); the last element should be \( \texttt{'circle'} \)  instead of \( \texttt{'cirlce'} \).

    In the constraint you pointed out, we generate the pairs of indices \( \texttt{(i, j)} \) such that \( \texttt{shapes[i]} \) is a triangle, \( \texttt{shapes[j]} \) is a circle, and the top colors of the two shapes match. The \( \texttt{(i, j)} \) pairs that satisfy this condition are:

    [(0, 6), (4, 10), (8, 2), (8, 13), (12, 2), (12, 13)]

    Let \(x\) be the model variables. Based on these tuples, the constraint we want is:

    $$\begin{align*}x_0 + x _6 = 2 \lor x_4 + x_{10} = 2 \lor \ldots \lor x_{12} + x_{13} = 2,\end{align*}$$

    where \( \lor \) is the logical "or." However, the constraint you identified just sums together all of the variables in the list of tuples:

    $$\begin{align*}x_0 + 2 x_2 + x_4 + x_6 + 2x_8 + x_{10} + 2 x_{12} + 2 x_{13} &\geq 2.\end{align*}$$

    Not only is this constraint not we want, but it also doesn't even affect the feasible region of the model. This constraint is implied by the constraints requiring us to select one triangle shape and one circle shape:

    $$\begin{alignat*}{2}x_0 + x_4 + x_8 + x_{12} &= 1 \quad && \textrm{(pick one triangle)} \\ x_2 + x_6 + x_{10} + x_{13} &= 1 && \textrm{(pick one circle).}\end{alignat*}$$

    To model the desired constraint, we can create a special weight for our \( n \) variables based on the top color of the corresponding shapes:

    # yellow: 1, blue: 2, red: 3
    tc_weight = {i: unique_colors.index(top_color[i]) + 1 for i in range(n)}

    This gives us a mapping from variable index to top-color weight:

    >>> tc_weight
    {0: 2, 1: 3, 2: 1, 3: 2, 4: 3, 5: 1, 6: 2, 7: 3, 8: 1, 9: 2, 10: 3, 11: 1, 12: 1, 13: 1}

    Exactly one triangle and exactly one circle will be chosen. If we want the top colors of the two chosen shapes to match, we can add a constraint that the top-color weighted sum of the triangle variables equals the top-color weighted sum of the circle variables:

    model.addConstr(gp.quicksum(tc_weight[i] * decision_v_shapes[i] for i in range(n) if shapes[i] == 'triangle') == gp.quicksum(tc_weight[i] * decision_v_shapes[i] for i in range(n) if shapes[i] == 'circle'))

    This produces the following constraint:

    $$\begin{align*}2x_0 + 3x_4 + x_8 + x_{12} &= x_2 + 2x_6 + 3x_{10} + x_{13}\end{align*}$$

    Since the \( x \) variables are binary and the (unweighted) variables on each side sum to \( 1 \), the only way this constraint is satisfied is if

    $$\begin{align*}x_0 + x _6 = 2 \lor x_4 + x_{10} = 2 \lor \ldots \lor x_{12} + x_{13} = 2.\end{align*}$$

    as desired. The solution is:

     i      shape     top  bottom  weight  price
    --------------------------------------------
    5 square yellow red 4 8
    7 rectangle red yellow 7 7
    12 triangle yellow yellow 1 7
    13 circle yellow yellow 2 7
    TOTAL: 14 29

    Finally, because you have constraints that require one of each shape to be chosen, the constraint requiring a total of four shapes to be chosen is redundant.

    1
  • tjs
    • Gurobi-versary
    • First Comment
    • First Question

    Thank you very much for the detailed explanation and answer!

    0

投稿コメントは受け付けていません。