Parent Directory | Revision Log
Fixed debian build (still some 'lintian' problems) Updated ascend.spec from latest ascend.spec.in. Removed debug output in asc_conopt.c.
1 | johnpye | 843 | /* ASCEND modelling environment |
2 | johnpye | 1259 | Copyright (C) 1997, 2006, 2007 Carnegie Mellon University |
3 | aw0a | 1 | |
4 | johnpye | 843 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 59 Temple Place - Suite 330, | ||
17 | Boston, MA 02111-1307, USA. | ||
18 | *//** | ||
19 | @file | ||
20 | Connection of the CONOPT solver into ASCEND. | ||
21 | *//* | ||
22 | jpye | 1491 | originally by Ken Tyner and Vicente Rico-Ramirez, Jun-Aug 1997. |
23 | updated for CONOPT 3 by John Pye, July 2006. | ||
24 | johnpye | 843 | */ |
25 | |||
26 | aw0a | 1 | #include <math.h> |
27 | johnpye | 1183 | |
28 | johnpye | 399 | #include <utilities/ascMalloc.h> |
29 | johnpye | 920 | #include <utilities/ascPanic.h> |
30 | johnpye | 399 | #include <utilities/set.h> |
31 | #include <general/tm_time.h> | ||
32 | johnpye | 908 | #include <general/mathmacros.h> |
33 | johnpye | 399 | #include <utilities/mem.h> |
34 | #include <general/list.h> | ||
35 | johnpye | 1183 | |
36 | #include <linear/mtx_vector.h> | ||
37 | |||
38 | johnpye | 1316 | #include <system/calc.h> |
39 | #include <system/relman.h> | ||
40 | #include <system/slv_stdcalls.h> | ||
41 | #include <system/block.h> | ||
42 | jpye | 1491 | #include <solver/solver.h> |
43 | aw0a | 1 | |
44 | jpye | 1540 | #include <solver/conopt_dl.h> |
45 | aw0a | 1 | |
46 | jpye | 1491 | typedef struct conopt_system_structure *conopt_system_t; |
47 | |||
48 | #ifdef ASC_WITH_CONOPT | ||
49 | # define HAVE_CONOPT 1 | ||
50 | #else | ||
51 | # define HAVE_CONOPT 0 | ||
52 | #endif | ||
53 | |||
54 | ASC_DLLSPEC SolverRegisterFn conopt_register; | ||
55 | |||
56 | #define conopt_register_conopt_function register_conopt_function | ||
57 | #define conopt_coicsm coicsm | ||
58 | #define conopt_coimem coimem | ||
59 | |||
60 | johnpye | 783 | #ifndef ASC_WITH_CONOPT |
61 | jpye | 1516 | int conopt_register(void){ |
62 | johnpye | 1257 | ERROR_REPORTER_HERE(ASC_PROG_ERR,"CONOPT has not been compiled into this copy of ASCEND."); |
63 | aw0a | 1 | return 1; |
64 | } | ||
65 | johnpye | 783 | #else |
66 | aw0a | 1 | |
67 | /* | ||
68 | johnpye | 788 | Output in user defined CONOPT subroutines |
69 | */ | ||
70 | aw0a | 1 | #define CONDBG 0 |
71 | #define NONBASIC_DEBUG FALSE | ||
72 | |||
73 | johnpye | 788 | #if CONDBG |
74 | # define CONOPT_CONSOLE_DEBUG(...) CONSOLE_DEBUG(__VA_ARGS__) | ||
75 | #else | ||
76 | # define CONOPT_CONSOLE_DEBUG(...) (void)0 | ||
77 | #endif | ||
78 | |||
79 | aw0a | 1 | /* |
80 | johnpye | 788 | makes lots of extra spew |
81 | */ | ||
82 | aw0a | 1 | #define DEBUG FALSE |
83 | |||
84 | jpye | 1491 | #define CONOPT(s) ((conopt_system_t)(s)) |
85 | #define MI8F(s) slv_get_output_file( CONOPT(s)->p.output.more_important ) | ||
86 | johnpye | 1257 | #define SERVER (sys->slv) |
87 | jpye | 1491 | #define conopt_PA_SIZE 56 |
88 | johnpye | 1257 | #define SAFE_CALC_PTR (sys->parm_array[0]) |
89 | #define SAFE_CALC ((*(int *)SAFE_CALC_PTR)) | ||
90 | #define SCALEOPT_PTR (sys->parm_array[1]) | ||
91 | #define SCALEOPT ((*(char **)SCALEOPT_PTR)) | ||
92 | #define TOO_SMALL_PTR (sys->parm_array[2]) | ||
93 | #define TOO_SMALL ((*(real64 *)TOO_SMALL_PTR)) | ||
94 | aw0a | 1 | #define UPDATE_NOMINALS_PTR (sys->parm_array[3]) |
95 | #define UPDATE_NOMINALS ((*(int *)UPDATE_NOMINALS_PTR)) | ||
96 | #define UPDATE_RELNOMS_PTR (sys->parm_array[4]) | ||
97 | johnpye | 1257 | #define UPDATE_RELNOMS ((*(int *)UPDATE_RELNOMS_PTR)) |
98 | aw0a | 1 | #define UPDATE_WEIGHTS_PTR (sys->parm_array[5]) |
99 | johnpye | 1257 | #define UPDATE_WEIGHTS ((*(int *)UPDATE_WEIGHTS_PTR)) |
100 | #define DUMPCNORM_PTR (sys->parm_array[6]) | ||
101 | #define DUMPCNORM ((*(int *)DUMPCNORM_PTR)) | ||
102 | #define CNLOW_PTR (sys->parm_array[7]) | ||
103 | #define CNLOW ((*(real64 *)CNLOW_PTR)) | ||
104 | #define CNHIGH_PTR (sys->parm_array[8]) | ||
105 | #define CNHIGH ((*(real64 *)CNHIGH_PTR)) | ||
106 | aw0a | 1 | #define UPDATE_JACOBIAN_PTR (sys->parm_array[9]) |
107 | #define UPDATE_JACOBIAN ((*(int *)UPDATE_JACOBIAN_PTR)) | ||
108 | #define ITSCALELIM_PTR (sys->parm_array[10]) | ||
109 | #define ITSCALELIM ((*(int *)ITSCALELIM_PTR)) | ||
110 | #define ITSCALETOL_PTR (sys->parm_array[11]) | ||
111 | #define ITSCALETOL ((*(real64 *)ITSCALETOL_PTR)) | ||
112 | johnpye | 1257 | #define LIFDS_PTR (sys->parm_array[12]) |
113 | #define LIFDS ((*(int32 *)LIFDS_PTR)) | ||
114 | aw0a | 1 | #define REORDER_OPTION_PTR (sys->parm_array[13]) |
115 | johnpye | 1257 | #define REORDER_OPTION ((*(char **)REORDER_OPTION_PTR)) |
116 | #define CUTOFF_PTR (sys->parm_array[14]) | ||
117 | #define CUTOFF ((*(int32 *)CUTOFF_PTR)) | ||
118 | aw0a | 1 | #define RELNOMSCALE_PTR (sys->parm_array[15]) |
119 | johnpye | 1257 | #define RELNOMSCALE ((*(int *)RELNOMSCALE_PTR)) |
120 | aw0a | 1 | #define ITER_LIMIT_PTR (sys->parm_array[16]) |
121 | #define ITER_LIMIT ((*(int32 *)ITER_LIMIT_PTR)) | ||
122 | #define TIME_LIMIT_PTR (sys->parm_array[17]) | ||
123 | #define TIME_LIMIT ((*(int32 *)TIME_LIMIT_PTR)) | ||
124 | johnpye | 1257 | #define DOMLIM_PTR (sys->parm_array[18]) |
125 | #define DOMLIM ((*(int32 *)DOMLIM_PTR)) | ||
126 | #define RTMAXJ_PTR (sys->parm_array[19]) | ||
127 | #define RTMAXJ ((*(real64 *)RTMAXJ_PTR)) | ||
128 | aw0a | 1 | |
129 | /* | ||
130 | johnpye | 788 | Auxiliary structures |
131 | */ | ||
132 | aw0a | 1 | |
133 | struct update_data { | ||
134 | int jacobian; /* Countdown on jacobian updating */ | ||
135 | int weights; /* Countdown on weights updating */ | ||
136 | int nominals; /* Countdown on nominals updating */ | ||
137 | int relnoms; /* Countdown on relnom updating */ | ||
138 | int iterative; /* Countdown on iterative scale update */ | ||
139 | }; | ||
140 | |||
141 | |||
142 | /* | ||
143 | johnpye | 788 | varpivots, relpivots used only in optimizing, if we rewrite calc_pivots |
144 | without them. | ||
145 | */ | ||
146 | aw0a | 1 | struct jacobian_data { |
147 | linsolqr_system_t sys; /* Linear system */ | ||
148 | mtx_matrix_t mtx; /* Transpose gradient of residuals */ | ||
149 | real64 *rhs; /* RHS from linear system */ | ||
150 | unsigned *varpivots; /* Pivoted variables */ | ||
151 | unsigned *relpivots; /* Pivoted relations */ | ||
152 | unsigned *subregions; /* Set of subregion indeces */ | ||
153 | dof_t *dofdata; /* dof data pointer from server */ | ||
154 | mtx_region_t reg; /* Current block region */ | ||
155 | int32 rank; /* Numerical rank of the jacobian */ | ||
156 | johnpye | 788 | enum factor_method fm; /* Linear factorization method */ |
157 | aw0a | 1 | boolean accurate; /* ? Recalculate matrix */ |
158 | boolean singular; /* ? Can matrix be inverted */ | ||
159 | johnpye | 788 | boolean old_partition;/* old value of partition flag */ |
160 | aw0a | 1 | }; |
161 | |||
162 | jpye | 1491 | struct conopt_system_structure { |
163 | aw0a | 1 | |
164 | /* | ||
165 | johnpye | 788 | Problem definition |
166 | */ | ||
167 | slv_system_t slv; /* slv_system_t back-link */ | ||
168 | aw0a | 1 | struct rel_relation *obj; /* Objective function: NULL = none */ |
169 | struct rel_relation *old_obj;/* Objective function: NULL = none */ | ||
170 | struct var_variable **vlist; /* Variable list (NULL terminated) */ | ||
171 | struct rel_relation **rlist; /* Relation list (NULL terminated) */ | ||
172 | |||
173 | /* | ||
174 | johnpye | 788 | Solver information |
175 | */ | ||
176 | aw0a | 1 | int integrity; /* ? Has the system been created */ |
177 | int32 presolved; /* ? Has the system been presolved */ | ||
178 | int32 resolve; /* ? Has the system been resolved */ | ||
179 | slv_parameters_t p; /* Parameters */ | ||
180 | slv_status_t s; /* Status (as of iteration end) */ | ||
181 | struct update_data update; /* Jacobian frequency counters */ | ||
182 | int32 cap; /* Order of matrix/vectors */ | ||
183 | int32 rank; /* Symbolic rank of problem */ | ||
184 | int32 vused; /* Free and incident variables */ | ||
185 | int32 vtot; /* length of varlist */ | ||
186 | int32 rused; /* Included relations */ | ||
187 | int32 rtot; /* length of rellist */ | ||
188 | double clock; /* CPU time */ | ||
189 | |||
190 | jpye | 1491 | void *parm_array[conopt_PA_SIZE]; |
191 | struct slv_parameter pa[conopt_PA_SIZE]; | ||
192 | aw0a | 1 | |
193 | /* | ||
194 | johnpye | 788 | CONOPT DATA |
195 | */ | ||
196 | aw0a | 1 | struct conopt_data con; |
197 | |||
198 | /* | ||
199 | johnpye | 788 | Calculated data (scaled) |
200 | */ | ||
201 | aw0a | 1 | struct jacobian_data J; /* linearized system */ |
202 | |||
203 | johnpye | 1060 | struct vec_vector nominals; /* Variable nominals */ |
204 | struct vec_vector weights; /* Relation weights */ | ||
205 | struct vec_vector relnoms; /* Relation nominals */ | ||
206 | struct vec_vector variables; /* Variable values */ | ||
207 | struct vec_vector residuals; /* Relation residuals */ | ||
208 | aw0a | 1 | |
209 | johnpye | 788 | real64 objective; /* Objective function evaluation */ |
210 | aw0a | 1 | }; |
211 | |||
212 | |||
213 | johnpye | 788 | /*------------------------------------------------------------------------------ |
214 | INTEGRITY CHECKS | ||
215 | */ | ||
216 | aw0a | 1 | |
217 | #define OK ((int32)813029392) | ||
218 | #define DESTROYED ((int32)103289182) | ||
219 | |||
220 | johnpye | 788 | /** |
221 | Checks sys for NULL and for integrity. | ||
222 | */ | ||
223 | jpye | 1491 | static int check_system(conopt_system_t sys){ |
224 | jpye | 1487 | |
225 | aw0a | 1 | if( sys == NULL ) { |
226 | johnpye | 1257 | ERROR_REPORTER_HERE(ASC_PROG_ERR,"NULL system handle"); |
227 | aw0a | 1 | return 1; |
228 | } | ||
229 | |||
230 | switch( sys->integrity ) { | ||
231 | case OK: | ||
232 | return 0; | ||
233 | case DESTROYED: | ||
234 | johnpye | 1257 | ERROR_REPORTER_HERE(ASC_PROG_ERR,"System was recently destroyed."); |
235 | aw0a | 1 | return 1; |
236 | default: | ||
237 | johnpye | 1257 | ERROR_REPORTER_HERE(ASC_PROG_ERR,"System reused or never allocated."); |
238 | aw0a | 1 | return 1; |
239 | } | ||
240 | } | ||
241 | |||
242 | johnpye | 788 | /*------------------------------------------------------------------------------ |
243 | GENERAL INPUT/OUTPUT ROUTINES | ||
244 | */ | ||
245 | aw0a | 1 | |
246 | #define print_var_name(a,b,c) slv_print_var_name((a),(b)->slv,(c)) | ||
247 | #define print_rel_name(a,b,c) slv_print_rel_name((a),(b)->slv,(c)) | ||
248 | |||
249 | johnpye | 788 | /*------------------------------------------------------------------------------ |
250 | DEBUG OUTPUT ROUTINES | ||
251 | */ | ||
252 | aw0a | 1 | |
253 | johnpye | 788 | /** |
254 | Output a hyphenated line. | ||
255 | */ | ||
256 | static void debug_delimiter(){ | ||
257 | CONSOLE_DEBUG("------------------------------------------------"); | ||
258 | aw0a | 1 | } |
259 | |||
260 | #if DEBUG | ||
261 | |||
262 | johnpye | 788 | /** |
263 | Output a vector. | ||
264 | */ | ||
265 | jpye | 1491 | static void debug_out_vector(conopt_system_t sys |
266 | johnpye | 1060 | ,struct vec_vector *vec |
267 | johnpye | 788 | ){ |
268 | aw0a | 1 | int32 ndx; |
269 | johnpye | 788 | CONSOLE_DEBUG("Norm = %g, Accurate = %s, Vector range = %d to %d\n", |
270 | aw0a | 1 | calc_sqrt_D0(vec->norm2), vec->accurate?"TRUE":"FALSE", |
271 | johnpye | 788 | vec->rng->low,vec->rng->high |
272 | ); | ||
273 | CONSOLE_DEBUG("Vector --> "); | ||
274 | aw0a | 1 | for( ndx=vec->rng->low ; ndx<=vec->rng->high ; ++ndx ) |
275 | johnpye | 788 | CONSOLE_DEBUG("%g ", vec->vec[ndx]); |
276 | aw0a | 1 | } |
277 | |||
278 | johnpye | 788 | /** |
279 | Output all variable values in current block. | ||
280 | */ | ||
281 | jpye | 1491 | static void debug_out_var_values(conopt_system_t sys){ |
282 | aw0a | 1 | int32 col; |
283 | struct var_variable *var; | ||
284 | |||
285 | johnpye | 788 | CONSOLE_DEBUG("Var values -->"); |
286 | aw0a | 1 | for( col = sys->J.reg.col.low; col <= sys->J.reg.col.high ; col++ ) { |
287 | var = sys->vlist[mtx_col_to_org(sys->J.mtx,col)]; | ||
288 | johnpye | 788 | print_var_name(ASCERR,sys,var); /** @TODO fix this */ |
289 | CONSOLE_DEBUG("I Lb Value Ub Scale Col INom"); | ||
290 | CONSOLE_DEBUG("%d\t%.4g\t%.4g\t%.4g\t%.4g\t%d\t%.4g", | ||
291 | aw0a | 1 | var_sindex(var),var_lower_bound(var),var_value(var), |
292 | var_upper_bound(var),var_nominal(var), | ||
293 | johnpye | 788 | col,sys->nominals.vec[col] |
294 | ); | ||
295 | aw0a | 1 | } |
296 | } | ||
297 | |||
298 | johnpye | 788 | /** |
299 | Output all relation residuals in current block. | ||
300 | */ | ||
301 | jpye | 1491 | static void debug_out_rel_residuals(conopt_system_t sys){ |
302 | aw0a | 1 | int32 row; |
303 | |||
304 | johnpye | 788 | CONSOLE_DEBUG("Rel residuals -->"); |
305 | aw0a | 1 | for( row = sys->J.reg.row.low; row <= sys->J.reg.row.high ; row++ ) { |
306 | struct rel_relation *rel; | ||
307 | rel = sys->rlist[mtx_row_to_org(sys->J.mtx,row)]; | ||
308 | johnpye | 788 | CONSOLE_DEBUG(" %g : ",rel_residual(rel)); |
309 | print_rel_name(ASCERR,sys,rel); /** @TODO fix this */ | ||
310 | aw0a | 1 | } |
311 | } | ||
312 | |||
313 | |||
314 | johnpye | 788 | /** |
315 | Output permutation and values of the nonzero elements in the | ||
316 | the jacobian matrix. | ||
317 | */ | ||
318 | jpye | 1491 | static void debug_out_jacobian(conopt_system_t sys){ |
319 | aw0a | 1 | mtx_coord_t nz; |
320 | real64 value; | ||
321 | |||
322 | nz.row = sys->J.reg.row.low; | ||
323 | johnpye | 788 | for( ; nz.row <= sys->J.reg.row.high; ++(nz.row) ){ |
324 | CONSOLE_DEBUG("Row %d (rel %d)\n" | ||
325 | , nz.row, mtx_row_to_org(sys->J.mtx,nz.row) | ||
326 | ); | ||
327 | aw0a | 1 | nz.col = mtx_FIRST; |
328 | johnpye | 788 | |
329 | while( | ||
330 | value = mtx_next_in_row(sys->J.mtx,&nz,&(sys->J.reg.col)) | ||
331 | , nz.col != mtx_LAST | ||
332 | ){ | ||
333 | CONSOLE_DEBUG("Col %d (var %d) has value %g\n", nz.col, | ||
334 | aw0a | 1 | mtx_col_to_org(sys->J.mtx,nz.col), value); |
335 | } | ||
336 | } | ||
337 | } | ||
338 | |||
339 | johnpye | 788 | /** |
340 | Output permutation and values of the nonzero elements in the | ||
341 | reduced hessian matrix. | ||
342 | */ | ||
343 | jpye | 1491 | static void debug_out_hessian( FILE *fp, conopt_system_t sys){ |
344 | aw0a | 1 | mtx_coord_t nz; |
345 | |||
346 | for( nz.row = 0; nz.row < sys->ZBZ.order; nz.row++ ) { | ||
347 | nz.col = nz.row + sys->J.reg.col.high + 1 - sys->ZBZ.order; | ||
348 | FPRINTF(fp," ZBZ[%d (var %d)] = ", | ||
349 | nz.row, mtx_col_to_org(sys->J.mtx,nz.col)); | ||
350 | for( nz.col = 0; nz.col < sys->ZBZ.order; nz.col++ ) { | ||
351 | FPRINTF(fp,"%10g ",sys->ZBZ.mtx[nz.row][nz.col]); | ||
352 | } | ||
353 | PUTC('\n',fp); | ||
354 | } | ||
355 | } | ||
356 | |||
357 | #endif /* DEBUG */ | ||
358 | |||
359 | johnpye | 788 | /*------------------------------------------------------------------------------ |
360 | ARRAY AND VECTOR OPERATIONS | ||
361 | aw0a | 1 | |
362 | johnpye | 788 | destroy_array(p) |
363 | create_array(len,type) | ||
364 | johnpye | 908 | |
365 | johnpye | 788 | zero_vector(vec) |
366 | copy_vector(vec1,vec2) | ||
367 | prod = inner_product(vec1,vec2) | ||
368 | norm2 = square_norm(vec) | ||
369 | matrix_product(mtx,vec,prod,scale,transpose) | ||
370 | */ | ||
371 | aw0a | 1 | |
372 | #define destroy_array(p) \ | ||
373 | if( (p) != NULL ) ascfree((p)) | ||
374 | #define create_array(len,type) \ | ||
375 | ((len) > 0 ? (type *)ascmalloc((len)*sizeof(type)) : NULL) | ||
376 | #define create_zero_array(len,type) \ | ||
377 | ((len) > 0 ? (type *)asccalloc((len),sizeof(type)) : NULL) | ||
378 | |||
379 | johnpye | 1060 | #define zero_vector(v) vec_zero(v) |
380 | #define copy_vector(v,t) vec_copy((v),(t)) | ||
381 | #define inner_product(v,u) vec_inner_product((v),(u)) | ||
382 | #define square_norm(v) vec_square_norm(v) | ||
383 | #define matrix_product(m,v,p,s,t) vec_matrix_product((m),(v),(p),(s),(t)) | ||
384 | aw0a | 1 | |
385 | |||
386 | johnpye | 788 | /*------------------------------------------------------------------------------ |
387 | CALCULATION ROUTINES | ||
388 | aw0a | 1 | |
389 | johnpye | 788 | ok = calc_objective(sys) |
390 | ok = calc_residuals(sys) | ||
391 | ok = calc_J(sys) | ||
392 | calc_nominals(sys) | ||
393 | calc_weights(sys) | ||
394 | scale_J(sys) | ||
395 | scale_variables(sys) | ||
396 | scale_residuals(sys) | ||
397 | */ | ||
398 | |||
399 | /** | ||
400 | Count jacobian elements and set max to the number of elements | ||
401 | in the densest row | ||
402 | */ | ||
403 | jpye | 1491 | static int32 num_jacobian_nonzeros(conopt_system_t sys, int32 *max){ |
404 | aw0a | 1 | int32 row, len, licn,c,count,row_max; |
405 | struct rel_relation *rel; | ||
406 | rel_filter_t rf; | ||
407 | var_filter_t vf; | ||
408 | const struct var_variable **list; | ||
409 | |||
410 | rf.matchbits = (REL_INCLUDED | REL_EQUALITY | REL_ACTIVE); | ||
411 | rf.matchvalue = (REL_INCLUDED | REL_EQUALITY | REL_ACTIVE); | ||
412 | vf.matchbits = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR | VAR_FIXED); | ||
413 | vf.matchvalue = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR); | ||
414 | |||
415 | licn = 0; | ||
416 | *max = 0; | ||
417 | row_max = sys->con.m; | ||
418 | if (sys->obj != NULL) { | ||
419 | row_max--; | ||
420 | } | ||
421 | /* replace at leisure with | ||
422 | * relman_jacobian_count(sys->rlist,row_max,&vfilter,&rfilter,max); | ||
423 | */ | ||
424 | for( row = 0; row < row_max; row++ ) { | ||
425 | rel = sys->rlist[row]; | ||
426 | if (rel_apply_filter(rel,&rf)) { /* shouldn't be needed */ | ||
427 | len = rel_n_incidences(rel); | ||
428 | list = rel_incidence_list(rel); | ||
429 | count = 0; | ||
430 | for (c=0; c < len; c++) { | ||
431 | if( var_apply_filter(list[c],&vf) ) { | ||
432 | licn++; | ||
433 | count++; | ||
434 | } | ||
435 | } | ||
436 | *max = MAX(*max,count); | ||
437 | } | ||
438 | } | ||
439 | if (sys->obj != NULL) { | ||
440 | rel = sys->obj; | ||
441 | len = rel_n_incidences(rel); | ||
442 | list = rel_incidence_list(rel); | ||
443 | count = 0; | ||
444 | for (c=0; c < len; c++) { | ||
445 | if( var_apply_filter(list[c],&vf) ) { | ||
446 | licn++; | ||
447 | count++; | ||
448 | } | ||
449 | } | ||
450 | *max = MAX(*max,count); | ||
451 | } | ||
452 | return licn; | ||
453 | } | ||
454 | |||
455 | |||
456 | johnpye | 788 | /** |
457 | Evaluate the objective function. | ||
458 | */ | ||
459 | jpye | 1491 | static boolean calc_objective( conopt_system_t sys){ |
460 | aw0a | 1 | calc_ok = TRUE; |
461 | johnpye | 920 | asc_assert(sys->obj!=NULL); |
462 | johnpye | 788 | sys->objective = (sys->obj ? relman_eval(sys->obj,&calc_ok,SAFE_CALC) : 0.0); |
463 | aw0a | 1 | return calc_ok; |
464 | } | ||
465 | |||
466 | johnpye | 788 | /** |
467 | Evaluate all objectives. | ||
468 | */ | ||
469 | jpye | 1491 | static boolean calc_objectives( conopt_system_t sys){ |
470 | aw0a | 1 | int32 len,i; |
471 | static rel_filter_t rfilter; | ||
472 | struct rel_relation **rlist=NULL; | ||
473 | rfilter.matchbits = (REL_INCLUDED); | ||
474 | rfilter.matchvalue =(REL_INCLUDED); | ||
475 | rlist = slv_get_solvers_obj_list(SERVER); | ||
476 | len = slv_get_num_solvers_objs(SERVER); | ||
477 | calc_ok = TRUE; | ||
478 | for (i = 0; i < len; i++) { | ||
479 | if (rel_apply_filter(rlist[i],&rfilter)) { | ||
480 | johnpye | 920 | asc_assert(rlist[i]!=NULL); |
481 | aw0a | 1 | relman_eval(rlist[i],&calc_ok,SAFE_CALC); |
482 | #if DEBUG | ||
483 | if (calc_ok == FALSE) { | ||
484 | johnpye | 788 | ERROR_REPORTER_HERE(ASC_PROG_ERR,"error in calc_objectives"); |
485 | calc_ok = TRUE; | ||
486 | aw0a | 1 | } |
487 | #endif /* DEBUG */ | ||
488 | } | ||
489 | } | ||
490 | return calc_ok; | ||
491 | } | ||
492 | |||
493 | johnpye | 788 | /** |
494 | Calculate all of the residuals in the current block and compute | ||
495 | johnpye | 908 | the residual norm for block status. |
496 | johnpye | 788 | |
497 | @return true iff calculations preceded without error. | ||
498 | */ | ||
499 | jpye | 1491 | static boolean calc_residuals( conopt_system_t sys){ |
500 | aw0a | 1 | int32 row; |
501 | struct rel_relation *rel; | ||
502 | double time0; | ||
503 | |||
504 | if( sys->residuals.accurate ) return TRUE; | ||
505 | |||
506 | calc_ok = TRUE; | ||
507 | row = sys->residuals.rng->low; | ||
508 | time0=tm_cpu_time(); | ||
509 | for( ; row <= sys->residuals.rng->high; row++ ) { | ||
510 | rel = sys->rlist[mtx_row_to_org(sys->J.mtx,row)]; | ||
511 | #if DEBUG | ||
512 | if (!rel) { | ||
513 | int32r; | ||
514 | r=mtx_row_to_org(sys->J.mtx,row); | ||
515 | johnpye | 788 | ERROR_REPORTER_HERE(ASC_PROG_ERR |
516 | ,"NULL relation found at row %d rel %d in calc_residuals!",(int)row,r | ||
517 | ); | ||
518 | aw0a | 1 | } |
519 | #endif /* DEBUG */ | ||
520 | johnpye | 920 | asc_assert(rel!=NULL); |
521 | aw0a | 1 | sys->residuals.vec[row] = relman_eval(rel,&calc_ok,SAFE_CALC); |
522 | |||
523 | relman_calc_satisfied(rel,sys->p.tolerance.feasible); | ||
524 | } | ||
525 | sys->s.block.functime += (tm_cpu_time() -time0); | ||
526 | sys->s.block.funcs++; | ||
527 | square_norm( &(sys->residuals) ); | ||
528 | sys->s.block.residual = calc_sqrt_D0(sys->residuals.norm2); | ||
529 | johnpye | 919 | if(!calc_ok){ |
530 | CONOPT_CONSOLE_DEBUG("ERROR IN EVALUATION"); | ||
531 | } | ||
532 | aw0a | 1 | return(calc_ok); |
533 | } | ||
534 | |||
535 | |||
536 | johnpye | 788 | /** |
537 | Calculate the current block of the jacobian. | ||
538 | It is initially unscaled. | ||
539 | */ | ||
540 | jpye | 1491 | static boolean calc_J( conopt_system_t sys){ |
541 | aw0a | 1 | int32 row; |
542 | var_filter_t vfilter; | ||
543 | double time0; | ||
544 | real64 resid; | ||
545 | |||
546 | calc_ok = TRUE; | ||
547 | vfilter.matchbits = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR | VAR_FIXED); | ||
548 | vfilter.matchvalue = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR); | ||
549 | time0=tm_cpu_time(); | ||
550 | mtx_clear_region(sys->J.mtx,&(sys->J.reg)); | ||
551 | for( row = sys->J.reg.row.low; row <= sys->J.reg.row.high; row++ ) { | ||
552 | struct rel_relation *rel; | ||
553 | rel = sys->rlist[row]; | ||
554 | relman_diffs(rel,&vfilter,sys->J.mtx,&resid,SAFE_CALC); | ||
555 | } | ||
556 | sys->s.block.jactime += (tm_cpu_time() - time0); | ||
557 | sys->s.block.jacs++; | ||
558 | |||
559 | if( --(sys->update.nominals) <= 0 ) sys->nominals.accurate = FALSE; | ||
560 | if( --(sys->update.weights) <= 0 ) sys->weights.accurate = FALSE; | ||
561 | |||
562 | return(calc_ok); | ||
563 | } | ||
564 | |||
565 | johnpye | 788 | /** |
566 | Retrieve the nominal values of all of the block variables, | ||
567 | and ensure that they are all strictly positive. | ||
568 | */ | ||
569 | jpye | 1491 | static void calc_nominals( conopt_system_t sys){ |
570 | aw0a | 1 | int32 col; |
571 | FILE *fp = MIF(sys); | ||
572 | if( sys->nominals.accurate ) return; | ||
573 | fp = MIF(sys); | ||
574 | col = sys->nominals.rng->low; | ||
575 | if(strcmp(SCALEOPT,"NONE") == 0 || | ||
576 | strcmp(SCALEOPT,"ITERATIVE") == 0){ | ||
577 | for( ; col <= sys->nominals.rng->high; col++ ) { | ||
578 | sys->nominals.vec[col] = 1; | ||
579 | } | ||
580 | } else { | ||
581 | for( ; col <= sys->nominals.rng->high; col++ ) { | ||
582 | struct var_variable *var; | ||
583 | real64 n; | ||
584 | var = sys->vlist[mtx_col_to_org(sys->J.mtx,col)]; | ||
585 | n = var_nominal(var); | ||
586 | if( n <= 0.0 ) { | ||
587 | if( n == 0.0 ) { | ||
588 | n = TOO_SMALL; | ||
589 | johnpye | 788 | |
590 | ERROR_REPORTER_START_HERE(ASC_USER_ERROR); | ||
591 | FPRINTF(ASCERR,"Variable "); | ||
592 | aw0a | 1 | print_var_name(fp,sys,var); |
593 | johnpye | 788 | FPRINTF(ASCERR," has nominal value of zero.\n"); |
594 | FPRINTF(ASCERR,"Resetting to %g.\n",n); | ||
595 | error_reporter_end_flush(); | ||
596 | |||
597 | aw0a | 1 | var_set_nominal(var,n); |
598 | } else { | ||
599 | n = -n; | ||
600 | johnpye | 788 | |
601 | johnpye | 908 | ERROR_REPORTER_START_HERE(ASC_USER_ERROR); |
602 | johnpye | 788 | FPRINTF(fp,"Variable "); |
603 | aw0a | 1 | print_var_name(fp,sys,var); |
604 | johnpye | 788 | FPRINTF(fp," has negative nominal value.\n"); |
605 | FPRINTF(fp,"Resetting to %g.\n",n); | ||
606 | error_reporter_end_flush(); | ||
607 | |||
608 | aw0a | 1 | var_set_nominal(var,n); |
609 | } | ||
610 | } | ||
611 | #if DEBUG | ||
612 | FPRINTF(fp,"Column %d is"); | ||
613 | print_var_name(fp,sys,var); | ||
614 | FPRINTF(fp,"\nScaling of column %d is %g\n",col,n); | ||
615 | #endif /* DEBUG */ | ||
616 | sys->nominals.vec[col] = n; | ||
617 | } | ||
618 | } | ||
619 | square_norm( &(sys->nominals) ); | ||
620 | sys->update.nominals = UPDATE_NOMINALS; | ||
621 | sys->nominals.accurate = TRUE; | ||
622 | } | ||
623 | |||
624 | |||
625 | johnpye | 788 | /** |
626 | Calculate the weights of all of the block relations | ||
627 | to scale the rows of the Jacobian. | ||
628 | */ | ||
629 | jpye | 1491 | static void calc_weights( conopt_system_t sys) |
630 | aw0a | 1 | { |
631 | mtx_coord_t nz; | ||
632 | real64 sum; | ||
633 | |||
634 | if( sys->weights.accurate ) | ||
635 | return; | ||
636 | |||
637 | nz.row = sys->weights.rng->low; | ||
638 | if(strcmp(SCALEOPT,"NONE") == 0 || | ||
639 | strcmp(SCALEOPT,"ITERATIVE") == 0) { | ||
640 | for( ; nz.row <= sys->weights.rng->high; (nz.row)++ ) { | ||
641 | sys->weights.vec[nz.row] = 1; | ||
642 | } | ||
643 | } else if (strcmp(SCALEOPT,"ROW_2NORM") == 0 || | ||
644 | strcmp(SCALEOPT,"2NORM+ITERATIVE") == 0) { | ||
645 | for( ; nz.row <= sys->weights.rng->high; (nz.row)++ ) { | ||
646 | sum=mtx_sum_sqrs_in_row(sys->J.mtx,nz.row,&(sys->J.reg.col)); | ||
647 | sys->weights.vec[nz.row] = (sum>0.0) ? 1.0/calc_sqrt_D0(sum) : 1.0; | ||
648 | } | ||
649 | } else if (strcmp(SCALEOPT,"RELNOM") == 0 || | ||
650 | strcmp(SCALEOPT,"RELNOM+ITERATIVE") == 0) { | ||
651 | for( ; nz.row <= sys->weights.rng->high; (nz.row)++ ) { | ||
652 | sys->weights.vec[nz.row] = | ||
653 | 1.0/rel_nominal(sys->rlist[mtx_row_to_org(sys->J.mtx,nz.row)]); | ||
654 | } | ||
655 | } | ||
656 | square_norm( &(sys->weights) ); | ||
657 | sys->update.weights = UPDATE_WEIGHTS; | ||
658 | sys->residuals.accurate = FALSE; | ||
659 | sys->weights.accurate = TRUE; | ||
660 | } | ||
661 | |||
662 | |||
663 | johnpye | 788 | /** |
664 | Scale the jacobian. | ||
665 | */ | ||
666 | jpye | 1491 | static void scale_J( conopt_system_t sys){ |
667 | aw0a | 1 | int32 row; |
668 | int32 col; | ||
669 | |||
670 | if( sys->J.accurate ) return; | ||
671 | |||
672 | calc_nominals(sys); | ||
673 | for( col=sys->J.reg.col.low; col <= sys->J.reg.col.high; col++ ) | ||
674 | mtx_mult_col(sys->J.mtx,col,sys->nominals.vec[col],&(sys->J.reg.row)); | ||
675 | |||
676 | calc_weights(sys); | ||
677 | for( row=sys->J.reg.row.low; row <= sys->J.reg.row.high; row++ ) | ||
678 | mtx_mult_row(sys->J.mtx,row,sys->weights.vec[row],&(sys->J.reg.col)); | ||
679 | } | ||
680 | |||
681 | johnpye | 788 | /** |
682 | @TODO document this | ||
683 | */ | ||
684 | jpye | 1491 | static void jacobian_scaled(conopt_system_t sys){ |
685 | aw0a | 1 | int32 col; |
686 | if (DUMPCNORM) { | ||
687 | for( col=sys->J.reg.col.low; col <= sys->J.reg.col.high; col++ ) { | ||
688 | real64 cnorm; | ||
689 | johnpye | 788 | cnorm = calc_sqrt_D0(mtx_sum_sqrs_in_col(sys->J.mtx,col,&(sys->J.reg.row))); |
690 | aw0a | 1 | if (cnorm >CNHIGH || cnorm <CNLOW) { |
691 | johnpye | 788 | ERROR_REPORTER_HERE(ASC_PROG_NOTE,"[col %d org %d] %g\n", col, |
692 | mtx_col_to_org(sys->J.mtx,col), cnorm | ||
693 | ); | ||
694 | aw0a | 1 | } |
695 | } | ||
696 | } | ||
697 | |||
698 | sys->update.jacobian = UPDATE_JACOBIAN; | ||
699 | sys->J.accurate = TRUE; | ||
700 | sys->J.singular = FALSE; /* yet to be determined */ | ||
701 | #if DEBUG | ||
702 | johnpye | 788 | CONSOLE_DEBUG("Jacobian:"); |
703 | debug_out_jacobian(sys); | ||
704 | aw0a | 1 | #endif /* DEBUG */ |
705 | } | ||
706 | |||
707 | johnpye | 788 | /** |
708 | @TODO document this | ||
709 | */ | ||
710 | jpye | 1491 | static void scale_variables( conopt_system_t sys) |
711 | aw0a | 1 | { |
712 | int32 col; | ||
713 | |||
714 | if( sys->variables.accurate ) return; | ||
715 | |||
716 | col = sys->variables.rng->low; | ||
717 | for( ; col <= sys->variables.rng->high; col++ ) { | ||
718 | struct var_variable *var = sys->vlist[mtx_col_to_org(sys->J.mtx,col)]; | ||
719 | sys->variables.vec[col] = var_value(var)/sys->nominals.vec[col]; | ||
720 | } | ||
721 | square_norm( &(sys->variables) ); | ||
722 | sys->variables.accurate = TRUE; | ||
723 | #if DEBUG | ||
724 | johnpye | 788 | CONSOLE_DEBUG("Variables:"); |
725 | debug_out_vector(sys,&(sys->variables)); | ||
726 | aw0a | 1 | #endif /* DEBUG */ |
727 | } | ||
728 | |||
729 | |||
730 | /* | ||
731 | * Scales the previously calculated residuals. | ||
732 | */ | ||
733 | jpye | 1491 | static void scale_residuals( conopt_system_t sys) |
734 | aw0a | 1 | { |
735 | int32 row; | ||
736 | |||
737 | if( sys->residuals.accurate ) return; | ||
738 | |||
739 | row = sys->residuals.rng->low; | ||
740 | for( ; row <= sys->residuals.rng->high; row++ ) { | ||
741 | struct rel_relation *rel = sys->rlist[mtx_row_to_org(sys->J.mtx,row)]; | ||
742 | sys->residuals.vec[row] = rel_residual(rel)*sys->weights.vec[row]; | ||
743 | } | ||
744 | square_norm( &(sys->residuals) ); | ||
745 | sys->residuals.accurate = TRUE; | ||
746 | #if DEBUG | ||
747 | johnpye | 788 | CONSOLE_DEBUG("Residuals:"); |
748 | debug_out_vector(sys,&(sys->residuals)); | ||
749 | aw0a | 1 | #endif /* DEBUG */ |
750 | } | ||
751 | |||
752 | |||
753 | johnpye | 788 | /** |
754 | Calculate relnoms for all relations in sys | ||
755 | using variable nominals. | ||
756 | */ | ||
757 | jpye | 1491 | static void calc_relnoms(conopt_system_t sys){ |
758 | aw0a | 1 | int32 row, col; |
759 | struct var_variable *var; | ||
760 | struct rel_relation *rel; | ||
761 | real64 *var_list; | ||
762 | var_list = create_array(sys->cap,real64); | ||
763 | col = 0; | ||
764 | var = sys->vlist[col]; | ||
765 | /* store current variable values and | ||
766 | set variable value to nominal value */ | ||
767 | while(var != NULL){ | ||
768 | var_list[col] = var_value(var); | ||
769 | var_set_value(var, var_nominal(var)); | ||
770 | col++; | ||
771 | var = sys->vlist[col]; | ||
772 | } | ||
773 | row = 0; | ||
774 | rel = sys->rlist[row]; | ||
775 | /* calculate relation nominal */ | ||
776 | while(rel != NULL){ | ||
777 | relman_scale(rel); | ||
778 | row++; | ||
779 | rel = sys->rlist[row]; | ||
780 | } | ||
781 | col = 0; | ||
782 | var = sys->vlist[col]; | ||
783 | /* restore variable values */ | ||
784 | while(var != NULL){ | ||
785 | var_set_value(var, var_list[col]); | ||
786 | col++; | ||
787 | var = sys->vlist[col]; | ||
788 | } | ||
789 | destroy_array(var_list); | ||
790 | } | ||
791 | |||
792 | /* | ||
793 | johnpye | 788 | Return the maximum ratio of magnitudes of any two nonzero |
794 | elements in the same column of mtx. Only consider elements | ||
795 | in region reg. | ||
796 | */ | ||
797 | aw0a | 1 | static real64 col_max_ratio(mtx_matrix_t *mtx, |
798 | mtx_region_t *reg) | ||
799 | { | ||
800 | real64 ratio; | ||
801 | real64 max_ratio; | ||
802 | real64 num, denom, dummy; | ||
803 | mtx_coord_t coord; | ||
804 | max_ratio = 0; | ||
805 | for(coord.col = reg->col.low; | ||
806 | coord.col <= reg->col.high; coord.col++) { | ||
807 | ratio = 0; | ||
808 | num = mtx_col_max(*mtx,&(coord),&(reg->row),&(dummy)); | ||
809 | denom = mtx_col_min(*mtx,&(coord),&(reg->row),&(dummy),1e-7); | ||
810 | if(denom >0){ | ||
811 | ratio = num/denom; | ||
812 | } | ||
813 | if(ratio > 10000000){ | ||
814 | /* FPRINTF(stderr,"HELPME\n");*/ | ||
815 | } | ||
816 | if(ratio > max_ratio){ | ||
817 | max_ratio = ratio; | ||
818 | } | ||
819 | } | ||
820 | if(max_ratio == 0){ | ||
821 | max_ratio = 1; | ||
822 | } | ||
823 | return max_ratio; | ||
824 | } | ||
825 | |||
826 | |||
827 | johnpye | 788 | /** |
828 | Return the maximum ratio of magnitudes of any two nonzero | ||
829 | elements in the same row of mtx. Only consider elements | ||
830 | in region reg. | ||
831 | */ | ||
832 | aw0a | 1 | static real64 row_max_ratio(mtx_matrix_t *mtx, |
833 | mtx_region_t *reg) | ||
834 | { | ||
835 | real64 ratio; | ||
836 | real64 max_ratio; | ||
837 | real64 num, denom, dummy; | ||
838 | mtx_coord_t coord; | ||
839 | max_ratio = 0; | ||
840 | for(coord.row = reg->row.low; | ||
841 | coord.row <= reg->row.high; coord.row++) { | ||
842 | ratio = 0; | ||
843 | num = mtx_row_max(*mtx,&(coord),&(reg->col),&(dummy)); | ||
844 | denom = mtx_row_min(*mtx,&(coord),&(reg->col),&(dummy),1e-7); | ||
845 | if(denom >0){ | ||
846 | ratio = num/denom; | ||
847 | } | ||
848 | if(ratio > 10000000){ | ||
849 | /* FPRINTF(stderr,"HELPME\n");*/ | ||
850 | } | ||
851 | if(ratio > max_ratio){ | ||
852 | max_ratio = ratio; | ||
853 | } | ||
854 | } | ||
855 | if(max_ratio == 0){ | ||
856 | max_ratio = 1; | ||
857 | } | ||
858 | return max_ratio; | ||
859 | } | ||
860 | |||
861 | johnpye | 788 | /** |
862 | Calculate scaling factor suggested by Fourer. | ||
863 | |||
864 | For option==0, returns scaling factor for | ||
865 | row number loc. | ||
866 | |||
867 | For option==1, returns scaling factor for | ||
868 | col number loc. | ||
869 | */ | ||
870 | aw0a | 1 | static real64 calc_fourer_scale(mtx_matrix_t mtx, |
871 | mtx_region_t reg, | ||
872 | int32 loc, | ||
873 | int32 option) | ||
874 | { | ||
875 | mtx_coord_t coord; | ||
876 | real64 min, max, dummy; | ||
877 | real64 scale; | ||
878 | if(option == 0){ | ||
879 | if((loc < reg.row.low) || (loc > reg.row.high)){ | ||
880 | return 1; | ||
881 | } | ||
882 | coord.row = loc; | ||
883 | min = mtx_row_min(mtx,&(coord),&(reg.col),&(dummy),1e-7); | ||
884 | max = mtx_row_max(mtx,&(coord),&(reg.col),&(dummy)); | ||
885 | scale = min*max; | ||
886 | if(scale > 0){ | ||
887 | scale = sqrt(scale); | ||
888 | } else { | ||
889 | scale = 1; | ||
890 | } | ||
891 | return scale; | ||
892 | } else { | ||
893 | if(loc < reg.col.low || loc > reg.col.high){ | ||
894 | return 1; | ||
895 | } | ||
896 | coord.col = loc; | ||
897 | min = mtx_col_min(mtx,&(coord),&(reg.row),&(dummy),1e-7); | ||
898 | max = mtx_col_max(mtx,&(coord),&(reg.row),&(dummy)); | ||
899 | scale = min*max; | ||
900 | if(scale > 0){ | ||
901 | scale = sqrt(scale); | ||
902 | } else { | ||
903 | scale = 1; | ||
904 | } | ||
905 | return scale; | ||
906 | } | ||
907 | } | ||
908 | |||
909 | johnpye | 788 | /** |
910 | An implementation of the scaling routine by Fourer on | ||
911 | p304 of Mathematical Programing vol 23, (1982). | ||
912 | |||
913 | Scale the Jacobian and store the scaling | ||
914 | factors in sys->nominals and sys->weights. | ||
915 | If the Jacobian has been previously scaled | ||
916 | by another method (during this iteration) then these vectors | ||
917 | should contain the scale factors used in that scaling. | ||
918 | */ | ||
919 | jpye | 1491 | static void scale_J_iterative(conopt_system_t sys){ |
920 | aw0a | 1 | real64 rho_col_old, rho_col_new; |
921 | real64 rho_row_old, rho_row_new; | ||
922 | int32 k; | ||
923 | int32 done; | ||
924 | int32 row, col; | ||
925 | real64 *colvec = sys->nominals.vec; | ||
926 | real64 *rowvec = sys->weights.vec; | ||
927 | real64 rowscale, colscale; | ||
928 | rho_col_old = col_max_ratio(&(sys->J.mtx),&(sys->J.reg)); | ||
929 | rho_row_old = row_max_ratio(&(sys->J.mtx),&(sys->J.reg)); | ||
930 | k = 0; | ||
931 | done = 0; | ||
932 | while(done == 0){ | ||
933 | k++; | ||
934 | for(row = sys->J.reg.row.low; | ||
935 | row <= sys->J.reg.row.high; row++){ | ||
936 | rowscale = 1/calc_fourer_scale(sys->J.mtx,sys->J.reg,row,0); | ||
937 | mtx_mult_row(sys->J.mtx,row,rowscale,&(sys->J.reg.col)); | ||
938 | rowvec[row] *= rowscale; | ||
939 | } | ||
940 | for(col = sys->J.reg.col.low; | ||
941 | col <= sys->J.reg.col.high; col++){ | ||
942 | colscale = 1/calc_fourer_scale(sys->J.mtx,sys->J.reg,col,1); | ||
943 | mtx_mult_col(sys->J.mtx,col,colscale,&(sys->J.reg.row)); | ||
944 | colvec[col] *= colscale; | ||
945 | } | ||
946 | rho_col_new = col_max_ratio(&(sys->J.mtx),&(sys->J.reg)); | ||
947 | rho_row_new = row_max_ratio(&(sys->J.mtx),&(sys->J.reg)); | ||
948 | if((rho_col_new >= ITSCALETOL*rho_col_old && | ||
949 | rho_row_new >= ITSCALETOL*rho_row_old) | ||
950 | || k >= ITSCALELIM){ | ||
951 | done = 1; | ||
952 | /* FPRINTF(MIF(sys),"%d ITERATIVE SCALING ITERATIONS\n",k);*/ | ||
953 | } else { | ||
954 | rho_row_old = rho_row_new; | ||
955 | rho_col_old = rho_col_new; | ||
956 | } | ||
957 | } | ||
958 | square_norm( &(sys->nominals) ); | ||
959 | sys->update.nominals = UPDATE_NOMINALS; | ||
960 | sys->nominals.accurate = TRUE; | ||
961 | |||
962 | square_norm( &(sys->weights) ); | ||
963 | sys->update.weights = UPDATE_WEIGHTS; | ||
964 | sys->residuals.accurate = FALSE; | ||
965 | sys->weights.accurate = TRUE; | ||
966 | } | ||
967 | |||
968 | |||
969 | johnpye | 788 | /** |
970 | Scale system dependent on interface parameters | ||
971 | */ | ||
972 | jpye | 1491 | static void scale_system( conopt_system_t sys ){ |
973 | aw0a | 1 | if(strcmp(SCALEOPT,"NONE") == 0){ |
974 | if(sys->J.accurate == FALSE){ | ||
975 | calc_nominals(sys); | ||
976 | calc_weights(sys); | ||
977 | jacobian_scaled(sys); | ||
978 | } | ||
979 | scale_variables(sys); | ||
980 | scale_residuals(sys); | ||
981 | return; | ||
982 | } | ||
983 | if(strcmp(SCALEOPT,"ROW_2NORM") == 0 || | ||
984 | strcmp(SCALEOPT,"RELNOM") == 0){ | ||
985 | if(sys->J.accurate == FALSE){ | ||
986 | scale_J(sys); | ||
987 | jacobian_scaled(sys); | ||
988 | } | ||
989 | scale_variables(sys); | ||
990 | scale_residuals(sys); | ||
991 | return; | ||
992 | } | ||
993 | if(strcmp(SCALEOPT,"2NORM+ITERATIVE") == 0 || | ||
994 | strcmp(SCALEOPT,"RELNOM+ITERATIVE") == 0){ | ||
995 | if(sys->J.accurate == FALSE){ | ||
996 | --sys->update.iterative; | ||
997 | if(sys->update.iterative <= 0) { | ||
998 | scale_J(sys); | ||
999 | scale_J_iterative(sys); | ||
1000 | sys->update.iterative = | ||
1001 | UPDATE_WEIGHTS < UPDATE_NOMINALS ? UPDATE_WEIGHTS : UPDATE_NOMINALS; | ||
1002 | } else { | ||
1003 | sys->weights.accurate = TRUE; | ||
1004 | sys->nominals.accurate = TRUE; | ||
1005 | scale_J(sys); /* will use current scaling vectors */ | ||
1006 | } | ||
1007 | jacobian_scaled(sys); | ||
1008 | } | ||
1009 | scale_variables(sys); | ||
1010 | scale_residuals(sys); | ||
1011 | return; | ||
1012 | } | ||
1013 | if(strcmp(SCALEOPT,"ITERATIVE") == 0){ | ||
1014 | if(sys->J.accurate == FALSE){ | ||
1015 | --sys->update.iterative; | ||
1016 | if(sys->update.iterative <= 0) { | ||
1017 | calc_nominals(sys); | ||
1018 | calc_weights(sys); | ||
1019 | scale_J_iterative(sys); | ||
1020 | sys->update.iterative = | ||
1021 | UPDATE_WEIGHTS < UPDATE_NOMINALS ? UPDATE_WEIGHTS : UPDATE_NOMINALS; | ||
1022 | } else { | ||
1023 | sys->weights.accurate = TRUE; | ||
1024 | sys->nominals.accurate = TRUE; | ||
1025 | scale_J(sys); /* will use current scaling vectors */ | ||
1026 | } | ||
1027 | jacobian_scaled(sys); | ||
1028 | } | ||
1029 | scale_variables(sys); | ||
1030 | scale_residuals(sys); | ||
1031 | } | ||
1032 | return; | ||
1033 | } | ||
1034 | |||
1035 | |||
1036 | johnpye | 788 | /** |
1037 | Reset all flags to setup a new solve. | ||
1038 | Should set sys->s.block.current_block = -1 | ||
1039 | before calling. | ||
1040 | johnpye | 908 | |
1041 | johnpye | 788 | @TODO This is currently a HACK! Not sure if should call when done. |
1042 | */ | ||
1043 | jpye | 1491 | static void conopt_initialize( conopt_system_t sys){ |
1044 | aw0a | 1 | |
1045 | sys->s.block.current_block++; | ||
1046 | /* | ||
1047 | * Next line was added to create the aray cost, whis is used by | ||
1048 | * the interface to display residuals and number of iterations | ||
1049 | */ | ||
1050 | sys->s.costsize = 1+sys->s.block.number_of; | ||
1051 | |||
1052 | if( sys->s.block.current_block < sys->s.block.number_of ) { | ||
1053 | boolean ok; | ||
1054 | |||
1055 | sys->s.block.iteration = 0; | ||
1056 | sys->s.block.cpu_elapsed = 0.0; | ||
1057 | sys->s.block.functime = 0.0; | ||
1058 | sys->s.block.jactime = 0.0; | ||
1059 | sys->s.block.funcs = 0; | ||
1060 | sys->s.block.jacs = 0; | ||
1061 | |||
1062 | sys->s.calc_ok = TRUE; | ||
1063 | |||
1064 | if(sys->p.output.less_important && (LIFDS || | ||
1065 | sys->s.block.current_size > 1)) { | ||
1066 | johnpye | 788 | debug_delimiter(); |
1067 | aw0a | 1 | } |
1068 | if(sys->p.output.less_important && LIFDS) { | ||
1069 | johnpye | 788 | CONSOLE_DEBUG("%-40s ---> %d in [%d..%d]" |
1070 | , "Current block number", sys->s.block.current_block | ||
1071 | , 0, sys->s.block.number_of-1 | ||
1072 | ); | ||
1073 | CONSOLE_DEBUG("%-40s ---> %d", "Current block size" | ||
1074 | , sys->s.block.current_size | ||
1075 | ); | ||
1076 | aw0a | 1 | } |
1077 | if( !(ok = calc_objective(sys)) ) { | ||
1078 | johnpye | 788 | ERROR_REPORTER_HERE(ASC_PROG_ERR,"Objective calculation errors detected."); |
1079 | aw0a | 1 | } |
1080 | if(sys->p.output.less_important && sys->obj) { | ||
1081 | johnpye | 788 | CONSOLE_DEBUG("%-40s ---> %g", "Objective", sys->objective); |
1082 | aw0a | 1 | } |
1083 | sys->s.calc_ok = sys->s.calc_ok && ok; | ||
1084 | |||
1085 | johnpye | 788 | if(!(sys->p.ignore_bounds) ) { |
1086 | johnpye | 1054 | slv_ensure_bounds( |
1087 | johnpye | 788 | SERVER, sys->J.reg.col.low, |
1088 | sys->J.reg.col.high,MIF(sys) | ||
1089 | ); | ||
1090 | aw0a | 1 | } |
1091 | |||
1092 | sys->residuals.accurate = FALSE; | ||
1093 | if( !(ok = calc_residuals(sys)) ) { | ||
1094 | johnpye | 788 | ERROR_REPORTER_HERE(ASC_PROG_ERR,"Residual calculation errors detected."); |
1095 | aw0a | 1 | } |
1096 | johnpye | 788 | if(sys->p.output.less_important && |
1097 | aw0a | 1 | (sys->s.block.current_size >1 || |
1098 | johnpye | 788 | LIFDS) |
1099 | ){ | ||
1100 | CONSOLE_DEBUG("%-40s ---> %g", "Residual norm (unscaled)",sys->s.block.residual); | ||
1101 | aw0a | 1 | } |
1102 | sys->s.calc_ok = sys->s.calc_ok && ok; | ||
1103 | |||
1104 | /* Must be updated as soon as required */ | ||
1105 | sys->J.accurate = FALSE; | ||
1106 | sys->update.weights = 0; | ||
1107 | sys->update.nominals = 0; | ||
1108 | sys->update.relnoms = 0; | ||
1109 | sys->update.iterative = 0; | ||
1110 | sys->variables.accurate = FALSE; | ||
1111 | } | ||
1112 | } | ||
1113 | |||
1114 | |||
1115 | johnpye | 788 | /*------------------------------------------------------------------------------ |
1116 | ITERATION BEGIN/END ROUTINES | ||
1117 | */ | ||
1118 | aw0a | 1 | |
1119 | johnpye | 788 | /** |
1120 | Prepare sys for entering an iteration, increasing the iteration counts | ||
1121 | and starting the clock. | ||
1122 | */ | ||
1123 | jpye | 1491 | static void iteration_begins( conopt_system_t sys){ |
1124 | aw0a | 1 | sys->clock = tm_cpu_time(); |
1125 | ++(sys->s.block.iteration); | ||
1126 | ++(sys->s.iteration); | ||
1127 | if(sys->p.output.less_important && LIFDS) { | ||
1128 | johnpye | 788 | CONSOLE_DEBUG("%-40s ---> %d","Iteration", sys->s.block.iteration); |
1129 | CONSOLE_DEBUG("%-40s ---> %d","Total iteration", sys->s.iteration); | ||
1130 | aw0a | 1 | } |
1131 | } | ||
1132 | |||
1133 | |||
1134 | /* | ||
1135 | johnpye | 788 | Prepare sys for exiting an iteration, stopping the clock and recording |
1136 | the cpu time. | ||
1137 | */ | ||
1138 | jpye | 1491 | static void iteration_ends( conopt_system_t sys){ |
1139 | aw0a | 1 | double cpu_elapsed; /* elapsed this iteration */ |
1140 | |||
1141 | cpu_elapsed = (double)(tm_cpu_time() - sys->clock); | ||
1142 | sys->s.block.cpu_elapsed += cpu_elapsed; | ||
1143 | sys->s.cpu_elapsed += cpu_elapsed; | ||
1144 | if(sys->p.output.less_important && LIFDS) { | ||
1145 | johnpye | 788 | CONSOLE_DEBUG("%-40s ---> %g","Elapsed time", sys->s.block.cpu_elapsed); |
1146 | CONSOLE_DEBUG("%-40s ---> %g","Total elapsed time", sys->s.cpu_elapsed); | ||
1147 | aw0a | 1 | } |
1148 | } | ||
1149 | |||
1150 | |||
1151 | johnpye | 788 | /** |
1152 | Update the solver status. | ||
1153 | aw0a | 1 | */ |
1154 | jpye | 1491 | static void update_status( conopt_system_t sys){ |
1155 | aw0a | 1 | boolean unsuccessful; |
1156 | |||
1157 | if( !sys->s.converged ) { | ||
1158 | sys->s.time_limit_exceeded = | ||
1159 | (sys->s.block.cpu_elapsed >= TIME_LIMIT); | ||
1160 | sys->s.iteration_limit_exceeded = | ||
1161 | (sys->s.block.iteration >= ITER_LIMIT); | ||
1162 | } | ||
1163 | |||
1164 | unsuccessful = sys->s.diverged || sys->s.inconsistent || | ||
1165 | sys->s.iteration_limit_exceeded || sys->s.time_limit_exceeded; | ||
1166 | |||
1167 | sys->s.ready_to_solve = !unsuccessful && !sys->s.converged; | ||
1168 | sys->s.ok = !unsuccessful && sys->s.calc_ok && !sys->s.struct_singular; | ||
1169 | } | ||
1170 | |||
1171 | |||
1172 | static | ||
1173 | jpye | 1491 | int32 conopt_get_default_parameters(slv_system_t server, SlvClientToken asys |
1174 | johnpye | 788 | , slv_parameters_t *parameters |
1175 | ){ | ||
1176 | jpye | 1491 | conopt_system_t sys; |
1177 | aw0a | 1 | union parm_arg lo,hi,val; |
1178 | struct slv_parameter *new_parms = NULL; | ||
1179 | static char *reorder_names[] = { | ||
1180 | "SPK1","TEAR_DROP","OVER_TEAR" | ||
1181 | }; | ||
1182 | static char *scaling_names[] = { | ||
1183 | "NONE","ROW_2NORM","RELNOM" /*,"2NORM+ITERATIVE", | ||
1184 | "RELNOM+ITERATIVE","ITERATIVE" */ | ||
1185 | }; | ||
1186 | int32 make_macros = 0; | ||
1187 | if (server != NULL && asys != NULL) { | ||
1188 | jpye | 1491 | sys = CONOPT(asys); |
1189 | aw0a | 1 | make_macros = 1; |
1190 | } | ||
1191 | |||
1192 | #if DEBUG /* keep purify from whining on UMR */ | ||
1193 | lo.argr = hi.argr = val.argr = 0.0; | ||
1194 | #endif /* DEBUG */ | ||
1195 | |||
1196 | if (parameters->parms == NULL) { | ||
1197 | /* an external client wants our parameter list. | ||
1198 | jpye | 1491 | * an instance of conopt_system_structure has this pointer |
1199 | * already set in conopt_create | ||
1200 | aw0a | 1 | */ |
1201 | jpye | 1491 | new_parms = ASC_NEW_ARRAY(struct slv_parameter, conopt_PA_SIZE); |
1202 | aw0a | 1 | if (new_parms == NULL) { |
1203 | return -1; | ||
1204 | } | ||
1205 | parameters->parms = new_parms; | ||
1206 | parameters->dynamic_parms = 1; | ||
1207 | } | ||
1208 | parameters->num_parms = 0; | ||
1209 | |||
1210 | /* begin defining parameters */ | ||
1211 | |||
1212 | slv_define_parm(parameters, real_parm, | ||
1213 | "infinity","RTMAXV","Internal value of infinity", | ||
1214 | jpye | 1534 | U_p_real(val,CONOPT_BOUNDLIMIT),U_p_real(lo,10),U_p_real(hi,MAX_REAL),2); |
1215 | aw0a | 1 | |
1216 | slv_define_parm(parameters, real_parm, | ||
1217 | "maxjac","RTMAXJ","Maximum Jacobian Element", | ||
1218 | U_p_real(val,2e8),U_p_real(lo,10),U_p_real(hi,MAX_REAL),2); | ||
1219 | SLV_RPARM_MACRO(RTMAXJ_PTR,parameters); | ||
1220 | |||
1221 | slv_define_parm(parameters, real_parm, | ||
1222 | johnpye | 919 | "hessian_ub","RTMXJ2","Upper bound on 2nd derivatives", |
1223 | aw0a | 1 | U_p_real(val,1e4),U_p_real(lo,0),U_p_real(hi,MAX_REAL),2); |
1224 | |||
1225 | slv_define_parm(parameters, real_parm, | ||
1226 | "maxfeastol", "RTNWMA", | ||
1227 | johnpye | 919 | "Max. residual considered feasible (may be scaled)", |
1228 | aw0a | 1 | U_p_real(val, 1e-3),U_p_real(lo, 1e-13),U_p_real(hi,10e10),2); |
1229 | |||
1230 | slv_define_parm(parameters, real_parm, | ||
1231 | "minfeastol", "RTNWMI", | ||
1232 | johnpye | 919 | "Min. residual considered feasible", |
1233 | aw0a | 1 | U_p_real(val, 4e-10),U_p_real(lo, 1e-20),U_p_real(hi,10e10),2); |
1234 | |||
1235 | slv_define_parm(parameters, real_parm, | ||
1236 | johnpye | 919 | "oneDsearch","RTONED","Accuracy of one dimensional search", |
1237 | aw0a | 1 | U_p_real(val,0.2),U_p_real(lo,0.1),U_p_real(hi,0.7),2); |
1238 | |||
1239 | slv_define_parm(parameters, real_parm, | ||
1240 | johnpye | 919 | "stepmult","RVSTLM","Step-length multiplier", |
1241 | aw0a | 1 | U_p_real(val,4),U_p_real(lo,0),U_p_real(hi,MAX_REAL),2); |
1242 | |||
1243 | slv_define_parm(parameters, real_parm, | ||
1244 | johnpye | 919 | "objtol","RTOBJR","Relative objective tolerance", |
1245 | aw0a | 1 | U_p_real(val,3e-13),U_p_real(lo,0),U_p_real(hi,1),2); |
1246 | |||
1247 | slv_define_parm(parameters, real_parm, | ||
1248 | johnpye | 919 | "pivottol","RTPIVA","Absolute pivot tolerance", |
1249 | aw0a | 1 | U_p_real(val,1e-7),U_p_real(lo,1e-15),U_p_real(hi,1),2); |
1250 | |||
1251 | slv_define_parm(parameters, real_parm, | ||
1252 | johnpye | 919 | "pivtolrel","RTPIVR","Relative pivot tolerance", |
1253 | aw0a | 1 | U_p_real(val,0.05),U_p_real(lo,0),U_p_real(hi,1),2); |
1254 | |||
1255 | slv_define_parm(parameters, real_parm, | ||
1256 | johnpye | 919 | "opttol","RTREDG","Optimality tolerance", |
1257 | aw0a | 1 | U_p_real(val,2e-5),U_p_real(lo,0),U_p_real(hi,MAX_REAL),2); |
1258 | |||
1259 | johnpye | 919 | /* integer valued parameters */ |
1260 | |||
1261 | aw0a | 1 | slv_define_parm(parameters, int_parm, |
1262 | johnpye | 919 | "log_freq","LFILOG","How often (in iterations) to write logging info", |
1263 | aw0a | 1 | U_p_int(val,10),U_p_int(lo,1),U_p_int(hi,MAX_INT),1); |
1264 | |||
1265 | slv_define_parm(parameters, int_parm, | ||
1266 | johnpye | 919 | "log_freq","LFILOS","How often to write logging info during SLP and SQP", |
1267 | U_p_int(val,10),U_p_int(lo,1),U_p_int(hi,MAX_INT),1); | ||
1268 | |||
1269 | slv_define_parm(parameters, int_parm, | ||
1270 | "iterationlimit", "LFITER", "Maximum number of iterations", | ||
1271 | aw0a | 1 | U_p_int(val, 1000),U_p_int(lo, 1),U_p_int(hi,MAX_INT),1); |
1272 | SLV_IPARM_MACRO(ITER_LIMIT_PTR,parameters); | ||
1273 | |||
1274 | slv_define_parm(parameters, int_parm, | ||
1275 | johnpye | 919 | "slowproglim","LFNICR","Limit for slow progress", |
1276 | U_p_int(val,12),U_p_int(lo,2),U_p_int(hi,MAX_INT),1); | ||
1277 | aw0a | 1 | |
1278 | slv_define_parm(parameters, int_parm, | ||
1279 | johnpye | 919 | "maxhessdim","LFNSUP","Maximum Hessian dimension", |
1280 | U_p_int(val,500),U_p_int(lo,5),U_p_int(hi,MAX_INT),1); | ||
1281 | aw0a | 1 | |
1282 | slv_define_parm(parameters, int_parm, | ||
1283 | johnpye | 919 | "supbasiclim","LFMXNS","Limit on new super-basics", |
1284 | aw0a | 1 | U_p_int(val,5),U_p_int(lo,0),U_p_int(hi,MAX_INT),1); |
1285 | |||
1286 | slv_define_parm(parameters, int_parm, | ||
1287 | johnpye | 919 | "lfscal","LFSCAL","Minimum frequency for updating row/col scales (see LSSCAL)", |
1288 | U_p_int(val,20),U_p_int(lo,1),U_p_int(hi,MAX_INT),1); | ||
1289 | |||
1290 | slv_define_parm(parameters, int_parm, | ||
1291 | "lfstal","LFSTAL","Upper bound on the number of stalled iterations", | ||
1292 | U_p_int(val,100),U_p_int(lo,2),U_p_int(hi,MAX_INT),1); | ||
1293 | |||
1294 | slv_define_parm(parameters, int_parm, | ||
1295 | "lkdebg","LKDEBG","How often (in iterations) to write debugging info for derivatives", | ||
1296 | U_p_int(val,0),U_p_int(lo,-1),U_p_int(hi,MAX_INT),1); | ||
1297 | |||
1298 | slv_define_parm(parameters, int_parm, | ||
1299 | "lkdeb2","LKDEB2","How often (in iterations) to write debugging info for second derivs", | ||
1300 | U_p_int(val,0),U_p_int(lo,-1),U_p_int(hi,MAX_INT),1); | ||
1301 | |||
1302 | slv_define_parm(parameters, int_parm, | ||
1303 | "lmdebg","LMDEBG","Func/derivative debugging: 0=default, 1=additional continuity tests", | ||
1304 | U_p_int(val,0),U_p_int(lo,0),U_p_int(hi,1),1); | ||
1305 | |||
1306 | slv_define_parm(parameters, int_parm, | ||
1307 | "lmmxsf","LMMXSF","Method used to calc max step during Phase 0: 0=default, 1=new", | ||
1308 | U_p_int(val,0),U_p_int(lo,0),U_p_int(hi,1),1); | ||
1309 | |||
1310 | slv_define_parm(parameters, int_parm, | ||
1311 | "lmmxst","LMMXST","'As for LMMXSF but for when tolerances are tightened'", | ||
1312 | U_p_int(val,0),U_p_int(lo,0),U_p_int(hi,1),1); | ||
1313 | |||
1314 | slv_define_parm(parameters, int_parm, | ||
1315 | aw0a | 1 | "errlim","max # func errs", |
1316 | johnpye | 919 | "Limit on number of function evaluation errors", |
1317 | aw0a | 1 | U_p_int(val,500),U_p_int(lo,0),U_p_int(hi,MAX_INT),1); |
1318 | SLV_IPARM_MACRO(DOMLIM_PTR,parameters); | ||
1319 | |||
1320 | slv_define_parm(parameters, char_parm, | ||
1321 | johnpye | 919 | "scaleopt", "scaling option", "Scaling option", |
1322 | aw0a | 1 | U_p_string(val,scaling_names[1]), |
1323 | U_p_strings(lo,scaling_names), | ||
1324 | U_p_int(hi,sizeof(scaling_names)/sizeof(char *)),3); | ||
1325 | SLV_CPARM_MACRO(SCALEOPT_PTR,parameters); | ||
1326 | |||
1327 | slv_define_parm(parameters, bool_parm, | ||
1328 | johnpye | 919 | "lifds", "show singletons details", "Show singletons details", |
1329 | aw0a | 1 | U_p_bool(val, 0),U_p_bool(lo,0),U_p_bool(hi,1), 3); |
1330 | SLV_BPARM_MACRO(LIFDS_PTR,parameters); | ||
1331 | |||
1332 | slv_define_parm(parameters, bool_parm, | ||
1333 | johnpye | 919 | "safe_calc", "safe calculations", "Safe calculations", |
1334 | aw0a | 1 | U_p_bool(val, 1),U_p_bool(lo,0),U_p_bool(hi,1), 3); |
1335 | SLV_BPARM_MACRO(SAFE_CALC_PTR,parameters); | ||
1336 | |||
1337 | slv_define_parm(parameters, real_parm, | ||
1338 | "toosmall", "default for zero nominal", | ||
1339 | johnpye | 919 | "Default for zero nominal", |
1340 | aw0a | 1 | U_p_real(val, 1e-8),U_p_real(lo, 1e-12),U_p_real(hi,1.0), 3); |
1341 | SLV_RPARM_MACRO(TOO_SMALL_PTR,parameters); | ||
1342 | |||
1343 | slv_define_parm(parameters, int_parm, | ||
1344 | "upwts", "Row scaling update frequency", | ||
1345 | "Row scaling update frequency", | ||
1346 | U_p_int(val, 1),U_p_int(lo,0),U_p_int(hi,20000), 3); | ||
1347 | SLV_IPARM_MACRO(UPDATE_WEIGHTS_PTR,parameters); | ||
1348 | |||
1349 | slv_define_parm(parameters, int_parm, | ||
1350 | "upnom", "Column scaling update frequency", | ||
1351 | "Column scaling update frequency", | ||
1352 | U_p_int(val, 1000),U_p_int(lo,0),U_p_int(hi,20000), 3); | ||
1353 | SLV_IPARM_MACRO(UPDATE_NOMINALS_PTR,parameters); | ||
1354 | |||
1355 | slv_define_parm(parameters, bool_parm, | ||
1356 | "cncols", "Check poorly scaled columns", | ||
1357 | "Check poorly scaled columns", | ||
1358 | U_p_bool(val, 0),U_p_bool(lo,0),U_p_bool(hi,1), 3); | ||
1359 | SLV_BPARM_MACRO(DUMPCNORM_PTR,parameters); | ||
1360 | |||
1361 | slv_define_parm(parameters, real_parm, | ||
1362 | "cnlow", "smallest allowable column norm", | ||
1363 | "smallest allowable column norm", | ||
1364 | U_p_real(val, 0.01),U_p_real(lo, 0),U_p_real(hi,10e10), 3); | ||
1365 | SLV_RPARM_MACRO(CNLOW_PTR,parameters); | ||
1366 | |||
1367 | slv_define_parm(parameters, real_parm, | ||
1368 | "cnhigh", "largest allowable column norm", | ||
1369 | johnpye | 919 | "Largest allowable column norm", |
1370 | aw0a | 1 | U_p_real(val, 100.0),U_p_real(lo,0),U_p_real(hi,10e10), 3); |
1371 | SLV_RPARM_MACRO(CNHIGH_PTR,parameters); | ||
1372 | |||
1373 | slv_define_parm(parameters, int_parm, | ||
1374 | "upjac", "Jacobian update frequency", | ||
1375 | "Jacobian update frequency", | ||
1376 | U_p_int(val, 1),U_p_int(lo,0),U_p_int(hi,20000), 3); | ||
1377 | SLV_IPARM_MACRO(UPDATE_JACOBIAN_PTR,parameters); | ||
1378 | |||
1379 | slv_define_parm(parameters, int_parm, | ||
1380 | "itscalelim", "Iteration lim for iterative scale", | ||
1381 | "Iteration lim for iterative scale", | ||
1382 | U_p_int(val, 10),U_p_int(lo,0),U_p_int(hi,20000), 3); | ||
1383 | SLV_IPARM_MACRO(ITSCALELIM_PTR,parameters); | ||
1384 | |||
1385 | slv_define_parm(parameters, real_parm, | ||
1386 | "itscaletol", "Iterative scaling tolerance", | ||
1387 | "Iterative scaling tolerance", | ||
1388 | U_p_real(val, 0.99999),U_p_real(lo,0),U_p_real(hi,1.0), 3); | ||
1389 | SLV_RPARM_MACRO(ITSCALETOL_PTR,parameters); | ||
1390 | |||
1391 | slv_define_parm(parameters, char_parm, | ||
1392 | johnpye | 919 | "reorder", "reorder method", "Re-order method", |
1393 | aw0a | 1 | U_p_string(val,reorder_names[0]), |
1394 | U_p_strings(lo,reorder_names), | ||
1395 | U_p_int(hi,sizeof(reorder_names)/sizeof(char *)),3); | ||
1396 | SLV_CPARM_MACRO(REORDER_OPTION_PTR,parameters); | ||
1397 | |||
1398 | slv_define_parm(parameters, int_parm, | ||
1399 | "cutoff", "block size cutoff (MODEL-based)", | ||
1400 | "block size cutoff (MODEL-based)", | ||
1401 | U_p_int(val, 200),U_p_int(lo,0),U_p_int(hi,20000), 3); | ||
1402 | SLV_IPARM_MACRO(CUTOFF_PTR,parameters); | ||
1403 | |||
1404 | slv_define_parm(parameters, bool_parm, | ||
1405 | johnpye | 919 | "relnomscale", "calc rel nominals", "Whether to calculate relation nominals?", |
1406 | aw0a | 1 | U_p_bool(val, 0),U_p_bool(lo,0),U_p_bool(hi,1), 3); |
1407 | SLV_BPARM_MACRO(RELNOMSCALE_PTR,parameters); | ||
1408 | |||
1409 | slv_define_parm(parameters, int_parm, | ||
1410 | "timelimit", "time limit (CPU sec/block)", | ||
1411 | johnpye | 919 | "Time limit (CPU sec/block)", |
1412 | aw0a | 1 | U_p_int(val,1500),U_p_int(lo, 1),U_p_int(hi,20000),1); |
1413 | SLV_IPARM_MACRO(TIME_LIMIT_PTR,parameters); | ||
1414 | |||
1415 | johnpye | 919 | |
1416 | |||
1417 | // CONOPT boolean options | ||
1418 | |||
1419 | slv_define_parm(parameters, bool_parm, | ||
1420 | "ls2ptj", "LS2PTJ", "Allow computation of 2nd derivatives by peturbation", | ||
1421 | U_p_bool(val, 0),U_p_bool(lo,0),U_p_bool(hi,1), 4); | ||
1422 | |||
1423 | slv_define_parm(parameters, bool_parm, | ||
1424 | "lsanrm", "LSANRM", "Use 'steepest edge' procedure", | ||
1425 | U_p_bool(val, 0),U_p_bool(lo,0),U_p_bool(hi,1), 4); | ||
1426 | |||
1427 | slv_define_parm(parameters, bool_parm, | ||
1428 | "lscrsh", "LSCRSH", "Use Crash procedures to create initial basis", | ||
1429 | U_p_bool(val, 1),U_p_bool(lo,0),U_p_bool(hi,1), 4); | ||
1430 | |||
1431 | slv_define_parm(parameters, bool_parm, | ||
1432 | "lseslp", "LSESLP", "Enable SLP mode", | ||
1433 | U_p_bool(val, 1),U_p_bool(lo,0),U_p_bool(hi,1), 4); | ||
1434 | |||
1435 | slv_define_parm(parameters, bool_parm, | ||
1436 | "lsismp", "LSISMP", "Ignore small pivots", | ||
1437 | U_p_bool(val, 0),U_p_bool(lo,0),U_p_bool(hi,1), 4); | ||
1438 | |||
1439 | slv_define_parm(parameters, bool_parm, | ||
1440 | "lslack", "LSLACK", "Use the set of all slacks as the initial basis", | ||
1441 | U_p_bool(val, 0),U_p_bool(lo,0),U_p_bool(hi,1), 4); | ||
1442 | |||
1443 | slv_define_parm(parameters, bool_parm, | ||
1444 | "lspret", "LSPRET", "Identify and solve pre-triangular equations", | ||
1445 | U_p_bool(val, 1),U_p_bool(lo,0),U_p_bool(hi,1), 4); | ||
1446 | |||
1447 | slv_define_parm(parameters, bool_parm, | ||
1448 | "lspost", "LSPOST", "Identify post-triangular equations (that can combine with the Objective)", | ||
1449 | U_p_bool(val, 1),U_p_bool(lo,0),U_p_bool(hi,1), 4); | ||
1450 | |||
1451 | slv_define_parm(parameters, bool_parm, | ||
1452 | "lssqrs", "LSSQRS", "Modeller declares that this is a square system (c.f. COIDEF_Square)", | ||
1453 | U_p_bool(val, 0),U_p_bool(lo,0),U_p_bool(hi,1), 4); | ||
1454 | |||
1455 | slv_define_parm(parameters, bool_parm, | ||
1456 | "lsscal", "LSSCAL", "Use dynamic scaling algorithm (NB, manual scaling is preferred)", | ||
1457 | U_p_bool(val, 0),U_p_bool(lo,0),U_p_bool(hi,1), 4); | ||
1458 | |||
1459 | slv_define_parm(parameters, bool_parm, | ||
1460 | "lstcrs", "LSTCRS", "Try to crash triangular bases using Gould & Reid technique", | ||
1461 | U_p_bool(val, 0),U_p_bool(lo,0),U_p_bool(hi,1), 4); | ||
1462 | |||
1463 | slv_define_parm(parameters, bool_parm, | ||
1464 | "lstria", "LSTRIA", "Modeller declares that the equations form a triangular or recursive system", | ||
1465 | U_p_bool(val, 0),U_p_bool(lo,0),U_p_bool(hi,1), 4); | ||
1466 | |||
1467 | // Quick mode | ||
1468 | |||
1469 | slv_define_parm(parameters, bool_parm, | ||
1470 | "lsnop2", "LSNOP2", "No \"Phase 2\"", | ||
1471 | U_p_bool(val, 0),U_p_bool(lo,0),U_p_bool(hi,1), 5); | ||
1472 | |||
1473 | slv_define_parm(parameters, int_parm, | ||
1474 | "lfmxp4","LFMXP4","Maximum number of iterations in Phase 4", | ||
1475 | U_p_int(val,1000000000),U_p_int(lo,1),U_p_int(hi,MAX_INT),5); | ||
1476 | |||
1477 | slv_define_parm(parameters, real_parm, | ||
1478 | "rvobjl", "RVOBJL","Limit on objective in Quick Mode", | ||
1479 | U_p_real(val, 0),U_p_real(lo,0),U_p_real(hi,10e10), 5); | ||
1480 | |||
1481 | jpye | 1491 | asc_assert(parameters->num_parms==conopt_PA_SIZE); |
1482 | johnpye | 919 | |
1483 | aw0a | 1 | return 1; |
1484 | } | ||
1485 | |||
1486 | |||
1487 | johnpye | 788 | /*----------------------------------------------------------------------------- |
1488 | EXTERNAL ROUTINES (see slv_client.h) | ||
1489 | */ | ||
1490 | aw0a | 1 | |
1491 | jpye | 1491 | static SlvClientToken conopt_create(slv_system_t server, int32*statusindex){ |
1492 | conopt_system_t sys; | ||
1493 | aw0a | 1 | |
1494 | jpye | 1491 | sys = ASC_NEW_CLEAR(struct conopt_system_structure); |
1495 | aw0a | 1 | if (sys==NULL) { |
1496 | *statusindex = 1; | ||
1497 | return sys; | ||
1498 | } | ||
1499 | SERVER = server; | ||
1500 | sys->p.parms = sys->pa; | ||
1501 | sys->p.dynamic_parms = 0; | ||
1502 | jpye | 1491 | conopt_get_default_parameters(server,(SlvClientToken)sys,&(sys->p)); |
1503 | aw0a | 1 | sys->integrity = OK; |
1504 | sys->presolved = 0; | ||
1505 | sys->resolve = 0; | ||
1506 | sys->p.output.more_important = stdout; | ||
1507 | sys->p.output.less_important = stdout; | ||
1508 | |||
1509 | sys->p.whose = (*statusindex); | ||
1510 | |||
1511 | johnpye | 921 | sys->con.work=NULL; |
1512 | |||
1513 | aw0a | 1 | sys->s.ok = TRUE; |
1514 | sys->s.calc_ok = TRUE; | ||
1515 | sys->s.costsize = 0; | ||
1516 | sys->s.cost = NULL; /*redundant, but sanity preserving */ | ||
1517 | sys->vlist = slv_get_solvers_var_list(server); | ||
1518 | sys->rlist = slv_get_solvers_rel_list(server); | ||
1519 | sys->obj = slv_get_obj_relation(server); | ||
1520 | if (sys->vlist == NULL) { | ||
1521 | ascfree(sys); | ||
1522 | johnpye | 788 | ERROR_REPORTER_HERE(ASC_PROG_ERR,"CONOPT called with no variables."); |
1523 | aw0a | 1 | *statusindex = -2; |
1524 | return NULL; /* prolly leak here */ | ||
1525 | } | ||
1526 | if (sys->rlist == NULL && sys->obj == NULL) { | ||
1527 | ascfree(sys); | ||
1528 | johnpye | 788 | ERROR_REPORTER_HERE(ASC_PROG_ERR,"CONOPT called with no relations or objective."); |
1529 | aw0a | 1 | *statusindex = -1; |
1530 | return NULL; /* prolly leak here */ | ||
1531 | } | ||
1532 | /* we don't give a damn about the objective list or the pars or | ||
1533 | * bounds or extrels or any of the other crap. | ||
1534 | */ | ||
1535 | slv_check_var_initialization(server); | ||
1536 | *statusindex = 0; | ||
1537 | return((SlvClientToken)sys); | ||
1538 | } | ||
1539 | |||
1540 | jpye | 1491 | static void destroy_matrices( conopt_system_t sys){ |
1541 | aw0a | 1 | if( sys->J.mtx ) { |
1542 | mtx_destroy(sys->J.mtx); | ||
1543 | } | ||
1544 | } | ||
1545 | |||
1546 | jpye | 1491 | static void destroy_vectors( conopt_system_t sys){ |
1547 | aw0a | 1 | destroy_array(sys->nominals.vec); |
1548 | destroy_array(sys->weights.vec); | ||
1549 | destroy_array(sys->relnoms.vec); | ||
1550 | destroy_array(sys->variables.vec); | ||
1551 | destroy_array(sys->residuals.vec); | ||
1552 | } | ||
1553 | |||
1554 | |||
1555 | jpye | 1491 | static int32 conopt_eligible_solver(slv_system_t server){ |
1556 | johnpye | 787 | struct rel_relation **rp; |
1557 | for( rp=slv_get_solvers_rel_list(server); *rp != NULL ; ++rp ) { | ||
1558 | if( rel_less(*rp) || rel_greater(*rp) ){ | ||
1559 | ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"less-than and greater-than relations are not permitted with CONOPT"); | ||
1560 | return(FALSE); | ||
1561 | } | ||
1562 | } | ||
1563 | return(TRUE); | ||
1564 | aw0a | 1 | } |
1565 | |||
1566 | |||
1567 | jpye | 1491 | static void conopt_get_parameters(slv_system_t server, SlvClientToken asys |
1568 | johnpye | 788 | , slv_parameters_t *parameters |
1569 | ){ | ||
1570 | jpye | 1491 | conopt_system_t sys; |
1571 | aw0a | 1 | (void)server; /* stop gcc whine about unused parameter */ |
1572 | |||
1573 | jpye | 1491 | sys = CONOPT(asys); |
1574 | aw0a | 1 | if (check_system(sys)) return; |
1575 | mem_copy_cast(&(sys->p),parameters,sizeof(slv_parameters_t)); | ||
1576 | } | ||
1577 | |||
1578 | |||
1579 | jpye | 1491 | static void conopt_set_parameters(slv_system_t server, SlvClientToken asys |
1580 | jpye | 1487 | ,slv_parameters_t *parameters |
1581 | ){ | ||
1582 | jpye | 1491 | conopt_system_t sys; |
1583 | aw0a | 1 | (void)server; /* stop gcc whine about unused parameter */ |
1584 | |||
1585 | jpye | 1491 | sys = CONOPT(asys); |
1586 | aw0a | 1 | if (check_system(sys)) return; |
1587 | mem_copy_cast(parameters,&(sys->p),sizeof(slv_parameters_t)); | ||
1588 | } | ||
1589 | |||
1590 | |||
1591 | jpye | 1491 | static int conopt_get_status(slv_system_t server, SlvClientToken asys |
1592 | jpye | 1487 | ,slv_status_t *status |
1593 | ){ | ||
1594 | jpye | 1491 | conopt_system_t sys; |
1595 | johnpye | 1196 | (void)server; /* stop gcc whine about unused parameter */ |
1596 | aw0a | 1 | |
1597 | jpye | 1491 | sys = CONOPT(asys); |
1598 | johnpye | 1196 | if (check_system(sys)) return 1; |
1599 | mem_copy_cast(&(sys->s),status,sizeof(slv_status_t)); | ||
1600 | return 0; | ||
1601 | aw0a | 1 | } |
1602 | |||
1603 | |||
1604 | jpye | 1491 | static linsolqr_system_t conopt_get_linsolqr_sys(slv_system_t server |
1605 | jpye | 1487 | ,SlvClientToken asys |
1606 | johnpye | 788 | ){ |
1607 | jpye | 1491 | conopt_system_t sys; |
1608 | aw0a | 1 | (void)server; /* stop gcc whine about unused parameter */ |
1609 | |||
1610 | jpye | 1491 | sys = CONOPT(asys); |
1611 | aw0a | 1 | if (check_system(sys)) return NULL; |
1612 | return(sys->J.sys); | ||
1613 | } | ||
1614 | |||
1615 | johnpye | 788 | /** |
1616 | Perform structural analysis on the system, setting the flags in | ||
1617 | johnpye | 908 | status. |
1618 | aw0a | 1 | |
1619 | johnpye | 788 | The problem must be set up, the relation/variable list |
1620 | johnpye | 908 | must be non-NULL. The jacobian (linear) system must be created |
1621 | johnpye | 788 | and have the correct order (stored in sys->cap). Everything else |
1622 | will be determined here. | ||
1623 | |||
1624 | On entry there isn't yet a correspondence between var_sindex and | ||
1625 | jacobian column. Here we establish that. | ||
1626 | |||
1627 | @NOTE this function has been striped of its guts for CONOPT and may go away | ||
1628 | */ | ||
1629 | jpye | 1491 | static void structural_analysis(slv_system_t server, conopt_system_t sys){ |
1630 | johnpye | 788 | |
1631 | aw0a | 1 | var_filter_t vfilter; |
1632 | rel_filter_t rfilter; | ||
1633 | |||
1634 | /* | ||
1635 | * The server has marked incidence flags already. | ||
1636 | */ | ||
1637 | /* count included equalities */ | ||
1638 | rfilter.matchbits = (REL_INCLUDED | REL_EQUALITY | REL_ACTIVE); | ||
1639 | rfilter.matchvalue = (REL_INCLUDED | REL_EQUALITY | REL_ACTIVE); | ||
1640 | sys->rused = slv_count_solvers_rels(server,&rfilter); | ||
1641 | |||
1642 | /* count free and incident vars */ | ||
1643 | vfilter.matchbits = (VAR_FIXED | VAR_INCIDENT | VAR_SVAR | VAR_ACTIVE); | ||
1644 | vfilter.matchvalue = (VAR_INCIDENT | VAR_SVAR | VAR_ACTIVE); | ||
1645 | sys->vused = slv_count_solvers_vars(server,&vfilter); | ||
1646 | |||
1647 | /* Symbolic analysis */ | ||
1648 | sys->rtot = slv_get_num_solvers_rels(server); | ||
1649 | sys->vtot = slv_get_num_solvers_vars(server); | ||
1650 | |||
1651 | /* | ||
1652 | * The next few lines are used to calculate the rank of the nonlinear | ||
1653 | * system. We need it to evaluate if the system is structurally | ||
1654 | * singular or not. Calculating this number will keep CONOPT from | ||
1655 | * displaying a "structurally singular" error message | ||
1656 | */ | ||
1657 | if (sys->rtot) { | ||
1658 | slv_block_partition(server); | ||
1659 | } | ||
1660 | sys->J.dofdata = slv_get_dofdata(server); | ||
1661 | sys->rank = sys->J.dofdata->structural_rank; | ||
1662 | /* | ||
1663 | * Unify the partitions since we feed CONOPT with a single block. | ||
1664 | */ | ||
1665 | slv_block_unify(server); | ||
1666 | |||
1667 | |||
1668 | sys->J.reg.row.low = sys->J.reg.col.low = 0; | ||
1669 | johnpye | 788 | sys->J.reg.row.high = sys->con.m - 1; |
1670 | aw0a | 1 | if (sys->obj != NULL) sys->J.reg.row.high--; |
1671 | johnpye | 788 | sys->J.reg.col.high = sys->con.n - 1; |
1672 | johnpye | 783 | |
1673 | johnpye | 1055 | if(slv_check_bounds(SERVER,sys->vused,-1,"fixed ")){ |
1674 | johnpye | 1044 | sys->s.inconsistent = 1; |
1675 | } | ||
1676 | aw0a | 1 | |
1677 | /* Initialize Status */ | ||
1678 | sys->s.over_defined = (sys->rused > sys->vused); | ||
1679 | sys->s.under_defined = (sys->rused < sys->vused); | ||
1680 | sys->s.struct_singular = (sys->rank < sys->rused); | ||
1681 | sys->s.block.number_of = (slv_get_solvers_blocks(SERVER))->nblocks; | ||
1682 | |||
1683 | } | ||
1684 | |||
1685 | |||
1686 | jpye | 1491 | static void create_matrices(slv_system_t server, conopt_system_t sys){ |
1687 | aw0a | 1 | sys->J.mtx = mtx_create(); |
1688 | mtx_set_order(sys->J.mtx,sys->cap); | ||
1689 | structural_analysis(server,sys); | ||
1690 | } | ||
1691 | |||
1692 | |||
1693 | jpye | 1491 | static void create_vectors(conopt_system_t sys){ |
1694 | aw0a | 1 | sys->nominals.vec = create_array(sys->cap,real64); |
1695 | sys->nominals.rng = &(sys->J.reg.col); | ||
1696 | sys->weights.vec = create_array(sys->cap,real64); | ||
1697 | sys->weights.rng = &(sys->J.reg.row); | ||
1698 | sys->relnoms.vec = create_array(sys->cap,real64); | ||
1699 | sys->relnoms.rng = &(sys->J.reg.row); | ||
1700 | sys->variables.vec = create_array(sys->cap,real64); | ||
1701 | sys->variables.rng = &(sys->J.reg.col); | ||
1702 | sys->residuals.vec = create_array(sys->cap,real64); | ||
1703 | sys->residuals.rng = &(sys->J.reg.row); | ||
1704 | } | ||
1705 | |||
1706 | |||
1707 | jpye | 1491 | static void conopt_dump_internals(slv_system_t server |
1708 | johnpye | 788 | , SlvClientToken sys, int32 level |
1709 | ){ | ||
1710 | aw0a | 1 | (void)server; /* stop gcc whine about unused parameter */ |
1711 | |||
1712 | check_system(sys); | ||
1713 | if (level > 0) { | ||
1714 | johnpye | 788 | ERROR_REPORTER_HERE(ASC_PROG_ERR,"Can't dump internals with CONOPT"); |
1715 | aw0a | 1 | } |
1716 | } | ||
1717 | |||
1718 | |||
1719 | johnpye | 788 | /** |
1720 | Check if any fixed or included flags have | ||
1721 | changed since the last presolve. | ||
1722 | */ | ||
1723 | jpye | 1491 | static int32 conopt_dof_changed(conopt_system_t sys) |
1724 | aw0a | 1 | { |
1725 | int32 ind, result = 0; | ||
1726 | /* Currently we have two copies of the fixed and included flags | ||
1727 | which must be kept in sync. The var_fixed and rel_included | ||
1728 | functions perform the syncronization and hence must be called | ||
1729 | over the whole var list and rel list respectively. When we move | ||
1730 | to using only one set of flags (bit flags) this function can | ||
1731 | be changed to return 1 at the first indication of a change | ||
1732 | in the dof. */ | ||
1733 | |||
1734 | /* search for vars that were fixed and are now free */ | ||
1735 | for( ind = sys->vused; ind < sys->vtot; ++ind ) { | ||
1736 | if( !var_fixed(sys->vlist[ind]) && var_active(sys->vlist[ind]) ) { | ||
1737 | ++result; | ||
1738 | } | ||
1739 | } | ||
1740 | /* search for rels that were unincluded and are now included */ | ||
1741 | for( ind = sys->rused; ind < sys->rtot; ++ind ) { | ||
1742 | if( rel_included(sys->rlist[ind]) && rel_active(sys->rlist[ind])) { | ||
1743 | ++result; | ||
1744 | } | ||
1745 | } | ||
1746 | /* search for vars that were free and are now fixed */ | ||
1747 | for( ind = sys->vused -1; ind >= 0; --ind ) { | ||
1748 | if( var_fixed(sys->vlist[ind]) || !var_active(sys->vlist[ind])) { | ||
1749 | ++result; | ||
1750 | } | ||
1751 | } | ||
1752 | /* search for rels that were included and are now unincluded */ | ||
1753 | for( ind = sys->rused -1; ind >= 0; --ind ) { | ||
1754 | if( !rel_included(sys->rlist[ind]) || !rel_active(sys->rlist[ind]) ) { | ||
1755 | ++result; | ||
1756 | } | ||
1757 | } | ||
1758 | return result; | ||
1759 | } | ||
1760 | |||
1761 | |||
1762 | static void reset_cost(struct slv_block_cost *cost,int32 costsize) | ||
1763 | { | ||
1764 | int32 ind; | ||
1765 | for( ind = 0; ind < costsize; ++ind ) { | ||
1766 | cost[ind].size = 0; | ||
1767 | cost[ind].iterations = 0; | ||
1768 | cost[ind].funcs = 0; | ||
1769 | cost[ind].jacs = 0; | ||
1770 | cost[ind].functime = 0; | ||
1771 | cost[ind].jactime = 0; | ||
1772 | cost[ind].time = 0; | ||
1773 | cost[ind].resid = 0; | ||
1774 | } | ||
1775 | } | ||
1776 | |||
1777 | |||
1778 | johnpye | 788 | /** |
1779 | Update the values of the array cost, which is used by the interface | ||
1780 | to display residual and number of iterations. For use after running CONOPT | ||
1781 | */ | ||
1782 | jpye | 1491 | static void update_cost(conopt_system_t sys) |
1783 | aw0a | 1 | { |
1784 | int32 ci; | ||
1785 | if (sys->s.cost == NULL) { | ||
1786 | sys->s.cost = create_zero_array(sys->s.costsize,struct slv_block_cost); | ||
1787 | } else { | ||
1788 | reset_cost(sys->s.cost,sys->s.costsize); | ||
1789 | } | ||
1790 | ci=sys->s.block.current_block; | ||
1791 | sys->s.cost[ci].size = sys->s.block.current_size; | ||
1792 | sys->s.cost[ci].iterations = sys->s.block.iteration; | ||
1793 | sys->s.cost[ci].resid = sys->s.block.residual; | ||
1794 | } | ||
1795 | |||
1796 | johnpye | 788 | /*------------------------------------------------------------------------------ |
1797 | CONOPT ROUTINES | ||
1798 | */ | ||
1799 | aw0a | 1 | |
1800 | johnpye | 788 | /** |
1801 | @TODO | ||
1802 | - Fix interface so that solvers define status messages. We | ||
1803 | should not be stuck with one standard set that all solvers | ||
1804 | must deal with. | ||
1805 | johnpye | 908 | |
1806 | johnpye | 788 | - Reimplement old code to detect linear coefficients and use |
1807 | in conopt hookup. | ||
1808 | aw0a | 1 | |
1809 | johnpye | 788 | - Implement better communication routines. |
1810 | aw0a | 1 | |
1811 | johnpye | 788 | - Give more contol to interface (ex. turn off error counting, |
1812 | switch from we alocate to conopt allocates, etc.). | ||
1813 | |||
1814 | - Record marginal values and make available to user. | ||
1815 | |||
1816 | - Set up interface such that any variable can be selected and | ||
1817 | either maximized or minimized. | ||
1818 | |||
1819 | - Get rid of our Jacobian calculation routine and stuff conopt's | ||
1820 | workspace directly (in unsorted order). This will require | ||
1821 | rewriting the scaling functions. (This code really should | ||
1822 | not be in the solver) | ||
1823 | |||
1824 | - Fix up restart code...we don't keep track of which values | ||
1825 | change so must update entire Jacobian and residual vector | ||
1826 | but may save some time by not having to redo column pointers etc. | ||
1827 | |||
1828 | - Implement a way to bailout...check for ^C and tell conopt to | ||
1829 | return as soon as possible. | ||
1830 | |||
1831 | - Currently will not take problem like MIN x^2...it will complain | ||
1832 | about empty rows. Must formulate as y=x^2; MIN y; until we | ||
1833 | fix the way we handle objectives. | ||
1834 | */ | ||
1835 | |||
1836 | |||
1837 | /** | ||
1838 | jpye | 1534 | This is the 'ReadMatrix' callback. This provides the mechanism for ASCEND |
1839 | johnpye | 788 | to tell CONOPT about the lower and upper bounds on variables, the initial |
1840 | values, the initial basic/non-basis status of variables, the types of | ||
1841 | equation constraints and the values of the RHSes, and information about the | ||
1842 | structure of the equations. | ||
1843 | |||
1844 | See the CONOPT reference manual for full details. | ||
1845 | |||
1846 | @param lower lower bounds on the variables | ||
1847 | @param curr intial values of the variables | ||
1848 | @param upper upper bounds on the variables | ||
1849 | @param vsta initial status of the variable(o nonbasic, 1 basic) | ||
1850 | @param type types of equations (0 equality,1 greater,2 less) | ||
1851 | @param rhs values of the right hand sides | ||
1852 | @param esta initial status of the slack in the constraint (nonbasic,basic) | ||
1853 | @param colsta start of column pointers | ||
1854 | @param rowno row or equation numbers of the nonzeros | ||
1855 | @param value values of the jacobian elements | ||
1856 | @param nlflag nonlinearity flags(0 nonzero constant,1 varying) | ||
1857 | @param n number of variables | ||
1858 | @param m number of constraints | ||
1859 | @param nz number of jacobian elements | ||
1860 | @param usrmem user memory defined by conopt | ||
1861 | */ | ||
1862 | jpye | 1491 | static int COI_CALL conopt_readmatrix( |
1863 | johnpye | 783 | double *lower, double *curr, double *upper |
1864 | , int *vsta, int *type, double *rhs | ||
1865 | , int *esta, int *colsta, int *rowno | ||
1866 | , double *value, int *nlflag, int *n, int *m, int *nz | ||
1867 | , double *usrmem | ||
1868 | ){ | ||
1869 | aw0a | 1 | int32 col,row,count,count_old,len,c,r,offset, obj_count; |
1870 | real64 nominal, up, low; | ||
1871 | struct var_variable *var; | ||
1872 | const struct rel_relation **rlist=NULL; | ||
1873 | static rel_filter_t rfilter; | ||
1874 | static var_filter_t vfilter; | ||
1875 | real64 *derivatives; | ||
1876 | int32 *variables; | ||
1877 | mtx_coord_t coord; | ||
1878 | jpye | 1491 | conopt_system_t sys; |
1879 | aw0a | 1 | |
1880 | /* | ||
1881 | johnpye | 788 | stop gcc whining about unused parameter |
1882 | */ | ||
1883 | aw0a | 1 | (void)vsta; (void)rhs; (void)esta; (void)n; |
1884 | |||
1885 | jpye | 1491 | sys = (conopt_system_t)usrmem; |
1886 | aw0a | 1 | rfilter.matchbits = (REL_INCLUDED | REL_EQUALITY | REL_ACTIVE); |
1887 | rfilter.matchvalue =(REL_INCLUDED | REL_EQUALITY | REL_ACTIVE); | ||
1888 | |||
1889 | vfilter.matchbits = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR | VAR_FIXED); | ||
1890 | vfilter.matchvalue = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR); | ||
1891 | |||
1892 | calc_J(sys); | ||
1893 | calc_residuals(sys); | ||
1894 | scale_system(sys); | ||
1895 | |||
1896 | for (offset = col = sys->J.reg.col.low; | ||
1897 | col <= sys->J.reg.col.high; col++) { | ||
1898 | var = sys->vlist[mtx_col_to_org(sys->J.mtx,col)]; | ||
1899 | nominal = sys->nominals.vec[col]; | ||
1900 | low = var_lower_bound(var)/nominal; | ||
1901 | up = var_upper_bound(var)/nominal; | ||
1902 | johnpye | 1257 | |
1903 | johnpye | 799 | lower[col-offset] = low > -CONOPT_BOUNDLIMIT ? low : -CONOPT_BOUNDLIMIT; |
1904 | upper[col-offset] = up < CONOPT_BOUNDLIMIT ? up : CONOPT_BOUNDLIMIT; | ||
1905 | jpye | 1545 | /* CONSOLE_DEBUG("BOUNDS for var %d: [%g,%g]",col-offset,lower[col-offset],upper[col-offset]); */ |
1906 | aw0a | 1 | curr[col-offset] = sys->variables.vec[col]; /* already scaled */ |
1907 | vsta[col-offset] = !var_nonbasic(var); | ||
1908 | } | ||
1909 | johnpye | 788 | /* |
1910 | aw0a | 1 | for (offset = row = sys->J.reg.row.low; |
1911 | row <= sys->J.reg.row.high; row++) { | ||
1912 | johnpye | 908 | |
1913 | aw0a | 1 | rel = sys->rlist[mtx_row_to_org(sys->J.mtx,row)]; |
1914 | nominal = sys->weights.vec[row]; | ||
1915 | johnpye | 788 | * fv[row-offset] = sys->residuals.vec[row];* * already scaled * |
1916 | aw0a | 1 | } |
1917 | johnpye | 788 | */ |
1918 | |||
1919 | /* set relation types: all equalities except for last one */ | ||
1920 | aw0a | 1 | for (row = 0; row < *m; row++) { |
1921 | type[row] = 0; | ||
1922 | } | ||
1923 | if (sys->obj != NULL) { | ||
1924 | johnpye | 788 | type[*m - 1] = 3; /* objective function */ |
1925 | aw0a | 1 | } |
1926 | |||
1927 | johnpye | 788 | /* get derivatives of objective function? */ |
1928 | aw0a | 1 | if (sys->obj != NULL) { |
1929 | len = rel_n_incidences(sys->obj); | ||
1930 | johnpye | 669 | variables = ASC_NEW_ARRAY(int32,len); |
1931 | derivatives = ASC_NEW_ARRAY(real64,len); | ||
1932 | johnpye | 788 | |
1933 | relman_diff2( | ||
1934 | sys->obj,&vfilter,derivatives,variables | ||
1935 | , &(obj_count),SAFE_CALC | ||
1936 | ); | ||
1937 | johnpye | 909 | /* what about checking error code? -- JP */ |
1938 | aw0a | 1 | } |
1939 | |||
1940 | count = count_old = 0; | ||
1941 | |||
1942 | johnpye | 788 | colsta[0] = 0; |
1943 | aw0a | 1 | |
1944 | johnpye | 788 | for(offset = col = sys->J.reg.col.low |
1945 | ; col <= sys->J.reg.col.high | ||
1946 | ; col++ | ||
1947 | ){ | ||
1948 | aw0a | 1 | coord.col = col; |
1949 | var = sys->vlist[col]; | ||
1950 | #if CONDBG | ||
1951 | if (!var_apply_filter(var,&vfilter) ) { | ||
1952 | johnpye | 788 | CONSOLE_DEBUG("var doesn't pass filter"); |
1953 | aw0a | 1 | } |
1954 | #endif /* CONDBG */ | ||
1955 | len = var_n_incidences(var); | ||
1956 | rlist = var_incidence_list(var); | ||
1957 | count_old = count; | ||
1958 | for (c=0; c < len; c++) { | ||
1959 | /* assuming obj on list... check this */ | ||
1960 | if (rel_apply_filter(rlist[c],&rfilter)) { | ||
1961 | johnpye | 788 | coord.row = rel_sindex(rlist[c]); |
1962 | rowno[count] = (rel_sindex(rlist[c]) - offset); | ||
1963 | value[count] = mtx_value(sys->J.mtx,&coord); | ||
1964 | nlflag[count] = 1; /* fix this later */ | ||
1965 | if(rlist[c] == sys->obj) { | ||
1966 | aw0a | 1 | #if CONDBG |
1967 | johnpye | 788 | CONSOLE_DEBUG("found objective in unexpected location"); |
1968 | aw0a | 1 | #endif /* CONDBG */ |
1969 | johnpye | 788 | } |
1970 | if (fabs(value[count]) > RTMAXJ) { | ||
1971 | aw0a | 1 | #if CONDBG |
1972 | johnpye | 788 | CONSOLE_DEBUG("Large Jacobian value being set to RTMAXJ"); |
1973 | aw0a | 1 | #endif /* CONDBG */ |
1974 | johnpye | 788 | if (value[count] > 0) { |
1975 | value[count] = RTMAXJ-1; | ||
1976 | } else { | ||
1977 | value[count] = -RTMAXJ+1; | ||
1978 | } | ||
1979 | } | ||
1980 | count++; | ||
1981 | aw0a | 1 | } |
1982 | if(rlist[c] == sys->obj) { | ||
1983 | johnpye | 788 | for (r = 0; r < obj_count; r++) { |
1984 | if ( variables[r] == var_sindex(var) ) { | ||
1985 | rowno[count] = *m - 1; | ||
1986 | value[count] = derivatives[r]; | ||
1987 | nlflag[count] = 1; /* fix this later */ | ||
1988 | if (fabs(value[count]) > RTMAXJ) { | ||
1989 | if (value[count] > 0) { | ||
1990 | value[count] = RTMAXJ-1; | ||
1991 | } else { | ||
1992 | value[count] = -RTMAXJ+1; | ||
1993 | } | ||
1994 | } | ||
1995 | count++; | ||
1996 | } | ||
1997 | } | ||
1998 | aw0a | 1 | } |
1999 | } | ||
2000 | if (count_old != count) { | ||
2001 | johnpye | 788 | /* CONSOLE_DEBUG("COLSTA[%d] = %d",col-offset,count_old); */ |
2002 | colsta[col - offset] = count_old; | ||
2003 | aw0a | 1 | } |
2004 | } | ||
2005 | johnpye | 788 | /* CONSOLE_DEBUG("COLSTA[%d] = %d",*n,*nz + 1); */ |
2006 | colsta[*n] = *nz; | ||
2007 | aw0a | 1 | if (sys->obj != NULL) { |
2008 | ascfree(variables); | ||
2009 | ascfree(derivatives); | ||
2010 | } | ||
2011 | johnpye | 783 | |
2012 | return 0; | ||
2013 | aw0a | 1 | } |
2014 | |||
2015 | #if 0 /* not compatible with our version */ | ||
2016 | /* | ||
2017 | * COIFBL Defines the nonlinearities of the model by returning | ||
2018 | * numerical values. It works on a block of rows during each call. | ||
2019 | * COIFBL( x, g, otn, nto, from, to, jac, stcl, rnum, cnum, nl, strw, | ||
2020 | * llen, indx, mode, errcnt, n, m, n1, m1, nz, usrmem) | ||
2021 | * | ||
2022 | * x - punt of evaluation provided by conopt | ||
2023 | * g - vector of function values | ||
2024 | * otn - old to new permutation vector | ||
2025 | * nto - new to old permutation vector | ||
2026 | * from - range in permutation | ||
2027 | * to - range in permutation | ||
2028 | * jac - vector of jacobian values. | ||
2029 | * The following are vectors defining the jacobian structure | ||
2030 | * stcl - start of column pointers | ||
2031 | * rnum - row numbers | ||
2032 | * cnum - column numbers | ||
2033 | * nl - nonlinearity flags | ||
2034 | * strw - start row pointers | ||
2035 | * llen - count of linear jacobian elements | ||
2036 | * indx - pointers from the row-wise representation | ||
2037 | * mode - indicator of mode of evaluation | ||
2038 | * errcnt- number of function evaluation errors | ||
2039 | * n - umber of variables | ||
2040 | * m - number of constraints | ||
2041 | * n1 - n+1 | ||
2042 | * m1 - m+1 | ||
2043 | * nz - number of jacobian elements | ||
2044 | * usrmem- user memory defined by conopt | ||
2045 | */ | ||
2046 | jpye | 1491 | static void conopt_coifbl(real64 *x, real64 *g, int32 *otn, int32 *nto, |
2047 | aw0a | 1 | int32 *from, int32 *to, real64 *jac, int32 *stcl, |
2048 | int32 *rnum, int32 *cnum, int32 *nl, int32 *strw, | ||
2049 | int32 *llen, int32 *indx, int32 *mode, int32 *errcnt, | ||
2050 | int32 *n, int32 *m, int32 *n1, int32 *m1, int32 *nz, | ||
2051 | real64 *usrmem) | ||
2052 | { | ||
2053 | int32 offset, col, row, j, jj, len, c; | ||
2054 | real64 nominal, value; | ||
2055 | struct var_variable *var; | ||
2056 | struct rel_relation *rel; | ||
2057 | int32 *jac_row; | ||
2058 | int32 *variables; | ||
2059 | real64 *derivatives; | ||
2060 | static var_filter_t vfilter; | ||
2061 | jpye | 1491 | conopt_system_t sys; |
2062 | aw0a | 1 | |
2063 | /* | ||
2064 | * stop gcc whining about unused parameter | ||
2065 | */ | ||
2066 | (void)nto; (void)stcl; (void)rnum; (void)nl; | ||
2067 | (void)errcnt; (void)n1; (void)m1; (void)nz; | ||
2068 | |||
2069 | jpye | 1491 | sys = (conopt_system_t)usrmem; |
2070 | aw0a | 1 | |
2071 | for (offset = col = sys->J.reg.col.low; | ||
2072 | col <= sys->J.reg.col.high; col++) { | ||
2073 | var = sys->vlist[col]; | ||
2074 | nominal = sys->nominals.vec[col]; | ||
2075 | value = x[col-offset] * nominal; | ||
2076 | var_set_value(var, value); | ||
2077 | } | ||
2078 | /* NOTE: could be more efficient when mode = 3 */ | ||
2079 | if (*mode == 1 || *mode == 3) { | ||
2080 | for (offset = row = sys->J.reg.row.low; | ||
2081 | row <= sys->J.reg.row.high; row++) { | ||
2082 | if (F2C(*to) <= otn[row-offset] && otn[row-offset] <= F2C(*from)) { | ||
2083 | rel = sys->rlist[row]; | ||
2084 | g[row-offset] = relman_eval(rel,&calc_ok,SAFE_CALC) | ||
2085 | * sys->weights.vec[row]; | ||
2086 | } | ||
2087 | } | ||
2088 | if (F2C(*to) <= otn[F2C(*m)] && otn[F2C(*m)] <= F2C(*from)) { | ||
2089 | if(calc_objective(sys)){ | ||
2090 | g[F2C(*m)] = sys->objective; | ||
2091 | } else { | ||
2092 | jpye | 1491 | FPRINTF(MIF(sys),"conopt_coifbl: ERROR IN OBJECTIVE CALCULATION\n"); |
2093 | aw0a | 1 | } |
2094 | } | ||
2095 | } | ||
2096 | jac_row = (int32 *)ascmalloc((*n)*sizeof(int32)); | ||
2097 | if (*mode == 2 || *mode == 3) { | ||
2098 | len = sys->con.maxrow; | ||
2099 | johnpye | 669 | variables = ASC_NEW_ARRAY(int32,len); |
2100 | derivatives = ASC_NEW_ARRAY(real64,len); | ||
2101 | aw0a | 1 | vfilter.matchbits = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR | VAR_FIXED); |
2102 | vfilter.matchvalue = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR); | ||
2103 | for (offset = row = sys->J.reg.row.low; | ||
2104 | row <= sys->J.reg.row.high; row++) { | ||
2105 | if (F2C(*to) <= otn[row-offset] && otn[row-offset] <= F2C(*from)) { | ||
2106 | rel = sys->rlist[row]; | ||
2107 | relman_diff2(rel,&vfilter,derivatives,variables, | ||
2108 | &(len),SAFE_CALC); | ||
2109 | for (c = 0; c < len; c++) { | ||
2110 | jac_row[variables[c]] = derivatives[c]; | ||
2111 | } | ||
2112 | for (j = strw[row-offset] + llen[row-offset]; | ||
2113 | j < strw[row-offset + 1]; j++) { | ||
2114 | jj = indx[F2C(j)]; | ||
2115 | jac[F2C(jj)] = jac_row[F2C(cnum[F2C(jj)])] | ||
2116 | * sys->weights.vec[row] | ||
2117 | * sys->nominals.vec[F2C(cnum[F2C(jj)])]; | ||
2118 | if(fabs(jac[F2C(jj)]) > RTMAXJ) { | ||
2119 | if (jac[F2C(jj)] < 0) { | ||
2120 | jac[F2C(jj)] = -RTMAXJ+1; | ||
2121 | } else { | ||
2122 | jac[F2C(jj)] = RTMAXJ-1; | ||
2123 | } | ||
2124 | #if CONDBG | ||
2125 | FPRINTF(stderr,"large jac element\n"); | ||
2126 | #endif /* CONDBG */ | ||
2127 | } | ||
2128 | } | ||
2129 | } | ||
2130 | } | ||
2131 | } | ||
2132 | } | ||
2133 | #endif /* 0 */ | ||
2134 | |||
2135 | /* | ||
2136 | johnpye | 788 | COIFDE Defines the nonlinearities of the model by returning |
2137 | numerical values. It works on one row or equation at a time | ||
2138 | |||
2139 | @param x punt of evaluation provided by conopt | ||
2140 | @param g function value | ||
2141 | @param jac jacobian values | ||
2142 | @param rowno number of the row for which nonlinearities will be eval | ||
2143 | @param jcnm list of column number fon the NL nonzeros | ||
2144 | @param mode indicator of mode of evaluation, 1=G, 2=JAC, 3=G & JAC | ||
2145 | @param ignerr ??? | ||
2146 | @param errcnt sum of number of func evaluation errors thus far | ||
2147 | @param newpt new point indicator | ||
2148 | @param nj number of nonlinear nonzero jacobian elements | ||
2149 | @param n number of variables | ||
2150 | @param usrmem user memory | ||
2151 | */ | ||
2152 | jpye | 1491 | static int COI_CALL conopt_fdeval( |
2153 | johnpye | 783 | double *x, double *g, double *jac |
2154 | , int *rowno, int *jcnm, int *mode, int *ignerr | ||
2155 | , int *errcnt, int *newpt, int *n, int *nj | ||
2156 | , double *usrmem | ||
2157 | johnpye | 788 | ){ |
2158 | aw0a | 1 | int32 offset, col, row, len, c; |
2159 | real64 nominal, value; | ||
2160 | struct var_variable *var; | ||
2161 | struct rel_relation *rel; | ||
2162 | int32 *variables; | ||
2163 | real64 *derivatives; | ||
2164 | static var_filter_t vfilter; | ||
2165 | jpye | 1491 | conopt_system_t sys; |
2166 | johnpye | 919 | int status; |
2167 | aw0a | 1 | |
2168 | johnpye | 788 | /* stop gcc whining about unused parameter */ |
2169 | aw0a | 1 | (void)jcnm; (void)n; (void)nj; |
2170 | |||
2171 | johnpye | 919 | CONOPT_CONSOLE_DEBUG("EVALUATION STARTING (row=%d, n=%d, nj=%d)",*rowno,*n,*nj); |
2172 | johnpye | 788 | |
2173 | jpye | 1491 | sys = (conopt_system_t)usrmem; |
2174 | aw0a | 1 | if (*newpt == 1) { |
2175 | johnpye | 788 | /* CONSOLE_DEBUG("NEW POINT"); */ |
2176 | /* a new point */ | ||
2177 | aw0a | 1 | for (offset = col = sys->J.reg.col.low; |
2178 | col <= sys->J.reg.col.high; col++) { | ||
2179 | var = sys->vlist[col]; | ||
2180 | nominal = sys->nominals.vec[col]; | ||
2181 | value = x[col-offset] * nominal; | ||
2182 | var_set_value(var, value); | ||
2183 | } | ||
2184 | } | ||
2185 | johnpye | 908 | /** |
2186 | johnpye | 788 | @TODO could be more efficient when mode = 3 |
2187 | (with future versions of CONOPT) | ||
2188 | */ | ||
2189 | aw0a | 1 | if (*mode == 1 || *mode == 3) { |
2190 | johnpye | 919 | CONOPT_CONSOLE_DEBUG("FUNCTION VALUES"); |
2191 | aw0a | 1 | offset = sys->J.reg.row.low; |
2192 | johnpye | 788 | row = *rowno + offset; |
2193 | johnpye | 919 | CONOPT_CONSOLE_DEBUG("ROWNO = %d, OFFSET = %d: ROW = ROW = %d",*rowno, offset, row); |
2194 | johnpye | 788 | if ((*rowno == sys->con.m - 1) && (sys->obj != NULL)){ |
2195 | aw0a | 1 | if(calc_objective(sys)){ |
2196 | johnpye | 783 | *g = sys->objective; |
2197 | johnpye | 788 | }else{ |
2198 | ERROR_REPORTER_HERE(ASC_PROG_ERR,"Error in calculation of objective."); | ||
2199 | aw0a | 1 | } |
2200 | johnpye | 788 | }else{ |
2201 | johnpye | 783 | rel = sys->rlist[row]; |
2202 | johnpye | 920 | asc_assert(rel!=NULL); |
2203 | johnpye | 783 | *g = relman_eval(rel,&calc_ok,SAFE_CALC) |
2204 | * sys->weights.vec[row]; | ||
2205 | if (!calc_ok) { | ||
2206 | johnpye | 919 | CONOPT_CONSOLE_DEBUG("EVALUATION ERROR IN RELMAN_EVAL"); |
2207 | johnpye | 783 | (*errcnt)++; |
2208 | } | ||
2209 | aw0a | 1 | } |
2210 | } | ||
2211 | if (*mode == 2 || *mode == 3) { | ||
2212 | johnpye | 919 | CONOPT_CONSOLE_DEBUG("JACOBIAN VALUES"); |
2213 | aw0a | 1 | len = sys->con.maxrow; |
2214 | johnpye | 669 | variables = ASC_NEW_ARRAY(int32,len); |
2215 | derivatives = ASC_NEW_ARRAY(real64,len); | ||
2216 | aw0a | 1 | vfilter.matchbits = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR | VAR_FIXED); |
2217 | vfilter.matchvalue = (VAR_ACTIVE | VAR_INCIDENT | VAR_SVAR); | ||
2218 | |||
2219 | offset = sys->J.reg.row.low; | ||
2220 | johnpye | 788 | row = *rowno + offset; |
2221 | if ((*rowno == sys->con.m - 1) && (sys->obj != NULL)){ | ||
2222 | aw0a | 1 | rel = sys->obj; |
2223 | johnpye | 920 | asc_assert(rel!=NULL); |
2224 | johnpye | 919 | status = relman_diff2(rel,&vfilter,derivatives,variables, |
2225 | aw0a | 1 | &(len),SAFE_CALC); |
2226 | for (c = 0; c < len; c++) { | ||
2227 | johnpye | 919 | jac[variables[c]] = derivatives[c] * sys->nominals.vec[variables[c]]; |
2228 | CONOPT_CONSOLE_DEBUG("Jacobian for row %d, var %d = %f",*rowno,variables[c],jac[variables[c]]); | ||
2229 | aw0a | 1 | } |
2230 | johnpye | 919 | if(status){ |
2231 | CONOPT_CONSOLE_DEBUG("ERROR IN JACOBIAN EVALUATION (OBJECTIVE) (%d)",status); | ||
2232 | johnpye | 783 | (*errcnt)++; |
2233 | aw0a | 1 | } |
2234 | johnpye | 788 | }else{ |
2235 | johnpye | 919 | CONOPT_CONSOLE_DEBUG("NOT LAST ROW"); |
2236 | aw0a | 1 | rel = sys->rlist[mtx_row_to_org(sys->J.mtx,row)]; |
2237 | johnpye | 920 | asc_assert(rel!=NULL); |
2238 | johnpye | 919 | status = relman_diff2(rel,&vfilter,derivatives,variables, |
2239 | aw0a | 1 | &(len),SAFE_CALC); |
2240 | for (c = 0; c < len; c++) { | ||
2241 | johnpye | 783 | jac[variables[c]] = derivatives[c] |
2242 | * sys->weights.vec[row] * sys->nominals.vec[variables[c]]; | ||
2243 | johnpye | 919 | CONOPT_CONSOLE_DEBUG("Jacobian for row %d, var %d = %f",mtx_row_to_org(sys->J.mtx,row),variables[c],jac[variables[c]]); |
2244 | aw0a | 1 | } |
2245 | johnpye | 919 | if(status){ |
2246 | CONOPT_CONSOLE_DEBUG("ERROR IN JACOBIAN EVALUATION (%d)",status); | ||
2247 | johnpye | 783 | (*errcnt)++; |
2248 | aw0a | 1 | } |
2249 | } | ||
2250 | for (c = 0; c < len; c++) { | ||
2251 | if(fabs(jac[variables[c]]) > RTMAXJ) { | ||
2252 | johnpye | 919 | CONOPT_CONSOLE_DEBUG("large jac element"); |
2253 | aw0a | 1 | if (jac[variables[c]] < 0) { |
2254 | jac[variables[c]] = -RTMAXJ+1; | ||
2255 | johnpye | 783 | } else { |
2256 | aw0a | 1 | jac[variables[c]] = RTMAXJ-1; |
2257 | johnpye | 783 | } |
2258 | aw0a | 1 | } |
2259 | } | ||
2260 | ascfree(variables); | ||
2261 | ascfree(derivatives); | ||
2262 | } | ||
2263 | johnpye | 783 | return 0; |
2264 | aw0a | 1 | } |
2265 | |||
2266 | |||
2267 | johnpye | 788 | /** |
2268 | COISTA Pass the solution from CONOPT to the modeler. It returns | ||
2269 | completion status | ||
2270 | johnpye | 908 | |
2271 | johnpye | 788 | @param modsta model status |
2272 | @param solsta solver status | ||
2273 | @param iter number of iterations | ||
2274 | @param objval objective value | ||
2275 | @param usrmem user memory | ||
2276 | */ | ||
2277 | jpye | 1491 | static int COI_CALL conopt_status( |
2278 | johnpye | 788 | int32 *modsta, int32 *solsta, int32 *iter |
2279 | , real64 *objval, real64 *usrmem | ||
2280 | ){ | ||
2281 | jpye | 1491 | conopt_system_t sys; |
2282 | sys = (conopt_system_t)usrmem; | ||
2283 | johnpye | 921 | |
2284 | /* for later access from elsewhere */ | ||
2285 | aw0a | 1 | sys->con.modsta = *modsta; |
2286 | sys->con.solsta = *solsta; | ||
2287 | sys->con.iter = *iter; | ||
2288 | sys->con.obj = sys->objective = *objval; | ||
2289 | johnpye | 783 | |
2290 | johnpye | 788 | asc_conopt_status(modsta,solsta,iter,objval,usrmem); |
2291 | |||
2292 | johnpye | 783 | return 0; |
2293 | aw0a | 1 | } |
2294 | |||
2295 | |||
2296 | johnpye | 788 | /** |
2297 | COIRS passes the solution from CONOPT to the modeler. It returns | ||
2298 | solution values | ||
2299 | |||
2300 | @param xval - the solution values of the variables | ||
2301 | @param xmar - corresponding marginal values | ||
2302 | @param xbas - basis indicator for column (at bound, basic, nonbasic) | ||
2303 | @param xsta - status of column (normal, nonoptimal, infeasible,unbounded) | ||
2304 | @param yval - values of the left hand side in all the rows | ||
2305 | @param ymar - corresponding marginal values | ||
2306 | @param ybas - basis indicator for row | ||
2307 | @param ysta - status of row | ||
2308 | @param n - number of variables | ||
2309 | @param m - number of constraints | ||
2310 | @param usrmem - user memory | ||
2311 | */ | ||
2312 | jpye | 1491 | static int COI_CALL conopt_solution( |
2313 | johnpye | 788 | double *xval, double *xmar, int *xbas, int *xsta, |
2314 | johnpye | 783 | double *yval, double *ymar, int *ybas, int * ysta, |
2315 | int *n, int *m, double *usrmem | ||
2316 | ){ | ||
2317 | aw0a | 1 | int32 offset, col, c; |
2318 | real64 nominal, value; | ||
2319 | struct var_variable *var; | ||
2320 | jpye | 1491 | conopt_system_t sys; |
2321 | aw0a | 1 | |
2322 | johnpye | 789 | struct var_variable **vp; |
2323 | char *varname; | ||
2324 | const char *varstat; | ||
2325 | |||
2326 | aw0a | 1 | /* |
2327 | * stop gcc whining about unused parameter | ||
2328 | */ | ||
2329 | (void)xmar; (void)xsta; (void)yval; | ||
2330 | (void)ymar; (void)ysta; (void)ybas; (void)m; | ||
2331 | |||
2332 | jpye | 1491 | sys = (conopt_system_t)usrmem; |
2333 | johnpye | 789 | offset = sys->J.reg.col.low; |
2334 | aw0a | 1 | |
2335 | johnpye | 789 | /* the values returned... */ |
2336 | vp=slv_get_solvers_var_list(SERVER); | ||
2337 | for(c = 0; c < *n; ++c){ | ||
2338 | col = c + offset; | ||
2339 | aw0a | 1 | var = sys->vlist[mtx_col_to_org(sys->J.mtx,col)]; |
2340 | johnpye | 789 | nominal = sys->nominals.vec[col]; |
2341 | value = xval[c]*nominal; | ||
2342 | varname = var_make_name(SERVER,var); | ||
2343 | /* pass the value back to ASCEND */ | ||
2344 | var_set_value(var,value); | ||
2345 | /* pass the variable status (basic, nonbasic) back to ASCEND */ | ||
2346 | switch(xbas[c]){ | ||
2347 | case 0: varstat = "at lower bound"; break; | ||
2348 | case 1: varstat = "at upper bound"; break; | ||
2349 | case 2: varstat = "basic"; var_set_nonbasic(var,FALSE); break; | ||
2350 | case 3: varstat = "super-basic"; break; | ||
2351 | aw0a | 1 | } |
2352 | johnpye | 789 | if(xbas[c] != 2){ |
2353 | var_set_nonbasic(var,TRUE); | ||
2354 | } | ||
2355 | |||
2356 | johnpye | 919 | CONOPT_CONSOLE_DEBUG("%d: %s = %f (%s)",c,varname,value,varstat); |
2357 | johnpye | 789 | ASC_FREE(varname); |
2358 | aw0a | 1 | } |
2359 | |||
2360 | /* should pull out additional info here */ | ||
2361 | johnpye | 783 | return 0; |
2362 | aw0a | 1 | } |
2363 | |||
2364 | johnpye | 783 | #if 0 /* think that this is removed from the API now */ |
2365 | aw0a | 1 | /* |
2366 | * COIUSZ communicates and update of an existing model to CONOPT | ||
2367 | * COIUSZ(nintg, ipsz, nreal, rpsz, usrmem) | ||
2368 | * | ||
2369 | * nintg - number of positions in ipsz | ||
2370 | * ipsz - array describing problem size and options | ||
2371 | * nreal - number of positions in rpsz | ||
2372 | * rpsz - array of reals describing problem size and options | ||
2373 | * usrmem- user memory | ||
2374 | */ | ||
2375 | jpye | 1491 | static void conopt_coiusz(int32 *nintg, int32 *ipsz, int32 *nreal, |
2376 | aw0a | 1 | real64 *rpsz, real64 *usrmem) |
2377 | { | ||
2378 | /* | ||
2379 | * "zero changes" subroutines. the default for all the values is a | ||
2380 | * no change situation | ||
2381 | */ | ||
2382 | |||
2383 | /* | ||
2384 | * stop gcc whining about unused parameter | ||
2385 | */ | ||
2386 | (void)nintg; (void)ipsz; (void)nreal; (void)rpsz; | ||
2387 | (void)usrmem; | ||
2388 | |||
2389 | johnpye | 783 | $if 0 |
2390 | jpye | 1491 | conopt_system_t sys; |
2391 | aw0a | 1 | |
2392 | /* | ||
2393 | * To Ken: This was in the subroutine before. But all the values | ||
2394 | * are the same as in coipsz. So, no redefintion is necessary since | ||
2395 | * the defaults contain the same information | ||
2396 | */ | ||
2397 | |||
2398 | /* | ||
2399 | * stop gcc whining about unused parameter | ||
2400 | */ | ||
2401 | (void)nintg; (void)nreal; | ||
2402 | |||
2403 | jpye | 1491 | sys = (conopt_system_t)usrmem; |
2404 | aw0a | 1 | |
2405 | ipsz[F2C(1)] = sys->con.n; | ||
2406 | ipsz[F2C(2)] = sys->con.m; | ||
2407 | ipsz[F2C(3)] = sys->con.nz; | ||
2408 |