Parent Directory | Revision Log

Revision **2351** -
(**show annotations**)
(**download**)
(**as text**)

*Thu Jan 6 02:02:41 2011 UTC*
(7 years, 11 months ago)
by *jpye*

File MIME type: text/x-chdr

File size: 18186 byte(s)

File MIME type: text/x-chdr

File size: 18186 byte(s)

Resolved memory leak with test/test solver_ipopt.formula. Still some issues to overcome with regard to inactive relations, probably. Some issue still occurring when attempting to run whole solver_ipopt suite in one go.

1 | /* ASCEND modelling environment |

2 | Copyright (C) 2006 Carnegie Mellon University |

3 | Copyright (C) 1994 Joseph Zaher, Benjamin Andrew Allan |

4 | Copyright (C) 1993 Joseph Zaher |

5 | Copyright (C) 1990 Karl Michael Westerberg |

6 | |

7 | This program is free software; you can redistribute it and/or modify |

8 | it under the terms of the GNU General Public License as published by |

9 | the Free Software Foundation; either version 2, or (at your option) |

10 | any later version. |

11 | |

12 | This program is distributed in the hope that it will be useful, |

13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |

14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |

15 | GNU General Public License for more details. |

16 | |

17 | You should have received a copy of the GNU General Public License |

18 | along with this program; if not, write to the Free Software |

19 | Foundation, Inc., 59 Temple Place - Suite 330, |

20 | Boston, MA 02111-1307, USA. |

21 | *//** @file |

22 | Relation manipulator module for the SLV solver. |

23 | |

24 | This module will provide supplemental operations for |

25 | relations such as simplification, evaluation, and |

26 | differentiation. |

27 | |

28 | Dates: 06/90 - original version |

29 | 06/93 - separated out exprman |

30 | 11/93 - added relman_calc_satisfied |

31 | |

32 | *//* |

33 | by Karl Michael Westerberg and Joseph Zaher, 2/6/90 |

34 | Last in CVS: $Revision: 1.29 $ $Date: 1998/04/23 23:56:24 $ $Author: ballan $ |

35 | */ |

36 | |

37 | #ifndef ASC_RELMAN_H |

38 | #define ASC_RELMAN_H |

39 | |

40 | #include <ascend/general/platform.h> |

41 | |

42 | #include <ascend/linear/mtx.h> |

43 | #include <ascend/general/ltmatrix.h> |

44 | |

45 | #include "var.h" |

46 | #include "rel.h" |

47 | |

48 | /** @addtogroup solver Solver |

49 | @{ |

50 | */ |

51 | |

52 | #define relman_is_linear(a,b) (FALSE) |

53 | /**< |

54 | * Determines whether or not the given relation is linear in |

55 | * all of the variables which pass through the variable filter, treating |

56 | * those variables which fail to pass as constants.<br><br> |

57 | * |

58 | * Example: |

59 | * x1 + x2 >= 3 is a linear relation. |

60 | */ |

61 | |

62 | extern real64 relman_linear_coef(struct rel_relation *rel, |

63 | struct var_variable *var, |

64 | var_filter_t *filter); |

65 | /**< |

66 | * Computes the coefficient of the given variable in a linear |

67 | * relation. If var=NULL, then the "RHS" is returned instead. More |

68 | * nprecisely, "a[var]" is returned where:<br><br> |

69 | * |

70 | * rel : sum[variables v](a[v] * v) COMPARISON a[NULL]<br><br> |

71 | * |

72 | * It is assumed that the relation is linear, otherwise, |

73 | * something will be returned, but it won't be very meaningful. |

74 | */ |

75 | |

76 | #if 0 |

77 | extern void relman_simplify(struct rel_relation *rel, int opt_level); |

78 | /**< NOT IMPLEMENTED |

79 | * The left and right hand sides of the given relation are simplified |

80 | * to the extent given by opt_level. The effect of varying values of |

81 | * opt_level is given in the description for exprman_simplify(). |

82 | */ |

83 | |

84 | extern void relman_dissolve_vars(struct rel_relation *rel, var_filter_t *filter); |

85 | /**< NOT IMPLEMENTED |

86 | * Variables which pass through the filter are replaced in the |

87 | * relation by their current values. |

88 | */ |

89 | #endif |

90 | |

91 | extern void relman_decide_incidence(struct rel_relation *rel); |

92 | /**< |

93 | * Sets the incidence field of each variable which is found to be |

94 | * incident in the relation rel to TRUE. If these variables make |

95 | * up a subset of some larger variable list, it is important to first |

96 | * set the incidence field of all of the variables to FALSE before |

97 | * using this function in order to determine the unattached variables. |

98 | */ |

99 | |

100 | extern void relman_get_incidence(struct rel_relation *rel, |

101 | var_filter_t *filter, |

102 | mtx_matrix_t matrix); |

103 | /**< |

104 | * Upon return, coefficient (rel_n,var_n) (using original row and column |

105 | * numbers) is non-zero if and only if the relation rel with index rel_n |

106 | * depends on a variable with index var_n. |

107 | */ |

108 | |

109 | ASC_DLLSPEC real64 relman_eval(struct rel_relation *rel, int32 *calc_okp, int safe); |

110 | /**< |

111 | The residual of the relation is calculated and returned. In addition |

112 | to returning the residual, the residual field of the relation is |

113 | updated. The residual field of the relation is not updated when an error |

114 | occurs. |

115 | |

116 | @param safe If set nonzero, "safe" functions are used for evaluation (means |

117 | that overflows, divide by zero, etc are avoided) |

118 | @param calc_ok (returned) status of the calculation. 0=error, else ok. |

119 | @return residual (= LHS - RHS, regardless of comparison) |

120 | |

121 | @NOTE |

122 | This function should be surrounded by Asc_SignalHandlerPush/Pop both |

123 | with arguments (SIGFPE,SIG_IGN). If it is being called in a loop, |

124 | the push/pop should be _outside_ the loop. |

125 | */ |

126 | |

127 | ASC_DLLSPEC int32 relman_obj_direction(struct rel_relation *rel); |

128 | /**< |

129 | * Returns: |

130 | * - direction = -1 if objective is minimization |

131 | * - direction = 1 if objective is maximization |

132 | * - direction = 0 otherwise. (ie. if not an objective) |

133 | */ |

134 | |

135 | ASC_DLLSPEC real64 relman_scale(struct rel_relation *rel); |

136 | /**< |

137 | * Calculates relation nominal scaling factor for |

138 | * current values stored in the relations variables. |

139 | * Fills the relations nominal field and also returns |

140 | * the relations nominal. |

141 | */ |

142 | |

143 | #define relman_diff(a,b,c,d) (abort(),1) |

144 | /**< |

145 | Calculates the derivative of the relation residual with respect to |

146 | the specified variable and stuffs it in pd. if problem with |

147 | calculation, returns 1, else 0. |

148 | If the value of safe is nonzero, "safe" functions will be used to |

149 | calculate the residual. |

150 | |

151 | @TODO relman_diff() needs to be reimplemented - needs compiler-side work. |

152 | */ |

153 | |

154 | |

155 | ASC_DLLSPEC int relman_diff2(struct rel_relation *rel, |

156 | const var_filter_t *filter, |

157 | real64 *derivatives, |

158 | int32 *variables, |

159 | int32 *count, |

160 | int32 safe); |

161 | /**< |

162 | Calculates the row of the jacobian matrix (the transpose gradient of |

163 | the relation residual, \f$ \grad^{T}(f) \f$) corresponding to the relation |

164 | rel. The filter determines which variables actually contribute to the |

165 | jacobian. |

166 | |

167 | derivatives[i] will contain the derivative of the relation with |

168 | respect to the variable whose solver index is stored in |

169 | variables[i]. |

170 | |

171 | @param rel Relation being differentiated |

172 | @param filter Filter for variables for which derivs are desired |

173 | @param safe If nonzero, "safe" functions are used to for the calculations |

174 | @param derivatives output vector (allocated by the calling function) |

175 | @param variables output vector (allocated by the calling function) |

176 | @param count output value, will be set to the number of elements assigned upon exit. |

177 | |

178 | @return 0 on success, non-zero if an error is encountered in the calculation |

179 | */ |

180 | |

181 | |

182 | /* return 0 on success (derivatives, variables and count are output vars too) */ |

183 | ASC_DLLSPEC int relman_diff2_rev(struct rel_relation *rel, |

184 | const var_filter_t *filter, |

185 | real64 *derivatives, |

186 | int32 *variables, |

187 | int32 *count, int32 safe); |

188 | |

189 | /**< |

190 | similar to relman_diff2, but uses revers Automatic differentiation to obtain derivatives |

191 | */ |

192 | |

193 | ASC_DLLSPEC int relman_hess(struct rel_relation *rel, |

194 | const var_filter_t *filter, |

195 | hessian_mtx *hess_matrix, |

196 | int32 *count, |

197 | unsigned long max_dimension, |

198 | int32 safe); |

199 | /**< |

200 | Hessian Matrix Evaluation, |

201 | @param rel is the relation whose Hessian Matrix is desired |

202 | @param filter is the variable filter |

203 | @param hess_matrix is the Lower Triangular Matrix into which values are filled |

204 | @param count is the count of elements filled |

205 | @param safe is the boolean value indicating whether evaluation is safe or non-safe |

206 | |

207 | @return 0 on success, non-zero if an error is encountered in the calculation |

208 | */ |

209 | |

210 | ASC_DLLSPEC int relman_diff3(struct rel_relation *rel, |

211 | const var_filter_t *filter, |

212 | real64 *derivatives, |

213 | struct var_variable **variables, |

214 | int32 *count, |

215 | int32 safe); |

216 | /**< as relman_diff2 but fills a var_variable* array intest of an index array. */ |

217 | |

218 | ASC_DLLSPEC int relman_diff_grad(struct rel_relation *rel, |

219 | const var_filter_t *filter, |

220 | real64 *derivatives, |

221 | int32 *variables_master, |

222 | int32 *variables_solver, |

223 | int32 *count, |

224 | real64 *resid, |

225 | int32 safe); |

226 | /**< |

227 | * Calculates the row of the jacobian matrix (the transpose gradient of |

228 | * the relation residual grad^T(f) ) corresponding to the relation |

229 | * rel. The filter determines which variables actually contribute to the |

230 | * jacobian. The residual of the relation is also computed and returned. |

231 | * If an error is encountered in the calculation, the status returned is |

232 | * 1. Status = 0 is OK. |

233 | * If the value of safe is nonzero, "safe" functions are used to for |

234 | * the calculations.<br><br> |

235 | * The calling function should allocate the output vectors 'derivatives', |

236 | * 'variables_master' and 'variables_solver'. 'count' will be set to |

237 | * the number of elements assigned upon exit. |

238 | * derivative(i) will contain the derivative of the relation with |

239 | * respect to the variable whose master index is stored in |

240 | * variables_master(i). The solver index of each variable is stored in |

241 | * variables_solver(i). |

242 | * |

243 | * There are two differences wrt to relman_diff2: |

244 | * - the master index (solver independent) is obtained |

245 | * - the residual is evaluated |

246 | */ |

247 | |

248 | ASC_DLLSPEC int relman_diffs(struct rel_relation *rel, |

249 | const var_filter_t *filter, mtx_matrix_t mtx, |

250 | real64 *resid, int safe); |

251 | /**< |

252 | Calculates the row of the jacobian matrix (the transpose gradient of |

253 | the relation residual grad^T(f) ) corresponding to the relation |

254 | rel. The filter determines which variables actually contribute to the |

255 | jacobian. The residual of the relation is also computed and returned. |

256 | If an error is encountered in the calculation, the status returned is |

257 | 1 and the residual is set to some number we managed to calculate, |

258 | while the gradient is discarded. status = 0 is OK. |

259 | |

260 | @param rel relation for which jacobian entries are required |

261 | @param filter filter for which variables should actually contribute to the jacobian |

262 | @param mtx matrix into which the row (corresponding to rel) is written |

263 | @param safe if non-zero, "safe" functions are used to for the calucaltions. |

264 | |

265 | It doesn't matter how you have permuted the columns and rows: |

266 | for the vars which pass the filter you send we |

267 | fill the org row determined by rel_sindex and the org cols |

268 | determined by var_sindex. |

269 | |

270 | @return 0 on success, 1 on calculation error (residual will be returned, grad discarded) |

271 | |

272 | @NOTE The row of the mtx corresponding to rel should be cleared |

273 | before calling this function, since this FILLS with the gradient.<br><br> |

274 | |

275 | @NOTE *changed* -- This operator used to just ADD on top of any incidence |

276 | already in the row. This is not TRUE now. |

277 | |

278 | @TODO This operator really needs to be redesigned so it can deal with |

279 | harwellian matrices, glassbox rels and blackbox. |

280 | */ |

281 | |

282 | extern int32 relman_diff_harwell(struct rel_relation **rlist, |

283 | var_filter_t *vfilter, rel_filter_t *rfilter, |

284 | int32 rlen, int32 bias, int32 mors, |

285 | real64 *avec, int32 *ivec, int32 *jvec); |

286 | /**< |

287 | * This fills an "a-i-j" sparse matrix in the avec/ivec/jvec given. |

288 | * @param rlist struct rel_relation **, list of relations rlen long. |

289 | * @param vfilter var_filter_t *, stuffs gradient for matching variables only. |

290 | * @param rlen int32, length of list of relations. |

291 | * @param bias int32, 0 = row grouped together, 1 = column grouped together. |

292 | * There is a substantial penalty for bias = 1. we MODEL by row. |

293 | * @param mors int32, 0 = master var index of columns, master rel index of rows |

294 | * 1 = solver var index of columns, master rel index of rows |

295 | * 2 = master var index of columns, solver rel index of rows |

296 | * 3 = solver var index of columns, solver rel index of rows |

297 | * Size of avec,ivec,jvec given is assumed big enough. |

298 | * big_enough = relman_jacobian_count(rlist,rlen,vfilter,rfilter,&dummy); |

299 | * If ivec or jvec given is NULL, then neither is stuffed, though avec is. |

300 | @return 0 on success, <0 on floating point errors, 1 on unrecoverable error. |

301 | |

302 | err = 1 --> unrecoverable error/bad input. caller should probably punt. |

303 | err < 0 --> -(number of floating point errors in evaluation). |

304 | The matrix will contain an approximation only. |

305 | |

306 | @todo relman_diff_harwell() bias == 1 is not yet implemented. |

307 | */ |

308 | |

309 | ASC_DLLSPEC int32 relman_jacobian_count(struct rel_relation **rlist, |

310 | int32 rlen, |

311 | var_filter_t *vfilter, |

312 | rel_filter_t *rfilter, |

313 | int32 *rhomax); |

314 | /**< |

315 | * Return the number of nonzero gradient entries in the equations |

316 | * given. Only equations passing rfilter and entries passing vfilter |

317 | * are counted. rlen is the length of the relation list. |

318 | * *rhomax is the largest row count on return. |

319 | */ |

320 | |

321 | ASC_DLLSPEC int32 relman_hessian_count( |

322 | struct rel_relation **rlist, int32 rlen |

323 | , var_filter_t *vfilter, rel_filter_t *rfilter |

324 | , int32 *rhomax |

325 | ); |

326 | /**< |

327 | * Return the number of nonzero gradient entries in the equations |

328 | * given. Only equations passing rfilter and entries passing vfilter |

329 | * are counted. rlen is the length of the relation list. |

330 | * *rhomax is the largest row count on return. |

331 | */ |

332 | |

333 | ASC_DLLSPEC boolean relman_calc_satisfied_scaled(struct rel_relation *rel, |

334 | real64 tolerance); |

335 | /**< |

336 | * This definition of satisfaction includes the notion |

337 | * of scaling by the relation nominal before comparison. |

338 | * @see relman_calc_satisfied. |

339 | */ |

340 | ASC_DLLSPEC boolean relman_calc_satisfied(struct rel_relation *rel, |

341 | real64 tolerance); |

342 | /**< |

343 | * Returns TRUE or FALSE depending on whether the relation whose residual |

344 | * has been previously calculated is satisfied based on the value stored |

345 | * in the residual field. The satisfied field of the relation is also |

346 | * updated. A tolerance specification allows equalities to be declared |

347 | * satisfied as long as their residuals are close to zero. |

348 | * @see relman_calc_satisfied_scaled. |

349 | */ |

350 | |

351 | #define relman_directly_solve(r,s,a,n) \ |

352 | relman_directly_solve_new(r,s,a,n,1.0e-8) |

353 | /**< @see relman_directly_solve_new(). */ |

354 | extern real64 *relman_directly_solve_new(struct rel_relation *rel, |

355 | struct var_variable *solvefor, |

356 | int *able, |

357 | int *nsolns, |

358 | real64 tol); |

359 | /**< |

360 | * Attempts to solve the given equation for the given variable. If this |

361 | * function is able to determine the solution set, then *able is set to |

362 | * 1 and a newly allocated solution list is returned: *nsolns will be |

363 | * set to the length of this array. Otherwise *able is 0 and NULL |

364 | * is returned. NULL *may* also be returned if the solution set is empty. |

365 | * A return of able == 1, solution_list != NULL, and nsolns == 0 is |

366 | * possible for certain classes of floating point exceptions. |

367 | * It is assumed that the relation is a condition of equality.<br><br> |

368 | * |

369 | * relman_directly_solve_new() handles passing in a tolerance for glassbox |

370 | * relations so a rootfinder can do the work rather than leaving it to |

371 | * someone else. The rootfinder is based on Brent's algorithm. Old clients of |

372 | * relman_directly solve are grandfathered at a default tolerance of 1e-8. |

373 | * Once all these clients are gone, go back to the old name space for |

374 | * the new function.<br><br> |

375 | * |

376 | * Do NOT free or keep a persistent pointer to the solution_list this |

377 | * function returns. |

378 | */ |

379 | |

380 | #define relman_make_string_infix(sys,rel) \ |

381 | relman_make_vstring_infix((sys),(rel),TRUE) |

382 | /**< @see relman_make_xstring_infix() */ |

383 | #define relman_make_string_postfix(sys,rel) \ |

384 | relman_make_vstring_postfix((sys),(rel),TRUE) |

385 | /**< @see relman_make_xstring_infix() */ |

386 | #define relman_make_xstring_infix(sys,rel) \ |

387 | relman_make_vstring_infix((sys),(rel),FALSE) |

388 | /**< |

389 | @return string |

390 | @param sys |

391 | @param rel struct rel_relation *rel |

392 | |

393 | Creates a sufficiently large string (you must free it when you're |

394 | done with it) into which it converts a relation. The string will be |

395 | terminated with a '\0' character. |

396 | |

397 | The xstring versions of this call make strings where all the variables |

398 | are written as x<varindex> (e.g. x23) rather than as object names. |

399 | The MASTER index (var_mindex) is used, not the solver's sindex. |

400 | Currently the compiler does not support xstring postfix format, |

401 | but could easily do so if needed. |

402 | |

403 | The name of a var is context dependent, so you have to provide the |

404 | slv_system_t from which you got the relation. |

405 | |

406 | @see relman_make_string_postfix |

407 | @see relman_make_string_infix |

408 | */ |

409 | |

410 | #if 0 /* needs compiler-side work */ |

411 | # define relman_make_xstring_postfix(sys,rel) \ |

412 | relman_make_vstring_postfix((sys),(rel),FALSE) |

413 | #else |

414 | # define relman_make_xstring_postfix(sys,rel) \ |

415 | dummy_rel_string((sys),(rel),0) |

416 | #endif |

417 | /**< |

418 | * Not suppported. |

419 | * @TODO Consider adding support for xstring postfix format. |

420 | */ |

421 | |

422 | ASC_DLLSPEC char *relman_make_vstring_infix(slv_system_t sys, |

423 | struct rel_relation *rel, |

424 | int style); |

425 | /**< |

426 | * Implementation function for relman_make_string_infix() and |

427 | * relman_make_xstring_infix(). Do not call this function |

428 | * directly - use one of the macros instead. |

429 | */ |

430 | extern char *relman_make_vstring_postfix(slv_system_t sys, |

431 | struct rel_relation *rel, |

432 | int style); |

433 | /**< |

434 | * Implementation function for relman_make_string_postfix(). and |

435 | * Do not call this function directly - use the macro instead. |

436 | */ |

437 | |

438 | extern char *dummyrelstring(slv_system_t sys, |

439 | struct rel_relation *rel, |

440 | int style); |

441 | /**< Temporary no-op function to placehold unimplemented io functions. */ |

442 | |

443 | extern void relman_free_reused_mem(void); |

444 | /**< Call when desired to free memory cached internally. */ |

445 | |

446 | /* @} */ |

447 | |

448 | #endif /* ASC_RELMAN_H */ |

449 |

john.pye@anu.edu.au | ViewVC Help |

Powered by ViewVC 1.1.22 |