cone.hpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002     
00003     cone.hpp -- a representation of a polyhedral cone and operations on it.
00004 
00005     This file is a part of the Arageli library.
00006 
00007     Copyright (C) Sergey S. Lyalin, 2006
00008     University of Nizhni Novgorod, Russia, 2005--2006
00009 
00010 *****************************************************************************/
00011 
00021 #ifndef _ARAGELI_cone_hpp_
00022 #define _ARAGELI_cone_hpp_
00023 
00024 #include "config.hpp"
00025 
00026 #include "factory.hpp"
00027 #include "frwrddecl.hpp"
00028 #include "big_int.hpp"
00029 #include "matrix.hpp"
00030 
00031 
00032 namespace Arageli
00033 {
00034 
00035 
00036 // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00038 
00040 
00041 struct fromnull_t {};
00042 
00044 const fromnull_t fromnull = fromnull_t();
00045 
00046 struct fromspace_t {};
00047 
00049 const fromspace_t fromspace = fromspace_t();
00050 
00051 struct fromineq_t {};
00052 
00054 const fromineq_t fromineq = fromineq_t();
00055 
00056 struct fromeq_t {};
00057 
00059 const fromeq_t fromeq = fromeq_t();
00060 
00061 struct fromgen_t {};
00062 
00064 const fromgen_t fromgen = fromgen_t();
00065 
00066 struct frombasis_t {};
00067 
00069 const frombasis_t frombasis = frombasis_t();
00070 
00071 struct fromdual_t {};
00072 
00073 const fromdual_t fromdual = fromdual_t();
00074 
00076 
00077 
00079 class cannot_represent_cone : public exception {};
00080 
00081 
00082 template <typename Out, typename T, typename M, typename CFG>
00083 void output_list (Out& out, const cone<T, M, CFG>& x);
00084 
00085 
00086 template <typename T, typename M> class cone_default_config {};
00087 
00088 
00090 
00108 template <typename T, typename M, typename CFG>
00109 class cone
00110 {
00111 public:
00112 
00113     // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00115 
00117 
00118     typedef T inequation_element_type;
00119     typedef T equation_element_type;
00120     typedef T generatrix_element_type;
00121     typedef T basis_element_type;
00122 
00123     typedef M inequation_type;
00124     typedef M equation_type;
00125     typedef M generatrix_type;
00126     typedef M basis_type;
00127 
00128     typedef typename M::difference_type dim_type;
00129     typedef typename M::difference_type difference_type;
00130     typedef typename M::size_type size_type;
00131 
00133 
00134 
00135     // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00137 
00139 
00140 
00142 
00144     cone () : state(STATE_ALL) {}
00145 
00146 
00148 
00150     template <typename D>
00151     cone (const D& dim, const fromnull_t&)
00152     :   basis_m(0, dim),
00153         generatrix_m(0, dim),
00154         state(STATE_PARAMETRIC)
00155     { if(Arageli::is_null(dim))set_flag(STATE_IMPLICIT); }
00156          
00157 
00159 
00161     template <typename D>
00162     cone (const D& dim, const fromspace_t&)
00163     :   inequation_m(0, dim),
00164         equation_m(0, dim),
00165         state(STATE_IMPLICIT)
00166     { if(Arageli::is_null(dim))set_flag(STATE_PARAMETRIC); }
00167          
00168 
00170 
00172     template <typename M1>
00173     cone (const M1& ineqmat, const fromineq_t&)
00174     :   inequation_m(ineqmat),
00175         equation_m(0, ineqmat.ncols()),
00176         state(STATE_IMPLICIT_VALID)
00177     {}
00178 
00179 
00181 
00183     template <typename M1>
00184     cone (const M1& eqmat, const fromeq_t&)
00185     :   inequation_m(0, eqmat.ncols()),
00186         equation_m(eqmat),
00187         state(STATE_IMPLICIT_VALID)
00188     {}
00189 
00190 
00192 
00194     template <typename M1>
00195     cone (const M1& genmat, const fromgen_t&)
00196     :   generatrix_m(genmat),
00197         basis_m(0, genmat.ncols()),
00198         state(STATE_PARAMETRIC_VALID)
00199     {}
00200 
00201 
00203 
00205     template <typename M1>
00206     cone (const M1& basismat, const frombasis_t&)
00207     :   generatrix_m(0, basismat.ncols()),
00208         basis_m(basismat),
00209         state(STATE_PARAMETRIC_VALID)
00210     {}
00211 
00212 
00214 
00216     template <typename Cone1>
00217     cone (const Cone1& c, const fromdual_t&);
00218 
00219 
00221 
00222 
00223     // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00225 
00227 
00228 
00230     bool is_implicit_valid () const
00231     {
00232         ARAGELI_ASSERT_1(is_correct_flags());
00233         return get_flag(STATE_IMPLICIT_VALID);
00234     }
00235 
00237     bool is_parametric_valid () const
00238     {
00239         ARAGELI_ASSERT_1(is_correct_flags());
00240         return get_flag(STATE_PARAMETRIC_VALID);
00241     }
00242 
00244     bool is_all_valid () const
00245     {
00246         ARAGELI_ASSERT_1(is_correct_flags());
00247         return get_flag(STATE_VALID);
00248     }
00249 
00250 
00252 
00256     bool is_implicit_normal () const
00257     {
00258         ARAGELI_ASSERT_1(is_correct_flags());
00259         return get_flag(STATE_IMPLICIT);
00260     }
00261 
00262 
00264 
00268     bool is_parametric_normal () const
00269     {
00270         ARAGELI_ASSERT_1(is_correct_flags());
00271         return get_flag(STATE_PARAMETRIC);
00272     }
00273 
00274 
00276     bool is_all_normal () const
00277     {
00278         ARAGELI_ASSERT_1(is_correct_flags());
00279         return get_flag(STATE_ALL);
00280     }
00281 
00282 
00284 
00285 
00286     // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00288 
00290 
00291 
00293 
00295     void validate_implicit () const
00296     {
00297         ARAGELI_ASSERT_1(is_correct_flags());
00298         if(!get_flag(STATE_IMPLICIT_VALID))force_validate_implicit();
00299     }
00300 
00302 
00304     void validate_parametric () const
00305     {
00306         ARAGELI_ASSERT_1(is_correct_flags());
00307         if(!get_flag(STATE_PARAMETRIC_VALID))force_validate_parametric();
00308     }
00309 
00311     void validate_all () const
00312     {
00313         ARAGELI_ASSERT_1(is_correct_flags());
00314 
00315         if(!get_flag(STATE_IMPLICIT_VALID))force_validate_implicit();
00316         if(!get_flag(STATE_PARAMETRIC_VALID))force_validate_parametric();
00317     }
00318     
00320 
00322     void normalize_implicit () const
00323     {
00324         ARAGELI_ASSERT_1(is_correct_flags());
00325         if(!get_flag(STATE_IMPLICIT))force_normalize_implicit();
00326     }
00327 
00329 
00331     void normalize_parametric () const
00332     {
00333         ARAGELI_ASSERT_1(is_correct_flags());
00334         if(!get_flag(STATE_PARAMETRIC))force_normalize_parametric();
00335     }
00336     
00338     void normalize_all () const
00339     {
00340         ARAGELI_ASSERT_1(is_correct_flags());
00341         if(!get_flag(STATE_ALL))force_normalize_all();
00342     }
00343 
00344 
00346 
00347 
00348     // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00350 
00352 
00353     
00355 
00358     void set_valid_implicit ()
00359     {
00360         ARAGELI_ASSERT_1(is_correct_flags());
00361         set_flag(STATE_IMPLICIT_VALID);
00362     }
00363 
00365 
00368     void set_valid_parametric ()
00369     {
00370         ARAGELI_ASSERT_1(is_correct_flags());
00371         set_flag(STATE_PARAMETRIC_VALID);
00372     }
00373 
00375 
00378     void set_valid_all ()
00379     {
00380         ARAGELI_ASSERT_1(is_correct_flags());
00381         set_flag(STATE_VALID);
00382     }
00383 
00385 
00388     void set_normal_implicit ()
00389     {
00390         ARAGELI_ASSERT_1(is_correct_flags());
00391         set_flag(STATE_IMPLICIT);
00392     }
00393 
00395 
00398     void set_normal_parametric ()
00399     {
00400         ARAGELI_ASSERT_1(is_correct_flags());
00401         set_flag(STATE_PARAMETRIC);
00402     }
00403 
00405 
00408     void set_normal_all ()
00409     {
00410         ARAGELI_ASSERT_1(is_correct_flags());
00411         set_flag(STATE_ALL);
00412     }
00413 
00415 
00416 
00417     // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00419 
00421 
00422     
00424 
00425     bool is_pointed () const;
00426 
00428     bool is_subspace () const;
00429 
00431     bool is_space () const;
00432 
00434     bool is_null () const;
00435 
00437     bool is_point () const { return is_null(); }
00438 
00440     dim_type space_dim () const;
00441 
00443     dim_type dim () const;
00444 
00446     bool is_bodily () const
00447     { return dim() == space_dim(); }
00448 
00450     bool is_simplicial () const;
00451 
00453 
00454 
00455     // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00457 
00459 
00460     template <typename V1>
00461     bool strict_inside (const V1& x) const
00462     {
00463         normalize_implicit();
00464         return
00465             all_greater(inequation_m*x, null<typename V1::element_type>()) &&
00466             Arageli::is_null(equation_m*x);
00467     }
00468 
00469     template <typename V1>
00470     bool strict_outside (const V1& x) const
00471     {
00472         normalize_implicit();
00473         return
00474             !all_greater_equal(inequation_m*x, null<typename V1::element_type>()) ||
00475             !Arageli::is_null(equation_m*x);
00476     }
00477 
00478     template <typename V1>
00479     bool unstrict_inside (const V1& x) const
00480     {
00481         normalize_implicit();
00482         return
00483             all_greater_equal(inequation_m*x, null<typename V1::element_type>()) &&
00484             Arageli::is_null(equation_m*x);
00485     }
00486 
00487     template <typename V1>
00488     bool unstrict_outside (const V1& x) const
00489     {
00490         normalize_implicit();
00491         return
00492             !all_greater(inequation_m*x, null<typename V1::element_type>()) ||
00493             !Arageli::is_null(equation_m*x);
00494     }
00495 
00497 
00498     
00499     // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00501 
00503 
00505 
00507     inequation_type inequation () const;
00508 
00510 
00512     const equation_type& equation () const;
00513 
00515 
00517     generatrix_type generatrix () const;
00518 
00520 
00522     const basis_type& basis () const;
00523 
00524     const equation_type& min_ambient_equation () const;
00525     
00526     basis_type min_ambient_basis () const;
00527     //{ return inverse(min_ambient_equation()); }   // It's incorrect.
00528     
00529     equation_type max_embedded_equation () const;
00530     //{ return inverse(max_embedded_basis()); } // It's incorrect.
00531 
00532     const basis_type& max_embedded_basis () const;
00533 
00535     inequation_type min_inequation () const;
00536 
00538     generatrix_type min_generatrix () const;
00539 
00541 
00542 
00543     // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00545 
00547 
00548     const inequation_type& inequation_matrix () const
00549     { return inequation_m; }
00550 
00551     inequation_type& inequation_matrix ()
00552     {
00553         clear_flag(STATE_PARAMETRIC | STATE_IMPLICIT_NORMAL);
00554         return inequation_m;
00555     }
00556 
00557     const equation_type& equation_matrix () const
00558     { return equation_m; }
00559 
00560     equation_type& equation_matrix ()
00561     {
00562         clear_flag(STATE_PARAMETRIC | STATE_IMPLICIT_NORMAL);
00563         return equation_m;
00564     }
00565 
00566     const generatrix_type& generatrix_matrix () const
00567     { return generatrix_m; }
00568     
00569     generatrix_type& generatrix_matrix ()
00570     {
00571         clear_flag(STATE_IMPLICIT | STATE_PARAMETRIC_NORMAL);
00572         return generatrix_m;
00573     }
00574 
00575     const basis_type& basis_matrix () const
00576     { return basis_m; }
00577     
00578     basis_type& basis_matrix ()
00579     {
00580         clear_flag(STATE_IMPLICIT | STATE_PARAMETRIC_NORMAL);
00581         return basis_m;
00582     }
00583 
00585 
00586 
00588     void pack ();
00589 
00591     void keep_only_implicit ();
00592 
00594     void keep_only_parametric ();
00595     
00596     void assign_null ();
00597 
00599     matrix<bool> relation () const
00600     {
00601         validate_all();
00602         return generatrix_m*transpose(inequation_m);
00603     }
00604 
00605     
00606     // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00608 
00610 
00611     template <typename Cone1>
00612     cone& intersection (const Cone1& x);
00613 
00614     template <typename Cone1>
00615     cone& conic_union (const Cone1& x);
00616 
00618 
00619 private:
00620 
00621     void force_validate_implicit () const;
00622     void force_validate_parametric () const;
00623     void force_normalize_implicit () const;
00624     void force_normalize_parametric () const;
00625     void force_normalize_all () const;
00626 
00627     template <typename M1, typename M2>
00628     inline void extend_rep_matrix (M1& res, const M2& x) const
00629     {
00630         // WARNING! Here we add 2*x.nrows() rows in res,
00631         // but only (x.nrows()+1) is enough.
00632         res.insert_matrix_bottom(x);
00633         res.insert_matrix_bottom(-x);
00634     }
00635 
00636     template <typename M1, typename M2>
00637     inline void fast_extend_rep_matrix (M1& res, const M2& x) const
00638     {
00639         res.insert_matrix_bottom(x);
00640         res.insert_matrix_bottom(-x);
00641     }
00642 
00643     enum State
00644     {
00645         STATE_IMPLICIT_VALID    = 0x01,
00646         STATE_IMPLICIT_NORMAL   = 0x01 << 1,
00647         STATE_PARAMETRIC_VALID  = 0x01 << 2,
00648         STATE_PARAMETRIC_NORMAL = 0x01 << 3,
00649 
00650         STATE_VALID = STATE_IMPLICIT_VALID | STATE_PARAMETRIC_VALID,
00651         STATE_NORMAL = STATE_IMPLICIT_NORMAL | STATE_PARAMETRIC_NORMAL,
00652         STATE_IMPLICIT = STATE_IMPLICIT_VALID | STATE_IMPLICIT_NORMAL,
00653         STATE_PARAMETRIC = STATE_PARAMETRIC_VALID | STATE_PARAMETRIC_NORMAL,
00654 
00655         STATE_ALL = STATE_IMPLICIT | STATE_PARAMETRIC
00656     };
00657 
00658     bool get_flag (int st) const { return (state & st) == st; }
00659     void set_flag (int st) const { state = State(state | st); }
00660     void clear_flag (int st) const { state = State(state & ~st); }
00661 
00662 
00663     mutable inequation_type inequation_m;
00664     mutable equation_type equation_m;
00665     mutable generatrix_type generatrix_m;
00666     mutable basis_type basis_m;
00667 
00668     mutable State state;
00669 
00670     
00671     // We suppose that the following functions will be called
00672     // only in the debug purposes.
00673     
00674     bool is_correct_flags () const
00675     {
00676         return
00677             (get_flag(STATE_IMPLICIT_NORMAL) ?
00678                 get_flag(STATE_IMPLICIT_VALID) : true) &&
00679             (get_flag(STATE_PARAMETRIC_NORMAL) ?
00680                 get_flag(STATE_PARAMETRIC_VALID) : true);
00681     }
00682 
00683     bool is_there_valid () const
00684     {
00685         return
00686             get_flag(STATE_IMPLICIT_VALID) &&
00687                 inequation_m.ncols() == equation_m.ncols() ||
00688             get_flag(STATE_PARAMETRIC_VALID) &&
00689                 generatrix_m.ncols() == basis_m.ncols();
00690     }
00691 
00692     
00693     template <typename Out, typename T2, typename M2, typename CFG2>
00694     friend void output_list (Out& out, const cone<T2, M2, CFG2>& x);
00695 
00696 };
00697 
00698 
00700 template <typename TT, typename M, typename CFG>
00701 struct factory<cone<TT, M, CFG> >
00702 {
00703 private:
00704 
00705     typedef cone<TT, M, CFG> T;
00706 
00707 public:
00708 
00709     static const bool is_specialized = true;
00710 
00712     //static const T& unit ();
00713     
00715     //static const T& unit (const T& x);
00716 
00718     //static const T& opposite_unit ();
00719     
00721     //static const T& opposite_unit (const T& x);
00722 
00724     static const T& null ()
00725     {
00726         static const T null_s = T();
00727         return null_s;
00728     }
00729     
00731     static const T& null (const T& x)
00732     { return null(); }
00733 
00734 };
00735 
00736 
00737 
00738 template <typename Out, typename T, typename M, typename CFG>
00739 inline Out& operator<< (Out& out, const cone<T, M, CFG>& x)
00740 { output_list(out, x); return out; }
00741 
00742 
00743 
00744 template
00745 <
00746     typename T1, typename M1, typename CFG1,
00747     typename T2, typename M2, typename CFG2
00748 >
00749 inline cone<T1, M1, CFG1> intersection
00750 (
00751     cone<T1, M1, CFG1> a,
00752     const cone<T2, M2, CFG2>& b
00753 )
00754 { return a.intersection(b); }
00755 
00756 
00757 template
00758 <
00759     typename T1, typename M1, typename CFG1,
00760     typename T2, typename M2, typename CFG2
00761 >
00762 inline cone<T1, M1, CFG1> cone_union
00763 (
00764     cone<T1, M1, CFG1> a,
00765     const cone<T2, M2, CFG2>& b
00766 )
00767 { return a.cone_union(b); }
00768 
00769 
00770 template
00771 <
00772     typename T1, typename M1, typename CFG1,
00773     typename T2, typename M2, typename CFG2
00774 >
00775 int cmp
00776 (
00777     const cone<T1, M1, CFG1>& a,
00778     const cone<T2, M2, CFG2>& b
00779 )
00780 {
00781     // WARNING! Temporary implimentation. Maybe it doesn't work always.
00782     
00783     if(int c = cmp(a.space_dim(), b.space_dim()))return c;
00784     if(int c = cmp(a.dim(), b.dim()))return c;
00785     if(is_null(a.dim()) && is_null(b.dim()))return 0;
00786 
00787     ARAGELI_ASSERT_1
00788     (
00789         a.min_ambient_equation().nrows() ==
00790         b.min_ambient_equation().nrows()
00791     );
00792 
00793     a.normalize_implicit();
00794     b.normalize_implicit();
00795 
00796     if(int c = cmp(a.inequation_matrix().nrows(), b.inequation_matrix().nrows()))
00797         return -c;
00798 
00799     // WARNING! Too expensive!
00800 
00801     vector<vector<T1>, false> arows(a.inequation_matrix().nrows());
00802     vector<vector<T2>, false> brows(b.inequation_matrix().nrows());
00803     ARAGELI_ASSERT_1(arows.size() == brows.size());
00804 
00805     for(typename cone<T1, M1, CFG1>::size_type i = 0; i < arows.size(); ++i)
00806     {
00807         arows[i] = a.inequation_matrix().copy_row(i);
00808         arows[i] /= _Internal::content(arows[i].begin(), arows[i].end());
00809         brows[i] = b.inequation_matrix().copy_row(i);
00810         brows[i] /= _Internal::content(brows[i].begin(), brows[i].end());
00811     }
00812 
00813     std::sort(arows);
00814     std::sort(brows);
00815 
00816     if(int c = cmp(arows, brows))return c;
00817     
00818     if(int c = cmp(a.equation_matrix().nrows(), b.equation_matrix().nrows()))
00819         return -c;
00820 
00821     if(a.equation_matrix().nrows() == 0)return 0;
00822     
00823     if
00824     (
00825         int c = cmp
00826         (
00827             rref(matrix<rational<T1>, false>(a.equation_matrix())),
00828             rref(matrix<rational<T1>, false>(b.equation_matrix()))
00829         )
00830     )
00831         return c;
00832 
00833     return 0;
00834 }
00835 
00836 
00837 } // namesapce Arageli
00838 
00839 
00840 #ifdef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE
00841     #define ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_cone
00842     #include "cone.cpp"
00843     #undef  ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_cone
00844 #endif
00845 
00846 #endif  // #ifndef _ARAGELI_cone_hpp_

Generated on Thu Aug 31 17:38:05 2006 for Arageli by  doxygen 1.4.7