00001
00002
00003
00004
00005
00006
00007
00008
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
00528
00529 equation_type max_embedded_equation () const;
00530
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
00631
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
00672
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
00713
00715
00716
00718
00719
00721
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
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
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 }
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_