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