1Unfortunately, we have not yet had time to update "Hooking Your Solver 2to AMPL" to explain facilities we added a few years ago for exchanging 3suffixes with AMPL. Use of these facilities from a user's perspective 4are described in chapter 14 of the second edition of the AMPL book, 5with older descriptions appearing in 6 7 http://www.ampl.com/NEW/statuses.html 8and 9 http://www.ampl.com/NEW/suffixes.html 10 11If your solver deals with a basis, it would be good if your driver 12could accept an incoming basis and return an optimal basis. The 13process is fairly straightforward. You declare 14 15 static SufDecl 16 suftab[] = { 17 { "sstatus", 0, ASL_Sufkind_var, 1 }, 18 { "sstatus", 0, ASL_Sufkind_con, 1 } 19 }; 20 21Before calling the .nl reader, you invoke 22 23 suf_declare(suftab, sizeof(suftab)/sizeof(SufDecl)); 24 25to tell the reader to save the incoming .sstatus values. If you were 26interested in other incoming or outgoing suffix values, you would also 27include lines for them in suftab. See, for example, 28/netlib/ampl/solvers/cplex/cplex.c or /netlib/ampl/solvers/osl/osl.c . 29 30To access an incoming suffix array (after calling the .nl reader, 31which reads them), say an array of priorities on variables, declare 32 33 SufDesc *dp; 34 35and invoke 36 37 dp = suf_get("priority", ASL_Sufkind_var); 38 39suf_get returns a pointer to a SufDesc (which is declared in asl.h); 40the second argument indicates the kind of entity to which the suffix 41pertains: variable, constraints, objective, or problem. 42 43If you wanted to see integer values for the suffix, then dp->u.i is 44the array of suffix values; otherwise dp->u.r is the array of (real) 45suffix values. 46 47To return .sstatus values (i.e., a basis), you call suf_iput 48twice, once for constraint.sstatus and once for variable.sstatus. 49It's probably simplest to proceed as in /netlib/ampl/solvers/minos/m55.c: 50having declared 51 52 int *varstat; 53 SufDesc *csd, *vsd; 54 55and having computed NB = M + N, where M >= n_con and N >= n_var are the 56numbers of constraints and variables (possibly adjusted, depending on the 57needs of your solver -- for example, some solvers require adding an 58extra variable and possibly an extra constraint to add a constant term 59to the objective values that they report if they're asked to print 60progress lines during their solution process), you allocate storage 61for the .sstatus values by (something equivalent to) 62 63 varstat = (int*)M1alloc(NB*sizeof(int)); 64 vsd = suf_iput("sstatus", ASL_Sufkind_var, varstat); 65 csd = suf_iput("sstatus", ASL_Sufkind_con, varstat + N); 66 67before invoking the .nl reader. After calling the reader, deal 68appropriately with the incoming .sstatus values, if present: 69 70 if (vsd->kind & ASL_Sufkind_input) 71 72then you have incoming variable.sstatus values in array varstat 73(the third argument to suf_iput); similarly, 74 75 if (csd->kind & ASL_Sufkind_input) 76 77then you have incoming constraint.sstatus values (which, in the 78above example, are in varstat+N, though you might wish to give 79a separate name to this array). The values are encoded as in 80the first column of AMPL's default $sstatus_table: 81 82 0 none no status assigned 83 1 bas basic 84 2 sup superbasic 85 3 low nonbasic <= (normally =) lower bound 86 4 upp nonbasic >= (normally =) upper bound 87 5 equ nonbasic at equal lower and upper bounds 88 6 btw nonbasic between bounds 89 90After solving the problem and before calling write_sol (which will 91transmit the suffix arrays mentioned in previous suf_iput and, for 92real, i.e., double, values, suf_rput calls), translate your basis 93information to values in the outgoing status arrays that accord with 94the above table. 95 96For returning real (floating-point) suffix values, call suf_rput 97rather than suf_iput. Examples (for sensitivity information, i.e., 98suffixes .up, .current, and .down) appear in the cplex.c and osl.c 99files mentioned above. 100 101Another detail not yet documented in "Hooking Your Solver..." is that 102you should assign a solve_result_num value to indicate success, 103failure, iteration limit, etc. before calling write_sol. This is 104an integer value in one of the ranges indicated by AMPL's default 105$solve_result_table: 106 107 0 solved 108 100 solved? 109 200 infeasible 110 300 unbounded 111 400 limit 112 500 failure 113 114For successful solves, solve_result_num should thus be an integer 115in [0,99]. If the problem might be solved, but tolerances may have 116been too tight to satisfy all stopping tests, assign an integer in 117[100,199], etc. -- any value >= 500 indicates failure (such as 118insufficient memory). Then AMPL's symbolic solve_result will be 119assigned one of the values in the second column of the above table, 120and scripts that need more detail can base tests on solve_result_num. 121 122Many of the sample solver interfaces appearing in subdirectories 123of netlib's ampl/solvers directory make use of suffixes and supply 124solve_result_num. 125