Click here to Skip to main content
15,892,161 members
Articles / Desktop Programming / Win32

True Natural Language Understanding through a Conceptual Language Understanding Engine

Rate me:
Please Sign up or sign in to vote.
4.97/5 (55 votes)
11 Jan 201029 min read 68K   3.1K   118  
An article introducing an Artificial Intelligence technique that understands and manipulates concepts from text.
/*
The usage of this source code file, including but not limited to the reading, the compilation and 
redistribution, is subject to the license agreement detailed in the license.txt and license.pdf files
which accompany this source code. By proceeding to use this file you are acknowledging that you have
read either license.txt or license.pdf, and that you agree to be bound by the terms and conditions of
the license. If license.txt and license.pdf are not available, you are not licensed this file and you 
must delete it permanently; or contact the author at proy@conceptualspeech.com to obtain a copy of 
the license before proceeding to use this file.

Copyright Philippe Roy 2010 - proy@conceptualspeech.com.
*/

#include "stdafx.h"

#include <iostream>
#include <cstdlib>
#include <time.h>
#include <string>
#include <stdio.h>

#pragma warning( disable : 4251 )
#include "v8.h"

#include "StringUtils.h"
#include "DigitalConceptBuilder.h"
#include "POSList.h"
#include "POSTransformScript.h"
#include "Predicate.h"
#include "CalculationContext.h"
#include "KnowledgeBaseInferencePredicate.h"
#include "Parser.h"
#include "BottomUpParser.h"
#include "MultiDimEarleyParser.h"
#include "StackBasedContext.h"

#include "DebugDefinitions.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

using namespace v8;

using std::string;

#define KFEEDBACKWORDSTEPS 3000

#pragma warning( disable : 4290 )

DigitalConceptBuilder *DigitalConceptBuilder::m_singleton = NULL;

shared_auto_ptr<DigitalConceptBuilder> DigitalConceptBuilder::ConstructDigitalConceptBuilder(string dictionaryText, string dictionaryTree, string decisionFile, bool forceReset) throw(FileErrorException)
{
	if (!forceReset)
	{
		try
		{
			DigitalConceptBuilder *dReturn = new DigitalConceptBuilder(dictionaryTree, decisionFile);
			if (dReturn->m_runningState)
			{
				return shared_auto_ptr<DigitalConceptBuilder>(dReturn);
			}
			else
			{
				delete dReturn;
			}
		}
		catch (...) {}
	}
	DigitalConceptBuilder *dReturn = new DigitalConceptBuilder(dictionaryText, dictionaryTree, decisionFile);
	return shared_auto_ptr<DigitalConceptBuilder>(dReturn);
}

DigitalConceptBuilder::DigitalConceptBuilder(string dictionaryTree, string decisionFile) throw(FileErrorException):
m_POS_Dictionary(dictionaryTree), m_decisionFileName(dictionaryTree + "_flat.txt"), m_runningState(false), m_curCalculationContext(0)
{
	m_singleton = this;
	{
		POSEntry::Reset();
		ifstream dInputStream((dictionaryTree + "_POSDesc.txt").c_str(), ios::in | ios::binary);
		dInputStream.unsetf(ios::skipws);
		string dBuffer;
		char dChar;
		while (dInputStream >> dChar)
		{
			switch (dChar)
			{
				case '\n':
				case '\r':
					if (dBuffer.length() > 0)
					{
						// By creating the POSEntry in the same order, we ensure the values are the same as once the
						// dictionary was created.
						POSEntry dTmpEntry(dBuffer);
					}
					dBuffer = "";
					break;
				default:
					dBuffer += dChar;
			}
		}
		if (POSEntry::StatGetDescriptor(0) == "")
		{
			// m_runningState will stay false as we return now.
			return;
		}
	}
	POSTransformScript::ManageSyntacticDecisions(decisionFile, m_decisionFileName);
	ifstream dInputStream((dictionaryTree + "_POSData.txt").c_str(), ios::in | ios::binary);
	dInputStream.unsetf(ios::skipws);
	string dBuffer;
	char dChar;
	while (dInputStream >> dChar)
	{
		switch (dChar)
		{
			case '\n':
			case '\r':
				if (dBuffer.length() > 0)
				{
					m_data.push_back(dBuffer);
				}
				dBuffer = "";
				break;
			default:
				dBuffer += dChar;
		}
	}
	m_runningState = true;
}

DigitalConceptBuilder::DigitalConceptBuilder(string dictionaryText, string dictionaryTree, string decisionFile) throw(FileErrorException):
m_POS_Dictionary(kNODESIZE), m_decisionFileName(dictionaryTree + "_flat.txt"), m_runningState(false), m_curCalculationContext(0)
{
	m_singleton = this;
	BuildDictionary(dictionaryText, dictionaryTree);
	POSTransformScript::ManageSyntacticDecisions(decisionFile, m_decisionFileName);
	m_runningState = true;
}

shared_auto_ptr<CalculationContext> DigitalConceptBuilder::GetCurCalculationContext()
{
	if ((m_singleton != NULL) && (m_singleton->m_curCalculationContext >= 0) && (m_singleton->m_curCalculationContext < (int)m_singleton->m_testCases.size()))
	{
		return m_singleton->m_testCases[m_singleton->m_curCalculationContext];
	}
	else
	{
		exception dError("Context out of range.");
		throw(dError);
	}
}

void DigitalConceptBuilder::CleanupDictionary(string dictionaryTree)
{
	remove(dictionaryTree.c_str());
	remove((dictionaryTree + "_POSDesc.txt").c_str());
	remove((dictionaryTree + "_POSData.txt").c_str());
}

void DigitalConceptBuilder::BuildDictionary(string dictionaryText, string dictionaryTree)
{
	try
	{
		clock_t dClock;
		dClock = clock();
		{
			POSEntry::Reset();
			ifstream dInputStream(dictionaryText.c_str(), ios::in | ios::binary);
			dInputStream.unsetf(ios::skipws);
			vector<long> counts;
			vector<string> parts;
			string dWord;
			string dLastWord;
			string dPOSString;
			string dBuffer;
			unsigned long wordsCount = 0;
			unsigned long posCount = 0;
			unsigned long wordsStep = 0;
			char dChar;
			printf("Unless you explicitely instruct otherwise, this should happen only once.\nBuilding dictionary...\n");
			while (dInputStream >> dChar)
			{
				switch (dChar)
				{
					case ':':
						parts.push_back(dBuffer);
						dBuffer = "";
						break;
					case '\n':
					case '\r':
						{
							parts.push_back(dBuffer);
							if (parts.size() > 2)
							{
								posCount++;
								string usePos = parts[2];
								vector<string> matches;
								int dData = -1;
								if (PatternMatch(usePos, "*(*)", &matches, false) == 2)
								{
									usePos = matches[0];
									for (unsigned int i = 0; i < m_data.size(); i++)
									{
										if (m_data[i] == matches[1])
										{
											dData = i;
											break;
										}
									}
									if (dData == -1)
									{
										dData = m_data.size();
										m_data.push_back(matches[1]);
									}
								}
								POSEntry dPosEntry(usePos);
								if (counts.size() <= (unsigned int)dPosEntry.GetValue())
								{
									counts.resize(dPosEntry.GetValue() + 1);
								}
								counts[dPosEntry.GetValue()]++;
								StoredPOSNode dPOSNode(usePos, dData);
								wordsStep++;
								UppercaseString(parts[0]);
								if (m_POS_Dictionary.HasData(parts[0]))
								{
									m_POS_Dictionary[parts[0]].Add(usePos, dData);
								}
								else
								{
									wordsCount++;
									m_POS_Dictionary[parts[0]] = dPOSNode;
								}
								if (wordsStep == KFEEDBACKWORDSTEPS)
								{
									for (unsigned int i = 0; i < dLastWord.length(); i++)
									{
										originalprintf("\b");
										originalprintf(" ");
										originalprintf("\b");
									}
									wordsStep = 0;
									dLastWord = parts[0];
									originalprintf(dLastWord.c_str());
								}
							}
							parts.clear();
							dBuffer = "";
						}
						break;
					default:
						dBuffer += dChar;
				}
			}
			dInputStream.close();
			for (unsigned int i = 0; i < dLastWord.length(); i++)
			{
				printf("\b");
				printf(" ");
				printf("\b");
			}
			printf("\nDictionary built with %lu words (%lu parts-of-speech) into %lu nodes.\n", wordsCount, posCount, m_POS_Dictionary.GetNodesCount());
			printf("Expected size is %lu.\n", m_POS_Dictionary.GetHeaderSize() + (m_POS_Dictionary.GetNodesCount() * m_POS_Dictionary.OneNodeLength()));
			printf("\nComposition is as following:\n\n");
			for (unsigned int i = 0; i < counts.size(); i++)
			{
				printf("\t%s : %d\n", POSEntry::StatGetDescriptor(i).c_str(), counts[i]);
			}
			printf("\n");
			printf("Saving dictionary...\n");
			m_POS_Dictionary.Save(dictionaryTree.c_str());
			printf("Dictionary saved.\n\n");
			fstream dOutputStream;
			dOutputStream.open((dictionaryTree + "_POSData.txt").c_str(), ios::out | ios::binary | ios::trunc);
			for (unsigned int i = 0; i < m_data.size(); i++)
			{
				dOutputStream << m_data[i].c_str();
				dOutputStream << "\r\n";
			}
			dOutputStream.close();
			dOutputStream.open((dictionaryTree + "_POSDesc.txt").c_str(), ios::out | ios::binary | ios::trunc);
			int dValue = 0;
			while (true)
			{
				string dDescriptor = POSEntry::StatGetDescriptor(dValue);
				if (dDescriptor == "")
				{
					break;
				}
				dOutputStream << dDescriptor.c_str();
				dOutputStream << "\r\n";
				dValue++;
			}
			dOutputStream.close();
		}
	}
	catch (fstream::failure &f)
	{
		cout << "Failure exception caught: " << f.what() << "\n";
	}
	catch (...)
	{}
}

IndexStructure<StoredPOSNode> *DigitalConceptBuilder::GetDictionary()
{
	return &m_POS_Dictionary;
}

DigitalConceptBuilder::~DigitalConceptBuilder() 
{
	m_singleton = NULL;
}

string DigitalConceptBuilder::GetCurSequence()
{
	return FormattedString("%s:%d", GetCurCalculationContext()->GetId().c_str(), CPredicate::GetPermutationCount());
}

bool DigitalConceptBuilder::IsDelimitor(char dChar)
{
	return ((tolower(dChar) == toupper(dChar)) && (!((dChar >= '0') && (dChar <= '9'))));
}

bool DigitalConceptBuilder::PassedDefinitionRequirement(shared_auto_ptr<POSNode> dNode, bool needsDefinition)
{
	if (!needsDefinition)
	{
		return true;
	}
	string res = CPredicate::LocatePredicateBuilderScript(dNode->GetSpelling(), eCalculatingWordScript);
	return (((res != "") && (res.find("case \"" + dNode->GetPOSEntry().GetDescriptor() + "\":") != -1)) ||
		(CPredicate::LocatePredicateBuilderScript(dNode->GetPOSEntry().GetDescriptor(), eCalculatingPOSScript) != ""));
}

shared_auto_ptr<POSList> DigitalConceptBuilder::Tokenize(string dContent, 
														 string posNumbers, 
														 string posPunctuation, 
														 string punctuationAllowed,
														 bool definitionNeeded)
{
	struct TokenizationPath
	{
		TokenizationPath(shared_auto_ptr<IndexStructureNodePosition<StoredPOSNode>> dPosition, unsigned int dStartIndex): m_position(dPosition), m_startIndex(dStartIndex) {}
		shared_auto_ptr<IndexStructureNodePosition<StoredPOSNode>> m_position;
		unsigned int m_startIndex;
	};
	unsigned int dWordIndex = 0;
	shared_auto_ptr<POSList> dReturn = shared_auto_ptr<POSList>(new POSList(true));
	string dNumberBuffer;
	vector<TokenizationPath> activePaths;
	vector<POSNode*> floatingBridges;
	int latestBridge = -1;
	for (unsigned int i = 0; i <= dContent.length(); i++)
	{
		bool isAllowedPunctuation = false;
		string dCharStr = "";
		if (i < dContent.length())
		{
			dCharStr += dContent.c_str()[i];
			if ((posPunctuation.length()) && (punctuationAllowed.find(dCharStr) != string.npos))
			{
				isAllowedPunctuation = true;
				latestBridge = i;
			}
		}
		activePaths.push_back(TokenizationPath(shared_auto_ptr<IndexStructureNodePosition<StoredPOSNode>>(new IndexStructureNodePosition<StoredPOSNode>(m_POS_Dictionary.GetTopNode())), i));
		for (unsigned int j = 0; j < activePaths.size(); j++)
		{
			if ((activePaths[j].m_position.get() != NULL) && (activePaths[j].m_position->get() != NULL) && (activePaths[j].m_position->get()->m_data != NULL))
			{
				if ((i == dContent.length()) || (IsDelimitor(dContent.c_str()[i])))
				{
					string dKey = activePaths[j].m_position->GetNode()->GetKey();
					if ((i < dKey.length()) || (IsDelimitor(dContent.c_str()[i - dKey.length() - 1])))
					{
						StoredPOSNode *dPOS = activePaths[j].m_position->get();
						for (int k = 0; k < kMAXPOSALLOWED; k++)
						{
							if (dPOS->m_pos[k] != -1)
							{
								shared_auto_ptr<POSNode> candidate = POSNode::Construct("["+POSEntry::StatGetDescriptor(dPOS->m_pos[k]) + " & \"" + dKey + "\"]", NULL, activePaths[j].m_startIndex, i-1, 0, (dPOS->m_data[k] != -1)?m_data[dPOS->m_data[k]]:"");
								if (PassedDefinitionRequirement(candidate, definitionNeeded))
								{
									POSNode *dNewNode = dReturn->AddToPOSList(candidate);
									if (dNewNode != NULL)
									{
										floatingBridges.push_back(dNewNode);
									}
									latestBridge = activePaths[j].m_startIndex;
								}
							}
						}
					}
				}
			}
			if ((latestBridge != -1) && (((i < dContent.length()) && (!IsDelimitor(dContent.c_str()[i]))) || (i == dContent.length()) || (isAllowedPunctuation)))
			{
				bool atLeastOneAdded = false;
				for (int l = (floatingBridges.size() - 1); l >= 0; l--)
				{
					if ((floatingBridges[l]->GetBridgePosition() == 0) && (floatingBridges[l]->GetStartPosition() != latestBridge))
					{
						atLeastOneAdded = true;
						floatingBridges[l]->SetWordIndex(dWordIndex);
						floatingBridges[l]->SetBridgePosition(latestBridge);
						floatingBridges.erase(floatingBridges.begin() + l);
					}
				}
				if (atLeastOneAdded)
				{
					dWordIndex++;
				}
				if (isAllowedPunctuation)
				{
					shared_auto_ptr<POSNode> candidate = POSNode::Construct("[" + posPunctuation + " & \"" + dCharStr + "\"]", NULL, i, i, 0);
					if (PassedDefinitionRequirement(candidate, definitionNeeded))
					{
						POSNode *dNewNode = dReturn->AddToPOSList(candidate);
						if (dNewNode != NULL)
						{
							floatingBridges.push_back(dNewNode);
						}
						latestBridge = i;
					}
				}
				else
				{
					latestBridge = -1;
				}
			}
			if (i == dContent.length())
			{
				break;
			}
			shared_auto_ptr<IndexStructureNodePosition<StoredPOSNode>> dNewPosition = m_POS_Dictionary.ForwardNodeOneChar(activePaths[j].m_position, toupper(dContent.c_str()[i]));
			if (dNewPosition.get() != NULL)
			{
				activePaths[j].m_position = dNewPosition;
			}
			else
			{
				activePaths[j].m_position->Clear();
			}
		}
		if ((posNumbers.length() > 0) && ((dContent.c_str()[i] >= '0') && (dContent.c_str()[i] <= '9') || ((dContent.c_str()[i] == '.') && (dContent.length() > 0))))
		{
			if ((i == 0) || (dNumberBuffer.length() > 0) || (IsDelimitor(dContent.c_str()[i-1])))
			{
				dNumberBuffer += dContent.c_str()[i];
			}
		}
		else if (dNumberBuffer.length() > 0)
		{
			shared_auto_ptr<POSNode> candidate = POSNode::Construct("["+posNumbers + " & \"" + dNumberBuffer + "\"]", NULL, i - dNumberBuffer.length(), i - 1, 0);
			if (PassedDefinitionRequirement(candidate, definitionNeeded))
			{
				POSNode *dNewNode = dReturn->AddToPOSList(candidate);
				if (dNewNode != NULL)
				{
					floatingBridges.push_back(dNewNode);
				}
				latestBridge = i - dNumberBuffer.length();
				dNumberBuffer = "";
			}
		}
		for (int j = (activePaths.size() - 1); j >= 0; j--)
		{
			if ((activePaths[j].m_position.get() == NULL) || (activePaths[j].m_position->GetNode().get() == NULL))
			{
				activePaths.erase(activePaths.begin() + j);
			}
		}
	}
	for (int l = (floatingBridges.size() - 1); l >= 0; l--)
	{
		floatingBridges[l]->SetWordIndex(dWordIndex);
	}
	return dReturn;
}

void InspectWord(IndexStructure<StoredPOSNode> *dict, string dWord)
{
	shared_auto_ptr< IndexStructureNodePosition<StoredPOSNode> > dPosition = new IndexStructureNodePosition<StoredPOSNode>(dict->GetTopNode());
	for (unsigned int j = 0; j < dWord.length(); j++)
	{
		dPosition = dict->ForwardNodeOneChar(dPosition, toupper(dWord.c_str()[j]));
	}
	StoredPOSNode *dPOS = dPosition->get();
	printf("*** Inspection of word %s\n", dWord.c_str());
	for (int i = 0; i < kMAXPOSALLOWED; i++)
	{
		if (dPOS->m_pos[i] != -1)
		{
			printf("%s", POSEntry::StatGetDescriptor(dPOS->m_pos[i]).c_str());
			printf("\n");
		}
	}
}

void DigitalConceptBuilder::RunTestCase(Persistent<Context> context, shared_auto_ptr<POSTransformScript> dTransform)
{
	clock_t startTime = clock();
	printf("\nEvaluating: \"%s\" (ID:%s)\n", GetCurCalculationContext()->GetDigitalInput().c_str(), GetCurCalculationContext()->GetId().c_str());
	shared_auto_ptr<POSList> dList = Tokenize(GetCurCalculationContext()->GetDigitalInput(), 
		GetCurCalculationContext()->GetNumberPOS(), 
		GetCurCalculationContext()->GetPunctuationPOS(), 
		GetCurCalculationContext()->GetPunctuation(),
		GetCurCalculationContext()->GetNeedsDefinition());
	if (GetCurCalculationContext()->OutputBeforeSyntaxAnalysis())
	{
		printf("\nTokens before syntactic analysis:\n\n");
		dList->Output();
	}
	shared_auto_ptr<Parser> useParser;
	switch (GetCurCalculationContext()->GetParsingMethod())
	{
		case CalculationContext::eBottomUp:
			useParser = shared_auto_ptr<Parser>(new BottomUpParser(dTransform));
			break;
		case CalculationContext::eMultiDimEarley:
			useParser = shared_auto_ptr<Parser>(new MultiDimEarleyParser(dTransform));
			break;
	}
	useParser->ParseList(dList);
	string dSyntacticTime = GetTimeSpentStr(GetDeltaTimeSpent(&startTime));
	if (GetCurCalculationContext()->OutputAfterSyntaxAnalysis())
	{
		printf("\nTokens after syntactic analysis:\n\n");
		dList->Output();
	}
	clock_t startTime2 = clock();
	CPredicate::PerformConceptualAnalysis(context, dList);
	string dConceptualTime = GetTimeSpentStr(GetDeltaTimeSpent(&startTime2));
	if (GetCurCalculationContext()->OutputTimeSpent())
	{
		printf("\n  Total time: %s\n   Syntactic: %s\n  Conceptual: %s.\n", GetTimeSpentStr(GetDeltaTimeSpent(&startTime)).c_str(), dSyntacticTime.c_str(), dConceptualTime.c_str());
	}
}

void DigitalConceptBuilder::RunTestCases(Persistent<Context> context)
{
	shared_auto_ptr<POSTransformScript> dTransform(new POSTransformScript());
	dTransform->BuildFromFile(m_decisionFileName);
	for (m_curCalculationContext = 0; m_curCalculationContext < (int)m_testCases.size(); m_curCalculationContext++)
	{
		if (GetCurCalculationContext()->Enabled())
		{
			RunTestCase(context, dTransform);
		}
	}
	CPredicate::PerformPredicateGarbageCollection();
}

void DigitalConceptBuilder::AddTestCases(vector< shared_auto_ptr< CalculationContext > > dTestCases)
{
	for (unsigned int i = 0; i < dTestCases.size(); i++)
	{
		m_testCases.push_back(dTestCases[i]);
	}
}

void PredicateCalculusTest()
{
	string dConclusion;

	// A car.
	shared_auto_ptr<CPredicate> dCarPredicate(new CPredicate());
	dCarPredicate.get()->SetPredicateString("PP[TYPE:VEHICULE/CLASS:CAR]");
	printf("\"A car\":\n\n%s\n\n", dCarPredicate->ToString().c_str());

	// A red car.
	shared_auto_ptr<CPredicate> dRedCarPredicate(new CPredicate());
	dRedCarPredicate.get()->SetPredicateString("PP[TYPE:VEHICULE/CLASS:CAR/COLOR:RED]");
	printf("\"A red car\":\n\n%s\n\n", dRedCarPredicate->ToString().c_str());
	printf("\tIs a red car a car?: %s\n\n", CPredicate::IsTest(dRedCarPredicate, dCarPredicate).c_str());
	printf("\tIs a car a red car?: %s\n\n", CPredicate::IsTest(dCarPredicate, dRedCarPredicate).c_str());

	// A car of undefined color.
	shared_auto_ptr<CPredicate> dUndefinedColorCarPredicate(new CPredicate());
	dUndefinedColorCarPredicate.get()->SetPredicateString("PP[TYPE:VEHICULE/CLASS:CAR/COLOR:{NULL}]");
	printf("\"A car of undefined color\":\n\n%s\n\n", dUndefinedColorCarPredicate->ToString().c_str());
	printf("\tIs a car of undefined color a car?: %s\n\n", CPredicate::IsTest(dUndefinedColorCarPredicate, dCarPredicate).c_str());
	printf("\tIs a car a car of undefined color?: %s\n\n", CPredicate::IsTest(dCarPredicate, dUndefinedColorCarPredicate).c_str());
	printf("\tIs a car of undefined color a red car?: %s\n\n", CPredicate::IsTest(dUndefinedColorCarPredicate, dRedCarPredicate).c_str());
	printf("\tIs a red car a car of undefined color?: %s\n\n", CPredicate::IsTest(dRedCarPredicate, dUndefinedColorCarPredicate).c_str());

	// A car of defined color.
	shared_auto_ptr<CPredicate> dDefinedColorPredicate(new CPredicate());
	dDefinedColorPredicate.get()->SetPredicateString("PP[TYPE:VEHICULE/CLASS:CAR/COLOR:{DEFINED}]");
	printf("\"A car of defined color\":\n\n%s\n\n", dDefinedColorPredicate->ToString().c_str());
	printf("\tIs a car of defined color a car?: %s\n\n", CPredicate::IsTest(dDefinedColorPredicate, dCarPredicate).c_str());
	printf("\tIs a car a car of defined color?: %s\n\n", CPredicate::IsTest(dCarPredicate, dDefinedColorPredicate).c_str());
	printf("\tIs a car of defined color a red car?: %s\n\n", CPredicate::IsTest(dDefinedColorPredicate, dRedCarPredicate).c_str());
	printf("\tIs a red car a car of defined color?: %s\n\n", CPredicate::IsTest(dRedCarPredicate, dDefinedColorPredicate).c_str());

	// A colored car.
	shared_auto_ptr<CPredicate> dColoredCarPredicate(new CPredicate());
	dColoredCarPredicate.get()->SetPredicateString("PP[TYPE:VEHICULE/CLASS:CAR/COLOR:{COLOR}]");
	printf("\"A colored car\":\n\n%s\n\n", dColoredCarPredicate->ToString().c_str());
	dConclusion = CPredicate::IsTest(dColoredCarPredicate, dCarPredicate);
	printf("\tIs a colored car a car?: %s, variables: %s\n\n", dConclusion.c_str(), CPredicate::GetVariablesString(dColoredCarPredicate).c_str());
	dConclusion = CPredicate::IsTest(dCarPredicate, dColoredCarPredicate);	
	printf("\tIs a car a colored car?: %s, variables: %s\n\n", dConclusion.c_str(), CPredicate::GetVariablesString(dCarPredicate).c_str());
	dConclusion = CPredicate::IsTest(dColoredCarPredicate, dRedCarPredicate);	
	printf("\tIs a colored car a red car?: %s, variables: %s\n\n", dConclusion.c_str(), CPredicate::GetVariablesString(dColoredCarPredicate).c_str());
	dConclusion = CPredicate::IsTest(dRedCarPredicate, dColoredCarPredicate);
	printf("\tIs a red car a colored car?: %s, variables: %s\n\n", dConclusion.c_str(), CPredicate::GetVariablesString(dRedCarPredicate).c_str());

	// A car that is not red.
	shared_auto_ptr<CPredicate> dNotRedCarPredicate(new CPredicate());
	dNotRedCarPredicate.get()->SetPredicateString("PP[TYPE:VEHICULE/CLASS:CAR/COLOR:!RED]");
	printf("\"A car that is not red\":\n\n%s\n\n", dNotRedCarPredicate->ToString().c_str());
	dConclusion = CPredicate::IsTest(dNotRedCarPredicate, dCarPredicate);
	printf("\tIs a car that is not red a car?: %s, variables: %s\n\n", dConclusion.c_str(), CPredicate::GetVariablesString(dNotRedCarPredicate).c_str());
	dConclusion = CPredicate::IsTest(dCarPredicate, dNotRedCarPredicate);
	printf("\tIs a car a car that is not red?: %s, variables: %s\n\n", dConclusion.c_str(), CPredicate::GetVariablesString(dCarPredicate).c_str());
	dConclusion = CPredicate::IsTest(dNotRedCarPredicate, dRedCarPredicate);	
	printf("\tIs a car that is not red a red car?: %s, variables: %s\n\n", dConclusion.c_str(), CPredicate::GetVariablesString(dNotRedCarPredicate).c_str());
	dConclusion = CPredicate::IsTest(dRedCarPredicate, dNotRedCarPredicate);	
	printf("\tIs a red car a car that is not red?: %s, variables: %s\n\n", dConclusion.c_str(), CPredicate::GetVariablesString(dRedCarPredicate).c_str());

	// A Boat.
	shared_auto_ptr<CPredicate> dBoatPredicate(new CPredicate());
	dBoatPredicate.get()->SetPredicateString("PP[TYPE:VEHICULE/CLASS:BOAT]");

	// An object that is not a car.
	shared_auto_ptr<CPredicate> dNotACarPredicate(new CPredicate());
	dNotACarPredicate.get()->SetPredicateString("NOT[VALUE:PP[TYPE:VEHICULE/CLASS:CAR]]");
	printf("\"An object that is not a car\":\n\n%s\n\n", dNotACarPredicate->ToString().c_str());
	dConclusion = CPredicate::IsTest(dNotACarPredicate, dCarPredicate);
	printf("\tIs an object that is not a car a car?: %s, variables: %s\n\n", dConclusion.c_str(), CPredicate::GetVariablesString(dNotACarPredicate).c_str());
	dConclusion = CPredicate::HasTest(dNotACarPredicate, dCarPredicate);
	printf("\tIs an object that is not a car has anything to do with a car?: %s\n\n", dConclusion.c_str());
	dConclusion = CPredicate::HasTest(dNotACarPredicate, dBoatPredicate);
	printf("\tIs an object that is not a car has anything to do with a boat?: %s\n\n", dConclusion.c_str());
	dConclusion = CPredicate::IsTest(dNotACarPredicate, dBoatPredicate);
	printf("\tIs an object that is not a car a boat?: %s\n\n", dConclusion.c_str());
	dConclusion = CPredicate::IsTest(dBoatPredicate, dNotACarPredicate);
	printf("\tIs a boat an object that is not a car?: %s\n\n", dConclusion.c_str());
	dConclusion = CPredicate::IsTest(dCarPredicate, dNotACarPredicate);
	printf("\tIs a car an object that is not a car?: %s\n\n", dConclusion.c_str());

	// An object that is a car or a boat
	shared_auto_ptr<CPredicate> dCarOrBoatPredicate(new CPredicate());
	dCarOrBoatPredicate.get()->SetPredicateString("OR[VALUE1:PP[TYPE:VEHICULE/CLASS:CAR]/VALUE2:PP[TYPE:VEHICULE/CLASS:BOAT]]");
	printf("\"An object that is a car or a boat\":\n\n%s\n\n", dCarOrBoatPredicate->ToString().c_str());
	printf("\tIs an object that is a car or a boat a car?: %s\n\n", CPredicate::IsTest(dCarOrBoatPredicate, dCarPredicate).c_str());
	printf("\tIs an object that is a car or a boat a red car?: %s\n\n", CPredicate::IsTest(dCarOrBoatPredicate, dRedCarPredicate).c_str());
	printf("\tIs a car an object that is a car or a boat?: %s\n\n", CPredicate::IsTest(dCarPredicate, dCarOrBoatPredicate).c_str());
	printf("\tIs a red car an object that is a car or a boat?: %s\n\n", CPredicate::IsTest(dRedCarPredicate, dCarOrBoatPredicate).c_str());

	// An object that is a car and a boat
	shared_auto_ptr<CPredicate> dCarAndBoatPredicate(new CPredicate());
	dCarAndBoatPredicate.get()->SetPredicateString("AND[VALUE1:PP[TYPE:VEHICULE/CLASS:CAR]/VALUE2:PP[TYPE:VEHICULE/CLASS:BOAT]]");
	printf("\"An object that is a car and a boat\":\n\n%s\n\n", dCarAndBoatPredicate->ToString().c_str());
	printf("\tIs an object that is a car and a boat a car?: %s\n\n", CPredicate::IsTest(dCarAndBoatPredicate, dCarPredicate).c_str());
	printf("\tIs an object that is a car and a boat a red car?: %s\n\n", CPredicate::IsTest(dCarAndBoatPredicate, dRedCarPredicate).c_str());
	printf("\tIs a car an object that is a car and a boat?: %s\n\n", CPredicate::IsTest(dCarPredicate, dCarAndBoatPredicate).c_str());
	printf("\tIs a red car an object that is a car and a boat?: %s\n\n", CPredicate::IsTest(dRedCarPredicate, dCarAndBoatPredicate).c_str());

	// John went to New-York in a red car.
	shared_auto_ptr<CPredicate> dPredicate11(new CPredicate());
	dPredicate11.get()->SetPredicateString("PTRANS[ACTOR:PP[TYPE:PERSON/NAME:JOHN]/OBJECT:PP[TYPE:PERSON/NAME:JOHN]/TIME:PAST/DESTINATION:PP[TYPE:LOCATION/COUNTRY:USA/CITY:NEW-YORK]/INSTRUMENT:PP[TYPE:VEHICULE/CLASS:CAR/COLOR:RED]]");
	printf("\"John went to New-York in a red car\":\n\n%s\n\n", dPredicate11->ToString().c_str());
 	
	// John went to New-York somehow.
	shared_auto_ptr<CPredicate> dPredicate6(new CPredicate());
	dPredicate6.get()->SetPredicateString("PTRANS[ACTOR:PP[TYPE:PERSON/NAME:JOHN]/OBJECT:PP[TYPE:PERSON/NAME:JOHN]/TIME:PAST/DESTINATION:PP[TYPE:LOCATION/COUNTRY:USA/CITY:NEW-YORK]/INSTRUMENT:{HOW}]");

	dConclusion = CPredicate::IsTest(dPredicate6, dPredicate11);
	printf("\tHow did John went to New-York?: %s\n\n", (dConclusion != "NO")?CPredicate::GetVariablesString(dPredicate6).c_str():"N/A");

	// John went somewhere.
	shared_auto_ptr<CPredicate> dPredicate7(new CPredicate());
	dPredicate7.get()->SetPredicateString("PTRANS[ACTOR:PP[TYPE:PERSON/NAME:JOHN]/OBJECT:PP[TYPE:PERSON/NAME:JOHN]/DESTINATION:{WHERE}/TIME:PAST]");

	dConclusion = CPredicate::HasTest(dPredicate11, dPredicate7);
	printf("\tWhere did John go?: %s\n\n", (dConclusion != "NO")?CPredicate::GetVariablesString(dPredicate11).c_str():"N/A");

	// Someone went somewhere.
	shared_auto_ptr<CPredicate> dPredicate8(new CPredicate());
	dPredicate8.get()->SetPredicateString("PTRANS[ACTOR:{WHO}/OBJECT:{WHO}/DESTINATION:{WHERE}/TIME:PAST]");

	dConclusion = CPredicate::HasTest(dPredicate11, dPredicate8);
	printf("\tWho went where?: %s\n\n", (dConclusion != "NO")?CPredicate::GetVariablesString(dPredicate11).c_str():"N/A");

	// Someone went somewhere somehow.
	shared_auto_ptr<CPredicate> dPredicate9(new CPredicate());
	dPredicate9.get()->SetPredicateString("PTRANS[ACTOR:{WHO}/OBJECT:{WHO}/DESTINATION:{WHERE}/INSTRUMENT:{HOW}/TIME:PAST]");

	dConclusion = CPredicate::HasTest(dPredicate11, dPredicate9);
	printf("\tWho went where and how?: %s\n\n", (dConclusion != "NO")?CPredicate::GetVariablesString(dPredicate11).c_str():"N/A");

	// Someone with a name went to a city.
	shared_auto_ptr<CPredicate> dPredicate10(new CPredicate());
	dPredicate10.get()->SetPredicateString("PTRANS[ACTOR:PP[TYPE:PERSON/NAME:{NAME}]/OBJECT:PP[TYPE:PERSON/NAME:{NAME}]/DESTINATION:PP[CITY:{CITY}]/TIME:PAST]");

	dConclusion = CPredicate::HasTest(dPredicate11, dPredicate10);
	printf("\tWhat is the name of the person who went to a defined city?: %s\n\n", (dConclusion != "NO")?CPredicate::GetVariablesString(dPredicate11).c_str():"N/A");

	// Someone will go somewhere.
	shared_auto_ptr<CPredicate> dPredicate12(new CPredicate());
	dPredicate12.get()->SetPredicateString("PTRANS[ACTOR:{WHO}/OBJECT:{WHO}/DESTINATION:{WHERE}/TIME:FUTURE]");

	dConclusion = CPredicate::HasTest(dPredicate11, dPredicate12);
	printf("\tWho will go where?: %s\n\n", (dConclusion != "NO")?CPredicate::GetVariablesString(dPredicate11).c_str():"N/A");

	/*

	printf("******** NUMBERS HANDLING ***********\n\n");

	shared_auto_ptr<CPredicate> dTestNumberPredicate1(new CPredicate());
	dTestNumberPredicate1.get()->SetPredicateString("MBUILD[NUMBER:=1+1]");
	shared_auto_ptr<CPredicate> dTestNumberPredicate2(new CPredicate());
	dTestNumberPredicate2.get()->SetPredicateString("MBUILD[NUMBER:=1+2]");
	shared_auto_ptr<CPredicate> dTestNumberPredicate3(new CPredicate());
	dTestNumberPredicate3.get()->SetPredicateString("MBUILD[NUMBER:<1+2]");
	shared_auto_ptr<CPredicate> dTestNumberPredicate4(new CPredicate());
	dTestNumberPredicate4.get()->SetPredicateString("MBUILD[NUMBER:>1+2]");
	shared_auto_ptr<CPredicate> dTestNumberPredicate5(new CPredicate());
	dTestNumberPredicate5.get()->SetPredicateString("MBUILD[NUMBER:!1+2]");
	shared_auto_ptr<CPredicate> dTestNumberPredicate6(new CPredicate());
	dTestNumberPredicate6.get()->SetPredicateString("MBUILD[NUMBER:!2]");

	// The mental construction of the number 2.
	shared_auto_ptr<CPredicate> dNumber2Predicate(new CPredicate());
	dNumber2Predicate.get()->SetPredicateString("MBUILD[NUMBER:=2]");
	printf("\"The mental construction of the number 2\":\n\n%s\n\n", dNumber2Predicate->ToString().c_str());
	printf("\tIs the mental construction of the number 2 the same as the mental construction of the number 1+1?: %s\n\n", IsTest(dNumber2Predicate, dTestNumberPredicate1).c_str());
	printf("\tIs the mental construction of the number 2 the same as the mental construction of the number 1+2?: %s\n\n", IsTest(dNumber2Predicate, dTestNumberPredicate2).c_str());
	printf("\tIs the mental construction of the number 2 the same as the mental construction of a number smaller than 1+2?: %s\n\n", IsTest(dNumber2Predicate, dTestNumberPredicate3).c_str());
	printf("\tIs the mental construction of the number 2 the same as the mental construction of a number greater than 1+2?: %s\n\n", IsTest(dNumber2Predicate, dTestNumberPredicate4).c_str());
	printf("\tIs the mental construction of the number 2 the same as the mental construction of a number not 1+2?: %s\n\n", IsTest(dNumber2Predicate, dTestNumberPredicate5).c_str());
	printf("\tIs the mental construction of the number 2 the same as the mental construction of a number not 2?: %s\n\n", IsTest(dNumber2Predicate, dTestNumberPredicate6).c_str());

	// The mental construction of a number less than 2.
	shared_auto_ptr<CPredicate> dNumberLess2Predicate(new CPredicate());
	dNumberLess2Predicate.get()->SetPredicateString("MBUILD[NUMBER:<2]");
	printf("\"The mental construction of a number less than 2\":\n\n%s\n\n", dNumberLess2Predicate->ToString().c_str());
	printf("\tIs the mental construction of a number less than 2 the same as the mental construction of the number 1+1?: %s\n\n", IsTest(dNumberLess2Predicate, dTestNumberPredicate1).c_str());
	printf("\tIs the mental construction of a number less than 2 the same as the mental construction of the number 1+2?: %s\n\n", IsTest(dNumberLess2Predicate, dTestNumberPredicate2).c_str());
	printf("\tIs the mental construction of a number less than 2 the same as the mental construction of a number smaller than 1+2?: %s\n\n", IsTest(dNumberLess2Predicate, dTestNumberPredicate3).c_str());
	printf("\tIs the mental construction of a number less than 2 the same as the mental construction of a number greater than 1+2?: %s\n\n", IsTest(dNumberLess2Predicate, dTestNumberPredicate4).c_str());
	printf("\tIs the mental construction of a number less than 2 the same as the mental construction of a number less than 2?: %s\n\n", IsTest(dNumberLess2Predicate, dNumberLess2Predicate).c_str());
	printf("\tIs the mental construction of a number less than 2 the same as the mental construction of a number not 1+2?: %s\n\n", IsTest(dNumberLess2Predicate, dTestNumberPredicate5).c_str());
	printf("\tIs the mental construction of a number less than 2 the same as the mental construction of a number not 2?: %s\n\n", IsTest(dNumberLess2Predicate, dTestNumberPredicate6).c_str());

	// The mental construction of a number greater than 2.
	shared_auto_ptr<CPredicate> dNumberGreater2Predicate(new CPredicate());
	dNumberGreater2Predicate.get()->SetPredicateString("MBUILD[NUMBER:>2]");
	printf("\"The mental construction of a number greater than 2\":\n\n%s\n\n", dNumberGreater2Predicate->ToString().c_str());
	printf("\tIs the mental construction of a number greater than 2 the same as the mental construction of the number 1+1?: %s\n\n", IsTest(dNumberGreater2Predicate, dTestNumberPredicate1).c_str());
	printf("\tIs the mental construction of a number greater than 2 the same as the mental construction of the number 1+2?: %s\n\n", IsTest(dNumberGreater2Predicate, dTestNumberPredicate2).c_str());
	printf("\tIs the mental construction of a number greater than 2 the same as the mental construction of a number smaller than 1+2?: %s\n\n", IsTest(dNumberGreater2Predicate, dTestNumberPredicate3).c_str());
	printf("\tIs the mental construction of a number greater than 2 the same as the mental construction of a number greater than 1+2?: %s\n\n", IsTest(dNumberGreater2Predicate, dTestNumberPredicate4).c_str());
	printf("\tIs the mental construction of a number greater than 2 the same as the mental construction of a number greater than 2?: %s\n\n", IsTest(dNumberGreater2Predicate, dNumberGreater2Predicate).c_str());
	printf("\tIs the mental construction of a number greater than 2 the same as the mental construction of a number not 1+2?: %s\n\n", IsTest(dNumberGreater2Predicate, dTestNumberPredicate5).c_str());
	printf("\tIs the mental construction of a number greater than 2 the same as the mental construction of a number not 2?: %s\n\n", IsTest(dNumberGreater2Predicate, dTestNumberPredicate6).c_str());

	// The mental construction of a number not 2.
	shared_auto_ptr<CPredicate> dNumberNot2Predicate(new CPredicate());
	dNumberNot2Predicate.get()->SetPredicateString("MBUILD[NUMBER:!2]");
	printf("\"The mental construction of a number not 2\":\n\n%s\n\n", dNumberNot2Predicate->ToString().c_str());
	printf("\tIs the mental construction of a number not 2 the same as the mental construction of the number 1+1?: %s\n\n", IsTest(dNumberNot2Predicate, dTestNumberPredicate1).c_str());
	printf("\tIs the mental construction of a number not 2 the same as the mental construction of the number 1+2?: %s\n\n", IsTest(dNumberNot2Predicate, dTestNumberPredicate2).c_str());
	printf("\tIs the mental construction of a number not 2 the same as the mental construction of a number smaller than 1+2?: %s\n\n", IsTest(dNumberNot2Predicate, dTestNumberPredicate3).c_str());
	printf("\tIs the mental construction of a number not 2 the same as the mental construction of a number greater than 1+2?: %s\n\n", IsTest(dNumberNot2Predicate, dTestNumberPredicate4).c_str());
	printf("\tIs the mental construction of a number not 2 the same as the mental construction of a number not 2?: %s\n\n", IsTest(dNumberNot2Predicate, dNumberNot2Predicate).c_str());

	*/

	printf("******** INTRA-PREDICATE INFERENCE ***********\n\n");

	// A car that travels at a speed of 2 m/s and accelerates at 2.1 m/s2 for a period of 4 seconds.
	shared_auto_ptr<CPredicate> dSpeedPredicate(new CPredicate());
	dSpeedPredicate.get()->SetPredicateString("PTRANS[OBJECT:PP[TYPE:VEHICULE/CLASS:CAR]/INITIALSPEED:2/ACCELERATION:2.1/TIMEPERIOD:4/TIME:PRESENT]");
	printf("\"The car speeding predicate\":\n\n%s\n\n", dSpeedPredicate->ToString().c_str());
	
	// We infer the final speed from that predicate (V = Vi + at)
	shared_auto_ptr<CPredicate> dSpeedInferencePredicate(new CKnowledgePredicate());
	dSpeedInferencePredicate.get()->SetPredicateString("PTRANS[INITIALSPEED:{DEFINED}/ACCELERATION:{DEFINED}/TIMEPERIOD:{DEFINED}/FINALSPEED:{NULL};='INITIALSPEED'+('ACCELERATION'*'TIMEPERIOD')]");
	
	printf("\"The speeding intra-predicate inference\":\n\n%s\n\n", dSpeedInferencePredicate->ToString().c_str());	
	
	dConclusion = CPredicate::HasTest(dSpeedPredicate, dSpeedInferencePredicate);
	shared_auto_ptr<CPredicate> dEvaluatedPredicate = dSpeedPredicate;
	dEvaluatedPredicate->Evaluate();
	printf("\"The car speeding predicate after intra-predicate inference\":\n\nResult: %s\n\n%s\n\n", dConclusion.c_str(), dEvaluatedPredicate->ToString().c_str());

	printf("******** KNOWLEDGE BASE INFERENCE ***********\n\n");
	
	shared_auto_ptr<CKnowledgeBase> dHeightKnowledgeBase(new CKnowledgeBase());

	shared_auto_ptr<CKnowledgePredicate> dPredHolder1(new CKnowledgePredicate());
	dPredHolder1.get()->SetPredicateString(dSpeedInferencePredicate.get()->ToString());
	dHeightKnowledgeBase->Add(dPredHolder1);
	shared_auto_ptr<CKnowledgePredicate> dPredHolder2(new CKnowledgePredicate());
	dPredHolder2.get()->SetPredicateString("PROPEL[ACTOR:PP[NAME:JOHN/LASTNAME:SMITH/HEIGHT:180]/OBJECT::PP[TYPE:FOOTBALL]/DISTANCE::85/TIME:PAST]]");
	dHeightKnowledgeBase->Add(dPredHolder2);
	shared_auto_ptr<CKnowledgePredicate> dPredHolder3(new CKnowledgePredicate());
	dPredHolder3.get()->SetPredicateString("MBUILD[OBJECT:PP[NAME:JOHN/LASTNAME:WILSON/HEIGHT:205]]");
	dHeightKnowledgeBase->Add(dPredHolder3);
	shared_auto_ptr<CKnowledgePredicate> dPredHolder4(new CKnowledgePredicate());
	dPredHolder4.get()->SetPredicateString("MBUILD[OBJECT:PP[NAME:PETER/HEIGHT:142]]");
	dHeightKnowledgeBase->Add(dPredHolder4);
	shared_auto_ptr<CKnowledgePredicate> dPredHolder5(new CKnowledgePredicate());
	dPredHolder5.get()->SetPredicateString("MBUILD[OBJECT:PP[NAME:PETER/LASTNAME:WALKER/HEIGHT:135]]");
	dHeightKnowledgeBase->Add(dPredHolder5);
	shared_auto_ptr<CKnowledgePredicate> dPredHolder6(new CKnowledgePredicate());
	dPredHolder6.get()->SetPredicateString("MBUILD[FROM:PP[NAME:JOHN/LASTNAME:RICHTER/HEALTH:!-10]/TO:PP[NAME:JOHN/LASTNAME:RICHTER/HEALTH:-10]/TIME:PAST]");
	dHeightKnowledgeBase->Add(dPredHolder6);

	printf("Populating knowledge base: \"Speed inference predicate\":\n\n%s\n\n", dPredHolder1.get()->ToString().c_str());
	printf("Populating knowledge base: \"John Smith, 180 cm tall, threw a football 85 yards.\":\n\n%s\n\n", dPredHolder2.get()->ToString().c_str());
	printf("Populating knowledge base: \"John Wilson is 205 cm tall.\":\n\n%s\n\n", dPredHolder3.get()->ToString().c_str());
	printf("Populating knowledge base: \"Peter is 142 cm tall.\":\n\n%s\n\n", dPredHolder4.get()->ToString().c_str());
	printf("Populating knowledge base: \"Peter Walker is 135 cm tall.\":\n\n%s\n\n", dPredHolder5.get()->ToString().c_str());
	printf("Populating knowledge base: \"John Richter died in the past.\":\n\n%s\n\n", dPredHolder6.get()->ToString().c_str());

	// Lee is 20% taller than Peter and smaller than John Wilson

	shared_auto_ptr<CPredicate> dHeightPredicate2(new CKnowledgeBaseInferencePredicate());
	dHeightPredicate2.get()->SetPredicateString("PP[NAME:LEE/HEIGHT:AND[VALUE1:>{PETERHEIGHT}*1.2;KB >> PP[NAME:PETER/HEIGHT:{PETERHEIGHT}]/VALUE2:<{JOHNHEIGHT};KB >> PP[NAME:JOHN/LASTNAME:WILSON/HEIGHT:{JOHNHEIGHT}]]]");
	
	printf("\"Creating predicate: Lee is 20 percent taller than Peter and smaller than John Wilson.\":\n\n%s\n\n", dHeightPredicate2->ToString().c_str());

	((CKnowledgeBaseInferencePredicate*)dHeightPredicate2.get())->Evaluate(dHeightKnowledgeBase);

	printf("\"Following inference\":\n\n%s\n\n", dHeightPredicate2->ToString().c_str());

	shared_auto_ptr<CPredicate> dTestHeightPredicate(new CKnowledgeBaseInferencePredicate());
	dTestHeightPredicate.get()->SetPredicateString("PP[NAME:LEE/HEIGHT:<200]");

	dConclusion = CPredicate::IsTest(dHeightPredicate2, dTestHeightPredicate);
	printf("Is Lee smaller than 200 cm?: %s\n\n", dConclusion.c_str());

	// Lee is 20% taller than Peter and smaller than John

	shared_auto_ptr<CPredicate> dHeightPredicate(new CKnowledgeBaseInferencePredicate());
	dHeightPredicate.get()->SetPredicateString("PP[NAME:LEE/HEIGHT:AND[VALUE1:>{PETERHEIGHT}*1.2;KB >> PP[NAME:PETER/HEIGHT:{PETERHEIGHT}]/VALUE2:<{JOHNHEIGHT};KB >> PP[NAME:JOHN/HEIGHT:{JOHNHEIGHT}]]]");
	
	printf("\"Creating predicate: Lee is 20 percent taller than Peter and smaller than John.\":\n\n%s\n\n", dHeightPredicate->ToString().c_str());

	((CKnowledgeBaseInferencePredicate*)dHeightPredicate.get())->Evaluate(dHeightKnowledgeBase);

	printf("\"Following inference\":\n\n%s\n\n", dHeightPredicate->ToString().c_str());

	dConclusion = CPredicate::IsTest(dHeightPredicate, dTestHeightPredicate);
	printf("Is Lee smaller than 200 cm?: %s\n\n", dConclusion.c_str());

	printf("******** MIXED KNOWLEDGE BASE AND INTRA-PREDICATE INFERENCE ***********\n\n");

	printf("The concept: Lee, of a height greater than 1.1 times the one of Peter, and smaller than John, travelling in a car at a speed of 3 m/s and accelerates at 1.8 m/s2 for a period of 3 seconds.\n\n");

	// Lee, of a height greater than 1.1 times the one of Peter, and smaller than John, travelling in a car at a speed of 3 m/s and accelerates at 1.8 m/s2 for a period of 3 seconds.
	shared_auto_ptr<CPredicate> dComplexPredicate(new CKnowledgeBaseInferencePredicate());
	dComplexPredicate.get()->SetPredicateString("PTRANS[OBJECT:PP[NAME:LEE/HEIGHT:AND[VALUE1:>{PETERHEIGHT}*1.1;KB >> PP[NAME:PETER/HEIGHT:{PETERHEIGHT}]/VALUE2:<{JOHNHEIGHT};KB >> PP[NAME:JOHN/HEIGHT:{JOHNHEIGHT}]]]/INSTRUMENT:PP[TYPE:VEHICULE/CLASS:CAR]/INITIALSPEED:3/ACCELERATION:1.8/TIMEPERIOD:3/TIME:PRESENT]");
	printf("\"The construction of the predicate\":\n\n%s\n\n", dComplexPredicate->ToString().c_str());

	((CKnowledgeBaseInferencePredicate*)dComplexPredicate.get())->Evaluate(dHeightKnowledgeBase);

	printf("\"Following inference\":\n\n%s\n\n", dComplexPredicate->ToString().c_str());

	dConclusion = CPredicate::HasTest(dComplexPredicate, dTestHeightPredicate);
	printf("Is Lee smaller than 200 cm?: %s\n\n", dConclusion.c_str());
}

string PickDictionary()
{
	string useStreamsFile = "streams.txt";
	FILE *dFile = NULL;
	fopen_s(&dFile, useStreamsFile.c_str(), "rt");
	if (dFile != NULL)
	{
		fclose(dFile);
		dFile = NULL;
		fopen_s(&dFile, "_article_testcases_streams", "rt");
		if (dFile != NULL)
		{
			fclose(dFile);
			remove("_article_testcases_streams");
			remove("POSDictionary");
		}
	}
	else
	{
		useStreamsFile = "article_testcases_streams.txt";
		dFile = NULL;
		fopen_s(&dFile, "_article_testcases_streams", "wt");
		fclose(dFile);
	}
	return useStreamsFile;
}

int _tmain(int argc, _TCHAR* argv[])
{
	OutputToFile("DigitalConceptBuilderOutput.txt");
	HandleScope handle_scope;
	StackBasedContext context;
	Context::Scope context_scope(*context.getV8Object());
	string useStreamsFile = PickDictionary();
	shared_auto_ptr<DigitalConceptBuilder> dConceptBuilder = DigitalConceptBuilder::ConstructDigitalConceptBuilder(useStreamsFile.c_str(), "POSDictionary", "SyntaxTransform.txt");
	dConceptBuilder->AddTestCases(CalculationContext::LoadTestCases("TestCases/SimpleTestCases.txt"));
	DigitalConceptBuilder::GetCurCalculationContext()->SetJavascriptContext(context.getV8Object());
	dConceptBuilder->RunTestCases(*context.getV8Object());
	printf("\nDone.\n");
	while (true) {}
	return 0;
}

#pragma warning( default : 4290 )

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
Canada Canada
Philippe Roy was a key contributor throughout his 20+ years career with many high-profile companies such as Nuance Communications, IBM (ViaVoice and ProductManager), VoiceBox Technologies, just to name a few. He is creative and proficient in OO coding and design, knowledgeable about the intellectual-property world (he owns many patents), tri-lingual, and passionate about being part of a team that creates great solutions.

Oh yes, I almost forgot to mention, he has a special thing for speech recognition and natural language processing... The magic of first seeing a computer transform something as chaotic as sound and natural language into intelligible and useful output has never left him.

Comments and Discussions