Sindbad~EG File Manager
#!/usr/bin/php
<?php
// Strings can be written on two lines by using a period to concatenate the lines.
// We did this in some places to permit this file to be printed for archival purposes.
error_reporting(E_ALL|E_STRICT);
ini_set('display_errors', true);
require_once('Axioms.php');
class Stack {
public $stk = array(); //OK fine, it's not really a stack then.
public function __construct() {
}
public function push($data) {
array_push($this->stk, $data);
// echo "pushing $data\n";
}
public function pop() {
if(count($this->stk) == 0)
{ echo "Error in pop--can't pop empty stack\n";
die();
}
return array_pop($this->stk);
}
public function peek() {
if(count($this->stk) == 0)
{ return false;
}
return $this->stk[count($this->stk)-1];
}
public function mark() {
$this->push("marker");
}
public function backtrack(){
$flag = true;
while($flag)
{ $t = $this->pop();
if($t=="marker")
return $prev;
$prev = $t;
}
}
public function marked(){
return in_array("marker", $this->stk);
}
}
//___________________________________________________
function functor($p)
// return the first two characters of $p
{ if(strlen($p) < 2)
{ echo "Error in functor $p\n";
die();
}
return substr($p,0,2);
}
//___________________________________________________
function args($p)
{ if(strlen($p) < 3)
{ echo "Error in args of $p\n";
die();
}
return substr($p,2,strlen($p)-2);
}
//___________________________________________________
function exhaustive($a)
// $a$ is an array of propositions. Return true if these cases are exhaustive.
{ if(count($a) == 2 && contradictory($a[0], $a[1]))
return true;
// example: (EQBC,EQBD,EQCD,EQAC,EQAD,ANNEBC+NEBD+NECD+NEAC+NEAD)
// is exhaustive. It occurs in collinear4.
$n = count($a);
foreach($a as $z)
{ if(strlen($z) < 2)
{ echo "Error in exhaustive\n"; print_r($a); die();
}
}
if(functor($a[$n-1]) == "AN")
{ $t = explode("+",args($a[$n-1]));
if(count($t) != $n-1)
return false;
for($i=0;$i<$n-1;$i++)
if(negation($a[$i]) != $t[$i])
return false;
return true;
}
if(functor($a[0]) == "AN")
{ $t = explode("+",args($a[0]));
if(count($t) != $n-1)
return false;
for($i=0;$i<$n-1;$i++)
if(negation($a[$i+1]) != $t[$i])
return false;
return true;
}
return false;
}
//___________________________________________________
function contradictory($p, $q)
// return true if $p$ and $q$ are negations of each other
{ // echo "contradictory? $p $q%\n";
if(functor($p) == "NO" && args($p) == $q)
return true;
if(functor($q) == "NO" && args($q) == $p)
return true;
if(functor($p) == "NE" && functor($q) == "EQ" && args($p) == args($q))
return true;
if(functor($q) == "NE" && functor($p) == "EQ" && args($p) == args($q))
return true;
if(functor($p) == "NC" && functor($q) == "CO" && args($p) == args($q))
return true;
if(functor($q) == "NC" && functor($p) == "CO" && args($p) == args($q))
return true;
if($p == negation($q) || $q == negation($p))
return true;
return false;
}
// __________________________________________________
function lookup_reason($reason)
// $reason is "defn:xx", or "lemma:xx", or "cn:xx", or "proposition:xx", or "postulate:xx",
// or "axiom:xx. Return an object with the mentioned identification that has fields
// "conclusion" and "hypotheses".
{ global $definitions, $results, $axioms;
$v = array_map('trim',explode(":", $reason));
if(count($v)<2)
{ echo("Error in lookup_reason: $reason\n");
}
$kind = $v[0];
$name = $v[1];
if($kind == "defn")
$target = $definitions;
if($kind == "lemma" || $kind == "proposition")
$target = $results;
if($kind == "axiom" || $kind == "postulate" || $kind == "cn")
$target = $axioms;
foreach($target as $x)
{ if($x->label == $name && ($kind == "defn" || $x->kind == $kind))
return $x;
}
echo("Can't look up $reason in $kind\n");
die();
}
// __________________________________________________
function unify($p, $q, $initial_unifier = 0)
// unify two propositions. The matching assigns variables in $q$ to
// variables in $p$. Also $q can be an array of propositions,
// in which case it is converted to a conjunction.
// return false if they do not unify
{ if(!is_string($p))
{ echo "non-string in unify\n";
die();
}
if(is_array($q) && count($q) == 1)
$q = $q[0];
if(!is_string($q))
{ if(!is_array($q))
{ echo("wrong type in unify\n");
echo("Maybe you forgot to list the conclusion of a theorem in Axioms.php.\n");
die();
}
// print_r($q);
$temp = "";
foreach($q as $x)
{ $temp = $temp . "+$x";
}
$q = "AN" . substr($temp,1);
// echo "$p\n$q\n";
}
if(strlen($p) != strlen($q))
return false;
if(strlen($p) < 2)
{ echo "unify called with length less than 2";
die();
}
if(strlen($p) < 2 || strlen($q) < 2)
{ echo "aargh"; die();}
$f = functor($p);
$g = functor($q);
if($f != $g)
return false;
if($f == "NO")
return unify(args($p),args($q),$initial_unifier);
$p = args($p);
$q = args($q);
if($f == "AN" || $f == "OR")
{ if($f == "AN")
{ $P = explode("+",$p);
$Q = explode("+",$q);
}
else
{ $P = explode("|",$p);
$Q = explode("|",$q);
// echo "hey, unifying disjunctions\n";
}
// echo "Hey: $p and \n $q\n";
$m = count($P);
if($m != count($Q))
{ echo "Error in unifying $f $p $q\n";
die();
}
$old = $initial_unifier;
for($i=0;$i<$m;$i++)
{ // print_r($old);
$v = unify($P[$i], $Q[$i], $old);
// echo $P[$i] . "\n" . $Q[$i] . "\n";
if(!$v)
return false;
$old = $v;
}
return $v;
}
if(strlen($p) != arity($f))
{ echo "wrong arity for $f$\n";
die();
}
$n = strlen($p);
if(strlen($q) != $n)
{ echo "ouch!";
die();
}
if($initial_unifier == 0)
$match = array();
else
{ $match = $initial_unifier;
// echo "passed\n";
// print_r($match);
// echo "$p $q\n";
}
for($i = 0; $i < $n; $i++)
{ if(key_exists($q[$i], $match) && $match[$q[$i]] != $p[$i])
{ // echo "failing on " . $i . "\n";
return false; // that variable is already matched to something else
}
// echo "Key " . $q[$i] . "\n";
$match[$q[$i]] = $p[$i];
// print_r($match);
}
// echo "unifying $p and $q:\n";
// echo "given\n"; print_r($initial_unifier);
// echo "returning\n"; print_r($match);
return $match;
}
// __________________________________________________
function apply_unifier($unifier, $input)
// return the result of applying $unifier to $input.
{ if(is_array($input))
{ $ans = array();
foreach($input as $x)
$ans[] = apply_unifier($unifier, $x);
return $ans;
}
$n = strlen($input);
$ans = $input;
if(functor($input) == "NO")
$start = 4;
else
$start = 2;
for($i=$start;$i<$n;$i++)
{ if(key_exists($input[$i], $unifier))
$ans[$i] = $unifier[$input[$i]];
else
{ if ($input[$i] == '+' || $input[$i] == '|')
{ $ans[$i] = $input[$i];
$ans[$i+1] = $input[$i+1]; // copy the next functor
$ans[$i+2] = $input[$i+2];
$i += 2;
$ans[$start] = $input[$start];
$ans[$start+1] = $input[$start+1];
}
else
{ $unifier[$input[$i]] = $ans[$i]; // add it to the unifier
}
}
}
if(strlen($ans) != strlen($input))
echo "oops! $ans% $input%\n";
// echo "apply_unifier $input% returning $ans%\n";
// print_r($unifier);
return $ans;
}
//____________________________________________________
function implies($eq, $r, $p)
// $eq is an equality, $r is an atomic proposition.
// return true if $p$ results from $r$ by substituting
// one side of $eq for the other in $p
{ if(strlen($eq) != 4)
{ echo "implies wrongly called on $eq\n";
die();
}
if(strlen($r) != strlen($p)
|| functor($r) != functor($p)
)
return false;
// echo "implies $eq $r $p\n";
$r = args($r);
$p = args($p);
$n = strlen($r);
$X = $eq[2];
$Y = $eq[3];
for($i=0;$i<$n;$i++)
{ if($r[$i] == $p[$i])
continue;
if($r[$i] == $X && $p[$i] == $Y)
continue;
if($r[$i] == $Y && $p[$i] == $X)
continue;
return false;
}
return true;
}
//____________________________________________________
function remove($item, $list)
// return a new array with all items of $list that are not equal to $item
{ $ans = array();
foreach($list as $x)
{ if($x != $item)
$ans[] = $x;
}
return $ans;
}
//___________________________________________________
function negation($x)
{ $f = functor($x);
if($f == "NO")
return args($x);
if($f == "AN")
{ $g = "OR";
$p = explode("+", args($x));
foreach($p as $z)
{ $g = $g . negation($z) . "|";
}
$g = substr($g,0,strlen($g)-1);
return $g;
}
if($f == "OR")
{ $g = "AN";
$p = explode("|", args($x));
foreach($p as $z)
{ $g = $g . negation($z) . "+";
}
$g = substr($g,0,strlen($g)-1);
return $g;
}
if($f == "EQ")
$g = "NE";
else if($f == "NE")
$g = "EQ";
else if($f == "CO")
$g = "NC";
else if ($f == "NC")
$g = "CO";
else
$g = "NO" . $f;
return $g . args($x);
}
//___________________________________________________
function verify($tocheck, $unifier, $given)
// if the array $given implies the result of
// applying $unifier to $tocheck; return the (extended) unifier used.
// On failure return false.
{ if(is_string($tocheck) && functor($tocheck) == "OR")
{ // it's enough to verify one disjunct
$x = explode("|", args($tocheck));
foreach($x as $disjunct)
{ // echo "hey $disjunct\n";
$ans = verify($disjunct, $unifier, $given);
if($ans != false)
return $ans;
}
// don't give up, the entire disjunction might be in $given
}
if(is_string($tocheck))
{ // echo "trying to verify $tocheck\n";
$tocheck = array($tocheck);
}
return search(0,$tocheck, $given, $unifier);
}
//________________________________________
function search($n,$tocheck, $given, $unifier)
// find a unifier extending $unifier
// that unifies $tocheck[$n] with
// some member of $given, and return that unifier.
// If none exists, return false.
// Nodes are pairs ($m, unifier extending $unifier).
// Neighbors of that node are ($m+1, unifier extension)
{ if(!is_array($tocheck))
{ echo "search received a non-array\n.";
if(is_string($tocheck)) echo("$tocheck\n");
die();
}
if($n == count($tocheck))
{ // done
// echo "verified \n"; print_r($tocheck); print_r($unifier);
return $unifier;
}
$h = $tocheck[$n];
/* echo "search $n of " . count($tocheck) . " $h \n";
print_r($unifier);
echo "now\n";
print_r($given); */
if(functor($h) == "OR")
{ // it's enough to verify one disjunct
$x = explode("|", args($h));
foreach($x as $disjunct)
{ // echo "hey $disjunct\n";
$ans = verify($disjunct, $unifier, $given);
if($ans != false)
{ $temp2 = search($n+1,$tocheck,$given, $ans);
if($temp2 != false)
return $temp2;
}
}
}
foreach( array_reverse($given) as $q)
{ if(functor($q) != functor($h))
continue;
$temp = unify($q,$h, $unifier);
if($temp == false)
{ // echo "Failed to unify $q and $h\n";
continue;
}
$temp2 = search($n+1, $tocheck, $given, $temp);
if($temp2 != false)
return $temp2;
}
return false;
}
//__________________________________________________
function check_hypotheses($given, $filename)
// and die if there is a problem
// these hypotheses better be the ones listed in the $results array in Axioms.php
// So we will check that next, before checking the proof itself
// is this a proposition or a lemma?
{ global $results;
if(strstr($filename, "Prop"))
$kind = "proposition";
else
$kind = "lemma";
$hyp = false;
$lemmaname = substr($filename,0,strlen($filename)-4); // drop the ".prf" at the end
if(strstr($lemmaname, "Prop"))
$lemmaname = substr($lemmaname,4); // take the part after "Prop"
foreach($results as $r)
{ if($r->kind == $kind && $r->label == $lemmaname)
{ $hyp = $r->hypotheses;
$con = $r->conclusion;
break;
}
}
if($hyp === false)
// if $hyp is an empty array it is == false but not === false
{ echo "$filename missing in results array.\n";
die();
}
if(!is_array($hyp) || count($given) != count($hyp))
{ echo "Problem with hypotheses of $filename\n";
echo count($given) . " " . count($hyp) . "\n";
print_r($given);
die();
}
$n = count($hyp);
for($i=0;$i<$n;$i++)
{ if ($hyp[$i] != $given[$i])
{ echo "Problem with hypothesis $i (of $n) of $filename\n";
echo $r->label . "\n";
echo $hyp[$i] . " " . $given[$i] . "\n";
die();
}
}
// OK, everything OK with the hypotheses.
}
//___________________________________________________
function check_conclusion($lastline, $filename)
/* $lastline should be the conclusion of the theorem,
or if the conclusion is an array, it should be the
conjunction of the members of that array.
check_conclusion dies if that is not the case.
*/
{ global $results;
if(strstr($filename, "Prop"))
$kind = "proposition";
else
$kind = "lemma";
$con = false;
$lemmaname = substr($filename,0,strlen($filename)-4); // drop the ".prf" at the end
if(strstr($lemmaname, "Prop"))
$lemmaname = substr($lemmaname,4); // take the part after "Prop"
foreach($results as $r)
{ if($r->kind == $kind && $r->label == $lemmaname)
{ $hyp = $r->hypotheses;
$con = $r->conclusion;
$new = $r->existential;
break;
}
}
if($con === false)
// if $con is an empty array it is == false but not === false
{ echo "$filename missing in results array.\n";
die();
}
$lastline = trim($lastline);
if(strstr($lastline, " "))
{ $t = explode(" ", $lastline);
$lastline = $t[0]; // discard the justification
}
$unifier = unify($lastline,$con,array());
if($unifier === false)
{ echo "Problem in conclusion of $filename\n";
echo "$lastline\n"; print_r($con);
die();
}
foreach($unifier as $var => $value)
{ if(strstr("XYZUVWxyzuvw", $var)==false && $var != $value)
{ echo "Problem in conclusion of $filename with $var and $value\n";
echo "$lastline\n"; print_r($con);
print_r($unifier);
die();
}
}
// print_r($unifier);
}
// _________________________________________________
function vars_in($given)
// create a string listing all variables in the formula or
// list of formulas $given
// and return the result. Duplicates are OK.
{ if(is_string($given))
{ if(functor($given) == "AN")
return vars_in(explode("+",args($given)));
if(functor($given) == "OR")
return vars_in(explode("|",args($given)));
if(functor($given)== "NO")
return vars_in(args($given));
return args($given);
}
if(!is_array($given))
{ echo("Error in vars, wrong type.\n");
die();
}
$ans = "";
foreach($given as $formula)
{ if($formula == "marker")
continue;
$ans = $ans . vars_in($formula);
}
return $ans;
}
//_________________________________________________
function check_fresh($prop, $unifier, $vars, $given)
// $vars is a list of variables
// $check that the values assigned to those variables by $unifier
// do not occur in $given. If they do, print an error message and die.
{ $oldvars = vars_in($given);
// echo "Calling check_fresh with $vars\n";
// echo "oldvars = $oldvars\n";
foreach($unifier as $var=>$value)
{ if( strstr($vars, $var)!== FALSE && strstr($oldvars,$value)!== FALSE)
{ echo("Fresh variable condition violated when deducing $prop with $var = $value\n");
print_r($given);
die();
}
// echo "$var = $value\n";
}
}
//____________________________________________________
function check_proof($filename)
// check if the proof in $filename is correct.
// return true if it is, false if not.
// Does not check whether it has the correct assumptions and
// conclusions specified in $lemmas or $propositions.
{ $valid = new Stack(); // propositions proved
$variables = new Stack();
$goals = new Stack();
$caselists = new Stack();
$inference_count = 0; // number of inferences
if(!file_exists($filename))
{ echo "Expected $filename to exist.\n";
die();
}
$proof = file($filename);
if(count($proof) == 0)
{ echo "$filename is empty\n";
die();
}
$n = count($proof);
for($i = $n-1; $i > 0; $i--)
{ if(trim($proof[$i]) != "")
{ $lastline = $proof[$i];
break;
}
}
if(!isset($lastline))
{ echo "Trouble with lastline of $filename\n";
die();
}
check_conclusion($lastline, $filename);
/* $lastline should be the conclusion of the theorem,
or if the conclusion is an array, it should be the
conjunction of the members of that array.
check_conclusion dies if that is not the case.
*/
$hypflag = 1; // read the hypotheses
$a = array(1,2,3,4);
foreach($proof as $line)
{ $line = trim($line);
// echo "Checking $line\n";
if($line == "")
{ if($hypflag == 1)
$hypflag = -1; // first blank line before any justified line , signals end of hypotheses
continue; // skip blank lines (which occur sometimes at the end)
}
if($line[0] == '%') // skip commented-out lines
continue;
if($hypflag!= 0)
{ if(strstr($line, " ") || $hypflag == -1)
{ $hypflag = 0; // done reading hypotheses
check_hypotheses($valid->stk, $filename); // and die if there's a problem
}
else
{ $valid->push($line); // assume this line
continue;
}
}
if( preg_match("~^cases~", $line))
{
$p = array_map('trim',explode(":", $line));
$thecases = "OR" . $p[1];
// echo "$thecases\n";
// print_r($valid);
preg_match("~^cases( *)(.*)~",$p[0],$a);
$goals->push($a[2]); // the thing to be proved by cases
// echo "setting goal = " . $a[2] ."\n";
if(isset($list_of_cases) && count($list_of_cases)!= 0)
{ // this is a nested cases, so store the old caselist
$caselists->push($list_of_cases);
// echo "Pushing caselist \n";
// print_r($list_of_cases);
}
$list_of_cases = array_map('trim',explode("|", $p[1]));
if(in_array($thecases, $valid->stk))
continue; // OK, proceed to the cases
if(!exhaustive($list_of_cases))
{ echo "cases not checked to be exhaustive\n";
print_r($list_of_cases);
die();
}
continue; // OK, proceed to the cases
}
if(strstr($line, "|"))
{ // if a disjunction occurs to set up a proof by cases, then the cases should be exhaustive
$cases = explode("|", $line);
$t = array();
foreach($cases as $x)
{ $t[] = trim($x);
}
if(exhaustive($t))
continue; // these cases are exhaustive
// echo "failed to check the cases are exhaustive\n";
// don't die, maybe this line can be checked normally
}
if(preg_match("~^case ~", $line, $a))
{ $p = explode(":", $line);
$valid->mark();
$currentcase = trim($p[1]);
$valid->push($currentcase);
// echo "pushing $currentcase\n";
continue;
}
if(preg_match("~qedcase~", $line))
{ if(count($goals->stk) == 0)
{ echo "error at line 530\n"; die();
}
if($valid->peek() != $goals->peek())
{ echo("Can't check case $currentcase\n");
echo "because " . $goals->peek() . "doesn't match " . $valid->peek() . "\n";
// print_r($valid);
$valid->backtrack();
die();
}
$list_of_cases = remove($currentcase, $list_of_cases);
// echo "Removed $currentcase from the caselist leaving\n";
// print_r($list_of_cases);
$valid->backtrack();
// echo "backtracking $currentcase\n";
// print_r($valid);
continue; // go on to the next line
}
if(strstr($line, " "))
{ preg_match("~(\S*)(\s*)(\S*)~", $line, $a);
$prop = $a[1];
$reason = trim($a[3]);
if($reason == "")
{ echo "Ooops, blank reason in $line\n";
echo "$prop%\n";
die();
}
// echo "$reason\n";
if($reason == "reductio")
{ $p = $valid->pop(); // previous line
// look for something that $p contradicts
$flag = false;
foreach($valid->stk as $r)
{ if(contradictory($p, $r))
{ $valid->push($prop);
$flag = true;
break;
}
}
if(!$flag)
{ echo("reductio error at $line\n");
echo("$p not contradictory\n");
print_r($valid);
die();
}
$lastassumption = $valid -> backtrack();
// check that $prop is the negation
// of the last assumption
if(negation($prop) != $lastassumption &&
negation($lastassumption) != $prop &&
$prop != "NO" . $lastassumption &&
$lastassumption != "NO" . $prop
)
{ echo("reductio error at $line\n");
echo "Conclusion is not negation of assumption.\n";
echo "$prop versus $lastassumption\n";
die();
}
$valid -> push($prop);
// echo "pushing $prop\n";
// print_r($valid);
++$inference_count;
continue; // this line has been checked
}
if($reason == "cases")
{ if($prop != $goals->peek())
{ echo "goal " . $goals->peek() . "does not match claim $prop in cases\n";
die();
}
$valid->push($prop);
if(!empty($list_of_cases))
{ echo "Not all cases checked for " . $goals->peek() . "\n";
print_r($list_of_cases);
die();
}
$goals->pop();
// echo "popping goal\n";
$temp = $caselists->peek();
if($temp)
{ $list_of_cases = $temp;
$caselists->pop();
$currentcase = $list_of_cases[0];
// echo "popping cases\n";
// print_r($list_of_cases);
}
++$inference_count;
continue; // this line checks OK
}
if($reason == "assumption") // starting a proof by contradiction
{ $valid->mark();
$valid->push($prop);
continue;
}
if(strstr($reason, ":"))
{ $a = array(1,2,3);
preg_match("~(.*)\.prf~", $filename, $a);
$proofname = $a[1];
if(!precedes($reason, $proofname))
{ echo "Proof of $proofname illegally cites $reason\n";
die();
}
++$inference_count;
}
$authority = lookup_reason($reason);
if($authority->label == "equalitysub")
{ // see if any equality in $valid->stk implies $prop
$err = true;
// echo "prop = $prop\n";
foreach($valid->stk as $q)
{ // echo "q = $q\n";
if(functor($q) != "EQ")
continue;
foreach($valid->stk as $r)
{ if(implies($q,$r,$prop))
{ $err = false;
break;
}
}
if($err==false)
break;
}
if($err)
{ echo "Can't verify $prop by equalitysub\n";
die();
}
$valid->push($prop);
continue;
}
if( functor($prop) != "AN"
&& functor($prop) != "OR"
&& is_array($authority->conclusion)
)
{ $unifier = false;
$flag89 = false;
$conclusion = $authority->conclusion;
foreach($authority->conclusion as $x)
{ $unifier = unify($prop, $x);
// echo "Unifying $prop and $x with \n";
// print_r($unifier);
// if($unifier == false) echo "failed\n";
if($unifier != false && $authority->existential != "")
{
check_fresh($prop, $unifier, $authority->existential, $valid->stk);
}
if($unifier != false)
{ $new_unifier = verify($authority->hypotheses, $unifier, $valid->stk);
if($new_unifier != false)
{
$flag89 = true; // this line is checked
break;
}
}
/* if($unifier == false)
echo "Can't unify $prop and any conclusion of " . $authority->label. "\n";
else
{ echo "Can't verify hypotheses of " . $authority->label . "\n";
echo "where the conclusion is $prop and $x\n";
} */
}
if($flag89)
{ $valid->push($prop);
// echo "pushing $prop\n";
continue; // this line is checked
}
if($unifier == false && get_class($authority) == 'Definition')
{ // definitions can be used 'backwards'
$unifier = unify($prop, $authority->hypotheses);
if($unifier == false)
echo "Can't unify $prop with " . $authority->hypotheses . "\n";
else
{ $new_unifier = verify($authority->conclusion, $unifier, $valid->stk);
if($new_unifier != false)
{ $valid->push($prop); // this line is checked
/* echo "hey $prop\n";
print_r($unifier);
print_r($new_unifier);
print_r($authority->conclusion); */
continue;
}
else if(is_array($authority->conclusion) && count($authority->conclusion) == 1
&& functor($authority->conclusion[0]) == "OR"
)
{ $temp = explode("|", args($authority->conclusion[0]));
$flag72 = false;
foreach($temp as $x)
{ $new_unifier = verify($x, $unifier, $valid->stk);
if($new_unifier)
{ $flag72 = true;
$valid->push($prop); // this line is checked
break;
}
}
if($flag72)
continue;
}
echo "Can't verify conclusion of " . $authority->label . "\n";
}
}
if($unifier == false || $new_unifier == false)
{ echo "AARGH! failed to check $prop " . $authority->label . "\n";
print_r($valid);
die();
}
}
else
{ $unifier = unify($prop, $authority->conclusion);
if($unifier == false)
{ if(get_class($authority) == "Definition" &&
functor($prop) == "AN" &&
is_array($authority->hypotheses)
)
{ $unifier = unify($prop, $authority->hypotheses);
$new_unifier = verify($authority->conclusion, $unifier, $valid->stk);
if($new_unifier != false)
{ $valid->push($prop);
continue;
}
}
echo "Can't unify $prop with conclusion of " . $authority->kind . $authority->label . "\n";
print_r($authority->conclusion);
echo "Hypotheses:"; print_r($authority->hypotheses);
die();
}
// echo "Hey! $prop\n";
check_fresh($prop,$unifier,$authority->existential,$valid->stk);
$new_unifier = verify($authority->hypotheses, $unifier,$valid->stk);
if($new_unifier != false)
{ $valid->push($prop);
continue;
}
echo "Can't verify hypotheses of " . $authority->label .
" with conclusion $prop\n";
if(is_array($authority->hypotheses))
{ echo "Namely,\n";
foreach($authority->hypotheses as $z)
{ echo "$z\n";
}
echo "after applying some extension of this unifier:\n";
print_r($unifier);
}
die();
}
}
else // there's no justification given for this line
{ // check that $prop is in $valid or follows from
// something in $valid
$notyet = true;
$prop = $line;
$unifier = array(); // an empty array
if(functor($prop)=="AN")
{ // first check if it follows by deMorgan's law from something in $valid
$premise = "NO" . negation($prop);
if(in_array($premise, $valid->stk))
{ $valid->push($line);
continue;
}
$r = explode("+", args($prop));
foreach($r as $s)
{ $notyet = true;
foreach($valid->stk as $q)
{ if($s == $q)
{ $notyet = false;
break; // $s is verified
}
}
if($notyet)
{ echo "Could not check $s in $line\n";
die();
}
}
$valid->push($line);
continue;
}
else
{ foreach($valid->stk as $q)
{ if($prop != $q && functor($q) != "AN")
continue;
if(functor($q) == "AN")
{ $r = explode("+", args($q));
$flag44 = false;
foreach($r as $s)
{ if($prop == $s)
{ $flag44 = true;
break;
}
}
if($flag44== false)
continue;
}
$notyet = false;
$valid->push($prop);
// echo "pushing $prop\n";
break; // $prop is verified
}
if($notyet && functor($prop) == "OR")
{ // it's enough if one of the disjuncts is in $valid->stk
$flag44 = false;
$disjuncts = explode("|",args($prop));
foreach($disjuncts as $x)
{ // echo "checking $x\n";
foreach($valid->stk as $q)
{ if($x == $q)
{ $valid->push($prop); // $prop is verified
$flag44=true;
break;
}
}
if($flag44)
break;
}
if($flag44)
continue;
}
if($notyet)
{ if(functor($prop) == "OR")
{ $previous = $valid->peek();
if(functor($previous) == "OR")
{ $R = explode("|", args($previous));
// is every member of $disjuncts in $R$?
$flag63 = false;
foreach($disjuncts as $x)
{ if(!in_array($x, $R))
{ $flag63 = true;
break;
}
}
if($flag63)
{ echo("Dying at line 766\n");
print_r($valid);
echo "$previous $prop\n";
die();
}
// Now see if every member of $R$ is
// either in $disjuncts or its negation is in $valid->stk;
$flag64 = false;
foreach($R as $x)
{ if(in_array($x, $disjuncts))
continue;
if(in_array(negation($x), $valid->stk))
continue;
$flag64 = true;
break;
}
if($flag64)
{ echo "Dying at line 602 with $x\n";
print_r($R);
print_r($disjuncts);
die();
}
$valid->push($prop); // checked it successfully
// echo "pushing $prop\n";
continue;
}
}
echo "could not check $prop in $line\n";
print_r($valid);
die();
}
}
}
// echo "checked $line\n";
// $Now $line is successfully checked
}
// all done. But there should now be no marks in $valid
if($valid->marked())
{ echo("Final stack contains a mark\n");
print_r($valid);
die();
}
echo "Proof checked OK. ";
echo $inference_count; echo " inferences. ";
}
//_____________________________________________________
ini_set('memory_limit', '1024M');
$count = 0;
foreach($results as $lemma)
{ $testfile = $lemma->label . ".prf";
if($lemma->kind == "proposition")
$testfile = "Prop" . $testfile;
echo "Checking $testfile\n";
check_proof($testfile);
++$count;
echo ("That makes $count proofs.\n");
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists