00001
00002
00217
00218
00219 #ifndef CDDInterface_h_
00220 #define CDDInterface_h_
00221
00222 #include "extrafwd.h"
00223
00224 #include "pbori_defs.h"
00225
00226
00227
00228
00229 #include "CCuddNavigator.h"
00230
00231
00232 #include "CCuddFirstIter.h"
00233
00234
00235 #include "CCuddLastIter.h"
00236
00237
00238 #include "CCuddGetNode.h"
00239
00240
00241 #include "PBoRiOutIter.h"
00242
00243
00244 #include "PBoRiGenericError.h"
00245
00246
00247 #include "cuddInt.h"
00248
00249 #include "pbori_algo.h"
00250
00251 #include "pbori_tags.h"
00252 #include "pbori_routines_hash.h"
00253
00254
00255 #include <vector>
00256 #include <numeric>
00257
00258 #include "CCuddInterface.h"
00259 #include "pbori_traits.h"
00260
00261 BEGIN_NAMESPACE_PBORI
00262
00263
00264 inline Cudd*
00265 extract_manager(const Cudd& mgr) {
00266 return &const_cast<Cudd&>(mgr);
00267 }
00268
00269 inline CCuddInterface::mgrcore_ptr
00270 extract_manager(const CCuddInterface& mgr) {
00271 return mgr.managerCore();
00272 }
00273
00274 template <class MgrType>
00275 inline const MgrType&
00276 extract_manager(const MgrType& mgr) {
00277 return mgr;
00278 }
00279
00280 inline Cudd&
00281 get_manager(Cudd* mgr) {
00282 return *mgr;
00283 }
00284
00285 template <class MgrType>
00286 inline const MgrType&
00287 get_manager(const MgrType& mgr) {
00288 return mgr;
00289 }
00297 template<class DDType>
00298 class CDDInterfaceBase {
00299
00300 public:
00301
00303 typedef DDType interfaced_type;
00304
00306 typedef CDDInterfaceBase<interfaced_type> self;
00307
00309 CDDInterfaceBase() :
00310 m_interfaced() {}
00311
00313 CDDInterfaceBase(const interfaced_type& interfaced) :
00314 m_interfaced(interfaced) {}
00315
00317 CDDInterfaceBase(const self& rhs) :
00318 m_interfaced(rhs.m_interfaced) {}
00319
00321 ~CDDInterfaceBase() {}
00322
00324 operator const interfaced_type&() const { return m_interfaced; }
00325
00326 protected:
00327 interfaced_type m_interfaced;
00328 };
00329
00332 template<class CuddLikeZDD>
00333 class CDDInterface:
00334 public CDDInterfaceBase<CuddLikeZDD> {
00335 public:
00336
00338 typedef CuddLikeZDD interfaced_type;
00339
00341 typedef typename zdd_traits<interfaced_type>::manager_base manager_base;
00342
00344 typedef typename manager_traits<manager_base>::tmp_ref mgr_ref;
00345
00347 typedef typename manager_traits<manager_base>::core_type core_type;
00348
00350 typedef CDDManager<CCuddInterface> manager_type;
00351
00353 typedef CDDInterfaceBase<interfaced_type> base_type;
00354 typedef base_type base;
00355 using base::m_interfaced;
00356
00358 typedef CDDInterface<interfaced_type> self;
00359
00361 typedef CTypes::size_type size_type;
00362
00364 typedef CTypes::idx_type idx_type;
00365
00367 typedef CTypes::ostream_type ostream_type;
00368
00370 typedef CTypes::bool_type bool_type;
00371
00373 typedef CTypes::hash_type hash_type;
00374
00376 typedef CCuddFirstIter first_iterator;
00377
00379 typedef CCuddLastIter last_iterator;
00380
00382 typedef CCuddNavigator navigator;
00383
00385 typedef FILE* pretty_out_type;
00386
00388 typedef const char* filename_type;
00389
00391 typedef valid_tag easy_equality_property;
00392
00394 CDDInterface(): base_type() {}
00395
00397 CDDInterface(const self& rhs): base_type(rhs) {}
00398
00400 CDDInterface(const interfaced_type& rhs): base_type(rhs) {}
00401
00403 CDDInterface(const manager_base& mgr, const navigator& navi):
00404 base_type(self::newDiagram(mgr, navi)) {}
00405
00407 CDDInterface(const manager_base& mgr,
00408 idx_type idx, navigator thenNavi, navigator elseNavi):
00409 base_type( self::newNodeDiagram(mgr, idx, thenNavi, elseNavi) ) {
00410 }
00411
00414 CDDInterface(const manager_base& mgr,
00415 idx_type idx, navigator navi):
00416 base_type( self::newNodeDiagram(mgr, idx, navi, navi) ) {
00417 }
00418
00420 CDDInterface(idx_type idx, const self& thenDD, const self& elseDD):
00421 base_type( self::newNodeDiagram(thenDD.manager(), idx,
00422 thenDD.navigation(),
00423 elseDD.navigation()) ) {
00424 }
00425
00427 ~CDDInterface() {}
00428
00430 hash_type hash() const {
00431 return static_cast<hash_type>(reinterpret_cast<std::ptrdiff_t>(m_interfaced
00432 .getNode()));
00433 }
00434
00436 hash_type stableHash() const {
00437 return stable_hash_range(navigation());
00438 }
00439
00441 self unite(const self& rhs) const {
00442 return self(base_type(m_interfaced.Union(rhs.m_interfaced)));
00443 };
00444
00446 self& uniteAssign(const self& rhs) {
00447 m_interfaced = m_interfaced.Union(rhs.m_interfaced);
00448 return *this;
00449 };
00451 self ite(const self& then_dd, const self& else_dd) const {
00452 return self(m_interfaced.Ite(then_dd, else_dd));
00453 };
00454
00456 self& iteAssign(const self& then_dd, const self& else_dd) {
00457 m_interfaced = m_interfaced.Ite(then_dd, else_dd);
00458 return *this;
00459 };
00460
00462 self diff(const self& rhs) const {
00463 return m_interfaced.Diff(rhs.m_interfaced);
00464 };
00465
00467 self& diffAssign(const self& rhs) {
00468 m_interfaced = m_interfaced.Diff(rhs.m_interfaced);
00469 return *this;
00470 };
00471
00473 self diffConst(const self& rhs) const {
00474 return m_interfaced.DiffConst(rhs.m_interfaced);
00475 };
00476
00478 self& diffConstAssign(const self& rhs) {
00479 m_interfaced = m_interfaced.DiffConst(rhs.m_interfaced);
00480 return *this;
00481 };
00482
00484 self intersect(const self& rhs) const {
00485 return m_interfaced.Intersect(rhs.m_interfaced);
00486 };
00487
00489 self& intersectAssign(const self& rhs) {
00490 m_interfaced = m_interfaced.Intersect(rhs.m_interfaced);
00491 return *this;
00492 };
00493
00495 self product(const self& rhs) const {
00496 return m_interfaced.Product(rhs.m_interfaced);
00497 };
00498
00500 self& productAssign(const self& rhs) {
00501 m_interfaced = m_interfaced.Product(rhs.m_interfaced);
00502 return *this;
00503 };
00504
00506 self unateProduct(const self& rhs) const {
00507 return m_interfaced.UnateProduct(rhs.m_interfaced);
00508 };
00509
00510
00511
00513 self dotProduct(const self& rhs) const {
00514 return interfaced_type(m_interfaced.manager(),
00515 Extra_zddDotProduct(
00516 manager().getManager(),
00517 m_interfaced.getNode(),
00518 rhs.m_interfaced.getNode()));
00519 }
00520
00521 self& dotProductAssign(const self& rhs){
00522 m_interfaced=interfaced_type(m_interfaced.manager(),
00523 Extra_zddDotProduct(
00524 manager().getManager(),
00525 m_interfaced.getNode(),
00526 rhs.m_interfaced.getNode()));
00527 return *this;
00528 }
00529
00530 self Xor(const self& rhs) const {
00531 if (rhs.emptiness())
00532 return *this;
00533 #ifdef PBORI_LOWLEVEL_XOR
00534 return interfaced_type(m_interfaced.manager(),
00535 pboriCudd_zddUnionXor(
00536 manager().getManager(),
00537 m_interfaced.getNode(),
00538 rhs.m_interfaced.getNode()));
00539 #else
00540 return interfaced_type(m_interfaced.manager(),
00541 Extra_zddUnionExor(
00542 manager().getManager(),
00543 m_interfaced.getNode(),
00544 rhs.m_interfaced.getNode()));
00545 #endif
00546 }
00547
00548
00550 self& unateProductAssign(const self& rhs) {
00551 m_interfaced = m_interfaced.UnateProduct(rhs.m_interfaced);
00552 return *this;
00553 };
00554
00556 self subset0(idx_type idx) const {
00557 return m_interfaced.Subset0(idx);
00558 };
00559
00561 self& subset0Assign(idx_type idx) {
00562 m_interfaced = m_interfaced.Subset0(idx);
00563 return *this;
00564 };
00565
00567 self subset1(idx_type idx) const {
00568 return m_interfaced.Subset1(idx);
00569 };
00570
00572 self& subset1Assign(idx_type idx) {
00573 m_interfaced = m_interfaced.Subset1(idx);
00574 return *this;
00575 };
00576
00578 self change(idx_type idx) const {
00579
00580 return m_interfaced.Change(idx);
00581 };
00582
00584 self& changeAssign(idx_type idx) {
00585 m_interfaced = m_interfaced.Change(idx);
00586 return *this;
00587 };
00588
00590 self ddDivide(const self& rhs) const {
00591 return m_interfaced.Divide(rhs);
00592 };
00593
00595 self& ddDivideAssign(const self& rhs) {
00596 m_interfaced = m_interfaced.Divide(rhs);
00597 return *this;
00598 };
00600 self weakDivide(const self& rhs) const {
00601 return m_interfaced.WeakDiv(rhs);
00602 };
00603
00605 self& weakDivideAssign(const self& rhs) {
00606 m_interfaced = m_interfaced.WeakDiv(rhs);
00607 return *this;
00608 };
00609
00611 self& divideFirstAssign(const self& rhs) {
00612
00613 PBoRiOutIter<self, idx_type, subset1_assign<self> > outiter(*this);
00614 std::copy(rhs.firstBegin(), rhs.firstEnd(), outiter);
00615
00616 return *this;
00617 }
00618
00620 self divideFirst(const self& rhs) const {
00621
00622 self result(*this);
00623 result.divideFirstAssign(rhs);
00624
00625 return result;
00626 }
00627
00628
00630 size_type nNodes() const {
00631 return Cudd_zddDagSize(m_interfaced.getNode());
00632 }
00633
00635 ostream_type& print(ostream_type& os) const {
00636
00637 FILE* oldstdout = manager().ReadStdout();
00638
00640 if (os == std::cout)
00641 manager().SetStdout(stdout);
00642 else if (os == std::cerr)
00643 manager().SetStdout(stderr);
00644
00645 m_interfaced.print( Cudd_ReadZddSize(manager().getManager()) );
00646 m_interfaced.PrintMinterm();
00647
00648 manager().SetStdout(oldstdout);
00649 return os;
00650 }
00651
00653 void prettyPrint(pretty_out_type filehandle = stdout) const {
00654 DdNode* tmp = m_interfaced.getNode();
00655 Cudd_zddDumpDot(m_interfaced.getManager(), 1, &tmp,
00656 NULL, NULL, filehandle);
00657 };
00658
00660 bool_type prettyPrint(filename_type filename) const {
00661
00662 FILE* theFile = fopen( filename, "w");
00663 if (theFile == NULL)
00664 return true;
00665
00666 prettyPrint(theFile);
00667 fclose(theFile);
00668
00669 return false;
00670 };
00671
00673 bool_type operator==(const self& rhs) const {
00674 return (m_interfaced == rhs.m_interfaced);
00675 }
00676
00678 bool_type operator!=(const self& rhs) const {
00679 return (m_interfaced != rhs.m_interfaced);
00680 }
00681
00683 mgr_ref manager() const {
00684 return get_manager(m_interfaced.manager());
00685 }
00686 core_type managerCore() const{
00687 return m_interfaced.manager();
00688 }
00690 size_type nSupport() const {
00691 return Cudd_SupportSize(manager().getManager(), m_interfaced.getNode());
00692 }
00693
00694 #if 1
00696 self support() const {
00697
00698
00699 DdNode* tmp = Cudd_Support(manager().getManager(), m_interfaced.getNode());
00700 Cudd_Ref(tmp);
00701
00702 self result = interfaced_type(m_interfaced.manager(),
00703 Cudd_zddPortFromBdd(manager().getManager(), tmp));
00704 Cudd_RecursiveDeref(manager().getManager(), tmp);
00705
00706
00707
00708 return result;
00709 }
00710 #endif
00711
00713 template<class VectorLikeType>
00714 void usedIndices(VectorLikeType& indices) const {
00715
00716 int* pIdx = Cudd_SupportIndex( manager().getManager(),
00717 m_interfaced.getNode() );
00718
00719
00720
00721 size_type nlen(nVariables());
00722
00723 indices.reserve(std::accumulate(pIdx, pIdx + nlen, size_type()));
00724
00725 for(size_type idx = 0; idx < nlen; ++idx)
00726 if (pIdx[idx] == 1){
00727 indices.push_back(idx);
00728 }
00729 FREE(pIdx);
00730 }
00731
00733 int* usedIndices() const {
00734
00735 return Cudd_SupportIndex( manager().getManager(),
00736 m_interfaced.getNode() );
00737
00738
00739 }
00740
00741
00743 first_iterator firstBegin() const {
00744 return first_iterator(m_interfaced.getNode());
00745 }
00746
00748 first_iterator firstEnd() const {
00749 return first_iterator();
00750 }
00751
00753 last_iterator lastBegin() const {
00754 return last_iterator(m_interfaced.getNode());
00755 }
00756
00758 last_iterator lastEnd() const {
00759 return last_iterator();
00760 }
00761
00763 self firstMultiples(const std::vector<idx_type>& multipliers) const {
00764
00765 std::vector<idx_type> indices( std::distance(firstBegin(), firstEnd()) );
00766
00767 std::copy( firstBegin(), firstEnd(), indices.begin() );
00768
00769 return cudd_generate_multiples( manager(),
00770 indices.rbegin(), indices.rend(),
00771 multipliers.rbegin(),
00772 multipliers.rend() );
00773 }
00774
00775
00776
00777 self subSet(const self& rhs) const {
00778
00779 return interfaced_type(m_interfaced.manager(),
00780 Extra_zddSubSet(manager().getManager(),
00781 m_interfaced.getNode(),
00782 rhs.m_interfaced.getNode()) );
00783 }
00784
00785 self supSet(const self& rhs) const {
00786
00787 return interfaced_type(m_interfaced.manager(),
00788 Extra_zddSupSet(manager().getManager(),
00789 m_interfaced.getNode(),
00790 rhs.m_interfaced.getNode()) );
00791 }
00793 self firstDivisors() const {
00794
00795 std::vector<idx_type> indices( std::distance(firstBegin(), firstEnd()) );
00796
00797 std::copy( firstBegin(), firstEnd(), indices.begin() );
00798
00799 return cudd_generate_divisors(manager(), indices.rbegin(), indices.rend());
00800 }
00801
00803 navigator navigation() const {
00804 return navigator(m_interfaced.getNode());
00805 }
00806
00808 bool_type emptiness() const {
00809 return ( m_interfaced.getNode() == manager().zddZero().getNode() );
00810 }
00811
00813 bool_type blankness() const {
00814
00815 return ( m_interfaced.getNode() ==
00816 manager().zddOne( nVariables() ).getNode() );
00817
00818 }
00819
00820 bool_type isConstant() const {
00821 return (m_interfaced.getNode()) && Cudd_IsConstant(m_interfaced.getNode());
00822 }
00823
00825 size_type size() const {
00826 return m_interfaced.Count();
00827 }
00828
00830 size_type length() const {
00831 return size();
00832 }
00833
00835 size_type nVariables() const {
00836 return Cudd_ReadZddSize(manager().getManager() );
00837 }
00838
00840 self minimalElements() const {
00841 return interfaced_type(m_interfaced.manager(),
00842 Extra_zddMinimal(manager().getManager(),m_interfaced.getNode()));
00843 }
00844
00845 self cofactor0(const self& rhs) const {
00846
00847 return interfaced_type(m_interfaced.manager(),
00848 Extra_zddCofactor0(manager().getManager(),
00849 m_interfaced.getNode(),
00850 rhs.m_interfaced.getNode()) );
00851 }
00852
00853 self cofactor1(const self& rhs, idx_type includeVars) const {
00854
00855 return interfaced_type(m_interfaced.manager(),
00856 Extra_zddCofactor1(manager().getManager(),
00857 m_interfaced.getNode(),
00858 rhs.m_interfaced.getNode(),
00859 includeVars) );
00860 }
00861
00863 bool_type ownsOne() const {
00864 navigator navi(navigation());
00865
00866 while (!navi.isConstant() )
00867 navi.incrementElse();
00868
00869 return navi.terminalValue();
00870 }
00871 double sizeDouble() const {
00872 return m_interfaced.CountDouble();
00873 }
00874
00876 self emptyElement() const {
00877 return manager().zddZero();
00878 }
00879
00881 self blankElement() const {
00882 return manager().zddOne();
00883 }
00884
00885 private:
00886 navigator newNode(const manager_base& mgr, idx_type idx,
00887 navigator thenNavi, navigator elseNavi) const {
00888 assert(idx < *thenNavi);
00889 assert(idx < *elseNavi);
00890 return navigator(cuddZddGetNode(mgr.getManager(), idx,
00891 thenNavi.getNode(), elseNavi.getNode()));
00892 }
00893
00894 interfaced_type newDiagram(const manager_base& mgr, navigator navi) const {
00895 return interfaced_type(extract_manager(mgr), navi.getNode());
00896 }
00897
00898 self fromTemporaryNode(const navigator& navi) const {
00899 navi.decRef();
00900 return self(manager(), navi.getNode());
00901 }
00902
00903
00904 interfaced_type newNodeDiagram(const manager_base& mgr, idx_type idx,
00905 navigator thenNavi,
00906 navigator elseNavi) const {
00907 if ((idx >= *thenNavi) || (idx >= *elseNavi))
00908 throw PBoRiGenericError<CTypes::invalid_ite>();
00909
00910 return newDiagram(mgr, newNode(mgr, idx, thenNavi, elseNavi) );
00911 }
00912
00913 interfaced_type newNodeDiagram(const manager_base& mgr,
00914 idx_type idx, navigator navi) const {
00915 if (idx >= *navi)
00916 throw PBoRiGenericError<CTypes::invalid_ite>();
00917
00918 navi.incRef();
00919 interfaced_type result =
00920 newDiagram(mgr, newNode(mgr, idx, navi, navi) );
00921 navi.decRef();
00922 return result;
00923 }
00924
00925
00926
00927 };
00928
00929
00930
00931
00932
00934 template <class DDType>
00935 typename CDDInterface<DDType>::ostream_type&
00936 operator<<( typename CDDInterface<DDType>::ostream_type& os,
00937 const CDDInterface<DDType>& dd ) {
00938 return dd.print(os);
00939 }
00940
00941 END_NAMESPACE_PBORI
00942
00943 #endif // of #ifndef CDDInterface_h_