Are they consistent?
A. The problem:
R: "It is raining."
S: "It is snowing."
I: "I get ill."
W: "I get wet."
D: "I need a doctor."
H: "It is hot."
F: "I have a fevor."
Now I give you some facts which can be regarded as a collection of rules:
1) ~R|W (R->W) If it is raining, then I get wet.
2) R|W (~R->S) If it is not raining, then it is snowing.
3) ~R|~S (R->~S) If it is raining, then it is not snowing.
4) ~S|~H (S->~H) If it is snowing, then it is not hot.
5) ~W|H|I ( W->(H|I) ) If it is wet, then it is either hot or I get ill.
6) ~I|~F|D (I-> (~F|D) ) If I get ill, then I either don't have a fever or need a doctor.
7) F|~D ( ~F->~D ) If I do not have a fever, then I don't need a doctor.
8) ~S|~H ( S->~H ) If it is snowing, then it is not hot.
9) ~I|H|D ( I->(H|D) ) If I get ill then it is either hot or I need a doctor.
10) H|~I|~W|F ( (I&&W)->(H|F)) If I get both wet and ill then it is either hot
or I have a fever.
Suppose we have following facts:
1) R 2)~H
Can we make conclusion that D?
or in other words that suppose "it is raining" and "it is not hot", can we conclude that
"I need a doctor"?
The answer is NO! And the program outcome proves that.This wrong!
The answer is YES! And the program outcome proves that. The problem is that I missed a input in checking function 6---"D".
so the correct outcome is
here.
B.Second Edition
This is the second edition of my Logic class, I only write a simple test program to check if a collection of
propositions are in consistent or in other words if there is a proper truth value for each proposition to
satisfy all propositions.
1¡£ Basic idea: It is quite streight forward to test all possible combination of truth value of all propostions.
2¡£ Program design: I make all seven facts to be seven Logic class objects and assign them all possible
combinations of truth values by a "setupFacts()" function, then for each "state", I use 10 rule-checking functions
to check if the truth value can satisfy all rules. If no combination can satisfy all rule function, it proves no
solution and as I make a assumption of the conclusion "D is true", then it means "if D is true, no combination
to satisfy all rules". So "D cannot be true."
3¡£ Major function£º
A. bool setupFacts(); bool checkConsistent()
setupFacts() function is like a "slot machine" which gives all truth value combination to the Facts[7].
And later by function "checkConsistent()" assign all these truth values to element[7] which are 7 Logic
class objects. Please before call "checkConsistent()", I use 3 bool variable to store the "predefined"
truth value of "R, H, D".
B. void prepare()
This function is a painful choice, as I mentioned in last version that I made a new Logic objects whenever
there is an operation. For example: (element[D])&&(element[F])||(element[H]); each operation will create
a new temperary object and this is also the return value to make further operation. However, I record all
these objects in a private static array---static Logic* temp[100]. And 100 is not enough for this simple
program. Even 1000 is not enough! So you see there are too many in-process objects, I have to clear them
every time I start a new "rule checking".¡¡
4¡£ Further improvement£º
A. It is still a painful compromise for me to use temperary objects for return value of each operation.
B. For a time, I made up my mind to use object itself for return value, however, it changes expression of
itself which is not good.
#include <iostream>
using namespace std;
enum LogicOp {AND, OR, NOT, CONDITIONAL};
const ElementNum = 7;
char* OpStr[4] = {" AND ", " OR ", " NOT "," CONDITIONAL "};
enum ELEMENT {R,S,I,W,D,H,F};
char* factStr[7] = {"It is raining", "It is snowing", "I get ill","I get wet", "I need doctor", "It is hot", "I have a fevor"};
bool Facts[ElementNum] = {false};
class Logic { private: static bool status; static int logicCount; char* express; int index; bool state; void catName(char*, const char*, LogicOp); static Logic* temp[100]; static int tempCount; static Logic* TRUE; static Logic* FALSE; Logic* checkList[30]; bool definedStatus; protected: void initialize(); bool compare(const Logic& dummy); void uninitialize(); public: Logic(const char* newExpress, const bool value=false); ~Logic(); Logic(); void prepare(); bool getStatus() const {return definedStatus;} void setStatus(const bool newStatus) {definedStatus = newStatus;} void setExpress(const char*); char* getExpress() const {return express;} void setIndex(const int newIndex) { index = newIndex;} int getIndex() const {return index;} void setState(bool newState) { state = newState;} bool getState() const{ return state;} static const int count() {return logicCount;} Logic& operator&&(const Logic& dummy); Logic& operator||(const Logic& dummy); Logic& operator!(); bool operator==(const Logic& dummy); Logic& operator&&(const bool value); Logic& operator||(const bool value); Logic& operator=(const Logic& dummy); Logic& operator>>(const Logic& dummy); void addRule(const Logic* rule); };
Logic element[ElementNum];
bool setupFacts();
void setFactStr();
bool checkConsistent();
Logic& check1();
Logic& check2();
Logic& check3();
Logic& check4();
Logic& check5();
Logic& check6();
Logic& check7();
Logic& check8();
Logic& check9();
Logic& check10();
Logic& (* checkLists[10])() = {check1, check2, check3, check4, check5, check6, check7, check8, check9, check10};
void displayResult();
int main() { setFactStr(); if (!setupFacts()) cout<<"no hope\n";
return 0; }
void displayResult() { for (int i=0; i<ElementNum; i++) { cout<<"\n"<<factStr[i]<<" is "<<(Facts[i]?"true":"false")<<endl; } for (i=0; i< 10; i++) { cout<<((Logic&)(checkLists[i]())).getExpress()<<" is true\n"; } }
void setFactStr() { for (int i=0; i< ElementNum; i++) { element[i].setExpress(factStr[i]); } }
Logic& check1() { return (!element[R])||(element[W]); }
Logic& check2() { return (element[R])||(element[S]); }
Logic& check3() { return (!element[R])||(!element[S]); }
Logic& check4() { return (!element[S])||(!element[H]); }
Logic& check5() { return (!element[W])||(element[H])||(element[I]); }
Logic& check6() { return (!element[I])||(!element[F])||(element[D]); //this is reason of error in last time. }
Logic& check7() { return (element[F])||(!element[D]); }
Logic& check8() { return (!element[S])||(!element[H]); }
Logic& check9() { return (!element[I])||(element[H])||(element[D]); }
Logic& check10() { return (element[H])||(!element[I])||(!element[W])||(element[F]); }
bool checkConsistent() {
for (int i =0; i< ElementNum; i++) { element[i].setState(Facts[i]); }
for (int j=0; j<10; j++) { element[0].prepare(); if (!((checkLists[j]()).getState())) { return false; } } return true; }
bool setupFacts() { bool rec1, rec2, rec3; int i=0; while (i<ElementNum) { Facts[i] = !Facts[i]; while(!Facts[i]) { i++; if (i == ElementNum) { return false; }
Facts[i] = !Facts[i]; }
rec1 = Facts[R]; rec2 = Facts[H]; rec3 = Facts[D]; Facts[R] = true; Facts[H] = false; Facts[D] = true; if (checkConsistent()) { displayResult(); //return true; } Facts[R] = rec1; Facts[H] = rec2; Facts[D] = rec3;
i=0; } return false;
}
void Logic::prepare() { for (int i=0; i< tempCount; i++) { free(temp[i]); } tempCount =0; } Logic& Logic::operator >>(const Logic& dummy) { char buffer[256]; catName(buffer, dummy.getExpress(), CONDITIONAL);
temp[tempCount] = new Logic(buffer);
if (state&&(!dummy.getState())) { temp[tempCount]->setState(false); } else { temp[tempCount]->setState(true); } tempCount++; return *temp[tempCount-1];
/* temp->setExpress(buffer); if (state&&(!dummy.getState())) { temp->setState(false); } else { temp->setState(true); } return *this; */ }
void Logic::uninitialize() { status = true;
for (int i=0; i< tempCount;i++) { delete temp[i]; } }
bool Logic::status = false;
Logic* Logic::temp[100] = {NULL}; // = new Logic;
int Logic::tempCount = 0;
Logic* Logic::FALSE = new Logic("FALSE", false);
Logic& Logic::operator =(const Logic& dummy) { setExpress(dummy.getExpress()); setState(dummy.getState()); return *this; }
Logic* Logic::TRUE = new Logic("TRUE", true);;
Logic& Logic::operator &&(const bool value) { if (value) { return (*this)&&(*TRUE); } else { return (*this)&&(*FALSE); } }
Logic& Logic::operator ||(const bool value) { if (value) { return (*this)||(*TRUE); } else { return (*this)||(*FALSE); } }
bool Logic::operator ==(const Logic& dummy) { return compare(dummy); }
bool Logic::compare(const Logic& dummy) { return (index==dummy.getIndex()); }
void Logic::catName(char* buffer, const char* second, LogicOp opcode) { strcpy(buffer, getExpress()); strcat(buffer, OpStr[opcode]); strcat(buffer, second); }
Logic& Logic::operator !() { char buffer[256]; strcpy(buffer, OpStr[NOT]); strcat(buffer, getExpress()); /* temp->setExpress(buffer); temp->setState(!getState()); return *this; */ temp[tempCount] = new Logic(buffer); temp[tempCount]->setState(!getState());
tempCount++; return *temp[tempCount-1]; }
Logic& Logic::operator &&(const Logic& dummy) { char buffer[256]; catName(buffer, dummy.getExpress(), AND);
temp[tempCount] = new Logic(buffer); temp[tempCount]->setState(getState()&&dummy.getState());
tempCount++; return *temp[tempCount-1];
/* temp->setExpress(buffer); temp->setState(getState()&&dummy.getState()); return *this; */ }
Logic& Logic::operator ||(const Logic& dummy) { char buffer[256]; catName(buffer, dummy.getExpress(), OR);
temp[tempCount] = new Logic(buffer); temp[tempCount]->setState(getState()||dummy.getState());
tempCount++; return *temp[tempCount-1];
/* temp->setExpress(buffer); temp->setState(getState()||dummy.getState()); return *this; */ }
int Logic::logicCount =0;
void Logic::initialize() { express = NULL; state = false; definedStatus = false; setIndex(logicCount); logicCount++; }
Logic::~Logic() {
if (!status) //if you destroy one, then you destroy all!!!!! { uninitialize(); }
if (express!=NULL) { free(express); } }
Logic::Logic(const char* newExpress, const bool value) { initialize(); setExpress(newExpress); setState(value); }
Logic::Logic() { initialize(); }
void Logic::setExpress(const char* newExpress) { int i; i = strlen(newExpress) +1;
if (express==NULL) { express = (char*)malloc(i); } else { express = (char*)realloc((void*)express, i); }
strcpy(express, newExpress);
}
¡¡