00001
00002
00003
00004
00005
00006
00007 #ifndef FUNC_H
00008 #define FUNC_H
00009
00010 #include "standard.h"
00011 #include "usermatrix.h"
00012
00013 class Func;
00014 class Decomposition;
00015
00020 class SparsityInfo {
00021 friend class Decomposition;
00022 private:
00023 void add_nonlinear(int index) {
00024 nonlinear->insert(pair<int, NonlinearVariable>(index, NonlinearVariable()));
00025 }
00026
00027 void add_quadratic(int index, double coeff_lin, double coeff_quad);
00028
00029 void add_linear(int index, double coeff) {
00030 linear->insert(pair<int, LinearVariable>(index, LinearVariable(coeff)));
00031 }
00032
00033 void add_sparsity_pattern(int index1, int index2, double coeff);
00034
00035 public:
00038 class LinearVariable {
00039 public:
00040 double coeff;
00041 LinearVariable(double coeff_)
00042 : coeff(coeff_)
00043 { }
00044
00045 friend ostream& operator<<(ostream& out, const LinearVariable& var) {
00046 out << var.coeff;
00047 return out;
00048 }
00049 };
00050
00053 class NonlinearVariable {
00054 public:
00055 };
00056
00059 class QuadraticVariable {
00060 public:
00063 double coeff_lin, coeff_quad;
00064
00065 QuadraticVariable(double coeff_lin_, double coeff_quad_)
00066 : coeff_lin(coeff_lin_), coeff_quad(coeff_quad_)
00067 { }
00068
00069 friend ostream& operator<<(ostream& out, const QuadraticVariable& var) {
00070 out << var.coeff_lin << ',' << var.coeff_quad;
00071 return out;
00072 }
00073 };
00074
00077 class NonlinearConnection {
00078 public:
00081 double coeff;
00082
00083 NonlinearConnection(double coeff_)
00084 : coeff(coeff_)
00085 { }
00086
00087 friend ostream& operator<<(ostream& out, const NonlinearConnection& nc) {
00088 out << nc.coeff;
00089 return out;
00090 }
00091 };
00092
00095 Pointer<map<int, SparsityInfo::LinearVariable> > linear;
00098 Pointer<map<int, SparsityInfo::NonlinearVariable> > nonlinear;
00099
00103 Pointer<map<int, SparsityInfo::QuadraticVariable> > quadratic;
00104
00105 Pointer<map<pair<int, int>, SparsityInfo::NonlinearConnection> > sparsity_pattern;
00106
00107 SparsityInfo(int init_level=0);
00108
00109 SparsityInfo(const SparsityInfo& si);
00110
00114 SparsityInfo(const SparsityInfo& si1, const SparsityInfo& si2);
00115
00116 friend ostream& operator<<(ostream& out, const SparsityInfo& si);
00117
00118 bool compute_sparsity_pattern(const Func& f, const vector<dvector>& sample_set);
00119
00120
00121
00122 void add(const UserVector<double>& b);
00123 void add(const UserVector<double>& b, const ivector& block);
00124 void add(const UserMatrix& A);
00125 void add(const UserMatrix& A, const ivector& block);
00126 void add(const SparsityInfo& si);
00127 void add(const SparsityInfo& si, const ivector& block);
00128
00129 int nr_var(bool linear_=true, bool nonlinear_=true) {
00130 return (linear_ ? linear->size() : 0)+(nonlinear_ ? nonlinear->size() : 0);
00131 }
00132 };
00133
00137 class VariableIterator_Type {
00138 protected:
00141 bool linear;
00144 bool nonlinear;
00148 bool quadratic;
00149
00150 public:
00151 typedef enum { LINEAR=0, NONLINEAR=1, QUADRATIC=3, END=4 } VarType;
00152
00153 VariableIterator_Type(bool linear_=true, bool nonlinear_=true, bool quadratic_=false)
00154 : linear(linear_), nonlinear(nonlinear_), quadratic(quadratic_)
00155 { }
00156
00157 virtual ~VariableIterator_Type() { }
00158
00161 virtual int operator()() const=0;
00162
00166 virtual double coeff_lin() const=0;
00167
00171 virtual double coeff_quad() const=0;
00172
00175 virtual VarType type() const=0;
00176
00179 virtual void operator++()=0;
00180
00183 virtual operator bool() const=0;
00184 };
00185
00186 class VariableIterator : public VariableIterator_Type {
00187 private:
00188 const SparsityInfo& sparsity;
00189 map<int, SparsityInfo::LinearVariable>::iterator it_linear;
00190 map<int, SparsityInfo::NonlinearVariable>::iterator it_nonlinear;
00191 map<int, SparsityInfo::QuadraticVariable>::iterator it_quadratic;
00194 VarType whereami;
00195
00196 void init();
00197 public:
00198 VariableIterator(const Func& f_, bool linear_=true, bool nonlinear_=true, bool quadratic_=false);
00199 VariableIterator(const SparsityInfo& sparsity_, bool linear_=true, bool nonlinear_=true, bool quadratic_=false);
00200
00201 virtual int operator()() const;
00202
00203 virtual double coeff_lin() const;
00204 virtual double coeff_quad() const;
00205
00206 virtual VarType type() const { return whereami; }
00207
00208 virtual void operator++();
00209
00210 virtual operator bool() const { return (whereami!=END); }
00211 };
00212
00221 class Func {
00229 friend ostream& operator << (ostream& out, const Func& a)
00230 { a.print(out); return out; };
00231
00232 friend class VariableIterator;
00233 friend class MinusFunc;
00234 friend class SumFunc;
00235
00236 protected:
00239 int dim_;
00240
00241 Pointer<SparsityInfo> sparsity;
00242
00243 virtual SparsityInfo& get_sparsity() { assert(sparsity); return *sparsity; }
00244
00245 public:
00250 Pointer<ostream> out_func_p;
00251
00257 #define out_func if (out_func_p) (*out_func_p)
00258
00262 Pointer<ostream> out_func_log_p;
00268 #define out_func_log if (out_func_log_p) (*out_func_log_p)
00269
00270
00276 Func(int n=0, Pointer<ostream> out_func_p_=out_out_p, Pointer<ostream> out_func_log_p_=out_log_p)
00277 : dim_(n), out_func_p(out_func_p_), out_func_log_p(out_func_log_p_)
00278 { };
00279
00282 virtual ~Func() { }
00283
00288 int dim() const { return dim_; };
00289
00293 virtual bool sparsity_available() const { return sparsity; }
00294
00297 virtual const SparsityInfo& get_sparsity() const { assert(sparsity); return *sparsity; }
00298
00299 virtual bool compute_sparsity_pattern(const vector<dvector>& sample_set) { return get_sparsity().compute_sparsity_pattern(*this, sample_set); }
00300
00306 virtual double eval(const UserVector<double>& x) const=0;
00307
00317 virtual void grad(UserVector<double>& g, const UserVector<double>& x) const=0;
00318
00326 virtual dvector grad(const dvector& x) const {
00327 dvector g(x.dim());
00328 grad(g, x);
00329 return g;
00330 }
00331
00339 virtual void HessMult(UserVector<double>& y, const UserVector<double>& x, const UserVector<double>& z) const=0;
00340
00347 virtual dvector HessMult(const dvector& x, const dvector& z) const {
00348 dvector y(x.size());
00349 HessMult(y, x, z);
00350 return y;
00351 }
00352
00362 virtual int valgrad(double& val, UserVector<double>& g, const UserVector<double>& x) const {
00363 val=eval(x);
00364 grad(g,x);
00365 return 0;
00366 };
00367
00375 virtual void add_grad(UserVector<double>& g, const UserVector<double>& x) const {
00376 Pointer<UserVector<double> > gr(g.getemptycopy());
00377 grad(*gr, x);
00378 g+=*gr;
00379 };
00380
00388 virtual void add_valgrad(double& val, UserVector<double>& g, const UserVector<double>& x) const {
00389 val+=eval(x);
00390 add_grad(g,x);
00391 };
00392
00398 virtual double min_eig_hess(const UserVector<double>& x, Param* param=NULL) const;
00399
00407
00408
00409 #ifdef FILIB_AVAILABLE
00410
00412 virtual bool is_interval_compliant() const { return false; }
00413
00414 virtual interval<double> eval(const IntervalVector& x) const {
00415 IntervalVector g(x.dim());
00416 interval<double> val;
00417 valgrad(val, g, x);
00418 return val;
00419 };
00420
00421 virtual void grad(IntervalVector& g, const IntervalVector& x) const {
00422 interval<double> val;
00423 valgrad(val, g, x);
00424 };
00425
00426 virtual int valgrad(interval<double>& val, IntervalVector& g, const IntervalVector& x) const {
00427 out_err << "Interval evaluation not implemented for this class." << endl;
00428 exit(-1);
00429 return 1;
00430 }
00431 #endif
00432 typedef enum { CONVEX=1, CONCAVE=2, LINEAR=CONVEX | CONCAVE, UNKNOWN=4, INDEFINITE=12 } CurvatureType;
00433
00434 friend ostream& operator<<(ostream& out, const CurvatureType& ct);
00435
00436 virtual void set_curvature(CurvatureType ct)=0;
00437 virtual CurvatureType get_curvature() const=0;
00438
00439 static CurvatureType add_curvatures(double a1, CurvatureType ct1, double a2, CurvatureType ct2);
00440 static CurvatureType mult_curvature(double a, CurvatureType ct);
00441
00446 virtual void print(ostream &out) const
00447 { out << "Func: dim=" << dim() << endl; };
00448 };
00449
00450
00451
00456 class HessMatrix : public UserMatrix {
00457 protected:
00460 Pointer<const UserVector<double> > x0;
00461
00464 Pointer<const Func> f;
00465
00466 public:
00471 HessMatrix(Pointer<const Func> f_, Pointer<const UserVector<double> > x0_)
00472 : UserMatrix(f_->dim()), f(f_), x0(x0_)
00473 { }
00474
00475 HessMatrix(const Func& f_, const UserVector<double>& x0_)
00476 : UserMatrix(f_.dim()), f(&f_, false), x0(&x0_, false)
00477 { }
00478
00484 void MultV(UserVector<double> &y, const UserVector<double> &x) const {
00485 f->HessMult(y, *x0, x);
00486 }
00487
00488 using UserMatrix::MultV;
00489
00494 void print(ostream &out) const {
00495 out << "HessMatrix for UserVector<double>: " << *x0 << "function: " << *f;
00496 }
00497
00498 };
00499
00500
00501
00505 class MinusFunc : public Func {
00506 protected:
00509 Pointer<Func> f;
00510
00511 SparsityInfo& get_sparsity() { return sparsity ? *sparsity : f->get_sparsity(); }
00512
00513 public:
00519 MinusFunc(Pointer<Func> f_, Pointer<ostream> out_func_p_=out_out_p, Pointer<ostream> out_func_log_p_=out_log_p)
00520 : Func(f_ ? f_->dim() : 0, out_func_p_, out_func_log_p_), f(f_)
00521 { assert(f_ != NULL);
00522 }
00523
00524 virtual bool sparsity_available() const { return sparsity || f->sparsity_available(); }
00525
00526 virtual const SparsityInfo& get_sparsity() const { return sparsity ? *sparsity : ((const Func*)(Func*)f)->get_sparsity(); }
00527
00528 virtual bool compute_sparsity_pattern(const vector<dvector>& sample_set);
00529
00534 double eval(const UserVector<double>& x) const {
00535 return - f->eval(x);
00536 }
00537
00542 void grad(UserVector<double>& g, const UserVector<double>& x) const {
00543 f->grad(g,x);
00544 g*=-1;
00545 }
00546
00547 dvector grad(const dvector& x) const {
00548 return -f->grad(x);
00549 }
00550
00556 void HessMult(UserVector<double>& y, const UserVector<double>& x, const UserVector<double>& z) const {
00557 f->HessMult(y, x, z);
00558 y*=-1;
00559 }
00560
00561 dvector HessMult(const dvector& x, const dvector& z) const {
00562 return -f->HessMult(x,z);
00563 }
00564
00565 #ifdef FILIB_AVAILABLE
00566 bool is_interval_compliant() const { return f->is_interval_compliant(); }
00567
00568 interval<double> eval(const IntervalVector& x) const {
00569 return -f->eval(x);
00570 };
00571
00572 void grad(IntervalVector& g, const IntervalVector& x) const {
00573 f->grad(g,x);
00574 g*=-1;
00575 };
00576
00577 int valgrad(interval<double>& val, IntervalVector& g, const IntervalVector& x) const {
00578 int ret=f->valgrad(val, g, x);
00579 val*=-1;
00580 g*=-1;
00581 return ret;
00582 }
00583
00584 using Func::valgrad;
00585
00586 #endif
00587
00588 virtual void set_curvature(CurvatureType ct) {
00589 switch(ct) {
00590 case Func::CONVEX: f->set_curvature(Func::CONCAVE); break;
00591 case Func::CONCAVE: f->set_curvature(Func::CONVEX); break;
00592 default: f->set_curvature(ct);
00593 }
00594 }
00595
00596 virtual CurvatureType get_curvature() const {
00597 Func::CurvatureType ct(f->get_curvature());
00598 switch(ct) {
00599 case Func::CONVEX: return Func::CONCAVE;
00600 case Func::CONCAVE: return Func::CONVEX;
00601 }
00602 return ct;
00603 }
00604
00608 void print(ostream& out) const {
00609 out << "MinusFunc: function: " << *f;
00610 }
00611
00612 };
00613
00614
00615
00620 class SumFunc: public Func {
00621 private:
00624 Pointer<Func> f;
00627 Pointer<Func> g;
00630 double a,b;
00631
00632 Func::CurvatureType curv_type;
00633
00634 SparsityInfo& get_sparsity() {
00635 assert(sparsity_available());
00636 if (sparsity) return *sparsity;
00637 return f->get_sparsity();
00638 }
00639
00640 public:
00648 SumFunc(Pointer<Func> f_, Pointer<Func> g_, double a_=1., double b_=1., Pointer<ostream> out_func_p_=out_out_p, Pointer<ostream> out_func_log_p_=out_log_p)
00649 : Func(f_ ? f_->dim() : (g_ ? g_->dim() : 0), out_func_p_, out_func_log_p_), f(f_), g(g_), a(a_), b(b_),
00650 curv_type(add_curvatures(f_ ? a_ : 0., f_ ? f_->get_curvature() : Func::LINEAR, g_ ? b_ : 0., g_ ? g_->get_curvature() : Func::LINEAR))
00651 { assert(f || g);
00652 if (!f) { f=g; a=b; g=NULL; }
00653 if (f && g && f->sparsity_available() && g->sparsity_available())
00654 sparsity=new SparsityInfo(((const Func*)(Func*)f)->get_sparsity(), ((const Func*)(Func*)g)->get_sparsity());
00655 };
00656
00657 virtual bool sparsity_available() const {
00658 if (sparsity) return true;
00659 if (g) return false;
00660 return f->sparsity_available();
00661 }
00662
00663 virtual const SparsityInfo& get_sparsity() const {
00664 assert(sparsity_available());
00665 if (sparsity) return *sparsity;
00666 return f->get_sparsity();
00667 }
00668
00669 virtual bool compute_sparsity_pattern(const vector<dvector>& sample_set);
00670
00676 double eval(const UserVector<double>& x) const {
00677 return a * (f ? f->eval(x) : 0) + b * (g ? g->eval(x) : 0);
00678 }
00679
00685 void grad(UserVector<double>& y, const UserVector<double>& x) const;
00686
00687 using Func::grad;
00688
00696 int valgrad(double& val, UserVector<double>& y, const UserVector<double>& x) const;
00697
00703 void HessMult(UserVector<double>& y, const UserVector<double>& x, const UserVector<double>& z) const;
00704
00705 using Func::HessMult;
00706
00707 #ifdef FILIB_AVAILABLE
00708 bool is_interval_compliant() const { return (f ? f->is_interval_compliant() : true) && (g ? g->is_interval_compliant() : true); }
00709
00710 interval<double> eval(const IntervalVector& x) const {
00711 return a*(f ? f->eval(x) : 0)+ b*(g ? g->eval(x) : 0);
00712 };
00713
00714 void grad(IntervalVector& y, const IntervalVector& x) const;
00715
00716 int valgrad(interval<double>& val, IntervalVector& y, const IntervalVector& x) const;
00717 #endif
00718
00719 Func::CurvatureType get_curvature() const { return curv_type; }
00720 void set_curvature(Func::CurvatureType ct) { curv_type=ct; }
00721
00726 void print(ostream& out) const {
00727 out << "SumFunc a*f(x)+b*g(x): a=" << a << " b=" << b;
00728 if (f) out << endl << *f; else out << " f=NULL";
00729 if (g) out << endl << *g; else out << " g=NULL" << endl;
00730 }
00731
00732 };
00733
00734
00735
00736
00740 class SepFunc : public Func {
00741 public:
00744 vector<ivector> block;
00745
00751 SepFunc(int n, Pointer<ostream> out_func_p_=out_out_p, Pointer<ostream> out_func_log_p_=out_log_p)
00752 : Func(n, out_func_p_, out_func_log_p_), block(1)
00753 { block[0].resize(n);
00754 for (int i=0; i<n; i++) block[0][i]=i;
00755 };
00756
00763 SepFunc(const vector<ivector>& block_, Pointer<ostream> out_func_p_=out_out_p, Pointer<ostream> out_func_log_p_=out_log_p)
00764 : Func(0, out_func_p_, out_func_log_p_), block(block_)
00765 { set_dim();
00766 };
00767
00770 SepFunc(const SepFunc& f)
00771 : Func(f.dim(), f.out_func_p, f.out_func_log_p), block(f.block)
00772 { }
00773
00778 void set_dim() {
00779 dim_=0;
00780 for (int i=0; i<block.size(); i++) dim_+=block[i].size();
00781 }
00782
00788 virtual void print(ostream &out) const {
00789 out << "SepFunc: dim=" << dim() << endl;
00790 for (int i=0; i<block.size(); i++)
00791 out << "block " << i << ": " << block[i];
00792 };
00793 };
00794
00795
00796
00800 class SepQcFunc: public SepFunc {
00801 friend class Decomposition;
00802 private:
00803 vector<Pointer<SparsityInfo> > sparsity_block;
00804 public:
00805 class VariableIterator : public VariableIterator_Type {
00806 private:
00807 const SepQcFunc& f;
00808 map<int, SparsityInfo::LinearVariable>::iterator it_linear;
00809 map<int, SparsityInfo::NonlinearVariable>::iterator it_nonlinear;
00810 map<int, SparsityInfo::QuadraticVariable>::iterator it_quadratic;
00813 VarType whereami;
00814 int blocknr;
00815 void find_start();
00816
00817 public:
00818 VariableIterator(const SepQcFunc& f_, bool linear_=true, bool nonlinear_=true, bool quadratic_=false);
00819
00820 virtual int bnr() const { return blocknr; }
00821 virtual int bindex() const;
00822 virtual int operator()() const { return f.block[blocknr][bindex()]; }
00823
00824 virtual double coeff_lin() const;
00825 virtual double coeff_quad() const;
00826
00827 virtual VarType type() const { return whereami; }
00828
00829 virtual void operator++();
00830
00831 virtual operator bool() const { return (whereami!=END); }
00832 };
00835 typedef enum { CONSTANT, LINEAR, QUADRATIC, NONQUAD } ftype;
00836 friend ostream& operator<<(ostream& out, const ftype& ft);
00837
00840 vector<Pointer<UserMatrix> > A;
00841
00844 vector<Pointer<UserVector<double> > > b;
00845
00848 vector<Pointer<Func> > s;
00849
00852 vector<Func::CurvatureType> curv_type;
00853
00856 double c;
00857
00863 SepQcFunc(int n, Pointer<ostream> out_func_p_=out_out_p, Pointer<ostream> out_func_log_p_=out_log_p)
00864 : SepFunc(n, out_func_p_, out_func_log_p_), A(1), b(1), c(0), s(1), curv_type(1, Func::UNKNOWN), sparsity_block(1)
00865 { }
00866
00872 SepQcFunc(const vector<ivector>& block_, Pointer<ostream> out_func_p_=out_out_p, Pointer<ostream> out_func_log_p_=out_log_p)
00873 : SepFunc(block_, out_func_p_, out_func_log_p_), A(block_.size()), b(block_.size()), c(0), s(block_.size()), curv_type(block_.size(), Func::UNKNOWN), sparsity_block(block_.size())
00874 { }
00875
00876 SepQcFunc(Pointer<UserMatrix> A_, Pointer<UserVector<double> > b_=NULL, Pointer<Func> s_=NULL, double c_=0, Pointer<SparsityInfo> sparsity_=NULL, Pointer<ostream> out_func_p_=out_out_p, Pointer<ostream> out_func_log_p_=out_log_p)
00877 : SepFunc(A_ ? A_->dim() : b_ ? b_->dim() : s_->dim(), out_func_p_, out_func_log_p_), A(1, A_), b(1, b_), s(1, s_), c(c_),
00878 curv_type(1, A_ ? Func::UNKNOWN : (s_ ? s_->get_curvature() : Func::LINEAR)), sparsity_block(1, sparsity_)
00879 { sparsity=sparsity_; }
00880
00885 SepQcFunc(const SepQcFunc &f, bool minus_func);
00886
00889 SepQcFunc(const SepQcFunc& f, const UserVector<double>& point, const int degree=2);
00890
00891 virtual bool sparsity_available(int k) const {
00892 if (sparsity_block[k]) return true;
00893 return false;
00894 }
00895
00896 virtual bool sparsity_available() const { return sparsity; }
00897
00898 virtual SparsityInfo& get_sparsity(int k) {
00899 return *sparsity_block[k];
00900 }
00901
00902 virtual const SparsityInfo& get_sparsity(int k) const {
00903 return *sparsity_block[k];
00904 }
00905
00906 virtual SparsityInfo& get_sparsity() { assert(sparsity); return *sparsity; }
00907
00908 using Func::get_sparsity;
00909
00910 virtual void set_sparsity(int k, Pointer<SparsityInfo> si) {
00911 sparsity_block[k]=si;
00912 }
00913 virtual void set_sparsity();
00914
00915 bool compute_sparsity(int block_nr, const vector<dvector>& sample_set, bool replace_if_quadratic=false);
00916
00921 virtual ftype type(int k) {
00922 if (s[k]) return NONQUAD;
00923 if (A[k]) return QUADRATIC;
00924 if (b[k]) return LINEAR;
00925 return CONSTANT;
00926 }
00927
00933 void add_var(int index, int bnum);
00934
00941 void addmult(const SepQcFunc& f, double a_=1., double b_=1.);
00942
00947 double eval(const UserVector<double>& x) const;
00948
00954 double eval(const UserVector<double>& x, int k) const {
00955 return (A[k] ? A[k]->xAx(x) : 0) + (b[k] ? 2* (*b[k]*x) : 0) + (s[k] ? s[k]->eval(x) : 0);
00956 }
00957
00962 void grad(UserVector<double>& g, const UserVector<double>& x) const;
00963
00964 using Func::grad;
00965
00971 void grad(UserVector<double>& g, const UserVector<double>& x, int bnum) const;
00972
00973 dvector grad(const UserVector<double>& x, int bnum) const {
00974 dvector g(x.dim()); grad(g,x,bnum); return g;
00975 }
00976
00983 int valgrad(double& val, UserVector<double>& g, const UserVector<double>& x) const;
00984
00990 void HessMult(UserVector<double>& y, const UserVector<double>& x, const UserVector<double>& z) const;
00991
00998 void HessMult(UserVector<double>& y, const UserVector<double>& x, const UserVector<double>& z, int k) const;
00999
01000 using Func::HessMult;
01001
01002 #ifdef FILIB_AVAILABLE
01003 bool is_interval_compliant() const;
01004
01005 interval<double> eval(const IntervalVector& x) const;
01006
01007 interval<double> eval(const IntervalVector& x, int k) const;
01008
01009 void grad(IntervalVector& g, const IntervalVector& x) const;
01010
01011 void grad(IntervalVector& g, const IntervalVector& x, int k) const;
01012
01013 int valgrad(interval<double>& val, IntervalVector& y, const IntervalVector& x) const;
01014 #endif
01015
01016 Func::CurvatureType get_curvature(int k) const { return curv_type[k]; }
01017 Func::CurvatureType get_curvature() const;
01018 void set_curvature(int k, Func::CurvatureType ct) { curv_type[k]=ct; }
01019 void set_curvature(Func::CurvatureType ct);
01020
01025 void print(ostream &out) const;
01026
01031 void print(ostream& out, vector<Pointer<char> > var_names) const;
01032
01033 };
01034
01035 #endif // FUNC_H