用逻辑类所作的一个反证法的实例

博客提供了Power Logic Applications的相关链接,即http://www3.sympatico.ca/qingzhehuang/LogicApp.htm 。

      Power Logic Applications

http://www3.sympatico.ca/qingzhehuang/LogicApp.htm

A.Fourth Edition
This is actually Fourth( Really? I don't remember clearly and who cares?) edition of my logic class. And it would be
more precise to call it an application. However, there is indeed some improvement with little code added but 
powerful function achieved!( Really? I guess I won't believe what I said myself.)
B. The problem to solve: 
I made little improvement to try to solve an logic proof in COMP238 sample test in other section. The problem is
like following:
//This is what we need to prove:
// [(p||t)&&(p-->q)&&(q-->r)&&(r-->s)&&(s-->t)] --> t
p,q,r,s,t are all propositional functions. And the problem suggests a proof by contradiction. Indeed, if you
don't go this way, it is quite difficult, at least very tedious. 
C. What is my approach?
I changed my major function "doAnalysing()" a little bit by adding a parameter of bool byContradiction to make
it look like "void doAnalysing(bool byContradiction = false)". So, when you want to prove by contradiction, 
simply pass a true parameter instead the default false parameter. Then in the implementation of the original 
function, I only compare the in-passing parameter and change the last result to be false to begin an analysing
if it is "proof by contradiction". That is it.
However, at first the program doesn't give correct outcome except only show that "t is false and all other is
unknown". This is quite normal as when program pass only once in formula, it won't make full use of newly-deducted
result of "t is false". How to make program to invoke new result as long as he gets it? Simply redo when there is
new discovery. That is what I did in changing the function "analysing" of class "Analyse". I simply add a 
recursive call of itself when "readStack()" return true which means the program did find new value and change it.
Originally I am so clever to write this "readStack()" as bool-return function. Now it proves it is worth the 
efforts!
D. Major function:
   A. void Analyse::analysing(bool byContradiction)
	Keep finding the "result" type in OpRec(the stack) and call "readStack", doing the analysing. Have to clear stack for 
	next expression checking. When "readStack()" returns true, recursively call analysing itself to restart 
	analysing job.
(want to know more about Logic and Analyse class function? click here to see Power Logic.)
E. Moral:
Once our great leader Chairman Mao taught us that "theory cannot be tested and developed unless it is combined with practice".
So, all the program I wrote needs to be put into practice to get qualified and developed.	
#include <iostream>

using namespace std;

const int StackLimit = 150;

enum LogicOp
{AND, OR, NOT, CONDITIONAL};

enum OpState
{Operand, Operator, Result};

enum LogicState
{Positive =1, Possible =0, Negative =-1};

bool operator == (LogicState self, LogicState dummy)
{
	return ((self - dummy) == 0);
}

//forward declaration
class Analyse;

char* OpStr[4] = {" AND ", " OR ", " NOT "," CONDITIONAL "};

class Logic
{
private:
	static Analyse* analyse;
	static bool status;
	static int logicCount;
	char* express;
	int index;
	LogicState state;
	void catName(char*, const char*, LogicOp); 
	static Logic* temp[100];
	static int tempCount;
	static Logic* TRUE;
	static Logic* FALSE;
	bool definedStatus;
	LogicState And(LogicState self, LogicState dummy);
	LogicState Or(LogicState self, LogicState dummy);
	LogicState Not(LogicState self);
	void pushStack(const Logic* self, const Logic* pDummy, LogicOp opCode); 
	Logic* getTemp() { return temp[tempCount -1];}
protected:
	void initialize();
	bool compare(const Logic& dummy);
	void uninitialize();
public:
	Analyse* getAnalyse();
	Logic(const char* newExpress, const LogicState value=Possible);
	~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(LogicState newState) { state = newState;}
	LogicState getState() const{ return state;}
	static const int count()  {return logicCount;}
	Logic& operator&&(Logic& dummy);
	Logic& operator||(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>>(Logic& dummy);
	void doAnalysing(bool byContradiction = false); 
	
};

union UNKNOWN
{
	LogicOp operator = (LogicOp dummy);
	Logic* operator = (const Logic* dummy);
	Logic* logic;
	LogicOp op;
};

struct OpRec
{
	OpState opType;
	union UNKNOWN unknown;
};


Logic* UNKNOWN::operator =(const Logic* dummy)
{
	logic = (Logic*)dummy;
	return logic;
}

LogicOp UNKNOWN::operator = (LogicOp dummy)
{
	op = dummy;
	return op;
}

class Analyse
{
private:
	bool analyAnd(Logic* op1, Logic* op2, Logic* result);
	bool analyOr(Logic* op1, Logic* op2, Logic* result);
	bool analyConditional(Logic* op1, Logic* op2, Logic* result);
	bool analyNot(Logic* op1, Logic* result);
	static OpRec* opStack[StackLimit];	
	int top;
	void clearStack();
	LogicOp findOpCode(int index);
	bool setNewOp(Logic* dummy, LogicState newValue);
	int findPreResult(int index);
	OpRec* getTop(){ if (top>0)  return opStack[top -1]; else return NULL;}
public:
	Analyse();
	~Analyse();
	void push(OpRec* newRec) {if (top<StackLimit) opStack[top++] = newRec;}
	OpRec* pop() {if (top>0) return opStack[--top];}
	bool readStack(int index);
	void analysing(bool byContradiction);
};

char* logicStr[3] = {"True", "Unknown", "False"};


//This is what we need to prove:
// [(p||t)&&(p-->q)&&(q-->r)&&(r-->s)&&(s-->t)] --> t

const int ElementNum = 5;

enum ElementIndex {P,Q,R,S,T};

Logic element[ElementNum];

char* factStr[ElementNum] = {"p","q","r","s","t"};

Logic& formular();



void displayResult();

void setFactStr();

int main()
{

	setFactStr();
	formular().doAnalysing(true);
	displayResult();
	return 0;
}


Logic& formular()
{
	return (((element[P]||element[T])&&(element[P]>>element[Q])&&(
		element[Q]>>element[R])&&(element[R]>>element[S])&&(element[S]>>
		element[T]))>>element[T]);
}


void setFactStr()
{
	for (int i=0; i< ElementNum; i++)
	{
		element[i].setExpress(factStr[i]);
	}
}

void displayResult()
{
	for (int i=0; i< ElementNum; i++)
	{
		cout<<"/nThe logic expression '"<<factStr[i]<<" 'is ";
		switch (element[i].getState())
		{
		case Positive:
			cout<<logicStr[0];
			break;
		case Possible:
			cout<<logicStr[1];
			break;
		case Negative:
			cout<<logicStr[2];
			break;
		}
		cout<<"/n";
	}
}




Analyse* Logic::getAnalyse()
{
	return analyse;
}


void Logic::doAnalysing(bool byContradiction)
{
	getAnalyse()->analysing(byContradiction);
}



int Analyse::findPreResult(int index)
{
	while (index > 0)
	{
		index -- ;
		if  (opStack[index]->opType== Result)
			return index;
	}
	return -1;
}

void Analyse::analysing(bool byContradiction)
{
	if (getTop()->opType!= Result)
	{
		cout<<"/nOpStack is not ended with Result:"<<endl;
			return ;
	}
	else
	{
	
		int i = top -1;
		if (!byContradiction)
		{
			opStack[i]->unknown.logic->setState(Positive);
		}
		else
		{
			opStack[i]->unknown.logic->setState(Negative);
		}

		while (i!= -1)
		{
			if (readStack(i))
			{
				analysing(byContradiction);
			}
			//readStack(i);
			i = findPreResult(i);		
		}
	}
	clearStack();
}



LogicOp Analyse::findOpCode(int index)
{
	int i = index;
	while (opStack[i]->opType != Operator)
	{
		i--;
	}
	return opStack[i]->unknown.op;
}

bool Analyse::readStack(int index)
{	
	bool result= false;
	LogicOp opCode;
	if (opStack[index]->opType != Result )
	{
		cout<<"Stack error!/n";
		return false;
	}
	opCode = findOpCode(index);
	switch (opCode)
	{
	case AND:
		result = analyAnd(opStack[index-3]->unknown.logic, 
			opStack[index - 1]->unknown.logic, 	opStack[index]->unknown.logic);
		break;
	case OR:
		result = analyOr(opStack[index-3]->unknown.logic, 
			opStack[index - 1]->unknown.logic, opStack[index]->unknown.logic);
		break;
	case CONDITIONAL:
		result = analyConditional(opStack[index-3]->unknown.logic, 
			opStack[index - 1]->unknown.logic, opStack[index]->unknown.logic);
		break;
	case NOT:
		result = analyNot(opStack[index -1]->unknown.logic, opStack[index]->unknown.logic);
		break;
	}
	return result;
}

bool Analyse::setNewOp(Logic* dummy, LogicState newValue)
{
	if (dummy->getState()!= newValue)
	{
		if (dummy->getState() != Possible)
		{
			cout<<"/nYou are changing expression '"<<dummy->getExpress()<<"' value!";
			return false;
		}
		else
		{
			dummy->setState(newValue);
			return true;
		}
	}
	else
		return false;
}

bool Analyse::analyAnd(Logic* op1, Logic* op2, Logic* result)
{
	bool newOp = false;
	switch (result->getState())
	{
	case Positive:
		if (op1->getState()==Negative||op2->getState()==Negative)
		{
			cout<<"/nThere is contradictive at:"<<result->getExpress();
			return false;
		}
	
		newOp =	setNewOp(op1, Positive) || setNewOp(op2 ,Positive);
			
		break;
	case Negative:
		if (op1->getState()==Positive&&op2->getState() == Positive)
		{
			cout<<"/nThere is contradictive at:"<<result->getExpress();
			return false;
		}
		if (op1->getState()==Positive)
		{
			newOp = setNewOp(op2, Negative);		
		}
		else
		{
			if (op2->getState() == Positive)
			{
				newOp = newOp || setNewOp(op1, Negative);
			}
		}
		break;
	case Possible:
		break;
	}
	return false;
}

bool Analyse::analyOr(Logic* op1, Logic* op2, Logic* result)
{
	bool newOp = false;
	switch(result->getState())
	{
	case Positive:
		if (op1->getState()==Negative && op2->getState()==Negative)
		{
			cout<<"/nThere is contradictive at:"<<result->getExpress();
			return false;
		}
		if (op1->getState() == Negative)
		{
			newOp = setNewOp(op2, Positive);
		}
		else
		{
			if (op2->getState() == Negative)
			{
				newOp = newOp || setNewOp(op1, Positive);
			}
		}
		break;
	case Negative:
		if (op1->getState()==Positive || op2->getState()== Positive)
		{
			cout<<"/nThere is contradictive at:"<<result->getExpress();
			return false;
		}
		break;
	case Possible:
		break;
	}
	return newOp;
}


bool Analyse::analyConditional(Logic* op1, Logic* op2, Logic* result)
{
	bool newOp = false;
	switch (result->getState())
	{
	case Positive:
		if (op1->getState()==Positive&& op2->getState()== Negative)
		{
			cout<<"/nThere is contradictive at:"<<result->getExpress();
			return false;
		}
		if (op1->getState()==Positive)
		{
			newOp = setNewOp(op2, Positive);
		}
		else
		{
			if (op2->getState() == Positive)
			{
				newOp = setNewOp(op1, Positive);
			}
		}
		break;
	case Negative:
		if (op1->getState() == Negative||op2->getState() == Positive)
		{
			cout<<"/nThere is contradictive at:"<<result->getExpress();
			return false;
		}
		newOp = setNewOp(op2, Negative);
		newOp = newOp || setNewOp(op1, Positive);
		break;
	case Possible:
		break;
	}
	return newOp;
}
	



bool Analyse::analyNot(Logic* op1, Logic* result)
{
	bool newOp = false;
	
	switch (result->getState())
	{
	case Positive:
		if (op1->getState() == Positive)
		{
			cout<<"/nThere is contradictive at:"<<result->getExpress();
			return false;
		}
		else
		{
			newOp = setNewOp(op1, Negative);
		}
		break;
	case Negative:
		if (op1->getState() == Negative)
		{
			cout<<"/nThere is contradictive at:"<<result->getExpress();
			return false;
		}
		else
		{
			newOp = setNewOp(op1, Positive);
		}
		break;
	case Possible:
		break;
	}
	return newOp;
}

	
Analyse* Logic::analyse = new Analyse;

OpRec* Analyse::opStack[StackLimit];

void Analyse::clearStack()
{
	for (int i =0; i< top; i++)
	{
		delete opStack[i];
	}
	top = 0;
}



Analyse::Analyse()
{
	top = 0;
}

Analyse::~Analyse()
{
	clearStack();
}

LogicState Logic::And(LogicState self, LogicState dummy)
{
	if (self!=dummy)
	{
		return (LogicState)(self*dummy);
	}
	else
	{
		return self;
	}
}

LogicState Logic::Or(LogicState self, LogicState dummy)
{
	return ((self>= dummy)?self: dummy);
}

LogicState Logic::Not(LogicState self)
{
	return (LogicState)(-1* self);
}



void Logic::prepare()
{
	for (int i=0; i< tempCount; i++)
	{
		free(temp[i]);
	}
	tempCount =0;
}



Logic& Logic::operator >>(Logic& dummy)
{
	char buffer[256];
	catName(buffer, dummy.getExpress(), CONDITIONAL);

	temp[tempCount] = new Logic(buffer);

	temp[tempCount]->setState(Or(Not(state), dummy.getState()));
	
	tempCount++;
	pushStack(this, &dummy, CONDITIONAL);

	return *temp[tempCount-1];		
}

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", Negative);

Logic& Logic::operator =(const Logic& dummy)
{
	setExpress(dummy.getExpress());
	setState(dummy.getState());
	return *this;
}

Logic* Logic::TRUE = new Logic("TRUE", Positive);;

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];
	OpRec* ptr;
	strcpy(buffer, OpStr[NOT]);
	strcat(buffer, getExpress());

	temp[tempCount] = new Logic(buffer);
	temp[tempCount]->setState(Not(getState()));

	tempCount++;
	
	ptr = new OpRec;
	ptr->opType = Operator;
	ptr->unknown = NOT;
	
	analyse->push(ptr);

	ptr = new OpRec;
	ptr->opType = Operand;
	ptr->unknown = this;

	analyse->push(ptr);

	ptr = new OpRec;
	ptr->opType = Result;
	ptr->unknown = temp[tempCount-1];

	analyse->push(ptr);

	return *temp[tempCount-1];	
}

void Logic::pushStack(const Logic* self, const Logic* pDummy, LogicOp opCode)
{
	OpRec* ptr;

	ptr = new OpRec;
	ptr->opType = Operand;
	ptr->unknown = self;
	analyse->push(ptr);

	ptr = new OpRec;
	ptr->opType = Operator;
	ptr->unknown = opCode;
	analyse->push(ptr);

	ptr = new OpRec;
	ptr->opType = Operand;
	ptr->unknown = pDummy;
	analyse->push(ptr);

	ptr = new OpRec;
	ptr->opType = Result;
	ptr->unknown = getTemp();
	analyse->push(ptr);
}
	

Logic& Logic::operator &&(Logic& dummy)
{
	char buffer[256];
	
	catName(buffer, dummy.getExpress(), AND);

	temp[tempCount] = new Logic(buffer);
	temp[tempCount]->setState(And(getState(),dummy.getState()));

	tempCount++;
	pushStack(this, &dummy, AND);

	return *temp[tempCount-1];
}

Logic& Logic::operator ||(Logic& dummy)
{
	char buffer[256];
	catName(buffer, dummy.getExpress(), OR);
	
	temp[tempCount] = new Logic(buffer);
	temp[tempCount]->setState(Or(getState(),dummy.getState()));

	tempCount++;
	pushStack(this, &dummy, OR);

	return *temp[tempCount-1];
}


int Logic::logicCount =0;

void Logic::initialize()
{
	express = NULL;
	state = Possible;
	definedStatus = false;
	setIndex(logicCount);
	logicCount++;
	status = false;
}

Logic::~Logic()
{

	if (!status)  //if you destroy one, then you destroy all!!!!!
	{
		uninitialize();
	}

	if (express!=NULL)
	{
		free(express);
	}
}

Logic::Logic(const char* newExpress, const LogicState 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);

}


                                   back.gif (341 bytes)       up.gif (335 bytes)         next.gif (337 bytes)

归结原理是谓词逻辑中一种强有力的证明方法,它在自动定理证明和机器推理中扮演着核心角色。为了深入理解如何应用归结原理,推荐参考《谓词逻辑在机器推理中的应用与归结原理》这一资料,它将为你提供理论知识和实战技巧,直接关联到你当前的问题。 参考资源链接:[谓词逻辑在机器推理中的应用与归结原理](https://wenku.youkuaiyun.com/doc/2r2i2efiyx?spm=1055.2569.3001.10343) 为了证明一个自然语言处理生成的定理,首先需要将自然语言表述的句子转换为谓词逻辑表达式。然后,通过应用归结规则来证明定理。具体步骤如下: 1. 将自然语言句子转换为谓词逻辑的表述形式。例如,如果自然语言句子是“所有诚实的人都是值得信赖的”,可以转换为谓词逻辑表达式为:∀x (Honest(x) → Trustworthy(x))。 2. 将已知事实和假设也转换为谓词逻辑的形式。例如,若知道“张三是诚实的”,则可以表达为:Honest(zhangsan)。 3. 应用归结原理,将上述表达式转化为标准形,并进行归结。标准形通常是消除了量词的子句形式。 4. 对于定理证明,我们通常需要构造一个否定的子句集,然后通过归结过程推导出一个矛盾,从而证明原定理的正确性。 以一个具体的实例来说明: 假设我们有一个定理:“如果一个人是诚实的,那么他是值得信赖的”,即: 假设P1: ∀x (Honest(x) → Trustworthy(x)) 现在需要证明定理G: ∀x (Honest(x) → Trustworthy(x)) 步骤如下: 1. 将P1转换为标准形子句集: C1: ¬Honest(x) ∨ Trustworthy(x) 2. 通过归结原理,我们从C1中取出子句¬Honest(x)和Trustworthy(x)。由于我们只需要证明G,所以可以直接将C1中的x用具体的实例(例如张三)替换,得到: C2: ¬Honest(zhangsan) ∨ Trustworthy(zhangsan) 3. 引入反证法,假设张三不值得信赖,即: C3: ¬Trustworthy(zhangsan) 4. 对C2和C3进行归结,得到矛盾: C4: ¬Honest(zhangsan) ∨ ¬Honest(zhangsan) 5. 由于C4是一个永真式(即自相矛盾的表达式),这意味着我们的假设C3是错误的,即张三实际上是值得信赖的。 6. 由于张三是任意选取的实例,我们可以推广到普遍情况,从而证明了定理G。 通过这个实例,我们可以看到归结原理在证明谓词逻辑中定理的直观应用。为了更深入地掌握归结原理及其在不同推理场景下的应用,建议详细阅读《谓词逻辑在机器推理中的应用与归结原理》,该资料不仅包含了基础理论,还有丰富的实例和练习,帮助你在机器推理领域更进一步。 参考资源链接:[谓词逻辑在机器推理中的应用与归结原理](https://wenku.youkuaiyun.com/doc/2r2i2efiyx?spm=1055.2569.3001.10343)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值