Ejemplo n.º 1
0
//frees the SatState
void sat_state_free(SatState* sat_state) {
	for (c2dSize i = 1; i <= sat_var_count(sat_state); i++) {
		Var* var = sat_index2var(i, sat_state);
		vector_free(&var->mentions);
		vector_free(&var->mentions_lc);
		free(var);
		free(sat_index2literal(i, sat_state));
		free(sat_index2literal(-i, sat_state));
	}
	for (c2dSize i = 1; i <= sat_clause_count(sat_state); i++) {
		Clause* clause = sat_index2clause(i, sat_state);
		vector_free(&clause->lits);
		free(clause);
	}
	vector_free(&sat_state->vars);
	vector_free(&sat_state->plits);
	vector_free(&sat_state->nlits);
	vector_free(&sat_state->kb);
	vector_free(&sat_state->lc);
	vector_free(&sat_state->ds);
	vector_free(&sat_state->il);
	vector_free(&sat_state->q);
	vector_free(&sat_state->s);
	free(sat_state);
}
Ejemplo n.º 2
0
/******************************************************************************
	Two literal watch algorithm for unit resolution
The algorithm taken from the Class Notes for CS264A, UCLA

******************************************************************************/
BOOLEAN two_literal_watch(SatState* sat_state, Lit** literals_list, unsigned long num_elements, unsigned long type){

	// Once I entered here I must have elements in the decision array
	assert(sat_state->num_literals_in_decision > 0);

	// initialize the list of watched clauses already initialized in ParseDIMACS
//	if(!INIT_LITERAL_WATCH)
//		intitialize_watching_clauses(sat_state);

	BOOLEAN contradiction_flag = 0;

	//TODO: Due to recursion of pending list we may need to consider more than one decided literal then we need a list that captures all literals of last decision

	//loop on all decided literals

	// Lit** literals_in_decision = literals_list;
	// unsigned long max_size_decision_list = capacity;
	// unsigned long num_decision_lit = num_elements;


	// Create pending literal list
	Lit** pending_list = (Lit**)malloc(sizeof(Lit*));
	unsigned long max_size_pending_list = 1;
	unsigned long num_pending_lit = 0;


	unsigned long initial_num_elements = num_elements;


	for(unsigned long i =0; i< num_elements; i++){
#ifdef DEBUG
		printf("--------------------------------------\n");
		printf("Decision list now in two literal watch: ");
		for(unsigned long j =0; j<  num_elements;j++){
			printf("%ld\t", literals_list[j]->sindex );
		}
		printf("\n");
#endif

		if(type == CASE1 && (sat_state->decisions[i]->decision_level != sat_state->current_decision_level)){
			continue; // don't re-evaluate this literal
		}else if(type == CASE2 && sat_state->decisions[i]->decision_level != sat_state->current_decision_level){
			continue;
		}else if(type == CASE2 && sat_state->decisions[i]->decision_level == sat_state->current_decision_level && i < initial_num_elements-1){
			continue;
		}
		else{

			//Lit* decided_literal = sat_state->decisions[sat_state->num_literals_in_decision -1];
			Lit* decided_literal = literals_list[i];
			Lit* resolved_literal = get_resolved_lit(decided_literal, sat_state);

#ifdef DEBUG
			printf("Resolved Literal: %ld\n", resolved_literal->sindex);
#endif

			//Update clauses state based on the decided literal
			sat_update_clauses_state(decided_literal , sat_state);

			//If no watching clauses on the resolved literal then do nothing and record the decision
			if(resolved_literal->num_watched_clauses == 0){
				// The decided literal is already in the decision list so no need to record it again
#ifdef DEBUG
				printf("Number of watching clause on literal %ld is %ld\n",resolved_literal->sindex,resolved_literal->num_watched_clauses );
#endif
				//wait for a new decision
				continue;
			}
			else{
				//Get the watched clauses for the resolved literal
				for(unsigned long k = 0; k < resolved_literal->num_watched_clauses && contradiction_flag == 0; k++){
						//check dirty flag
						if(resolved_literal->list_of_dirty_watched_clauses[k] == 0) continue;

						Clause* wclause = sat_index2clause( resolved_literal->list_of_watched_clauses[k], sat_state);
						//TODO: Check if this actually works to skip the subsumed clauses
						//TODO: Enhance: we can only get the watched clauses that are not subsumed to speed it up and to avoid checking the unit clause
						if(wclause->is_subsumed)
							continue;

						unsigned long num_free_literals = 0;



						// I have to check the other watched literal
						Lit* the_other_watched_literal = NULL;
						if(resolved_literal->sindex == wclause->L1->sindex)
							the_other_watched_literal = wclause->L2;
						else if(resolved_literal->sindex == wclause->L2->sindex)
							the_other_watched_literal = wclause->L1;

						// FIXME the_other_watched_literal is not always set by this point
						// but is being dereferenced in the loop below
#ifdef DEBUG
						printf("Current watching clause = %ld\n", wclause->cindex);
				//printf("Before assertion, resolved literal %ld, wcluase 1 index=%ld, wclause 2 idx =%ld \n", resolved_literal->sindex, wclause->L1->sindex, wclause->L2->sindex );
				//print_all_clauses(sat_state);
#endif
						assert(the_other_watched_literal!=NULL);

						for(unsigned long l = 0; l < wclause->num_literals_in_clause; l++){
							//check for not resolved literal = free or asserted
							if( !sat_is_resolved_literal(wclause->literals[l])  && wclause->literals[l]->sindex != the_other_watched_literal->sindex  ) {
								num_free_literals++;
							}
						}

						if (num_free_literals == 0){ //3cases

							//contradiction --> everything is resolved
							//subsumed clause --> do nothing
							//implication --> free literal
							if(sat_is_resolved_literal(the_other_watched_literal)){

								// all literal of the clause are resolved --> contradiction
								contradiction_flag = 1;
#ifdef DEBUG
								printf("-------------Contradiction happens with clause: %ld in level: %ld\n",wclause->cindex, sat_state->current_decision_level);
#endif
								sat_state->conflict_clause = wclause;
								break; //break from loop of watched clauses over this decided literal
							}
							else if(sat_is_asserted_literal(the_other_watched_literal)){
								// we do nothing since this clause is subsumed

								wclause->is_subsumed = 1;
								contradiction_flag = 0; // just checking  if I have to reassign the value in order to avoid the compilation optimization
								continue;
							}
							else if (the_other_watched_literal->LitState == 0){
								// implication

								if(sat_literal_var(the_other_watched_literal)->antecedent == 0){

									sat_literal_var(the_other_watched_literal)->antecedent = wclause->cindex;  // remember the decision list is updated with the pending list so that's ok
#ifdef DEBUG
									printf("free literal %ld\n",the_other_watched_literal->sindex);
									//print_clause(wclause);
									printf("Antecedent: \n");
									print_clause(sat_index2clause(sat_literal_var(the_other_watched_literal)->antecedent, sat_state));
#endif
									add_literal_to_list(&pending_list,  the_other_watched_literal , &max_size_pending_list, &num_pending_lit);
#ifdef DEBUG
									printf("Add the free literal %ld to the pending list with antecedent %ld\n",the_other_watched_literal->sindex, (sat_literal_var(the_other_watched_literal)->antecedent) );
#endif
									continue; // go to the next clause
								}
								else { //this means I implied the opposite (contradiction) or the same literal again(redundancy) in another clause
									//TODO: first check if pending list contains the same literal, if yes then just continue to the next clause else contradiction
									BOOLEAN lit_is_already_in_pending = 0;
									for(unsigned long pendelem =0; pendelem<num_pending_lit; pendelem ++){
										if (pending_list[pendelem]->sindex == the_other_watched_literal->sindex)
											lit_is_already_in_pending =1;
									}
									if(lit_is_already_in_pending == 1)
										continue; //go to the next clause
									else{
										contradiction_flag= 1;
#ifdef DEBUG
										printf("free literal %ld\n",the_other_watched_literal->sindex);
										printf("-------------Contradiction(opposite implication) happens with clause: %ld\n",wclause->cindex);
#endif
										sat_state->conflict_clause = wclause;
										break; //break from loop of watched clauses over this decided literal
									}
								}
							} //end of the implication case
						} // end of the three cases

						else if (num_free_literals > 0) { // find another literal to watch that is free
							for(unsigned long z = 0; z < wclause->num_literals_in_clause; z++){
								if((!sat_is_resolved_literal(wclause->literals[z])) && wclause->literals[z] != wclause->L1 && wclause->literals[z] != wclause->L2){
									Lit* new_watched_lit = wclause->literals[z];
									//remove_watching_clause(k, resolved_literal);
									resolved_literal->list_of_dirty_watched_clauses[k] = 0;
									//add the watching clause to the free literal
									add_watching_clause(wclause, new_watched_lit);

									assert(resolved_literal->sindex == wclause->L1->sindex || resolved_literal->sindex == wclause->L2->sindex );
									// remove the resolved literal from the watch and update the clause watch list
									if(resolved_literal->sindex == wclause->L1->sindex)
										wclause->L1 = new_watched_lit;
									else if (resolved_literal->sindex == wclause->L2->sindex)
										wclause->L2 = new_watched_lit;
									break;
								}
							}
						} //end of else number of free literals > 0

				} //end of for for watched clauses over this decided literal

				//SALMA removed and the contradiction !=1
				if(num_pending_lit >0){
				// Pass over the pending list and add the literals to the decision while maintaining the level
					for(unsigned long i =0; i < num_pending_lit; i++){
						//evaluate the pending list to make sure we didn't miss a chance of contraction // if the contradiction flag is raised then the conflict clause is already set in this function
						//BOOLEAN fails = evaluate_delta(sat_state, pending_list, i+1); //up till this pending literal


						// pending literal was an already watched clause so the associated list of watching clauses is already handled
						// fix values of pending literal before putting in decision
							Lit* pending_lit = pending_list[i];

							//TODO: the decision level should be the same as the max level of the antecedent not the current level.
							//pending_lit->decision_level =  sat_state->current_decision_level; // this is so wrong ... this will affect the UIP learning at contradiction because of stopping condition
							unsigned long pending_lit_decision =0;
							Var* pending_var = sat_literal_var(pending_lit);
							Clause* pending_antecedent = sat_index2clause(pending_var->antecedent, sat_state);

							for(unsigned long indxant =0; indxant < pending_antecedent->num_literals_in_clause; indxant++ ){
								Var* current_var = sat_literal_var(pending_antecedent->literals[indxant]);
								if(current_var->index == pending_var->index)
									continue; //skip the var
								else if(pending_antecedent->literals[indxant]->decision_level > pending_lit_decision)
									pending_lit_decision = pending_antecedent->literals[indxant]->decision_level;
							}

							pending_lit->decision_level = pending_lit_decision;


							//TODO: this part is already done in evaluate delta
							if(pending_lit->sindex <0){
								pending_lit->LitValue = 0;
								pending_lit->LitState = 1;
								Lit* opposite_lit = sat_literal_var(pending_lit)->posLit;
								opposite_lit->LitValue = 0;
								opposite_lit->LitState = 1;
								opposite_lit->decision_level = pending_lit->decision_level;
							}
							else if(pending_lit->sindex >0){
								pending_lit->LitValue = 1;
								pending_lit->LitState = 1;
								Lit* opposite_lit = sat_literal_var(pending_lit)->negLit;
								opposite_lit->LitValue = 1;
								opposite_lit->LitState = 1;
								opposite_lit->decision_level = pending_lit->decision_level;
							}

		//					for(unsigned long i = 0; i< sat_literal_var(pending_lit)->num_of_clauses_of_variables; i++){
		//						Clause* clause = sat_literal_var(pending_lit)->list_clause_of_variables[i];
		//
		//					}



							//update the decision list
							sat_state->decisions[sat_state->num_literals_in_decision++] = pending_lit;

							//update list of literals in last decision because this is the main loop

							literals_list[num_elements++] = pending_lit;

	//					if (fails == 1){
	//						contradiction_flag = 1;
	//						break;
	//					}
					}
	//				//free pending list for the next round
	//				if(pending_list != NULL && num_pending_lit != 0)
	//					FREE(pending_list);

				} // pending_list > 1


			}//Get the watched clauses for the resolved literal

			//free pending list for the next round
			//--> pending list is related to each decided literal. so before taking a new decision clear the pending list
			//double free or corruption (out):
			if(pending_list != NULL && num_pending_lit != 0){
				//FREE(pending_list);
				// TODO: free pending list
				num_pending_lit = 0;
			}


			if(contradiction_flag == 1) // no need to go for another literal in the decided literal list
				break;

		}//end of for for decide literal

	}

	//TODO: This is so bad ... need to figure out why this sentence is executed even if I have a return when the contradiction happens
	//TODO: needs to find a way to clear the literals in last_decision
//	if(literals_in_last_decision != NULL && num_last_decision_lit !=0)
//		FREE(literals_in_last_decision);

	if(contradiction_flag == 1)
		return 0;
	else
		return 1;

}
Ejemplo n.º 3
0
static BOOLEAN evaluate_current_assignment(SatState* sat_state, Lit** pending_list, unsigned long num_pending_lit){
#ifdef DEBUG
	printf("Evaluate the current assignment\n");
#endif
	BOOLEAN fails = 0;

	// just for the sake of this function but will be reset if contradiction happens
	for(unsigned long i =0; i<num_pending_lit; i++){
		Lit* pending_lit = pending_list[i];
		if(pending_lit->sindex <0){
			pending_lit->LitValue = 0;
			pending_lit->LitState = 1;
		}
		else if(pending_lit->sindex >0){
			pending_lit->LitValue = 1;
			pending_lit->LitState = 1;
		}
	}

	Lit** decisions = sat_state->decisions;
	//now I have the current decision and the pending list
	// instead of merging the two list in one list just pass by each one
	for(unsigned long i =0; i<sat_state->num_literals_in_decision; i++){
#ifdef DEBUG
		printf("In the decision literals loop: current literal %ld \n", decisions[i]->sindex);
#endif
		Var* corresponding_var = sat_literal_var(decisions[i]);
		unsigned long* decision_clause_list = corresponding_var->list_clause_of_variables;


		for(unsigned long j=0; j<corresponding_var->num_of_clauses_of_variables; j++){

			Clause* clause = sat_index2clause(decision_clause_list[j], sat_state);

			//check clause
			for(unsigned long k = 0; k<clause->num_literals_in_clause;k++){
				//check if the literal is asserted or not yet set
				if(sat_is_asserted_literal(clause->literals[k]) || (!sat_implied_literal(clause->literals[k]) )){
					break; //don't check the other literals of the clause
				}
				else if(k== clause->num_literals_in_clause-1){ // I reached the end of the loop with no break (contradicted clause)
					fails = 1;
					sat_state->conflict_clause = clause;
					// reset the pending list
					for(unsigned long i =0; i<num_pending_lit; i++){
						Lit* pending_lit = pending_list[i];
						pending_lit->LitValue = 'u';
						pending_lit->LitState = 0;
					}
					return fails;
				}
			} // for all literals in a clause
		} // for all clauses for this variable
	}// for all variables in decision list


	//repeat the same for pending list
	for(unsigned long i =0; i< num_pending_lit; i++){
#ifdef DEBUG
		printf("In the pending literals loop: current literal %ld \n", pending_list[i]->sindex);
#endif
		Var* corresponding_var = sat_literal_var(pending_list[i]);
		unsigned long* pending_clause_list = corresponding_var->list_clause_of_variables;

		for(unsigned long j=0; j<corresponding_var->num_of_clauses_of_variables; j++){

			Clause* clause = sat_index2clause(pending_clause_list[j], sat_state);

			//check clause
			for(unsigned long k = 0; k<clause->num_literals_in_clause;k++){
				//check if the literal is asserted or not yet set
				if(sat_is_asserted_literal(clause->literals[k]) || (!sat_implied_literal(clause->literals[k]) )){
					break; //don't check the other literals of the clause
				}
				else if(k== clause->num_literals_in_clause-1){ // I reached the end of the loop with no break (contradicted clause)
					fails = 1;
					sat_state->conflict_clause = clause;
					// reset the pending list
					for(unsigned long i =0; i<num_pending_lit; i++){
						Lit* pending_lit = pending_list[i];
						pending_lit->LitValue = 'u';
						pending_lit->LitState = 0;
					}
					return fails;

				}
			} // for all literals in a clause
		} // for all clauses for this variable
	}// for all variables in pending list


//TODO: check do i have to unset all the literals in the pending list
#ifdef DEBUG
	if(fails == 1){
		printf("Contradiction happens in evaluating clauses in the pending list\n");
	}
#endif

	return fails;
}
Ejemplo n.º 4
0
//constructs a SatState from an input cnf file
SatState* sat_state_new(const char* file_name) {
	FILE *file;
	if (!(file = fopen(file_name, "r")))
		return NULL;
	SatState *sat_state = malloc(sizeof(SatState));
	while (!feof(file)) {
		if (fgetc(file) == 'p')
			break;
		while (fgetc(file) != '\n')
			continue;
	}
	fscanf(file, " cnf %lu %lu", &sat_state->varnum, &sat_state->clausenum);
	vector_init(&sat_state->vars);
	vector_init(&sat_state->plits);
	vector_init(&sat_state->nlits);
	vector_init(&sat_state->kb);
	vector_init(&sat_state->lc);
	vector_init(&sat_state->ds);
	vector_init(&sat_state->il);
	vector_init(&sat_state->q);
	vector_init(&sat_state->s);
	sat_state->ac = NULL;
	for (c2dSize i = 1; i <= sat_var_count(sat_state); i++) {
		Var* var = malloc(sizeof(Var));
		var->index = i;
		var->mark = 0;
		vector_init(&var->mentions);
		vector_init(&var->mentions_lc);
		Lit* plit = malloc(sizeof(Lit));
		plit->index = i;
		plit->implied = 0;
		plit->var = var;
		Lit* nlit = malloc(sizeof(Lit));
		nlit->index = -i;
		nlit->implied = 0;
		nlit->var = var;
		vector_push(&sat_state->plits, plit);
		vector_push(&sat_state->nlits, nlit);
		var->plit = plit;
		var->nlit = nlit;
		vector_push(&sat_state->vars, var);
	}
	for (c2dSize i = 1; i <= sat_clause_count(sat_state); i++) {
		Clause* clause = malloc(sizeof(Clause));
		clause->index = i;
		clause->subsumed = 0;
		clause->mark = 0;
		vector_init(&clause->lits);
		while (1) {
			c2dLiteral index;
			while (!fscanf(file, "%ld", &index) || (index == 0 && vector_size(&clause->lits) == 0)) {
				while (fgetc(file) != '\n')
					continue;
			}
			if (index == 0)
				break;
			vector_push(&clause->lits, sat_index2literal(index, sat_state));
		}
		vector_push(&sat_state->kb, clause);
		vector_push(&sat_state->q, clause);
	}
	for (c2dSize i = 1; i <= sat_clause_count(sat_state); i++) {
		Clause* clause = sat_index2clause(i, sat_state);
		for (c2dSize j = 0; j < sat_clause_size(clause); j++) {
			Lit* lit = vector_get(&clause->lits, j);
			Var* var = sat_literal_var(lit);
			if (vector_size(&var->mentions) == 0 || vector_top(&var->mentions) != clause)
				vector_push(&var->mentions, clause);
		}
	}
	fclose(file);
	return sat_state;
}
Ejemplo n.º 5
0
//applies unit resolution to the cnf of sat state
//returns 1 if unit resolution succeeds, 0 if it finds a contradiction
BOOLEAN sat_unit_resolution(SatState* sat_state) {
  Lit* ret_lit;
  Var* var;

  c2dLiteral tmp_value;
  Clause* conflict_clause = NULL;

  c2dSize f = 0, r = 0;
  Lit** tmp_lit_list = sat_state->tmp_lit_list;

  // Push the new decided literal
  if (sat_state->unit_resolution_s == UNIT_RESOLUTION_AFTER_DECIDING_LITERAL) {
    if (sat_state->num_decided_literals > 0) {
      tmp_lit_list[++r] = sat_state->decided_literals[sat_state->num_decided_literals-1];
    }
    if (sat_state->num_implied_literals > 0) {
      c2dSize i = sat_state->num_implied_literals - 1;
      while (sat_state->implied_literals[i]->decision_level == sat_state->cur_level) {
        tmp_lit_list[++r] = sat_state->implied_literals[i];
        if (i == 0) break;
        i--;
      }
    }
  }

  // Check whether has unit clause
  c2dSize start_clauses = 1;
  if (sat_state->unit_resolution_s == UNIT_RESOLUTION_AFTER_ASSERTING_CLAUSE) 
    start_clauses = sat_state->num_cnf_clauses + sat_state->num_learned_clauses;
  if (sat_state->unit_resolution_s == UNIT_RESOLUTION_AFTER_DECIDING_LITERAL)
    start_clauses = sat_state->num_cnf_clauses + sat_state->num_learned_clauses + 1;
  for (c2dSize i = start_clauses; i <= sat_state->num_cnf_clauses + sat_state->num_learned_clauses; i++) {
    Clause* clause = sat_index2clause(i, sat_state);
    tmp_value = check_clause(clause, &ret_lit);
    if (tmp_value == -1) {
      conflict_clause = clause;
      break;
    }
    if (tmp_value == 2) {
      instantiate_literal(ret_lit, sat_state->cur_level, clause);
      sat_state->implied_literals[sat_state->num_implied_literals++] = ret_lit;
      tmp_lit_list[++r] = ret_lit;
    }
  }

  if (conflict_clause == NULL) {
    // BFS, expands the implied literals
    while (f < r) {
      var = sat_literal_var(tmp_lit_list[++f]);
      for (c2dSize i = 0; i < var->num_clauses; i++) {
        tmp_value = check_clause(var->clauses[i], &ret_lit);
        if (tmp_value == -1) {
          conflict_clause = var->clauses[i];
          break;
        }
        if (tmp_value == 2) {
          instantiate_literal(ret_lit, sat_state->cur_level, var->clauses[i]);
          sat_state->implied_literals[sat_state->num_implied_literals++] = ret_lit;
          tmp_lit_list[++r] = ret_lit;
        }
      }
    }
  }

  if (conflict_clause == NULL) {
    // No conflict
    sat_state->asserted_clause = NULL;
    return 1;
  }

  // Has conflict, derives asserted clause  
  //
  // It follows the algorithm:
  //
  //    In implication graph, if the contradition happended at node n.
  //    then 
  //           { {n}   if n is root 
  //    C(n) = {
  //           { ePa(n) \union \union_{m \in Pa(n)} C(m)
  //    where Pa(n) are the parents of node n which are set at the same level as n
  //          ePa(n) are the parents of ndoe n set at earlier levels
  // 
  BOOLEAN* seen = sat_state->seen;
  for (c2dSize i = 1; i <= sat_state->num_vars; i++) seen[i] = 0;
  Lit** lit_list = sat_state->lit_list;
  c2dSize lit_list_sz = 0;

  f = 0, r = 0;
  for (c2dSize i = 0; i < conflict_clause->size; i++) {
    if (!seen[conflict_clause->literals[i]->var->index]) {
      tmp_lit_list[++r] = conflict_clause->literals[i]->op_lit;
      seen[conflict_clause->literals[i]->var->index] = 1;
    }
  }

  c2dSize assertion_level = 1;
  c2dSize dl;
  while (f < r) {
    Lit* lit = tmp_lit_list[++f];
    if (lit->decision_level < sat_state->cur_level ||
        lit->decision_clause == NULL) {
      lit_list[lit_list_sz++] = lit->op_lit;
      dl = lit->decision_level;
      if (dl < sat_state->cur_level && dl > assertion_level) {
        assertion_level = dl;
      }
    } else {
      for (c2dSize i = 0; i < lit->decision_clause->size; i++) {
        if (!seen[lit->decision_clause->literals[i]->var->index]) {
          tmp_lit_list[++r] = lit->decision_clause->literals[i]->op_lit;
          seen[lit->decision_clause->literals[i]->var->index] = 1;
        }
      }
    }
  }
  sat_state->asserted_clause = new_clause(0, lit_list_sz, lit_list);
  sat_state->asserted_clause->assertion_level = assertion_level;

  return 0;
}