1 /* $Id$
2 *
3 * Name: nl2e.cpp
4 * Author: Pietro Belotti
5 * Purpose: converts a nl expression into a Couenne expression
6 *
7 * (C) Carnegie-Mellon University, 2006-09.
8 * This file is licensed under the Eclipse Public License (EPL)
9 */
10
11 #include "CouenneTypes.hpp"
12
13 #include "CouenneExprVar.hpp"
14 #include "CouenneExprAbs.hpp"
15 #include "CouenneExprSum.hpp"
16 #include "CouenneExprSub.hpp"
17 #include "CouenneExprMul.hpp"
18 #include "CouenneExprDiv.hpp"
19 #include "CouenneExprInv.hpp"
20 #include "CouenneExprSin.hpp"
21 #include "CouenneExprPow.hpp"
22 #include "CouenneExprClone.hpp"
23 #include "CouenneExprLog.hpp"
24 #include "CouenneExprOpp.hpp"
25 #include "CouenneExprCos.hpp"
26 #include "CouenneExprExp.hpp"
27
28 #include "asl.h"
29 #include "nlp.h"
30 #include "opcode.hd"
31
32 using namespace Couenne;
33
34 // get ASL op. code relative to function pointer passed as parameter
35 size_t getOperator (efunc *);
36
37
38 // warning for non-implemented functions -- return 0 constant expression
39 //expression *notimpl (const std::string &fname) {
notimpl(const std::string & fname)40 void notimpl (const std::string &fname) {
41 std::cerr << "*** Error: " << fname << " not implemented" << std::endl;
42 exit (-1);
43 }
44
45
46 // converts an AMPL expression (sub)tree into an expression* (sub)tree
nl2e(expr * e,const ASL * asl)47 expression *CouenneProblem::nl2e (expr *e, const ASL *asl) {
48
49 switch (getOperator (e -> op)) {
50
51 case OPPLUS: return new exprSum (nl2e (e -> L.e, asl), nl2e (e -> R.e, asl));
52 case OPMINUS: return new exprSub (nl2e (e -> L.e, asl), nl2e (e -> R.e, asl));
53 case OPMULT: return new exprMul (nl2e (e -> L.e, asl), nl2e (e -> R.e, asl));
54 case OPDIV: return new exprDiv (nl2e (e -> L.e, asl), nl2e (e -> R.e, asl));
55 case OPREM: notimpl ("remainder");
56 case OPPOW: return new exprPow (nl2e (e -> L.e, asl), nl2e (e -> R.e, asl));
57 case OPLESS: notimpl ("less");
58 case MINLIST: notimpl ("min");
59 case MAXLIST: notimpl ("max");
60 case FLOOR: notimpl ("floor");
61 case CEIL: notimpl ("ceil");
62 case ABS: return new exprAbs (nl2e (e -> L.e, asl));
63 case OPUMINUS:return new exprOpp (nl2e (e -> L.e, asl));
64 // return new exprOpp (nl2e (e -> L.e -> L.e, asl));
65 case OPIFnl: { notimpl ("ifnl");
66
67 // see ASL/solvers/rops.c, IfNL
68 }
69
70 case OP_tanh: return new exprDiv
71 (new exprSub (new exprExp (nl2e (e -> L.e, asl)),
72 new exprExp (new exprOpp (nl2e (e->L.e, asl)))),
73 new exprSum (new exprExp (nl2e (e -> L.e, asl)),
74 new exprExp (new exprOpp (nl2e (e->L.e, asl)))));
75
76 case OP_tan:
77 return new exprDiv (new exprSin (nl2e (e -> L.e, asl)), new exprCos (new exprClone (nl2e (e -> L.e, asl))));
78 case OP_sqrt: return new exprPow (nl2e (e -> L.e, asl), new exprConst (0.5));
79 case OP_sinh: return new exprMul (new exprConst (0.5),
80 new exprSub (new exprExp (nl2e (e -> L.e, asl)),
81 new exprExp (new exprOpp (nl2e (e->L.e, asl)))));
82 case OP_sin: return new exprSin (nl2e (e -> L.e, asl));
83 case OP_log10: return new exprMul (new exprConst (1.0 / log (10.0)),
84 new exprLog (nl2e (e -> L.e, asl)));
85 case OP_log: return new exprLog (nl2e (e -> L.e, asl));
86 case OP_exp: return new exprExp (nl2e (e -> L.e, asl));
87 case OP_cosh: return new exprMul (new exprConst (0.5),
88 new exprSum (new exprExp (nl2e (e -> L.e, asl)),
89 new exprExp (new exprOpp (nl2e (e->L.e, asl)))));
90
91 case OP_cos: return new exprCos (nl2e (e -> L.e, asl));
92 case OP_atanh: notimpl ("atanh");
93 case OP_atan2: notimpl ("atan2");
94 case OP_atan: notimpl ("atan");
95 case OP_asinh: notimpl ("asinh");
96 case OP_asin: notimpl ("asin");
97 case OP_acosh: notimpl ("acosh");
98 case OP_acos: notimpl ("acos");
99
100 case OPSUMLIST: {
101 int i=0;
102 expression **al = new expression * [(e->R.ep - e->L.ep)];
103 for (expr **ep = e->L.ep; ep < e->R.ep; ep++)
104 al [i++] = nl2e (*ep, asl);
105 return new exprSum (al, i);
106 }
107 case OPintDIV: notimpl ("intdiv");
108 case OPprecision: notimpl ("precision");
109 case OPround: notimpl ("round");
110 case OPtrunc: notimpl ("trunc");
111
112 case OP1POW: return new exprPow (nl2e (e -> L.e, asl), new exprConst (((expr_n *)e->R.e)->v));
113 case OP2POW: return new exprPow (nl2e (e -> L.e, asl), new exprConst (2.));
114 case OPCPOW: return new exprPow (new exprConst (((expr_n *)e->L.e)->v), nl2e (e -> R.e, asl));
115 case OPFUNCALL: notimpl ("function call");
116 case OPNUM: return new exprConst (((expr_n *)e)->v);
117 case OPPLTERM: notimpl ("plterm");
118 case OPIFSYM: notimpl ("ifsym");
119 case OPHOL: notimpl ("hol");
120 case OPVARVAL: {
121
122 int j = ((expr_v *) e) -> a;
123
124 if (j >= nOrigVars_) // common expression
125 // use base pointer otherwise the .a field returns an awkward, out-of-bound index
126 // TODO: fix! In itointqor.nl should return v51=y44 but returns v52=y44
127 // v??=y39 but returns v79=y39
128 j = ((expr_v *) e) - ((const ASL_fg *) asl) -> I.var_e_;
129
130 if (j >= nOrigVars_ + ndefined_) {
131 printf ("error: unknown variable x_%d\n", j);
132 //return new exprClone (variables_ [0]);
133 exit (-1);
134 }
135
136 return new exprClone (variables_ [j]);
137 }
138
139 default:
140 printf ("Couenne error: unknown operator (address %p), aborting.\n", Intcast (e -> op));
141 exit (-1);
142 //return new exprConst (0);
143 }
144
145 return new exprConst (0.);
146 }
147