Modeling guide

A guide to using the beta test release of x-gurobi, the enhanced AMPL-Gurobi interface, and copt, an interface to Cardinal Optimizer. Both can be compiled from source or downloaded in the AMPL distribution bundle.


  • Full support of logical expressions and constraints, as described in the AMPL page on Logic and Constraint Programming Extensions.

  • Algebraic expressions beyond linear and quadratic, including complementarity constraints.

  • Choice between conversions in the driver vs. native solver support.

Expressions supported

  • Arbitrary trees of logical, relational, and general non-linear expressions including higher-degree polynomials:

    (x<=0 or y!=2)  ==>
            (x<=-5 or
                    (max((x+1)*(x+2)*(y+3), y)<=3 and
  • Piecewise-linear expressions are natively supported by Gurobi. To pass them that way, set the following AMPL option:

    option pl_linearize 0;
  • Complementarity constraints:

    subject to Pri_Compl {i in PROD}:
        max(500.0, Price[i]) >= 0 complements
            sum {j in ACT} io[i,j] * Level[j] >= demand[i];
    subject to Lev_Compl {j in ACT}:
        level_min[j] <= Level[j] <= level_max[j] complements
            cost[j] - sum {i in PROD} Price[i] * io[i,j];
  • Constraint programming high-level constraints and expressions, for example:

    ## if-then
    minimize TotalCost:
        sum {j in JOBS, k in MACHINES}
            if MachineForJob[j] = k then cost[j,k];
    ## implied forall
    subj to HostNever {j in BOATS}:
        isH[j] = 1 ==> forall {t in TIMES} H[j,t] = j;
    ## alldiff global constraint
    subj to OneJobPerMachine:
        alldiff {j in JOBS} MachineForJob[j];
    ## implied alldiff
    subj to VisitOnce {j in BOATS}:
        isH[j] = 0 ==> alldiff {t in TIMES} H[j,t];
    ## numberof operator
    subj to CapacityOfMachine {k in MACHINES}:
        numberof k in ({j in JOBS} MachineForJob[j]) <= cap[k];
    ## count operator
    subj to CapacityOfMachine {k in MACHINES}:
        count {j in JOBS} (MachineForJob[j] = k) <= cap[k];
    ## implied atmost
    subj to VisitHosts {i in BOATS}:
        isH[i] = 0 ==> atmost 0 {j in BOATS, t in TIMES} (H[j,t] = i);
  • QP expressions are multiplied out. Example:

    -5 * (abs(x[1])-0.7)^2 + x[2]

    is converted as follows:

    -5*t^2 + 7*t - 2.45 + x[2]
    s.t. t = abs(x[1]);
  • Gurobi “general constraints” and, or, max, min, abs, as well as indicator (==>), are passed to Gurobi natively. This behavior can be changed with solver options acc:abs etc. to use big-M constraints instead (when the variables have finite bounds).

  • Nonlinear “generals” are passed to Gurobi:

    exp, log, sin, cos, tan, pow, pl, SOS1/2.

General modeling hints

For general modeling hints, refer to Guidelines for Numerical Issues and modeling webinars on the Gurobi website; Practical Considerations for Integer Programming in the AMPL Book, and the MOSEK Modeling Cookbook at

For logical expressions, it proves best to supply tight bounds on all participating variables. For any intermediate expressions which are known to have tighter bounds than those which can be deduced automatically, it is advisable to extract them into extra variables with the tight bounds. For example, given a disjunction

subj to: log(x+2)<=y^2  or  x-y>=z;

and knowing that -15 <= x-y-z <= 30, reformulate:

var t >=-15, <=30;
subj to: t == x-y-z;
subj to: log(x+2)<=y^2  or  t>=0;

In many cases, integer variables are more meaningful and efficient in logical constraints than continuous variables, for example in disequalities.