Example #1
0
//each vtree node is associated with a set of litsets (clauses or terms)
//the totality of these litsets represent an fnf (cnf or dnf)
//returns an sdd which is equivalent to the cnf/dnf associated with vtree
SddNode* apply_vtree_auto(Vtree* vtree, BoolOp op, SddManager* manager) {
  //get litsets associated with vtree node
  //do this first as vtree root may be changed by dynamic vtree search
  LitSet** litsets     = DATA(vtree,litsets);
  SddSize litset_count = DATA(vtree,litset_count);  
  
  sort_litsets_by_lca(litsets,litset_count,manager);

  SddNode* node;
  if(sdd_vtree_is_leaf(vtree)) node = ONE(manager,op);
  else {
    SddNode* l_node = apply_vtree_auto(sdd_vtree_left(vtree),op,manager);
    sdd_ref(l_node,manager);
    SddNode* r_node = apply_vtree_auto(sdd_vtree_right(vtree),op,manager);
    sdd_deref(l_node,manager);
    node = sdd_apply(l_node,r_node,op,manager);
  }
  
  while(litset_count--) { //compile and integrate litset
    sdd_ref(node,manager);
    SddNode* litset = apply_litset_auto(*litsets++,manager); //may gc node
    sdd_deref(node,manager);
   
    node = sdd_apply(litset,node,op,manager);
        
    //recompute lcas of remaining clauses and sort again
    sort_litsets_by_lca(litsets,litset_count,manager);
  }
  
  return node;
}
Example #2
0
int main(int argc, char** argv) {

  // set up vtree and manager
  SddLiteral var_count = 4;
  const char* type = "right";
  Vtree* vtree = sdd_vtree_new(var_count,type);
  SddManager* manager = sdd_manager_new(vtree);

  // construct the term X_1 ^ X_2 ^ X_3 ^ X_4
  SddNode* alpha = sdd_manager_literal(1,manager);
  alpha = sdd_conjoin(alpha,sdd_manager_literal(2,manager),manager);
  alpha = sdd_conjoin(alpha,sdd_manager_literal(3,manager),manager);
  alpha = sdd_conjoin(alpha,sdd_manager_literal(4,manager),manager);

  // construct the term ~X_1 ^ X_2 ^ X_3 ^ X_4
  SddNode* beta = sdd_manager_literal(-1,manager);
  beta = sdd_conjoin(beta,sdd_manager_literal(2,manager),manager);
  beta = sdd_conjoin(beta,sdd_manager_literal(3,manager),manager);
  beta = sdd_conjoin(beta,sdd_manager_literal(4,manager),manager);

  // construct the term ~X_1 ^ ~X_2 ^ X_3 ^ X_4
  SddNode* gamma = sdd_manager_literal(-1,manager);
  gamma = sdd_conjoin(gamma,sdd_manager_literal(-2,manager),manager);
  gamma = sdd_conjoin(gamma,sdd_manager_literal(3,manager),manager);
  gamma = sdd_conjoin(gamma,sdd_manager_literal(4,manager),manager);

  printf("== before referencing:\n");
  printf("  live sdd size = %zu\n", sdd_manager_live_size(manager));
  printf("  dead sdd size = %zu\n", sdd_manager_dead_size(manager));

  // ref SDDs so that they are not garbage collected
  sdd_ref(alpha,manager);
  sdd_ref(beta,manager);
  sdd_ref(gamma,manager);
  printf("== after referencing:\n");
  printf("  live sdd size = %zu\n", sdd_manager_live_size(manager));
  printf("  dead sdd size = %zu\n", sdd_manager_dead_size(manager));

  // garbage collect
  sdd_manager_garbage_collect(manager);
  printf("== after garbage collection:\n");
  printf("  live sdd size = %zu\n", sdd_manager_live_size(manager));
  printf("  dead sdd size = %zu\n", sdd_manager_dead_size(manager));

  sdd_deref(alpha,manager);
  sdd_deref(beta,manager);
  sdd_deref(gamma,manager);

  printf("saving vtree & shared sdd ...\n");
  sdd_vtree_save_as_dot("output/shared-vtree.dot",vtree);
  sdd_shared_save_as_dot("output/shared.dot",manager);

  sdd_vtree_free(vtree);
  sdd_manager_free(manager);

  return 0;
}
Example #3
0
SddNode* Prover::branchToSDD(std::vector<SddLiteral> variables, SddManager* m) {
    SddNode* alpha = sdd_manager_true(m);
    SddNode* tmp;
    for (SddLiteral i: variables) {
            alpha = sdd_conjoin(tmp = alpha, sdd_manager_literal(i,m),m);
            sdd_ref(alpha,m); sdd_deref(tmp,m);
    }
    sdd_deref(alpha,m);
    return alpha;
}
Example #4
0
SddNode* S4Prover::refineSdd(std::vector<SddLiteral> literals, SddNode* oldSdd, SddManager* m) {
        SddNode* tmp;
        SddNode* newSdd = sdd_manager_false(m);
        for (SddLiteral lit : literals) {
            newSdd = sdd_disjoin(tmp = newSdd, sdd_manager_literal(-lit,m),m);
            sdd_ref(newSdd,m); sdd_deref(tmp,m);
        }
        newSdd = sdd_conjoin(oldSdd,tmp = newSdd,m);
        sdd_deref(tmp,m);
        return newSdd;
}
Example #5
0
//each vtree node is associated with a set of litsets (clauses or terms)
//the totality of these litsets represent an fnf (cnf or dnf)
//returns an sdd which is equivalent to the cnf/dnf associated with vtree
SddNode* apply_vtree_manual(Vtree* vtree, BoolOp op, SddManager* manager) {
  SddNode* base;

  if(sdd_vtree_is_leaf(vtree)) base = ONE(manager,op);
  else {
    SddNode* l_node = apply_vtree_manual(sdd_vtree_left(vtree),op,manager);
    SddNode* r_node = apply_vtree_manual(sdd_vtree_right(vtree),op,manager);
    base            = sdd_apply_in_vtree(l_node,r_node,op,vtree,manager);
  }

  SddSize litset_count = DATA(vtree,litset_count);
  if(litset_count==0) return base; //no clauses/terms stored at vtree node
  
  //apply litsets may change root of vtree due to vtree search
  Vtree** vtree_loc = sdd_vtree_location(vtree,manager);
  SddNode* node     = apply_litsets_manual(base,op,vtree,manager);
  vtree             = *vtree_loc; //root may have changed

  SddManagerOptions* options = sdd_manager_options(manager);
  if(options->vtree_search_mode==2) {
    sdd_ref(node,manager);
    //to SWITCH-TO-LIBRARY-SEARCH, comment in the next line, comment out the one after
    vtree_search(vtree,manager);
//    sdd_vtree_minimize(vtree,manager); //library's version of vtree search algorithm
    sdd_deref(node,manager);
  }
  
  return node;
}
Example #6
0
//convert the clauses/terms associated with vtree into sdds and combine them with base using op
SddNode* apply_litsets_manual(SddNode* base, BoolOp op, Vtree* vtree, SddManager* manager) {

  //get litsets associated with vtree node
  LitSet** litsets     = DATA(vtree,litsets);
  SddSize litset_count = DATA(vtree,litset_count);
  
  assert(litset_count!=0);
  sort_litsets_by_lca(litsets,litset_count,manager);
  
  SddNode* result = base;
  sdd_ref(result,manager);
    
  //must be done after referencing
  SddSize prev_size = sdd_vtree_live_size(vtree);

  SddManagerOptions* options = sdd_manager_options(manager);
  while(litset_count--) {
    //compile and integrate litset
    SddNode* node = apply_litset_manual(*litsets++,vtree,manager);
    sdd_deref(result,manager);
    result        = sdd_apply_in_vtree(node,result,op,vtree,manager);
    sdd_ref(result,manager);

    if(options->vtree_search_mode==2) {
      SddSize cur_size  = sdd_vtree_live_size(vtree); //after integrating last litset
      if(cur_size  > prev_size*options->vtree_search_threshold) {
        //to SWITCH-TO-LIBRARY-SEARCH, comment in the next line, comment out the one after
        vtree = vtree_search(vtree,manager); // root of vtree may have changed
//        vtree = sdd_vtree_minimize(vtree,manager); //library's version of vtree search algorithm
        prev_size  = sdd_vtree_live_size(vtree); //since last call to dynamic vtree
        //recompute lcas of remaining clauses and sort again
        sort_litsets_by_lca(litsets,litset_count,manager);
      }
    }
      
    sdd_vtree_garbage_collect_if(options->gc_threshold,vtree,manager);
  }
 
  sdd_deref(result,manager);

  return result;
}
Example #7
0
bool S4Prover::isSatisfiable(SddNode* alpha, SddManager* m, std::unordered_set<SddLiteral> permVars, SddNode* permSdd,
                                std::unordered_set<SddNode*,SddHasher>& assumedSatSdds , std::unordered_set<SddLiteral>& responsibleVars) {
    
    //Match against cache
    if (satCache.count(alpha) == 1) {
        return true;
    }
    
    //Base cases
    if (sdd_node_is_true(alpha)) {
        return true;
    }
    
    if (sdd_node_is_false(alpha)) {
        return false;
    }
    
    //Scrape off a single satisfying set, corresponding to a single open tableaux branch.
    std::vector<SddLiteral> branch = getOpenBranch(alpha, std::vector<SddLiteral>());
    SddNode* branchSdd = branchToSDD(branch,m);
    sdd_ref(branchSdd,m);

    /*std::cout << "BRANCH\n\n";
    for (SddLiteral i : branch) {
        if (i < 0) std::cout << "~" << *literalsToAtoms[-i] << "\n\n";
        else std::cout << *literalsToAtoms[i] << "\n\n";
    }
    std::cout << "BRANCH END\n\n";*/
    
    //Extract all modal atoms from the branch.
    std::vector<SddLiteral> boxes;
    std::vector<SddLiteral> negBoxes;
    if (extractModals(branch,boxes,negBoxes) == 0) {
        return true;
    };

    //Checks for new boxed variables
    SddNode* tmp;
    std::unordered_set<SddLiteral> newPermVars = permVars;
    std::vector<SddLiteral> unboxed;
    SddNode* postUnboxingBranch = sdd_conjoin(sdd_manager_true(m),branchSdd,m);
    sdd_ref(postUnboxingBranch,m);
    SddNode* newPermSdd = sdd_conjoin(sdd_manager_true(m),permSdd,m);
    sdd_ref(newPermSdd,m);
    for (SddLiteral i : boxes) {
        if (newPermVars.count(i) == 0) {
            unboxed.push_back(i);
            newPermVars.insert(i);
            postUnboxingBranch = sdd_conjoin(tmp = postUnboxingBranch, compiler::KtoSDD(&literalsToAtoms[i]->getleft(),m),m);
            sdd_deref(tmp,m); sdd_ref(postUnboxingBranch,m);
            newPermSdd = sdd_conjoin(tmp = newPermSdd, compiler::KtoSDD(&literalsToAtoms[i]->getleft(),m),m);
            sdd_deref(tmp,m); sdd_ref(newPermSdd,m);
            newPermSdd = sdd_conjoin(tmp = newPermSdd, compiler::KtoSDD(literalsToAtoms[i],m),m);
            sdd_deref(tmp,m); sdd_ref(newPermSdd,m);
            //If becomes false while unboxing, recurse.
            if (sdd_node_is_false(postUnboxingBranch)) {

                //Determine minimal set of unboxed variables
                std::vector<SddLiteral> minLits;
                minLits.push_back(i);
                responsibleVars.insert(i);
                std::vector<SddLiteral>::iterator endIt = --(unboxed.end());
                SddNode* minimalSdd = sdd_conjoin(compiler::KtoSDD(&literalsToAtoms[i]->getleft(),m),branchSdd,m);
                sdd_ref(minimalSdd,m);
                SddNode* minBoxVarsSdd = sdd_conjoin(compiler::KtoSDD(&literalsToAtoms[i]->getleft(),m),sdd_manager_true(m),m);
                sdd_ref(minBoxVarsSdd,m);                       
                while (true) {
                    sdd_deref(postUnboxingBranch,m);
                    postUnboxingBranch = sdd_conjoin(minimalSdd, sdd_manager_true(m), m);
                    sdd_ref(postUnboxingBranch,m);
                    if (sdd_node_is_false(postUnboxingBranch)) break; //Last one added made it false
                    for (std::vector<SddLiteral>::iterator v = unboxed.begin();
							v != endIt; ++v) {
                        postUnboxingBranch = sdd_conjoin(tmp = postUnboxingBranch, compiler::KtoSDD(&literalsToAtoms[*v]->getleft(),m),m);
                        sdd_deref(tmp,m); sdd_ref(postUnboxingBranch,m);
						if (sdd_node_is_false(postUnboxingBranch)) {
							//Last one added made it false
							minimalSdd = sdd_conjoin(tmp = minimalSdd, compiler::KtoSDD(&literalsToAtoms[*v]->getleft(),m),m);
                            sdd_deref(tmp,m); sdd_ref(minimalSdd,m);
                            minBoxVarsSdd = sdd_conjoin(tmp = minBoxVarsSdd,compiler::KtoSDD(&literalsToAtoms[*v]->getleft(),m),m);
                            sdd_deref(tmp,m); sdd_ref(minBoxVarsSdd,m);
                            minLits.push_back(*v);
                            responsibleVars.insert(*v);
							endIt = v;
							break;
						}
					}
                }
                // Determine minimal set of branch variables together with unboxed variables
                std::vector<SddLiteral>::iterator BendIt = branch.end();
                sdd_deref(minimalSdd,m);
                minimalSdd = sdd_conjoin(sdd_manager_true(m),minBoxVarsSdd,m);
                sdd_ref(minimalSdd,m);
				while (true) {
                    sdd_deref(minBoxVarsSdd,m);
					minBoxVarsSdd = sdd_conjoin(minimalSdd, sdd_manager_true(m), m);
                    sdd_ref(minBoxVarsSdd,m);
                    if (sdd_node_is_false(minBoxVarsSdd)) break; //Last one added made it false
					for (std::vector<SddLiteral>::iterator v = branch.begin();
						v != BendIt; ++v) {
                        minBoxVarsSdd = sdd_conjoin(tmp = minBoxVarsSdd, sdd_manager_literal(*v,m), m);
                        sdd_deref(tmp,m); sdd_ref(minBoxVarsSdd,m);
                        if (sdd_node_is_false(minBoxVarsSdd)) {
    						//Last one added made it false
                            minimalSdd = sdd_conjoin(tmp = minimalSdd, sdd_manager_literal(*v,m),m);
                            sdd_deref(tmp,m); sdd_ref(minimalSdd,m);
							minLits.push_back(*v);
                            responsibleVars.insert(*v);
                            BendIt = v;
							break;
						}
					}
				}
                sdd_deref(minimalSdd,m); sdd_deref(postUnboxingBranch,m); sdd_deref(minBoxVarsSdd,m);
                
                //std::cout << *literalsToAtoms[minLits[0]] << " and " << *literalsToAtoms[minLits[1]] << "\n";
                SddNode* beta = refineSdd(minLits, alpha, m);
                sdd_ref(beta,m);
                dependentSdds.insert(alpha);
                bool isSat = isSatisfiableRefined(beta, m, permVars, permSdd, assumedSatSdds, responsibleVars);
                dependentSdds.erase(alpha);
                sdd_deref(beta,m); sdd_deref(branchSdd,m); sdd_deref(newPermSdd,m);
                return isSat;
            }
        }
    }
    // There were new boxes, so recurse.
    if (!unboxed.empty()) {
        dependentSdds.insert(alpha);
        std::unordered_set<SddLiteral> postResponsibleVars;
        if (!isSatisfiable(postUnboxingBranch,m,newPermVars,newPermSdd,assumedSatSdds, postResponsibleVars)) {
            std::vector<SddLiteral> minLits;
            for (SddLiteral v : branch) {
                if (postResponsibleVars.count(v) == 1) {
                    minLits.push_back(v);
                    responsibleVars.insert(v);
                }
            }
			for (SddLiteral v : unboxed) {
				std::unordered_set<SddLiteral> children;
				KFormula::computeChildrenBoxS4(&literalsToAtoms[v]->getleft(), children);
				if (shareAnElement(postResponsibleVars, children)) {
                    minLits.push_back(v);
                    responsibleVars.insert(v);
				}
			}
               SddNode* beta = refineSdd(minLits, alpha, m);
               sdd_ref(beta,m);
               bool isSat = isSatisfiableRefined(beta, m, permVars, permSdd, assumedSatSdds, responsibleVars);
               sdd_deref(beta,m); sdd_deref(branchSdd,m); sdd_deref(newPermSdd,m); sdd_deref(postUnboxingBranch,m);
               dependentSdds.erase(alpha);
               return isSat;
        }
        sdd_deref(branchSdd,m); sdd_deref(newPermSdd,m);
        dependentSdds.erase(alpha);
        return true;
    }
    
    // There are no new boxes, so start undiamonding.
    sdd_deref(branchSdd,m);
    if (negBoxes.empty()) {
		return true;
	}
	dependentSdds.insert(alpha);
	SddNode* nextWorld;
    for (SddLiteral i : negBoxes) {
        nextWorld = sdd_conjoin(permSdd, sdd_negate(compiler::KtoSDD(&literalsToAtoms[-i]->getleft(),m),m),m);
        sdd_ref(nextWorld,m);        
        
        if (sdd_node_is_false(nextWorld)) {
            
            sdd_deref(nextWorld,m);
            nextWorld = sdd_conjoin(sdd_manager_true(m), sdd_negate(compiler::KtoSDD(&literalsToAtoms[-i]->getleft(),m),m),m);
            sdd_ref(nextWorld,m);
			responsibleVars.insert(i);
			std::vector<SddLiteral> minLits;
            minLits.push_back(i);
			
			// Determine a minimal unsatisfiable subset.
			std::unordered_set<SddLiteral>::iterator endIt = permVars.end();
            SddNode* minimalSdd = sdd_conjoin(nextWorld, sdd_manager_true(m),m);
            sdd_ref(minimalSdd,m);
			while (true) {
                sdd_deref(nextWorld,m);
                nextWorld = sdd_conjoin(minimalSdd, sdd_manager_true(m), m);
                sdd_ref(nextWorld,m);
				if (sdd_node_is_false(nextWorld)) break;
				for (std::unordered_set<SddLiteral>::iterator v = permVars.begin();
							v != endIt; ++v) {
                    nextWorld = sdd_conjoin(tmp = nextWorld,compiler::KtoSDD(&literalsToAtoms[*v]->getleft(),m) ,m);
                    sdd_deref(tmp, m); sdd_ref(nextWorld,m);
                    nextWorld = sdd_conjoin(tmp = nextWorld,sdd_manager_literal(*v,m) ,m);
                    sdd_deref(tmp, m); sdd_ref(nextWorld,m);
					if (sdd_node_is_false(nextWorld)) {
                        minimalSdd = sdd_conjoin(tmp = minimalSdd,compiler::KtoSDD(&literalsToAtoms[*v]->getleft(),m) ,m);
                        sdd_deref(tmp, m); sdd_ref(minimalSdd,m);
                        minimalSdd = sdd_conjoin(tmp = minimalSdd,sdd_manager_literal(*v,m) ,m);
                        sdd_deref(tmp, m); sdd_ref(minimalSdd,m);
						minLits.push_back(*v);
						responsibleVars.insert(*v);
                        endIt = v;
						break;
					}
				}
			} 
			SddNode* beta = refineSdd(minLits, alpha, m);
            sdd_ref(beta,m);
            bool isSat = isSatisfiableRefined(beta, m, permVars, permSdd, assumedSatSdds, responsibleVars);
            sdd_deref(beta,m); sdd_deref(nextWorld,m); sdd_deref(minimalSdd,m);
            dependentSdds.erase(alpha);
            return isSat;	  
        }
        if (dependentSdds.count(nextWorld) == 1) {
            //Loop detected
            assumedSatSdds.insert(nextWorld);
            continue;
        }
        std::unordered_set<SddNode*,SddHasher> postModalAssumedSatSdds = assumedSatSdds;
        std::unordered_set<SddLiteral> postResponsibleVars;
        if (!isSatisfiable(nextWorld,m,permVars,permSdd,postModalAssumedSatSdds, postResponsibleVars)) {
            
            std::vector<SddLiteral> minLits;

			bool newPostModalJumpResVarsAdded = true;
			while (newPostModalJumpResVarsAdded) {
				newPostModalJumpResVarsAdded = false;
				for (std::unordered_set<SddLiteral>::iterator v = permVars.begin();
						v != permVars.end(); ++v) {
					if (responsibleVars.count(*v) != 0) {
						continue;
					}
					std::unordered_set<SddLiteral> children = getChildren(*v);
					children.insert(*v);
					if (shareAnElement(postResponsibleVars, children)) {
                        minLits.push_back(*v);
						responsibleVars.insert(*v);
						// Add in other children to postModalJumpResVars
						postResponsibleVars.insert(children.begin(),
													children.end());
						newPostModalJumpResVarsAdded = true;
					}
				}
				if (responsibleVars.count(i) != 0) {
					// Don't bother, we've already accounted for this dia var.
				} else if (shareAnElement(postResponsibleVars, getChildren(i))) {
					// Note, <>phi stored as []~phi, thus the nith.
					minLits.push_back(i);
					responsibleVars.insert(i);
					// Add in other children to postModalJumpResVars
					postResponsibleVars.insert(getChildren(i).begin(),
												getChildren(i).end());
					newPostModalJumpResVarsAdded = true;
				}
			}
	
            SddNode* beta = refineSdd(minLits, alpha, m);
            sdd_ref(beta,m);
            bool isSat = isSatisfiableRefined(beta, m, permVars, permSdd, assumedSatSdds, responsibleVars);
            sdd_deref(beta,m); sdd_deref(nextWorld,m);
            dependentSdds.erase(alpha);
            return isSat;
        }
        assumedSatSdds.insert(postModalAssumedSatSdds.begin(),postModalAssumedSatSdds.end());
    }
    
    satCache.insert(alpha);
    dependentSdds.erase(alpha);
    return true;
}
Example #8
0
SddNode* cfgWithRef(SddManager* m, Vtree* v, int nonTerminal, int terminal, int rules[][3], int start, int ruleCount, int* string, int len){
	SddNode* dy[len][len][nonTerminal];
	int i,j,k,index;
	
	//initialize everything to false
	for (i=0;i<len;i++) for (j=0;j<len;j++) for (k=0;k<nonTerminal;k++) dy[i][j][k] = sdd_manager_false(m);
	sdd_manager_auto_gc_and_minimize_on(m);
	
	//set diagonal according to terminal rules
	for (index = 0;index < len; index++){
		for (i = 0; i < ruleCount; i++){
			if (rules[i][0] == -1 && rules[i][2] == string[index]){
				dy[index][index][rules[i][1]] = sdd_manager_true(m);
			}
		}
	}
	
	//this section builds a dynamic array according to number of parsings
	//build from top down(according to diagram above)
	for (j = 1; j < len; j++){
		//build from right to left
		for (i = j-1; i >= 0; i--){
			//check each non-terminal rule
			for (k = 0; rules[k][0] != -1; k++){
				for (index = 0; index+i < j; index++){
					if (dy[i][i+index][rules[k][1]] && dy[i+index+1][j][rules[k][2]]){
						SddNode* tmp = sdd_apply_in_vtree(dy[i][i+index][rules[k][1]],dy[i+index+1][j][rules[k][2]],0,v,m);
						sdd_ref(tmp,m);
						dy[i][j][rules[k][0]] = sdd_apply_in_vtree(dy[i][j][rules[k][0]],tmp,1,v,m);
						sdd_ref(dy[i][j][rules[k][0]],m);
						sdd_deref(tmp,m);
					}
				}
			}
		}
	}
	
	
	//this section builds a dynamic array according to number of parsings
	//build from top down(according to diagram above)
	for (j = 1; j < len; j++){
		//build from right to left
		for (i = j-1; i >= 0; i--){
			//check each non-terminal rule
			for (k = 0; rules[k][0] != -1; k++){
				for (index = 0; index+i < j; index++){
					if (dy[i][i+index][rules[k][1]] && dy[i+index+1][j][rules[k][2]]){
						if (i != 0 || j != len-1 || rules[k][0] != start) sdd_deref(dy[i][j][rules[k][0]],m);
					}
				}
			}
		}
	}
	
	//int size = sdd_manager_size(m);
	int size = sdd_size(dy[0][len-1][start]);
	printf("size: %d\n",size);
	
	dy[0][len-1][start] = sdd_minimize_cardinality(dy[0][len-1][start],m);
	
	size = sdd_size(dy[0][len-1][start]);
	printf("size: %d\n",size);
	
	return dy[0][len-1][start];
}