"Solver" gjh is an addition to ampl/solvers/examples meant to be described in a revision of "Hooking Your Solver to AMPL". This "solver" computes the current objective gradient, constraint Jacobian matrix, and Lagrangian Hessian and writes them as AMPL params (by default called g, J, and H, respectively; assignments in $gjh_options can change these names). Here's an example interactive AMPL session (indented), plus comments (unindented): ampl: model pgon.mod ampl data? 6; ampl data: option solver gjh; ampl: solve; gjh: "/tmp/at19224.gjh" written. Execute include "/tmp/at19224.gjh" remove "/tmp/at19224.gjh"; Thus gjh writes its output to a file, reports the file name, and shows how to use and delete the file. The file written is stub.gjh; you can specify the stub explicitly by using a "write" command before "solve" (as described on pp. 332-333 of the AMPL book), perhaps constructing it from a string expression involving _pid, the current process number, so with a little effort, gjh can be used in scripts (and the scripts can clean up after themselves by using the "remove" command). Continuing the example, we execute the commands printed by gjh and display g, J, and H: ampl: include "/tmp/at19224.gjh" ampl: remove "/tmp/at19224.gjh"; ampl: display g; g [*] := 1 0.204082 2 0.367347 3 0.44898 4 0.44898 5 0.244898 6 -0.173133 7 -0.173133 8 -0.0692532 9 0.0692532 10 0.346266 ; ampl: display J; J [*,*] : 1 2 3 4 5 6 := 1 -0.434327 0.784302 . . . -0.399833 2 2.22045e-16 . 1.46939 . . -0.831038 3 0.979592 . . 1.95918 . -0.9596 4 1.79592 . . . 2.12245 -0.692532 5 0.979592 . . . . 0 6 . -0.0640498 0.545265 . . . 7 . 0.653061 . 1.14286 . . 8 . 1.63265 . . 1.63265 . 9 . 1.63265 . . . . 10 . . 0.262481 0.262481 . . 11 . . 1.14286 . 0.653061 . 12 . . 1.95918 . . . 13 . . . 0.545265 -0.0640498 . 14 . . . 1.95918 . . 15 . . . . 1.63265 . 16 . . . . . -1 : 7 8 9 10 := 1 0.399833 . . . 2 . 0.831038 . . 3 . . 0.9596 . 4 . . . 0.692532 6 -0.799667 0.799667 . . 7 -1.38506 . 1.38506 . 8 -1.33278 . . 1.33278 9 0 . . . 10 . -0.9596 0.9596 . 11 . -1.38506 . 1.38506 12 . 0 . . 13 . . -0.799667 0.799667 14 . . 0 . 15 . . . 0 16 1 . . . 17 -1 1 . . 18 . -1 1 . 19 . . -1 1 ; ampl: display H; H [*,*] : 1 2 3 4 5 6 := 1 . 0.25 . . . -0.35348 2 0.25 . 0.25 . . -0.212088 3 . 0.25 . 0.25 . . 4 . . 0.25 . 0.25 . 5 . . . 0.25 . . 6 -0.35348 -0.212088 . . . -0.0999584 7 0.35348 -0.212088 -0.35348 . . 0.0999584 8 . 0.424176 -0.070696 -0.424176 . . 9 . . 0.424176 0.070696 -0.424176 . 10 . . . 0.35348 0.424176 . : 7 8 9 10 := 1 0.35348 . . . 2 -0.212088 0.424176 . . 3 -0.35348 -0.070696 0.424176 . 4 . -0.424176 0.070696 0.35348 5 . . -0.424176 0.424176 6 0.0999584 . . . 7 -0.299875 0.199917 . . 8 0.199917 -0.439817 0.2399 . 9 . 0.2399 -0.439817 0.199917 10 . . 0.199917 -0.199917 ; Thus g, J, and H are indexed as though declared param g{1.._snvars}; param J{1.._sncons, 1.._snvars}; param H{1.._snvars, 1.._snvars}; Of course, J and H are sparse in general; gjh only writes the structurally nonzero components, and the display command only shows the components whose values have been supplied, but the declarations in the .gjh file include "default 0" phrases so you can reference all the components of J and H, including the structural zeros. An alternative is to specify the keyword "sparse" in $gjh_options: ampl: option gjh_options 'sparse'; ampl: solve; gjh: sparse gjh: "/tmp/at19224.gjh" written. Execute include "/tmp/at19224.gjh" remove "/tmp/at19224.gjh"; ampl: include "/tmp/at19224.gjh" ampl: remove "/tmp/at19224.gjh"; (Since the .gjh file begins with "delete" commands, you can repeatedly generate and include it with little fuss.) When "sparse" is specified, index sets SJ and SH of the structural nonzeros also appear in the .gjh file: ampl: display SJ; set SJ := (1,1) (3,1) (5,1) (7,7) (10,3) (12,3) (15,5) (19,9) (1,2) (3,4) (5,6) (7,9) (10,4) (12,8) (15,10) (19,10) (1,6) (3,6) (6,2) (8,2) (10,8) (13,4) (16,6) (1,7) (3,9) (6,3) (8,5) (10,9) (13,5) (16,7) (2,1) (4,1) (6,7) (8,7) (11,3) (13,9) (17,7) (2,3) (4,5) (6,8) (8,10) (11,5) (13,10) (17,8) (2,6) (4,6) (7,2) (9,2) (11,8) (14,4) (18,8) (2,8) (4,10) (7,4) (9,7) (11,10) (14,9) (18,9); ampl: display SH; set SH := (1,2) (2,7) (3,9) (5,4) (6,7) (7,8) (8,9) (9,10) (1,6) (2,8) (4,3) (5,9) (7,1) (8,2) (9,3) (10,4) (1,7) (3,2) (4,5) (5,10) (7,2) (8,3) (9,4) (10,5) (2,1) (3,4) (4,8) (6,1) (7,3) (8,4) (9,5) (10,9) (2,3) (3,7) (4,9) (6,2) (7,6) (8,7) (9,8) (10,10) (2,6) (3,8) (4,10) (6,6) (7,7) (8,8) (9,9); Variants JS and HS of J and H also appear, declared param JS{SJ}; param HS{SH}; and J and H are derived from them. Because of this derivation, under "sparse", "display J;" and "display H;" show all zeros explicitly: ampl: display J; J [*,*] : 1 2 3 4 5 6 := 1 -0.434327 0.784302 0 0 0 -0.399833 2 2.22045e-16 0 1.46939 0 0 -0.831038 3 0.979592 0 0 1.95918 0 -0.9596 4 1.79592 0 0 0 2.12245 -0.692532 5 0.979592 0 0 0 0 0 6 0 -0.0640498 0.545265 0 0 0 7 0 0.653061 0 1.14286 0 0 8 0 1.63265 0 0 1.63265 0 9 0 1.63265 0 0 0 0 10 0 0 0.262481 0.262481 0 0 11 0 0 1.14286 0 0.653061 0 12 0 0 1.95918 0 0 0 13 0 0 0 0.545265 -0.0640498 0 14 0 0 0 1.95918 0 0 15 0 0 0 0 1.63265 0 16 0 0 0 0 0 -1 17 0 0 0 0 0 0 18 0 0 0 0 0 0 19 0 0 0 0 0 0 : 7 8 9 10 := 1 0.399833 0 0 0 2 0 0.831038 0 0 3 0 0 0.9596 0 4 0 0 0 0.692532 5 0 0 0 0 6 -0.799667 0.799667 0 0 7 -1.38506 0 1.38506 0 8 -1.33278 0 0 1.33278 9 0 0 0 0 10 0 -0.9596 0.9596 0 11 0 -1.38506 0 1.38506 12 0 0 0 0 13 0 0 -0.799667 0.799667 14 0 0 0 0 15 0 0 0 0 16 1 0 0 0 17 -1 1 0 0 18 0 -1 1 0 19 0 0 -1 1 ; ampl: display H; H [*,*] : 1 2 3 4 5 6 := 1 0 0.25 0 0 0 -0.35348 2 0.25 0 0.25 0 0 -0.212088 3 0 0.25 0 0.25 0 0 4 0 0 0.25 0 0.25 0 5 0 0 0 0.25 0 0 6 -0.35348 -0.212088 0 0 0 -0.0999584 7 0.35348 -0.212088 -0.35348 0 0 0.0999584 8 0 0.424176 -0.070696 -0.424176 0 0 9 0 0 0.424176 0.070696 -0.424176 0 10 0 0 0 0.35348 0.424176 0 : 7 8 9 10 := 1 0.35348 0 0 0 2 -0.212088 0.424176 0 0 3 -0.35348 -0.070696 0.424176 0 4 0 -0.424176 0.070696 0.35348 5 0 0 -0.424176 0.424176 6 0.0999584 0 0 0 7 -0.299875 0.199917 0 0 8 0.199917 -0.439817 0.2399 0 9 0 0.2399 -0.439817 0.199917 10 0 0 0.199917 -0.199917 ; ampl: display HS; HS [*,*] : 1 2 3 4 5 6 := 1 . 0.25 . . . -0.35348 2 0.25 . 0.25 . . -0.212088 3 . 0.25 . 0.25 . . 4 . . 0.25 . 0.25 . 5 . . . 0.25 . . 6 -0.35348 -0.212088 . . . -0.0999584 7 0.35348 -0.212088 -0.35348 . . 0.0999584 8 . 0.424176 -0.070696 -0.424176 . . 9 . . 0.424176 0.070696 -0.424176 . 10 . . . 0.35348 0.424176 . : 7 8 9 10 := 1 0.35348 . . . 2 -0.212088 0.424176 . . 3 -0.35348 -0.070696 0.424176 . 4 . -0.424176 0.070696 0.35348 5 . . -0.424176 0.424176 6 0.0999584 . . . 7 -0.299875 0.199917 . . 8 0.199917 -0.439817 0.2399 . 9 . 0.2399 -0.439817 0.199917 10 . . 0.199917 -0.199917 ; Changing the current primal or dual variable values of course affects the values that gjh computes. For example, using lancelot to solve the problem results in modified primal and dual variable values. (The constraint names stand for the associated dual variable values.) ampl: option solver lancelot; ampl: solve; LANCELOT: problem solved. 16 iterations; objective 0.674981803 M = 19, N = 29, nslacks = 19, NEL = 39, NG = 23 14 nontrivial linear maps reduce 56 variables to 42. NFCALL = 17, NGCALL = 15 ampl: option solver gjh, gjh_options ''; ampl: solve; gjh: "/tmp/at19224.gjh" written. Execute include "/tmp/at19224.gjh" remove "/tmp/at19224.gjh"; ampl: include "/tmp/at19224.gjh" ampl: remove "/tmp/at19224.gjh"; ampl: display g; g [*] := 1 0.156506 2 0.263673 3 0.386322 4 0.469528 5 0.313462 6 -0.199432 7 -0.171877 8 -0.0505769 9 0.171882 10 0.250004 ; ampl: display J; J [*,*] : 1 2 3 4 5 6 := 1 -0.309183 0.534619 . . . -0.34993 2 -0.384327 . 1.16027 . . -0.738009 3 0.558972 . . 1.68755 . -1.0734 4 1.6111 . . . 1.7131 -0.662424 5 1.11795 . . . . 0 6 . -0.347709 0.514763 . . . 7 . 0.275106 . 1.00006 . . 8 . 1.53395 . . 1.25391 . 9 . 1.5584 . . . . 10 . . 0.312455 0.312455 . . 11 . . 1.5881 . 0.641791 . 12 . . 2 . . . 13 . . . 0.999983 -0.274577 . 14 . . . 2 . . 15 . . . . 1.28358 . 16 . . . . . -1 : 7 8 9 10 := 1 0.34993 . . . 2 . 0.738009 . . 3 . . 1.0734 . 4 . . . 0.662424 6 -0.471885 0.471885 . . 7 -1.19529 . 1.19529 . 8 -0.999987 . . 0.999987 9 0 . . . 10 . -1.0734 1.0734 . 11 . -1.2157 . 1.2157 12 . 0 . . 13 . . -0.804709 0.804709 14 . . 0 . 15 . . . 0 16 1 . . . 17 -1 1 . . 18 . -1 1 . 19 . . -1 1 ; ampl: display H; H [*,*] : 1 2 3 4 5 := 1 -0.403424 0.200853 -3.41214e-06 0.0895077 -0.0319518 2 0.200853 -0.34377 0.1514 -4.21932e-06 0.00654696 3 -3.41214e-06 0.1514 -0.0831951 0.268349 0.0266994 4 0.0895077 -4.21932e-06 0.268349 -0.320249 0.313462 5 -0.0319518 0.00654696 0.0266994 0.313462 -0.510149 6 -1.37886e-05 -0.255945 -1.67625e-06 0.171881 0.0429193 7 0.356783 8.11651e-06 -0.37131 -3.92999e-06 0.267824 8 2.9988e-06 0.476527 -1.25798e-06 -0.421887 0.0788024 9 -0.307494 5.04362e-06 0.421887 6.20126e-06 -0.38954 10 -0.0492784 -0.220595 -0.0505748 0.250004 -5.5473e-06 : 6 7 8 9 10 := 1 -1.37886e-05 0.356783 2.9988e-06 -0.307494 -0.0492784 2 -0.255945 8.11651e-06 0.476527 5.04362e-06 -0.220595 3 -1.67625e-06 -0.37131 -1.25798e-06 0.421887 -0.0505748 4 0.171881 -3.92999e-06 -0.421887 6.20126e-06 0.250004 5 0.0429193 0.267824 0.0788024 -0.38954 -5.5473e-06 6 -0.12605 0.0874818 -1.9073e-06 0.0500324 -0.0114625 7 0.0874818 -0.208723 0.117971 -3.28769e-06 0.00327403 8 -1.9073e-06 0.117971 -0.403453 0.268349 0.0171355 9 0.0500324 -3.28769e-06 0.268349 -0.519556 0.201178 10 -0.0114625 0.00327403 0.0171355 0.201178 -0.210125 ; Some of the small nonzeros are caused by tiny dual variable values that should problem be zero. Using generic synonyms _conname and _con, we can see all the dual variable names and values: ampl: display _conname, _con; : _conname _con := 1 'cd[1,2]' -1.02072e-06 2 'cd[1,3]' -2.27132e-06 3 'cd[1,4]' 0.160128 4 'cd[1,5]' 0.0415826 5 'cd[1,6]' 4.60307e-06 6 'cd[2,3]' -4.84438e-07 7 'cd[2,4]' -3.28789e-06 8 'cd[2,5]' 0.17189 9 'cd[2,6]' 1.12658e-07 10 'cd[3,4]' -9.93185e-07 11 'cd[3,5]' 0.0416013 12 'cd[3,6]' 0 13 'cd[4,5]' 2.66996e-07 14 'cd[4,6]' 1.79723e-07 15 'cd[5,6]' 6.35108e-07 16 'ac[2]' 3.30362e-06 17 'ac[3]' -2.04757e-06 18 'ac[4]' 3.14837e-07 19 'ac[5]' 1.76666e-06 20 'ac[6]' 0 21 fix_theta 0 22 fix_rho 0.14941 ; And with a suitable "let" command, we can zero the tiny ones: ampl: let{i in 1.._sncons: abs(_scon[i]) < 1e-5} _scon[i] := 0; ampl: display _conname, _con; : _conname _con := 1 'cd[1,2]' 0 2 'cd[1,3]' 0 3 'cd[1,4]' 0.160128 4 'cd[1,5]' 0.0415826 5 'cd[1,6]' 0 6 'cd[2,3]' 0 7 'cd[2,4]' 0 8 'cd[2,5]' 0.17189 9 'cd[2,6]' 0 10 'cd[3,4]' 0 11 'cd[3,5]' 0.0416013 12 'cd[3,6]' 0 13 'cd[4,5]' 0 14 'cd[4,6]' 0 15 'cd[5,6]' 0 16 'ac[2]' 0 17 'ac[3]' 0 18 'ac[4]' 0 19 'ac[5]' 0 20 'ac[6]' 0 21 fix_theta 0 22 fix_rho 0.149413 ; This results in a modified Lagrangian Hessian: ampl: solve; gjh: "/tmp/at19224.gjh" written. Execute include "/tmp/at19224.gjh" remove "/tmp/at19224.gjh"; ampl: include "/tmp/at19224.gjh" ampl: remove "/tmp/at19224.gjh"; ampl: display H; H [*,*] : 1 2 3 4 5 := 1 -0.403422 0.200855 0 0.0895077 -0.0319518 2 0.200855 -0.343779 0.151401 0 0.00654696 3 0 0.151401 -0.0832026 0.268351 0.0266994 4 0.0895077 0 0.268351 -0.320257 0.313462 5 -0.0319518 0.00654696 0.0266994 0.313462 -0.510147 6 -1.01508e-05 -0.255945 0 0.171881 0.0429193 7 0.356783 1.29951e-05 -0.371309 0 0.267824 8 0 0.476527 -2.09675e-06 -0.421886 0.0788024 9 -0.307494 0 0.421886 9.90327e-07 -0.389541 10 -0.0492784 -0.220595 -0.0505748 0.250004 -5.21252e-06 : 6 7 8 9 10 := 1 -1.01508e-05 0.356783 0 -0.307494 -0.0492784 2 -0.255945 1.29951e-05 0.476527 0 -0.220595 3 0 -0.371309 -2.09675e-06 0.421886 -0.0505748 4 0.171881 0 -0.421886 9.90327e-07 0.250004 5 0.0429193 0.267824 0.0788024 -0.389541 -5.21252e-06 6 -0.126052 0.0874826 0 0.0500324 -0.0114625 7 0.0874826 -0.208728 0.117971 0 0.00327403 8 0 0.117971 -0.403457 0.268351 0.0171355 9 0.0500324 0 0.268351 -0.51956 0.201177 10 -0.0114625 0.00327403 0.0171355 0.201177 -0.210124 ; ampl: quit Source for "gjh" is gjh.c; sample makefiles makefile.u and makefile.vc now have rules to permit invoking "make gjh" or "nmake gjh.exe", respectively (as usual, after copying makefile.u or makefile.vc to makefile and editing makefile if necessary -- see the comments in makefile.u for some system-specific changes).