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