// Add the specified clause to the solver void add_clause(vec<Lit>& clause) { #ifdef _DEBUG print_clause(clause); #endif for (int i = 0; i < clause.size(); i++) { while (var(clause[i]) >= _solver->nVars()) { _solver->newVar(); } } _solver->addClause(clause); }
static void print_clause_vector(FILE *f, clause_t **vector) { uint32_t i, n; if (vector != NULL) { n = get_cv_size(vector); for (i=0; i<n; i++) { print_clause(f, vector[i]); fputc('\n', f); } } }
static BOOLEAN evaluate_delta(SatState* sat_state, Lit** pending_list, unsigned long num_pending_lit){ BOOLEAN fails =0; #ifdef DEBUG printf("Evaluate delta loop: %ld at pending lit %ld \n",num_pending_lit, pending_list[num_pending_lit-1]->sindex ); #endif // 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]; pending_lit->decision_level = sat_state->current_decision_level; 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_state->num_clauses_in_delta; i++){ Clause* clause = &sat_state->delta[i]; //check clause BOOLEAN contradiction_found = 1; 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]) )){ contradiction_found = 0; break; //don't check the other literals of the clause } } // for all literals in a clause if(contradiction_found == 1){ fails = 1; sat_state->conflict_clause = clause; #ifdef DEBUG printf("In Evaluate Delta: \t"); print_clause(clause); #endif // for(unsigned long j = 0; j < num_pending_lit; j++){ // Lit* pending_lit = pending_list[j]; // pending_lit->LitValue = 'u'; // pending_lit->LitState = 0; // //SALMA added this // pending_lit->decision_level = 0; // if(pending_lit->sindex <0){ // Lit* opposite_Lit = sat_literal_var(pending_lit)->posLit; // opposite_Lit->LitValue = 'u'; // opposite_Lit->LitState = 0; // //SALMA added this // opposite_Lit->decision_level = 0; // }else{ // Lit* opposite_Lit = sat_literal_var(pending_lit)->negLit; // opposite_Lit->LitValue = 'u'; // opposite_Lit->LitState = 0; // //SALMA added this // opposite_Lit->decision_level = 0; // } // // } break; } }//end of for loop on clauses in delta #ifdef DEBUG printf("Contradiction_found = %d\n",fails); #endif return fails; }
/****************************************************************************** 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; }
void print_clause(FILE *fp, lst_node clause) { // A recursive function to print a clause as a string assert(clause); switch(clause->node_type) { case NULL_N : fprintf(fp, "{ } (empty clause)"); break; case FUNCTION_N : // Print it's name, open parentheses, recurse on parameters, and close parens fprintf(fp, "%s(", clause->value_string); for (lst_node curr = clause->left_child; curr != NULL; curr = curr->right_sib) { // Recurse on child print_clause(fp, curr); if (curr->right_sib) fprintf(fp, ", "); } fprintf(fp, ")"); break; case RELATION_N : // Print it's name, open parentheses, recurse on parameters, and close parens fprintf(fp, "%s(", clause->value_string); for (lst_node curr = clause->left_child; curr != NULL; curr = curr->right_sib) { // Recurse on child print_clause(fp, curr); if (curr->right_sib) fprintf(fp, ", "); } fprintf(fp, ")"); break; case SKOLEM_N : // Print it's name, open parentheses, recurse on parameters, and close parens fprintf(fp, "%s(", clause->value_string); for (lst_node curr = clause->left_child; curr != NULL; curr = curr->right_sib) { // Recurse on child print_clause(fp, curr); if (curr->right_sib) fprintf(fp, ", "); } fprintf(fp, ")"); break; case NEGATION_N : // print the negation sign, and then it's left child fprintf(fp, "~("); print_clause(fp, clause->left_child); fprintf(fp, ")"); break; case VARIABLE_N : // Print it's name only fprintf(fp, "%s", clause->value_string); break; case CONSTANT_N : // Print it's name only fprintf(fp, "%s", clause->value_string); break; case EQUALS_N: // Print it's first child, and equal sign, and then it's second child fprintf(fp, "("); print_clause(fp, clause->left_child); fprintf(fp, " = "); print_clause(fp, clause->left_child->right_sib); fprintf(fp, ")"); break; case DISJUNCTION_N: // Print it's first child, and equal sign, and then it's second child fprintf(fp, "("); print_clause(fp, clause->left_child); fprintf(fp, " v "); print_clause(fp, clause->left_child->right_sib); fprintf(fp, ")"); break; default : fprintf(fp, " SOMETHING_ELSE "); } }