00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <math.h>
00012
00013 #include "exprSin.hpp"
00014 #include "exprClone.hpp"
00015 #include "exprCos.hpp"
00016 #include "exprBSin.hpp"
00017 #include "exprMul.hpp"
00018
00019 static const CouNumber
00020 pi = M_PI,
00021 pi2 = M_PI * 2.,
00022 pih = M_PI / 2.;
00023
00024
00025
00026 expression *exprSin::differentiate (int index) {
00027
00028 return new exprMul (new exprCos (new exprClone (argument_)),
00029 argument_ -> differentiate (index));
00030 }
00031
00032
00033
00034 void exprSin::getBounds (expression *&lb, expression *&ub) {
00035
00036 expression *xl, *xu;
00037
00038 argument_ -> getBounds (xl, xu);
00039
00040 lb = new exprLBSin (xl, xu);
00041 ub = new exprUBSin (new exprClone (xl), new exprClone (xu));
00042 }
00043
00044
00045 void exprSin::getBounds (CouNumber &lb, CouNumber &ub) {
00046
00047 CouNumber l, u;
00048 argument_ -> getBounds (l, u);
00049
00050 if ((u - l > pi2) ||
00051 (floor (l/pi2 - 0.75) <
00052 floor (u/pi2 - 0.75)))
00053 lb = -1.;
00054 else lb = CoinMin (sin (l), sin (u));
00055
00056 if ((u - l > pi2) ||
00057 (floor (l/pi2 - 0.25) <
00058 floor (u/pi2 - 0.25)))
00059 ub = 1.;
00060 else ub = CoinMax (sin (l), sin (u));
00061 }
00062
00064 bool trigImpliedBound (enum cou_trig type, int wind, int xind,
00065 CouNumber *l, CouNumber *u, t_chg_bounds *chg) {
00066
00067
00068
00069 CouNumber *xl = l + xind, wl = l [wind],
00070 *xu = u + xind, wu = u [wind];
00071
00072 bool tighter = false;
00073
00074 CouNumber fl, fu, iwl, iwu, displacement;
00075
00076 if (type == COU_SINE) {fl = sin (*xl); fu = sin (*xu); displacement = pih;}
00077 else {fl = cos (*xl); fu = cos (*xu); displacement = 0.;}
00078
00079 iwl = acos (wl);
00080 iwu = acos (wu);
00081
00082
00083
00084
00085
00086
00088
00089 if (wu < fl - COUENNE_EPS) {
00090
00091 CouNumber base = displacement + pi2 * floor ((*xl + pi - displacement) / pi2);
00092
00093
00094
00095 if (updateBound (-1, xl, base + iwu)) {
00096 tighter = true;
00097 chg [xind]. setLower (t_chg_bounds::CHANGED);
00098 }
00099 }
00100
00101 if (wu < fu - COUENNE_EPS) {
00102
00103 CouNumber base = displacement + pi2 * floor ((*xu + pi - displacement) / pi2);
00104
00105
00106
00107 if (updateBound (+1, xu, base - iwu)) {
00108 tighter = true;
00109 chg [xind]. setUpper (t_chg_bounds::CHANGED);
00110 }
00111 }
00112
00113 if (wl > fl + COUENNE_EPS) {
00114
00115 CouNumber base = displacement + pi2 * floor ((*xl - displacement) / pi2) + pi;
00116
00117
00118
00119 if (updateBound (-1, xl, base + pi - iwl)) {
00120 tighter = true;
00121 chg [xind]. setLower (t_chg_bounds::CHANGED);
00122 }
00123 }
00124
00125 if (wl > fu + COUENNE_EPS) {
00126
00127 CouNumber base = displacement + pi2 * floor ((*xu - displacement) / pi2) + pi;
00128
00129
00130
00131 if (updateBound (+1, xu, base - pi + iwl)) {
00132 tighter = true;
00133 chg [xind]. setUpper (t_chg_bounds::CHANGED);
00134 }
00135 }
00136
00137
00138
00139 return tighter;
00140 }
00141
00142
00144 void exprSin::closestFeasible (expression *varind, expression *vardep,
00145 CouNumber& left, CouNumber& right) const
00146 {
00147 CouNumber curr = (*varind)() - pih;
00148 int period = (int)(curr/pi2);
00149 CouNumber curr_noperiod = curr - pi2*period;
00150 CouNumber inv = acos((*vardep)());
00151
00152 if (curr_noperiod < inv) {
00153 left = pi2*period - inv;
00154 right = pi2*period + inv;
00155 }
00156 else if (curr_noperiod < pi2-inv) {
00157 left = pi2*period + inv;
00158 right = pi2*(period+1) - inv;
00159 }
00160 else {
00161 left = pi2*(period+1) - inv;
00162 right = pi2*(period+1) + inv;
00163 }
00164 left += pih;
00165 right += pih;
00166 }