00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef __RVL_VLOp
00034 #define __RVL_VLOp
00035
00036 #include "space.hh"
00037
00038 namespace RVL {
00039
00056 template<class Scalar>
00057 class RVLScalarLogistic: public BinaryLocalFunctionObject<Scalar> {
00058 private:
00059 Scalar s;
00060 Scalar m;
00061 RVLScalarLogistic(const RVLScalarLogistic<Scalar> &) {}
00062 public:
00063 RVLScalarLogistic(Scalar fmin=ScalarFieldTraits<Scalar>::Zero(),
00064 Scalar fmax=ScalarFieldTraits<Scalar>::One()) {
00065 try {
00066 testRealOnly<Scalar>();
00067 if (!(fmin<fmax)) {
00068 RVLException e;
00069 e<<"ERROR: RVLScalarLogistic constructor\n";
00070 e<<"fmin="<<fmin<<" not less than fmax="<<fmax<<"\n";
00071 throw e;
00072 }
00073 s = 2.0 /(fmax-fmin);
00074 m = 0.5 *(fmax+fmin);
00075 }
00076 catch (RVLException & e) {
00077 e<<"\ncalled from RVLScalarLogistic constructor\n";
00078 throw e;
00079 }
00080 }
00081 ~RVLScalarLogistic() {}
00082
00088 using RVL::BinaryLocalEvaluation<Scalar>::operator();
00089 void operator()(LocalDataContainer<Scalar> & x,
00090 LocalDataContainer<Scalar> const & y) {
00091 if (x.getSize() != y.getSize()) {
00092 RVLException e; e<<"ERROR: RVLScalarLogistic\n";
00093 e<<"input size = "<<x.getSize()<<" output size = "<<y.getSize()<<"\n";
00094 e<<"required to be same\n";
00095 throw e;
00096 }
00097 else {
00098 size_t n = x.getSize();
00099 Scalar * px = x.getData();
00100 Scalar const * py = y.getData();
00101 for (size_t i=0;i<n;i++) {
00102 px[i]=m + py[i]/sqrt(1.0 + s*s*py[i]*py[i]);
00103 }
00104 }
00105 }
00106 string getName() const { return "RVLScalarLogistic"; }
00107 };
00108
00120 template<class Scalar>
00121 class RVLScalarLogisticInverse: public BinaryLocalFunctionObject<Scalar> {
00122 private:
00123 Scalar s;
00124 Scalar m;
00125 RVLScalarLogisticInverse(const RVLScalarLogisticInverse<Scalar> &) {}
00126 public:
00127 RVLScalarLogisticInverse(Scalar fmin=ScalarFieldTraits<Scalar>::Zero(),
00128 Scalar fmax=ScalarFieldTraits<Scalar>::One()) {
00129 try {
00130 testRealOnly<Scalar>();
00131 if (!(fmin<fmax)) {
00132 RVLException e;
00133 e<<"ERROR: RVLScalarLogisticInverse constructor\n";
00134 e<<"fmin="<<fmin<<" not less than fmax="<<fmax<<"\n";
00135 throw e;
00136 }
00137 s = 2.0 /(fmax-fmin);
00138 m = 0.5 *(fmax+fmin);
00139 }
00140 catch (RVLException & e) {
00141 e<<"\ncalled from RVLScalarLogisticInverse constructor\n";
00142 throw e;
00143 }
00144 }
00145 ~RVLScalarLogisticInverse() {}
00146
00152 using RVL::BinaryLocalEvaluation<Scalar>::operator();
00153 void operator()(LocalDataContainer<Scalar> & x,
00154 LocalDataContainer<Scalar> const & y) {
00155 if (x.getSize() != y.getSize()) {
00156 RVLException e; e<<"ERROR: RVLScalarLogisticInverse\n";
00157 e<<"input size = "<<x.getSize()<<" output size = "<<y.getSize()<<"\n";
00158 e<<"required to be same\n";
00159 throw e;
00160 }
00161 else {
00162 size_t n = x.getSize();
00163 Scalar * px = x.getData();
00164 Scalar const * py = y.getData();
00165 for (size_t i=0;i<n;i++) {
00166 if ((py[i] < m-1/s + numeric_limits<Scalar>::epsilon()) ||
00167 (py[i] > m+1/s - numeric_limits<Scalar>::epsilon())) {
00168 RVLException e;
00169 e<<"ERROR: RVLScalarLogisticInverse\n";
00170 e<<"input value = "<<py[i]<<" too close to \n";
00171 e<<"fmin = "<<m-1/s<<" or fmax = "<<m+1/s<<"\n";
00172 throw e;
00173 }
00174 px[i]=(py[i]-m)/sqrt(1.0 - s*s*(py[i]-m)*(py[i]-m));
00175 }
00176 }
00177 }
00178 string getName() const { return "RVLScalarLogisticInverse"; }
00179 };
00180
00195 template<class Scalar>
00196 class RVLScalarLogisticDeriv: public TernaryLocalFunctionObject<Scalar> {
00197 private:
00198 Scalar s;
00199 Scalar t;
00200 RVLScalarLogisticDeriv(const RVLScalarLogisticDeriv<Scalar> &) {}
00201 public:
00202 RVLScalarLogisticDeriv(Scalar fmin=ScalarFieldTraits<Scalar>::Zero(),
00203 Scalar fmax=ScalarFieldTraits<Scalar>::One()) {
00204 try {
00205 testRealOnly<Scalar>();
00206 if (!(fmin<fmax)) {
00207 RVLException e;
00208 e<<"ERROR: RVLScalarLogisticDeriv constructor\n";
00209 e<<"fmin="<<fmin<<" not less than fmax="<<fmax<<"\n";
00210 throw e;
00211 }
00212 s = 2.0 /(fmax-fmin);
00213 }
00214 catch (RVLException & e) {
00215 e<<"\ncalled from RVLScalarLogisticDeriv constructor\n";
00216 throw e;
00217 }
00218 }
00219 ~RVLScalarLogisticDeriv() {}
00220
00226 using RVL::TernaryLocalEvaluation<Scalar>::operator();
00227 void operator()(LocalDataContainer<Scalar> & x,
00228 LocalDataContainer<Scalar> const & y,
00229 LocalDataContainer<Scalar> const & dy) {
00230 if ((x.getSize() != y.getSize()) ||
00231 (x.getSize() != dy.getSize())) {
00232 RVLException e; e<<"ERROR: RVLScalarLogisticDeriv\n";
00233 e<<"input size = "<<y.getSize()<<"\n";
00234 e<<"input pert size = "<<dy.getSize()<<"\n";
00235 e<<"output size = "<<x.getSize()<<"\n";
00236 e<<"required to be same\n";
00237 throw e;
00238 }
00239 else {
00240 size_t n = x.getSize();
00241 Scalar * px = x.getData();
00242 Scalar const * py = y.getData();
00243 Scalar const * pdy = dy.getData();
00244 for (size_t i=0;i<n;i++) {
00245 t=1.0/sqrt(1.0 + s*s*py[i]*py[i]);
00246 px[i]=pdy[i]*t*t*t;
00247 }
00248 }
00249 }
00250 string getName() const { return "RVLScalarLogisticDeriv"; }
00251 };
00252
00271 template<class Scalar>
00272 class RVLVectorLogistic: public QuaternaryLocalFunctionObject<Scalar> {
00273 private:
00274 RVLVectorLogistic(const RVLVectorLogistic<Scalar> &) {}
00275 public:
00276 RVLVectorLogistic() {
00277 try {
00278 testRealOnly<Scalar>();
00279 }
00280 catch (RVLException & e) {
00281 e<<"\ncalled from RVLVectorLogistic constructor\n";
00282 throw e;
00283 }
00284 }
00285 ~RVLVectorLogistic() {}
00286
00292 using RVL::QuaternaryLocalEvaluation<Scalar>::operator();
00293 void operator()(LocalDataContainer<Scalar> & x,
00294 LocalDataContainer<Scalar> const & y,
00295 LocalDataContainer<Scalar> const & lb,
00296 LocalDataContainer<Scalar> const & ub) {
00297 if ((x.getSize() != y.getSize()) ||
00298 (x.getSize() != lb.getSize()) ||
00299 (x.getSize() != ub.getSize())) {
00300 RVLException e; e<<"ERROR: RVLVectorLogistic\n";
00301 e<<"input size = "<<x.getSize()<<"\n";
00302 e<<"output size = "<<y.getSize()<<"\n";
00303 e<<"lb size = "<<lb.getSize()<<"\n";
00304 e<<"ub size = "<<ub.getSize()<<"\n";
00305 e<<"required to be same\n";
00306 throw e;
00307 }
00308 else {
00309 size_t n = x.getSize();
00310 Scalar * px = x.getData();
00311 Scalar const * py = y.getData();
00312 Scalar const * fmin = lb.getData();
00313 Scalar const * fmax = ub.getData();
00314 for (size_t i=0;i<n;i++) {
00315 if (!(fmin[i]<fmax[i])) {
00316 RVLException e;
00317 e<<"ERROR: RVLVectorLogistic::operator()\n";
00318 e<<"array index = "<<i<<"\n";
00319 e<<"fmin="<<fmin[i]<<" not less than fmax="<<fmax[i]<<"\n";
00320 throw e;
00321 }
00322 Scalar s = 2.0/(fmax[i]-fmin[i]);
00323 Scalar m = 0.5 *(fmax[i]+fmin[i]);
00324 px[i]=m + py[i]/sqrt(1.0 + s*s*py[i]*py[i]);
00325 }
00326 }
00327 }
00328 string getName() const { return "RVLVectorLogistic"; }
00329 };
00330
00345 template<class Scalar>
00346 class RVLVectorLogisticDeriv: public LocalFunctionObject<Scalar> {
00347 public:
00348 RVLVectorLogisticDeriv() {}
00349 RVLVectorLogisticDeriv(const RVLVectorLogisticDeriv<Scalar> &) {}
00350 ~RVLVectorLogisticDeriv() {}
00351
00352 using RVL::LocalEvaluation<Scalar>::operator();
00353 void operator()(LocalDataContainer<Scalar> & x,
00354 std::vector<LocalDataContainer<Scalar> const *> & v) {
00355 if (v.size() != 4) {
00356 RVLException e;
00357 e<<"ERROR: RVLVectorLogisticDeriv::operator()\n";
00358 e<<" input std::vector must have size = 4\n";
00359 e<<" layout: v[0]=x, v[1]=dx, v[2]=xmin, v[3]=xmax\n";
00360 throw e;
00361 }
00362 if ((x.getSize() != v[0]->getSize()) ||
00363 (x.getSize() != v[1]->getSize()) ||
00364 (x.getSize() != v[2]->getSize()) ||
00365 (x.getSize() != v[3]->getSize())) {
00366 RVLException e; e<<"ERROR: RVLVectorLogisticDeriv\n";
00367 e<<" incompatible array lengths\n";
00368 throw e;
00369 }
00370 else {
00371 size_t n = x.getSize();
00372 Scalar * px = x.getData();
00373 Scalar const * py = v[0]->getData();
00374 Scalar const * pdy = v[1]->getData();
00375 Scalar const * fm = v[2]->getData();
00376 Scalar const * fp = v[3]->getData();
00377 for (size_t i=0;i<n;i++) {
00378 if (!(fm[i]<fp[i])) {
00379 RVLException e;
00380 e<<"ERROR: RVLVectorLogistic::operator()\n";
00381 e<<"array index = "<<i<<"\n";
00382 e<<"fmin="<<fm[i]<<" not less than fmax="<<fp[i]<<"\n";
00383 throw e;
00384 }
00385 Scalar s = 2.0/(fp[i]-fm[i]);
00386 Scalar t=1.0/sqrt(1.0 + s*s*py[i]*py[i]);
00387 px[i]=pdy[i]*t*t*t;
00388 }
00389 }
00390 }
00391 string getName() const { return "RVLVectorLogisticDeriv"; }
00392 };
00393
00404 template<class Scalar>
00405 class RVLVectorLogisticInverse: public LocalFunctionObject<Scalar> {
00406 public:
00407 RVLVectorLogisticInverse() {}
00408 RVLVectorLogisticInverse(const RVLVectorLogisticInverse<Scalar> &) {}
00409 ~RVLVectorLogisticInverse() {}
00410
00411 using RVL::LocalEvaluation<Scalar>::operator();
00412 void operator()(LocalDataContainer<Scalar> & x,
00413 std::vector<LocalDataContainer<Scalar> const *> & v) {
00414 if (v.size() != 3) {
00415 RVLException e;
00416 e<<"ERROR: RVLVectorLogisticInverse::operator()\n";
00417 e<<" input std::vector must have size = 4\n";
00418 e<<" layout: v[0]=x, v[1]=xmin, v[2]=xmax\n";
00419 throw e;
00420 }
00421 if ((x.getSize() != v[0]->getSize()) ||
00422 (x.getSize() != v[1]->getSize()) ||
00423 (x.getSize() != v[2]->getSize())) {
00424 RVLException e; e<<"ERROR: RVLVectorLogisticInverse\n";
00425 e<<" incompatible array lengths\n";
00426 throw e;
00427 }
00428 else {
00429 size_t n = x.getSize();
00430 Scalar * px = x.getData();
00431 Scalar const * py = v[0]->getData();
00432 Scalar const * fm = v[1]->getData();
00433 Scalar const * fp = v[2]->getData();
00434 for (size_t i=0;i<n;i++) {
00435 Scalar s = 2.0/(fp[i]-fm[i]);
00436 Scalar m = 0.5*(fp[i]+fm[i]);
00437 if (s*s*(py[i]-m)*(py[i]-m) > 1.0 - numeric_limits<Scalar>::epsilon()) {
00438
00439
00440 RVLException e;
00441 e<<"ERROR: RVLVectorLogisticInverse\n";
00442 e<<" input value = "<<py[i]<<" too close to \n";
00443 e<<" fmin = "<<m-1/s<<" or fmax = "<<m+1/s<<"\n";
00444 e<<" or exceeds these bounds - cannot invert logistic map\n";
00445 e<<" supplied function bounds are "<<fm[i]<<" and "<<fp[i]<<"\n";
00446 throw e;
00447 }
00448 px[i]=(py[i]-m)/sqrt(1.0 - s*s*(py[i]-m)*(py[i]-m));
00449 }
00450 }
00451 }
00452 string getName() const { return "RVLVectorLogisticInverse"; }
00453 };
00454
00455 template<typename Scalar>
00456 class VectorLogisticOp: public Operator<Scalar> {
00457
00458 private:
00459
00460
00461 Vector<Scalar> const & lb;
00462 Vector<Scalar> const & ub;
00463
00464 VectorLogisticOp();
00465
00466 protected:
00467
00468 void apply(Vector<float> const & x,
00469 Vector<float> & y) const {
00470 try {
00471 RVLVectorLogistic<Scalar> f;
00472 y.eval(f,x,lb,ub);
00473 }
00474 catch (RVLException & e) {
00475 e<<"\ncalled from VectorLogisticOp::apply\n";
00476 throw e;
00477 }
00478 }
00479
00480 void applyDeriv(Vector<float> const & x,
00481 Vector<float> const & dx,
00482 Vector<float> & dy) const {
00483 try {
00484 RVLVectorLogisticDeriv<Scalar> f;
00485 std::vector<RVL::Vector<Scalar> const *> v;
00486 v.push_back(&x);
00487 v.push_back(&dx);
00488 v.push_back(&lb);
00489 v.push_back(&ub);
00490 dy.eval(f,v);
00491 }
00492 catch (RVLException & e) {
00493 e<<"\ncalled from VectorLogisticOp::applyDeriv\n";
00494 throw e;
00495 }
00496 }
00497
00498 void applyAdjDeriv(Vector<float> const & x,
00499 Vector<float> const & dy,
00500 Vector<float> & dx) const {
00501 try {
00502 RVLVectorLogisticDeriv<Scalar> f;
00503 std::vector<RVL::Vector<Scalar> const *> v;
00504 v.push_back(&x);
00505 v.push_back(&dy);
00506 v.push_back(&lb);
00507 v.push_back(&ub);
00508 dx.eval(f,v);
00509 }
00510 catch (RVLException & e) {
00511 e<<"\ncalled from VectorLogisticOp::applyDeriv\n";
00512 throw e;
00513 }
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538 Operator<float> * clone() const { return new VectorLogisticOp<Scalar>(*this); }
00539
00540 public:
00541
00542 VectorLogisticOp(Vector<Scalar> const & _lb,
00543 Vector<Scalar> const & _ub)
00544 : lb(_lb), ub(_ub) {}
00545
00546 VectorLogisticOp(VectorLogisticOp<Scalar> const & op)
00547 : lb(op.lb), ub(op.ub) {}
00548
00549 ~VectorLogisticOp() {}
00550
00551 Space<Scalar> const & getDomain() const { return lb.getSpace(); }
00552 Space<Scalar> const & getRange() const { return lb.getSpace(); }
00553
00554 ostream & write(ostream & str) const {
00555 str<<"Vector Logistic Operator implementing field box constraints\n";
00556 str<<"*** lower bound vector: \n";
00557 lb.write(str);
00558 str<<"*** upper bound vector: \n";
00559 ub.write(str);
00560 return str;
00561 }
00562 };
00563
00564 }
00565
00566 #endif