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);
}
¡¡