How to encode sos type 1 constraints in AMPL

Hi AMPL team.
I am using ampl with gurobi solver, and I have been trying to implement an sos1 function but I don’t fully understand the documentation ampl provides.

The implementation I want to do is the following: i have variables A, B and C (actually I have many of these groups) all of them non negative integers, and only one of them (in each group) can be different than 0.

Is there any recommendation you can provide?

To see how you can encode sos type 1 constraints in AMPL, consider this example:

var X {1..5,1..7} integer >= 0, <= 10;

maximize obj:
   sum {i in 1..5, j in 1..7} Uniform(1,2) * X[i,j];

subject to con:
   sum {i in 1..5, j in 1..7} X[i,j] <= 35;

Additionally, it is required that, for each i in 1…5, at most one of X[i,1], X[i,2], . . . , X[i,7] is > 0. Thus there are 5 sos1 constraints, with 7 variables each. They can be expressed in AMPL by setting values for two user-defined suffixes, sosno and ref:

suffix sosno IN;
suffix ref IN;

let {i in 1..5, j in 1..7} X[i,j].sosno := i;
let {i in 1..5, j in 1..7} X[i,j].ref := j;

The general rules for setting these suffix values are as follows:

  • Members of each SOS1 set have a different, unique .sosno value.
  • Within each SOS1 set, members all have different .ref values.

Thus for the example, X[i,1].sosno, X[i,2].sosno, . . . , X[i,7].sosno are all equal to i, while X[i,1].ref, X[i,2].ref, . . . , X[i,7].ref are equal to 1, 2, . . . , 7, respectively.

If you have a hard problem, you may want to experiment with different settings of the Gurobi options presos1bigm and presos1enc; see the Gurobi Options listing and the Gurobi documentation of SOS Constraints.

Starting with Gurobi 10.0, you can also write this constraint directly, without any SOS suffixes, as

subj to OnePos {i in 1..5}:
   atmost 1 {j in 1..7} (X[i,j] > 0);

The AMPL-Gurobi interface will convert this to linear MIP constraints before sending the problem to Gurobi.