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; }
SddNode* cfgStringSdd(SddManager* m, int nonTerminal, int terminal, int rules[][3], int start, int ruleCount, int* string, int len){ sdd_manager_auto_gc_and_minimize_off(m); 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); //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]]){ dy[i][j][rules[k][0]] = sdd_disjoin(dy[i][j][rules[k][0]],sdd_conjoin(dy[i][i+index][rules[k][1]],dy[i+index+1][j][rules[k][2]],m),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); sdd_manager_auto_gc_and_minimize_on(m); return dy[0][len-1][start]; } }
/* # of literals = term*len + nonTerm*len*(len+1)/2 first term*len literals: Terminal i corresponds to S(i/term,i%term) next nonTerm*len*(len+1)/2 correspond to non-terminals literal for T[i][j][k] = (j*(j+1)/2)*nonTerm+i*nonTerm+k + firstNon */ SddNode* sddParsings(SddManager*m, int nonTerm, int term, int nonRules[][3], int termRules[][2], int nonRuleCount, int termRuleCount, int start, int len){ SddNode* S[term][len]; int i,j,k,index; for(j = 0; j < len; j++){ for(i = 0; i < term; i++){ S[i][j] = sdd_manager_literal(j*term+i+1,m); for(k = 0; k < term; k++){ if (k != i){ S[i][j] = sdd_conjoin(sdd_manager_literal(0-(j*term+k+1),m),S[i][j],m); } } } } int firstNon = term*len+1; SddNode* T[len][len][nonTerm]; //set diagonal according to terminal rules for (index = 0;index < len; index++){ for(k = 0; k < nonTerm; k++){ T[index][index][k] = sdd_manager_false(m); } for(i = 0; i < termRuleCount; i++){ k = termRules[i][0]; int termVal = termRules[i][1]; T[index][index][k] = sdd_disjoin(T[index][index][k],S[termVal][index],m); } for(k = 0; k < nonTerm; k++){ T[index][index][k] = sdd_conjoin(T[index][index][k],sdd_manager_literal((index*(index+1)/2)*nonTerm+index*nonTerm+k + firstNon,m),m); for(j = 0; j < nonTerm; j++){ if (j != k){ T[index][index][k] = sdd_conjoin(T[index][index][k],sdd_manager_literal(0-((index*(index+1)/2)*nonTerm+index*nonTerm+j + firstNon),m),m); } } } } return T[0][0][0]; }
// returns an SDD node representing ( node1 => node2 ) SddNode* sdd_imply(SddNode* node1, SddNode* node2, SddManager* manager) { return sdd_disjoin(sdd_negate(node1,manager),node2,manager); }
int main(int argc, char** argv) { // set up vtree and manager SddLiteral var_count = 5; int auto_gc_and_minimize = 0; SddManager* m = sdd_manager_create(var_count,auto_gc_and_minimize); SddLiteral A = 1, B = 2, C = 3, faulty1 = 4, faulty2 = 5; SddNode* delta = sdd_manager_true(m); SddNode* alpha; ////////// CONSTRUCT KNOWLEDGE BASE ////////// // ~faulty1 => ( A <=> ~B ) alpha = sdd_equiv(sdd_manager_literal(A,m),sdd_manager_literal(-B,m),m); alpha = sdd_imply(sdd_manager_literal(-faulty1,m),alpha,m); delta = sdd_conjoin(delta,alpha,m); // faulty1 => ( ( A <=> B ) v ~B ) alpha = sdd_equiv(sdd_manager_literal(A,m),sdd_manager_literal(B,m),m); alpha = sdd_disjoin(alpha,sdd_manager_literal(-B,m),m); alpha = sdd_imply(sdd_manager_literal(faulty1,m),alpha,m); delta = sdd_conjoin(delta,alpha,m); // ~faulty2 => ( B <=> ~C ) alpha = sdd_equiv(sdd_manager_literal(B,m),sdd_manager_literal(-C,m),m); alpha = sdd_imply(sdd_manager_literal(-faulty2,m),alpha,m); delta = sdd_conjoin(delta,alpha,m); // faulty2 => ( ( B <=> C ) v ~C ) alpha = sdd_equiv(sdd_manager_literal(B,m),sdd_manager_literal(C,m),m); alpha = sdd_disjoin(alpha,sdd_manager_literal(-C,m),m); alpha = sdd_imply(sdd_manager_literal(faulty2,m),alpha,m); delta = sdd_conjoin(delta,alpha,m); ////////// PERFORM QUERY ////////// int* variables; SddLiteral health_vars = 2, health_vars_count, missing_health_vars; // make observations delta = sdd_condition(A,delta,m); delta = sdd_condition(-C,delta,m); // check if observations are normal SddNode* gamma; gamma = sdd_condition(-faulty1,delta,m); gamma = sdd_condition(-faulty2,gamma,m); int is_abnormal = gamma == sdd_manager_false(m); // sdd_node_is_false(gamma,m); printf("observations normal? : %s\n", is_abnormal ? "abnormal":"normal"); // project onto faults SddNode* diagnosis = sdd_exists(B,delta,m); // diagnosis no longer depends on variables A,B or C // count the number of diagnoses SddModelCount count = sdd_model_count(diagnosis,m); // adjust for missing faults variables = sdd_variables(diagnosis,m); health_vars_count = variables[faulty1] + variables[faulty2]; missing_health_vars = health_vars - health_vars_count; count <<= missing_health_vars; // multiply by 2^missing_health_vars free(variables); // find minimum cardinality diagnoses SddNode* min_diagnosis = sdd_minimize_cardinality(diagnosis,m); variables = sdd_variables(min_diagnosis,m); // adjust for missing faults if ( variables[faulty1] == 0 ) min_diagnosis = sdd_conjoin(min_diagnosis,sdd_manager_literal(-faulty1,m),m); if ( variables[faulty2] == 0 ) min_diagnosis = sdd_conjoin(min_diagnosis,sdd_manager_literal(-faulty2,m),m) ; free(variables); // count the number of minimum cardinality diagnoses, and minimum cardinality SddModelCount min_count = sdd_model_count(min_diagnosis,m); SddLiteral min_card = sdd_minimum_cardinality(min_diagnosis); printf("sdd model count : %"PRImcS"\n",count); printf("sdd model count (min) : %"PRImcS"\n",min_count); printf("sdd cardinality : %"PRIlitS"\n",min_card); ////////// SAVE SDDS ////////// printf("saving sdd and dot ...\n"); sdd_save("output/circuit-kb.sdd",delta); sdd_save("output/diagnosis.sdd",diagnosis); sdd_save("output/diagnosis-min.sdd",min_diagnosis); sdd_save_as_dot("output/circuit-kb.dot",delta); sdd_save_as_dot("output/diagnosis.dot",diagnosis); sdd_save_as_dot("output/diagnosis-min.dot",min_diagnosis); ////////// CLEAN UP ////////// sdd_manager_free(m); return 0; }