/** * Tests the Term subsumption * * @param[in] t: term we are testing subsumption against * @return: true if this is subsumed by @p t */ SubsumptionResult Term::IsSubsumed(Term *t, bool unfoldAll) { // unfold the continuation if(this == t) { return E_TRUE; } if(t->type == TERM_CONTINUATION) { TermContinuation *continuation = reinterpret_cast<TermContinuation *>(t); Term* unfoldedContinuation = continuation->unfoldContinuation(UnfoldedInType::E_IN_SUBSUMPTION); return this->IsSubsumed(unfoldedContinuation, unfoldAll); } else if(this->type == TERM_CONTINUATION) { TermContinuation *continuation = reinterpret_cast<TermContinuation *>(this); Term* unfoldedContinuation = continuation->unfoldContinuation(UnfoldedInType::E_IN_SUBSUMPTION); return unfoldedContinuation->IsSubsumed(t, unfoldAll); } if(this->_inComplement != t->_inComplement) { this->dump(); std::cout << " and ";t->dump(); std::cout << "\n"; } assert(this->_inComplement == t->_inComplement); assert(this->type != TERM_CONTINUATION && t->type != TERM_CONTINUATION); // Else if it is not continuation we first look into cache and then recompute if needed SubsumptionResult result; #if (OPT_CACHE_SUBSUMES == true) if(this->type != TERM_FIXPOINT || !this->_isSubsumedCache.retrieveFromCache(t, result)) { #endif if (this->_inComplement) { if(this->type == TERM_EMPTY) { result = (t->type == TERM_EMPTY ? E_TRUE : E_FALSE); } else { result = t->_IsSubsumedCore(this, unfoldAll); } } else { if(t->type == TERM_EMPTY) { result = (this->type == TERM_EMPTY ? E_TRUE : E_FALSE); } else { result = this->_IsSubsumedCore(t, unfoldAll); } } #if (OPT_CACHE_SUBSUMES == true) if(result != E_PARTIALLY && this->type == TERM_FIXPOINT) this->_isSubsumedCache.StoreIn(t, result); } #endif assert(!unfoldAll || result != E_PARTIALLY); # if (DEBUG_TERM_SUBSUMPTION == true) this->dump(); std::cout << (result == E_TRUE ? " \u2291 " : " \u22E2 "); t->dump(); std::cout << " = " << (result == E_TRUE ? "true" : "false") << "\n\n"; # endif return result; }
SubsumptionResult TermProduct::_IsSubsumedCore(Term* t, bool unfoldAll) { assert(t->type == TERM_PRODUCT); // Retype and test the subsumption component-wise TermProduct *rhs = reinterpret_cast<TermProduct*>(t); Term *lhsl = this->left; Term *lhsr = this->right; Term *rhsl = rhs->left; Term *rhsr = rhs->right; if(!unfoldAll && (lhsr->IsNotComputed() && rhsr->IsNotComputed())) { #if (OPT_EARLY_PARTIAL_SUB == true) if(lhsr->type == TERM_CONTINUATION && rhsr->type == TERM_CONTINUATION) { return (lhsl->IsSubsumed(rhsl, unfoldAll) == E_FALSE ? E_FALSE : E_PARTIALLY); } else { SubsumptionResult leftIsSubsumed = lhsl->IsSubsumed(rhsl, unfoldAll); if(leftIsSubsumed == E_TRUE) { return lhsr->IsSubsumed(rhsr, unfoldAll); } else { return leftIsSubsumed; } } #else return (lhsl->IsSubsumed(rhsl) != E_FALSE && lhsr->IsSubsumed(rhsr) != E_FALSE) ? E_TRUE : E_FALSE; #endif } if(!unfoldAll && lhsl == rhsl) { return lhsr->IsSubsumed(rhsr, unfoldAll); } else if(!unfoldAll && lhsr == rhsr) { return lhsl->IsSubsumed(rhsl, unfoldAll); } else { if(lhsl->stateSpaceApprox < lhsr->stateSpaceApprox || unfoldAll) { return (lhsl->IsSubsumed(rhsl, unfoldAll) != E_FALSE && lhsr->IsSubsumed(rhsr, unfoldAll) != E_FALSE) ? E_TRUE : E_FALSE; } else { return (lhsr->IsSubsumed(rhsr, unfoldAll) != E_FALSE && lhsl->IsSubsumed(rhsl, unfoldAll) != E_FALSE) ? E_TRUE : E_FALSE; } } }