<html>

<head><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyFirstUnitAd -->
<ins class="adsbygoogle"
     style="display:inline-block;width:970px;height:250px"
     data-ad-client="ca-pub-5778386704669218"
     data-ad-slot="1503492166"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>3-CNF</title>
<style>
<!--
	table td.head{ 
		background-color: #3a6ba5;
		border: 1px #000000 solid;
		font-family: Verdana;
		font-weight: bold;
		font-size: 14px;
		color: #f79c19;
		padding: 6px;
	}

	table td.body{ 
		border-bottom: 1px #6699CC dotted;
		text-align: left;
		font-family: Verdana, sans-serif, Arial;
		font-weight: normal;
		font-size: 14px;
		color: #3A6BA5;
		background-color: #fafafa;
		padding: 6px;
	}
	
-->
</style>
</head>

<body>



<p align="left"><font size="6" color="#FF0000"><span lang="en-ca"><b>&nbsp; 
 
</b></span><b>&nbsp;&nbsp;&nbsp; <span lang="en-ca">&nbsp;&nbsp; </span></b></font>
<span lang="en-ca"><font size="6" color="#FF0000"><b>3-CNF</b></font></span></p>

<div align="left">
  <pre><b><font color="#ff0000" size="5">A. <span lang="en-ca">First </span>Edition</font></b></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>This is a mission impossible approach and I can guarantee you that it is impossible to find a fast algorithm for</b></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><b>solution of 3-CNF question. </b></span></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">B</span>.<span lang="en-ca"><a name="problem"></a>The problem</span></font></b></pre>
</div>
<div align="left" style="width: 806; height: 434">
  <font FACE="Arial" SIZE="2">
  <p ALIGN="LEFT"><span lang="en-ca"><b>What is 3-CNF problem? </b></span></p>
  <p ALIGN="LEFT"><span lang="en-ca"><b>
  (A17||A18||~A2)&amp;&amp;(~A10||~A11||~A19)&amp;&amp;(~A4||A10||A16)&amp;&amp;(A3||~A12||A7)&amp;&amp;(A13||A15||A14)&amp;&amp;<br>
  (~A16||A14||A11)&amp;&amp;(A10||~A3||A6)&amp;&amp;(A14||~A11||A16)&amp;&amp;(~A8||~A9||A10)&amp;&amp;(A2||A8||~A6)&amp;&amp;<br>
  (A19||A4||A7)&amp;&amp;(A7||A14||A1)&amp;&amp;(~A13||A9||A7)&amp;&amp;(A1||A8||A11)&amp;&amp;(~A7||~A2||~A16)&amp;&amp;<br>
  (A11||A17||A0)&amp;&amp;(A5||A16||A13)&amp;&amp;(~A12||~A18||A2)&amp;&amp;(~A6||A12||A11)&amp;&amp;(A8||A6||A17)&amp;&amp;<br>
  (~A18||~A1||A13)&amp;&amp;(A5||~A14||A3)&amp;&amp;(A15||A19||A13)&amp;&amp;(~A17||~A19||A13)&amp;&amp;(A18||A15||A12)&amp;&amp;<br>
  (~A12||~A14||~A9)&amp;&amp;(~A19||A13||~A9)&amp;&amp;(~A10||~A13||A0)&amp;&amp;(~A1||A15||~A9)&amp;&amp;(~A2||~A15||A7)&amp;&amp;<br>
  (A2||~A5||~A8)&amp;&amp;(A11||~A14||A15)&amp;&amp;(~A9||A12||~A11)&amp;&amp;(~A16||~A4||~A15)&amp;&amp;(~A14||A12||~A19)&amp;&amp;<br>
  (~A2||~A15||~A1)&amp;&amp;(A14||A1||A19)&amp;&amp;(A13||A12||~A2)&amp;&amp;(A16||A15||A2)&amp;&amp;(A5||~A3||~A13)</b></span></p>
  <p ALIGN="LEFT"><span lang="en-ca"><b>Each group is consisted of three symbols 
  with no same name and each symbol in each group can be in either true or false 
  states. Groups are in &quot;and&quot; and symbols in each group are in &quot;or&quot;. Can you 
  find a way to satisfy the whole expression? Or in other words, can you assign 
  true, false for each symbol such that the whole expression is true?</b></span></p>
  </font>
  <b><font color="#ff0000" size="5"><span lang="en-ca"><a name="explain"></a>C</span>.<span lang="en-ca">The
  </span></font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>idea of 
  program</b></font></span><p><font FACE="Arial" SIZE="2"><span lang="en-ca"><b>
  My way is nothing but a simple test by using bitmaps to ease the calculation 
  of sets. My idea is very straight forward:</b></span></font></p>
  <p><span lang="en-ca"><b><font face="Arial" size="2">Suppose there exists a 
  set of variables ( including the negative format of a symbol)&nbsp; such that 
  if each of them is assigned true, then the whole expression is true. Then I 
  call them a determine set. i.e. 
  {A13,A7,A11,A2,~A9,~A3,~A4,~A10,A12,A14,A17,~A1,A5,~A16} </font></b></span>
  </p>
  <p><span lang="en-ca"><b><font face="Arial" size="2">So, my task becomes to 
  how to find this determine set. I use a simple recursive function call to find 
  the result. Observe, if a&nbsp; is chosen, then we remove all groups which 
  includes this variable. </font></b></span></div>
<pre><b><font color="#ff0000" size="5">D.<span lang="en-ca"><a name="Method"></a>The </span>major functions</font></b></pre>
<pre><span lang="en-ca"><b>Originally I have some idea of better way than this, but I forget about them after almost one week.</b></span></pre>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">E</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>Further improvement</b></font></span></pre>
</div>
<div align="left">
  <pre>กก</pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">F</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>File listing</b></font></span></pre>
</div>
<div align="left">
  <pre><font size="3"><b><span lang="en-ca">1. set.h</span></b></font></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>2</b></font></span><font size="3"><b><span lang="en-ca">. set.cpp</span></b></font></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>3</b></font></span><font size="3"><b><span lang="en-ca">. 3cnf.h</span></b></font></pre>
</div>
<div align="left">
  <pre><font size="3"><b><span lang="en-ca">4. 3cnf.</span></b></font><span lang="en-ca"><font size="3"><b>cpp</b></font></span></pre>
</div>
<div align="left">
  <pre><font size="3"><b><span lang="en-ca">5. main.cpp</span></b></font></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3" color="#FF0000"><b>file name: set.h</b></font></span></pre>
</div>
<pre>#ifndef SET_H
#define SET_H

#include &lt;iostream&gt;
#include &lt;bitset&gt;

using namespace std;


const int MaxAttrNumber=50;

class Set
{
	//this is a long-pain for me, I have no other way to 
	//let compiler recognize this &quot;friend&quot; function outside declaration
	friend ostream&amp; operator&lt;&lt;(ostream&amp; out, const Set&amp; dummy)	
	{
		for (int i=0; i&lt;dummy.size; i++)
		{
			if (dummy.theSet.test(i))
			{
				out&lt;&lt;'1';
			}
			else
			{
				out&lt;&lt;'0';
			}
		}
		return out;
	}
private:
	bitset&lt;MaxAttrNumber&gt; theSet;
	int size;
	int current;
public:
	void setSize(const Set&amp; dummy);
	int getSize(){ return size;}
	int next(int current) const;
	int first() const;	
	int count() const;
	Set intersection(const Set&amp; dummy) const;
	Set unionSet(const Set&amp; dummy) const;
	Set difference(const Set&amp; dummy) const;
	bool isEmpty();
	//I am crazy about operator overloading!!!:)
	Set operator-(const Set&amp; dummy) const;
	Set operator+(const Set&amp; dummy) const;
	Set operator*(const Set&amp; dummy) const;
	void operator=(const Set&amp; dummy);
	bool operator==(const Set&amp; dummy) const;
	bool operator!=(const Set&amp; dummy) const;
	bool operator&gt;(const Set&amp; dummy) const;
	bool operator&gt;=(const Set&amp; dummy) const;
	bool operator&lt;(const Set&amp; dummy) const;
	bool operator&lt;=(const Set&amp; dummy) const;
	void set(int pos);
	void forEachSubSet(Set&amp; dummy) const;//must be called before &quot;eachSub()&quot;
	bool eachSub(Set&amp; dummy) const;
	bool eachSub(Set&amp; dummy, const Set&amp; excluding) const;
	void set();
	void reset(int pos);
	void reset();
	bool test(int pos) const;
	bool isIn(const Set&amp; dummy) const;
	void setSize(int theSize) {size=theSize;}
	Set(int theSize=10);
	void print();
};

#endif</pre>
<pre>
</pre>
<pre><span lang="en-ca"><font size="3" color="#FF0000"><b>file name: set.cpp</b></font></span></pre>
<pre>#include &quot;Set.h&quot;

void Set::print()
{
	char str[MaxAttrNumber+1];
	strcpy(str, (theSet.to_string()).c_str()+MaxAttrNumber-size);
	printf(&quot;%s&quot;, str);
}

bool Set::isEmpty()
{
	for (int i=0; i&lt;size; i++)
	{
		if (theSet.test(i))
		{
			return false;
		}
	}
	return true;
}

bool Set::isIn(const Set&amp; dummy) const
{
	for (int i=0; i&lt;size; i++)
	{
		if (theSet.test(i))
		{
			if (!dummy.test(i))//here I use Set.test() instead of set.test()
			{
				return false;
			}
		}
	}
	return true;		
}

bool Set::test(int pos) const
{
	return (pos&lt;size&amp;&amp;theSet.test(pos));
}

//current=-1;//initialize to -1 to prepare for being called
int Set::next(int current) const
{
	for (int i=current+1; i&lt;size; i++)//include situation current&gt;=size
	{
		if (theSet.test(i))
		{
			return i;
		}
	}
	return -1;//not found
}

bool Set::operator !=(const Set&amp; dummy)const
{
	return !(this-&gt;operator ==(dummy));
}

bool Set::operator &lt;(const Set&amp; dummy)const
{
	return (this-&gt;isIn(dummy)&amp;&amp;this-&gt;operator !=(dummy));
}

bool Set::operator &lt;=(const Set&amp; dummy)const
{
	return isIn(dummy);
}

bool Set::operator &gt;(const Set&amp; dummy)const
{
	return !(this-&gt;operator &lt;=(dummy));
}

bool Set::operator &gt;=(const Set&amp; dummy)const
{
	return !(this-&gt;operator &lt;(dummy));
}

bool Set::operator ==(const Set&amp; dummy)const
{
	for (int i=0; i&lt;(size&gt;dummy.size?size:dummy.size); i++)
	{
		if (test(i)^dummy.test(i))
		{
			return false;
		}
	}
	return true;
}

void Set::setSize(const Set&amp; dummy)
{
	size=dummy.size;
}

void Set::operator =(const Set&amp; dummy)
{
	size=dummy.size;
	for (int i=0; i&lt;size; i++)
	{
		if (dummy.test(i))
		{
			theSet.set(i);
		}
		else
		{
			theSet.reset(i);
		}
	}
}


Set::Set(int theSize)
{
	size=theSize;
	reset();
}

void Set::reset()
{
	for (int i=0; i&lt;size; i++)
	{
		theSet.reset(i);
	}
}

void Set::reset(int pos)
{
	if (pos&lt;size)
	{
		theSet.reset(pos);
	}
}

void Set::set()
{
	theSet.set();
}

void Set::set(int pos)
{
	theSet.set(pos);
}
	
void Set::forEachSubSet(Set&amp; dummy) const
{
	dummy.size=size;
	dummy.reset();//emptyset
}

bool Set::eachSub(Set&amp; dummy, const Set&amp; excluding) const
{
	int index=first();//starting from very first

	while (index!=-1)//not exceeding boundery
	{
		if (!excluding.test(index))//exluding this set
		{
			if (dummy.test(index))
			{
				dummy.reset(index);				
			}
			else
			{
				dummy.set(index);
				//return true;
							
				if (dummy&lt;*this)//only return the proper subset
				{
					return true;
				}			
			}
		}
		index=next(index);

	}
	return false;
}


bool Set::eachSub(Set&amp; dummy) const
{
	int index=first();//starting from very first

	while (index!=-1)//not exceeding boundery
	{
		if (dummy.test(index))
		{
			dummy.reset(index);
			index=next(index);
		}
		else
		{
			dummy.set(index);
			//return true;
						
			if (dummy&lt;*this)
			{
				return true;
			}			
		}
	}
	return false;
}

int Set::first()const
{
	return next(-1);
}

int Set::count()const
{
	return theSet.count();
}

Set Set::unionSet(const Set&amp; dummy) const
{
	Set result;
	result.size=size&gt;dummy.size?size:dummy.size;
	for (int i=0; i&lt;result.size; i++)
	{
		if (test(i)||dummy.test(i))
		{
			result.set(i);
		}
	}
	return result;//this is a temparory object;
}

Set Set::difference(const Set&amp; dummy) const
{
	Set result;
	result.size=size&gt;dummy.size?size:dummy.size;
	for (int i=0; i&lt;result.size; i++)
	{
		if (test(i)&amp;&amp;!dummy.test(i))
		{
			result.set(i);
		}
	}
	return result;
}

Set Set::operator +(const Set&amp; dummy) const
{
	return unionSet(dummy);
}

Set Set::operator -(const Set&amp; dummy) const
{
	return difference(dummy);
}

Set Set::intersection(const Set&amp; dummy) const
{
	Set result;
	result.size=size&lt;dummy.size?size:dummy.size;
	for (int i=0; i&lt;result.size; i++)
	{
		if (test(i)&amp;&amp;dummy.test(i))
		{
			result.set(i);
		}
	}
	return result;
}

Set Set::operator *(const Set&amp; dummy) const
{
	return intersection(dummy);
}

</pre>
<pre>
</pre>
<pre><span lang="en-ca"><font size="3" color="#FF0000"><b>file name: 3cnf.h</b></font></span></pre>
<pre>#include &quot;set.h&quot;


const int MaxSymbolCount=50;
const int MaxExprCount=MaxSymbolCount*8;

class CNF
{
private:
	char* symbols[MaxSymbolCount];
	int expr[MaxExprCount][3];//expression
	Set cnf_pos[MaxSymbolCount];//positive set of simbol
	Set cnf_neg[MaxSymbolCount];//neg all starts from 1
	int symbolCount;//
	int exprCount;
	int chooseSymbol(Set&amp; symbolSet, Set&amp; exprSet);
	bool solve(Set&amp; symbolSet, Set&amp; exprSet, int resultSet[], int&amp; count);
public:
	void randomGenerate(int symCount, int expCount);
	void printSymbol(int index);
	void displayExpr();
	bool satisfy(int resultSet[], int&amp; count);
};
</pre>
<pre>กก</pre>
<pre>	

		
<span lang="en-ca"><font size="3" color="#FF0000"><b>file name: 3cnf.cpp</b></font></span></pre>
<pre>#include &quot;3CNF.H&quot;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;


void CNF::randomGenerate(int symCount, int expCount)
{	
	symbolCount=symCount;
	exprCount=expCount;
	for (int i=0; i&lt;symbolCount; i++)
	{
		symbols[i]=new char[4];
		sprintf(symbols[i], &quot;A%d&quot;, i);
		cnf_pos[i].setSize(exprCount);
		cnf_neg[i].setSize(exprCount);
	}	
	for (i=0; i&lt;exprCount; i++)
	{
		for (int j=0; j&lt;3; j++)
		{
			//must check if there is repeat, otherwise never satisfy
			//i.e. ~A&amp;&amp;A ==false
			while (true)
			{
				expr[i][j]=rand()%symbolCount;
				if (j==0)
				{
					break;
				}
				if (j==1)
				{
					if (expr[i][j]!=expr[i][j-1]&amp;&amp;expr[i][j]!=-expr[i][j-1])
					{
						break;
					}
				}
				if (j==2)
				{
					if (expr[i][j]!=expr[i][j-1]&amp;&amp;expr[i][j]!=-expr[i][j-1]
						&amp;&amp;expr[i][j]!=expr[i][j-2]&amp;&amp;expr[i][j]!=-expr[i][j-2])
					{
						break;
					}
				}
			}
			if (rand()%2==0)
			{
				cnf_pos[expr[i][j]].set(i);
			}
			else
			{
				cnf_neg[expr[i][j]].set(i);
				expr[i][j]*=-1;
			}
		}
	}

}
	
void CNF::displayExpr()
{
	printf(&quot;print the 3CNF format:\n&quot;);
	for (int i=0; i&lt;exprCount; i++)
	{
		if (i%5==0)
		{
			printf(&quot;\n&quot;);
		}
		printf(&quot;(&quot;);
		for (int j=0; j&lt;3; j++)
		{
			if (expr[i][j]&lt;0)
			{
				printf(&quot;~%s&quot;, symbols[-expr[i][j]]);
			}
			else
			{
				printf(&quot;%s&quot;, symbols[expr[i][j]]);
			}
			if (j!=2)
			{
				printf(&quot;||&quot;);
			}
		}		
		printf(&quot;)&quot;);
		
		if (i!=exprCount-1)
		{
			printf(&quot;&amp;&amp;&quot;);
		}

	}
	printf(&quot;\n&quot;);
}
		
bool CNF::satisfy(int resultSet[], int&amp; count)
{
	Set symbolSet, exprSet;
	symbolSet.setSize(symbolCount);
	exprSet.setSize(exprCount);	
	symbolSet.set();
	exprSet.set();
	//symbolSet.print();
	return solve(symbolSet, exprSet, resultSet, count);
}


bool CNF::solve(Set&amp; symbolSet, Set&amp; exprSet, int resultSet[], int&amp; count)
{
	int index;
	//printf(&quot;no.%d call of solve: \n&quot;, count);
	//printf(&quot;symbolSet=&quot;);
	//symbolSet.print();
	//printf(&quot;exprSet=&quot;);
	//exprSet.print();
	//printf(&quot;\n&quot;);
	if (exprSet.isEmpty())
	{
		return true;
	}
	if (symbolSet.isEmpty())
	{
		return false;
	}

	//index must return absolue value bigger than 1
	//so that allow -1,1
	index=chooseSymbol(symbolSet, exprSet);
	//printf(&quot;\nand choose index of %d\n&quot;, index);
	//0 means the symbol set cannot cover expression set
	if (index==0)
	{
		return false;
	}
	resultSet[count]=index;
	count++;
	if (index&lt;0)
	{
		index*=-1;
		index-=1;
		exprSet=exprSet-cnf_neg[index];
	}
	else
	{
		index-=1;
		exprSet=exprSet-cnf_pos[index];
	}
	//printf(&quot;and expr is\n&quot;);
	//exprSet.print();
	//in any case, we reduce the symbol set
	symbolSet.reset(index);
	return solve(symbolSet, exprSet, resultSet, count);
}

//if no max symbol can be found, index is 0
int CNF::chooseSymbol(Set&amp; symbolSet, Set&amp; exprSet)
{
	int count=exprCount, result, index=0;
	Set temp;
	//printf(&quot;symbol set is\n&quot;);
	//symbolSet.print();

	for (int i=0; i&lt;symbolCount; i++)
	{
		if (symbolSet.test(i))
		{
			result=(exprSet-cnf_pos[i]).count();
			if (result&lt;count)
			{
				count=result;
				index=i+1;
			}
			result=(exprSet-cnf_neg[i]).count();
			if (result&lt;count)
			{
				count=result;
				index=(i+1)*(-1);
			}
		}
	}
	return index;

}
	

void CNF::printSymbol(int index)
{
	printf(&quot;%s&quot;, symbols[index]);
}


</pre>
<pre>กก</pre>
<pre><span lang="en-ca"><font size="3" color="#FF0000"><b>file name: main.cpp</b></font></span></pre>
<pre>#include &quot;3cnf.h&quot;
#include &lt;time.h&gt;

int main()
{
	CNF cnf;
	int count=0;
	int resultSet[MaxSymbolCount]={0};
	srand(time(0));
	cnf.randomGenerate(20, 40);
	cnf.displayExpr();
	if (cnf.satisfy(resultSet, count))
	{
		printf(&quot;\nit is satisfiable\n&quot;);
		for (int i=0; i&lt;count; i++)
		{
			if (resultSet[i]&lt;0)
			{
				printf(&quot;~&quot;);
				cnf.printSymbol(resultSet[i]*(-1)-1);
			}
			else
			{
				cnf.printSymbol(resultSet[i]-1);
			}
			printf(&quot;,&quot;);
		}				
	}
	else
	{
		printf(&quot;unsatisfiable\n&quot;);
	}
	printf(&quot;\n&quot;);
	return 0;
}</pre>
<pre>
</pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre><span lang="en-ca"><font color="#0000FF"><b>How to run?</b></font></span></pre>
<p>print the 3CNF format:<br>
<br>
(A17||A18||~A2)&amp;&amp;(~A10||~A11||~A19)&amp;&amp;(~A4||A10||A16)&amp;&amp;(A3||~A12||A7)&amp;&amp;(A13||A15||A14)&amp;&amp;<br>
(~A16||A14||A11)&amp;&amp;(A10||~A3||A6)&amp;&amp;(A14||~A11||A16)&amp;&amp;(~A8||~A9||A10)&amp;&amp;(A2||A8||~A6)&amp;&amp;<br>
(A19||A4||A7)&amp;&amp;(A7||A14||A1)&amp;&amp;(~A13||A9||A7)&amp;&amp;(A1||A8||A11)&amp;&amp;(~A7||~A2||~A16)&amp;&amp;<br>
(A11||A17||A0)&amp;&amp;(A5||A16||A13)&amp;&amp;(~A12||~A18||A2)&amp;&amp;(~A6||A12||A11)&amp;&amp;(A8||A6||A17)&amp;&amp;<br>
(~A18||~A1||A13)&amp;&amp;(A5||~A14||A3)&amp;&amp;(A15||A19||A13)&amp;&amp;(~A17||~A19||A13)&amp;&amp;(A18||A15||A12)&amp;&amp;<br>
(~A12||~A14||~A9)&amp;&amp;(~A19||A13||~A9)&amp;&amp;(~A10||~A13||A0)&amp;&amp;(~A1||A15||~A9)&amp;&amp;(~A2||~A15||A7)&amp;&amp;<br>
(A2||~A5||~A8)&amp;&amp;(A11||~A14||A15)&amp;&amp;(~A9||A12||~A11)&amp;&amp;(~A16||~A4||~A15)&amp;&amp;(~A14||A12||~A19)&amp;&amp;<br>
(~A2||~A15||~A1)&amp;&amp;(A14||A1||A19)&amp;&amp;(A13||A12||~A2)&amp;&amp;(A16||A15||A2)&amp;&amp;(A5||~A3||~A13)<br>
<br>
it is satisfiable<br>
A13,A7,A11,A2,~A9,~A3,~A4,~A10,A12,A14,A17,~A1,A5,~A16,<br>
Press any key to continue<br>
กก</p>

<pre></pre>

<pre></pre>

<pre></pre>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                                   
&nbsp;&nbsp;&nbsp; <a href="PocketRuler.htm">                  







                       <img src="picture/back.gif" style="border: medium none" alt="back.gif (341 bytes)" width="32" height="35"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<a href="index.htm">
<img src="picture/up.gif" style="border: medium none" alt="up.gif (335 bytes)" width="35" height="32"></a>       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                         
<img src="picture/next.gif" style="border: medium none" alt="next.gif (337 bytes)" width="32" height="35">          


</p>

</body>

</html>