Skip to content

Instantly share code, notes, and snippets.

@Iijil1
Created June 15, 2024 16:30
Show Gist options
  • Save Iijil1/d325da33be74a86ac2399c161a57166a to your computer and use it in GitHub Desktop.
Save Iijil1/d325da33be74a86ac2399c161a57166a to your computer and use it in GitHub Desktop.
Compile tms to 2 symbol tms encoding the symbols of the original tm with length 2
<?php
#erdos:
# php compiler.php 2RB2RB1RA3RA_0LC1RB3RB2RA_0LE1LC2LC3LD_0RB1LD2LD3LD_1RD2RD3RD1RZ
#ack14:
# php compiler.php 1RB3LB1RZ2RA_2LC3RB1LC2RA_3RB1LB3LC2RC
#ack11:
# php compiler.php 1RB1RZ1LA2RB_1RC3RC1LA2LB_2LB2RC1LC3RB
#bigfoot:
# php compiler.php 1RB2RA1LC_2LC1RB2RB_1RZ2LA1LA
# --- transitions in the input are treated as "undefined", meaning the compiled TM is allowed to do anything when it encounters this transition.
# For many champions or cryptids that are given with a --- transition it is important that it halts when the tm tries to use this transition.
# To specify that use 1RZ instead of ---.
const MAXSTEPS = 10000; //for TNF conversion
function done($text)
{
echo("$text\n"); die;
}
function output($tm)
{
echo(tmToString(convert($tm))."\n");
}
function outputMeta($stateMap, $leftEncoding, $rightEncoding)
{
echo("left side symbol encoding: ".encodingToString($leftEncoding)."\n");
echo("right side symbol encoding: ".encodingToString($rightEncoding)."\n");
echo("state encoding: ".stateMapToString($stateMap)."\n");
}
function encodingToString($encoding)
{
$symbols = [];
foreach ($encoding as $symbol => $macroSymbol) {
$symbols[] = implode("->",[$symbol,implode("",$macroSymbol)]);
}
return implode(", ", $symbols);
}
function stateMapToString($stateMap)
{
$states = [];
foreach ($stateMap as $state => $macroState) {
$states[] = implode("->",[$state,intToState($macroState)]);
}
return implode(", ", $states);
}
function convert($tm)
{
$startState = $tm["start"];
unset($tm["states"], $tm["symbols"], $tm["start"]);
$stateMap = [0 => $startState];
$symbolMap = [0 => 0];
$config = [$startState, 0, [0 => 0]];
for ($i = 0; $i < MAXSTEPS; $i++) {
$config = stepTm($tm, $config);
if ($config === "HALT") {
break;
}
[$state, $pos, $tape] = $config;
if (!isset($tape[$pos])) {
$tape[$pos] = 0;
$config[2][$pos] = 0;
}
if (!in_array($state, $stateMap)) {
$stateMap[] = $state;
}
if (isset($tape[$pos-1]) && !in_array($tape[$pos-1], $symbolMap)) {
$symbolMap[] = $tape[$pos-1];
}
if (isset($tape[$pos+1]) && !in_array($tape[$pos+1], $symbolMap)) {
$symbolMap[] = $tape[$pos+1];
}
}
$unseenStates = array_diff(array_keys($tm),$stateMap);
if (count($unseenStates) > 0) {
echo("unseen states: ". implode(", ", $unseenStates) ."\n");
}
$dirMap = ["R" => "R", "L" => "L"];
if ($tm[0][0][1] === "L") {
$dirMap = ["R" => "L", "L" => "R"];
}
$rtm = array_map(function ($state) use ($tm, $symbolMap, $dirMap, $stateMap) {
return array_map(function ($symbol) use ($tm, $symbolMap, $dirMap, $stateMap, $state) {
if (!isset($tm[$state][$symbol])) {
return "undef";
}
$transition = $tm[$state][$symbol];
if ($transition === "halt") {
return "halt";
}
[$nSymbol, $ndir, $nState] = $transition;
$rSymbol = array_search($nSymbol, $symbolMap);
$rState = array_search($nState, $stateMap);
$rDir = $dirMap[$ndir];
if ($rSymbol === false) {
echo("required symbol $nSymbol was unseen\n");
}
if ($rState === false) {
return "halt";
}
return [$rSymbol, $rDir, $rState];
}, $symbolMap);
}, $stateMap);
return $rtm;
}
function stepTm($tm, $config)
{
[$state, $pos, $tape] = $config;
$symbol = $tape[$pos];
if (!isset($tm[$state][$symbol])) {
return "HALT";
}
[$nextSymbol, $dir, $nextState] = $tm[$state][$symbol];
if (!isset($tm[$nextState])) {
return [$nextState, $pos, $tape];
}
$tape[$pos] = $nextSymbol;
$state = $nextState;
$pos = $pos + ["L" => -1, "R" => 1][$dir];
return [$state, $pos, $tape];
}
function tmToString($tm)
{
unset($tm["states"],$tm["symbols"]);
$maxState = 0;
foreach ($tm as $state => $data) {
if ($state > $maxState) {
$maxState = $state;
}
}
$states = [];
for ($i = 0; $i <= $maxState; $i++) {
$transitions = [];
for ($j = 0; $j < 2; $j++) {
if (!isset($tm[$i], $tm[$i][$j])) {
$transitions[] = "---";
continue;
}
$trans = $tm[$i][$j];
if ($trans === "halt") {
$transitions[] = "1RZ";
continue;
}
if ($trans === "undef") {
$transitions[] = "---";
continue;
}
[$symbol, $dir, $state] = $tm[$i][$j];
$transitions[] = implode("", [$symbol, $dir, intToState($state)]);
}
$states[] = implode("", $transitions);
}
return implode("_", $states);
}
function intToState($o)
{
if (!preg_match("/^\d+$/", $o)) {
return "[$o]";
}
return chr(ord("A")+$o);
}
function readTm($tmString)
{
$stateStrings = explode("_", $tmString);
if (count($stateStrings) == 0) {
done("tm must have a state");
}
$tm = [
"states" => count($stateStrings),
"symbols" => strlen($stateStrings[0])/3,
];
foreach ($stateStrings as $offset => $stateString) {
if (strlen($stateString) != $tm["symbols"]*3) {
done("invalid std format stateString length");
}
$curState = intToState($offset);
foreach (str_split($stateString, 3) as $curSymbol => $tranString) {
if ($tranString === "---") {
continue;
}
$tm[$curState][$curSymbol] = str_split($tranString, 1);
}
}
return $tm;
}
function compile($tm)
{
$done = false;
$maxStates = 1;
while (!$done) {
echo("trying $maxStates states\n");
foreach (getRequiredStatesAndSymbols($tm) as [$requiredStates, $requiredLeftSymbols, $requiredRightSymbols]) {
foreach (getEncodings($requiredLeftSymbols) as $leftEncoding) {
foreach (getEncodings($requiredRightSymbols, $leftEncoding) as $rightEncoding) {
$roleConditions = extractConditions($tm, $requiredStates, $leftEncoding, $rightEncoding);
global $mode;
if ($mode%2 == 1) {
if (bruteforceCompile($maxStates, $roleConditions, $requiredStates, $leftEncoding, $rightEncoding)) {
$done = true;
};
} else {
if (subTMCompile($tm, $maxStates, $roleConditions, $requiredStates, $leftEncoding, $rightEncoding)) {
$done = true;
};
}
}
}
}
$maxStates++;
}
}
function getEncodings($requiredSymbols, $existingEncoding = [0 => [0,0]])
{
if (count($requiredSymbols) > 4) {
done("more than 4 symbols required");
}
global $mode;
if ((($mode / 2) % 2) === 1) {
$existingEncoding = [0 => [0,0]];
}
foreach ($existingEncoding as $symbol => $enc) {
if (!in_array($symbol, $requiredSymbols)) {
unset($existingEncoding[$symbol]);
}
}
$possibleEncodings = removeEncodings([[0,0],[0,1],[1,0],[1,1]], $existingEncoding);
$requiredSymbols = array_diff($requiredSymbols, array_keys($existingEncoding));
return completeEncoding($requiredSymbols, $possibleEncodings, [$existingEncoding]);
}
function completeEncoding($requiredSymbols, $possibleEncodings, $existingEncodings)
{
if (count($requiredSymbols) === 0) {
return $existingEncodings;
}
$symbol = array_shift($requiredSymbols);
$extendedEncodings = [];
foreach ($possibleEncodings as $encoding) {
foreach (completeEncoding($requiredSymbols, removeEncodings($possibleEncodings, [$encoding]), $existingEncodings) as $extendedEncoding) {
$extendedEncoding[$symbol] = $encoding;
$extendedEncodings[] = $extendedEncoding;
}
}
return $extendedEncodings;
}
function removeEncodings($encs, $rems)
{
$encs = array_map(function ($arr) { return implode(",", $arr); }, $encs);
$rems = array_map(function ($arr) { return implode(",", $arr); }, $rems);
$encs = array_diff($encs, $rems);
$encs = array_map(function ($str) { return explode(",", $str); }, $encs);
return $encs;
}
function subTMCompile($targetTm, $maxStates, $roleConditions, $requiredStates, $leftEncoding, $rightEncoding)
{
$stateTms = [];
$todoStates = [];
for ($state = 0; $state < $targetTm["states"]; $state++) {
$todoStates[] = $state;
}
$success = false;
$stateMaxStates = 0;
while ($stateMaxStates * count($todoStates) <= $maxStates) {
foreach($todoStates as $state) {
[$tm, $conditions, $targetRoles, $stateMap] = initialMap($requiredStates, $roleConditions, $state);
$stateTms[$state] = [[], $stateMap];
if ($tm["states"] > $stateMaxStates) {
continue;
}
$tms = grow($tm, $stateMaxStates, $stateMap, $conditions, $targetRoles, $leftEncoding, $rightEncoding);
if (count($tms) > 0) {
$stateTms[$state] = [$tms, $stateMap];
$maxStates = $maxStates - $stateMaxStates - 1;
unset($todoStates[$state]);
}
}
if (count($todoStates) === 0) {
$success = true;
break;
}
$stateMaxStates++;
}
if ($success) {
[$prodTms, $stateMap] = combine($stateTms);
outputMeta($stateMap, $leftEncoding, $rightEncoding);
$minStates = $prodTms[0]["states"];
foreach ($prodTms as &$compiledTm) {
$compiledTm["states"] = count($compiledTm) - 2;
if ($compiledTm["states"] < $minStates) {
$minStates = $compiledTm["states"];
}
}
foreach ($prodTms as $compiledTm) {
if ($compiledTm["states"] === $minStates) {
$compiledTm["start"] = 0;
output($compiledTm);
}
}
}
return $success;
}
function bruteforceCompile($maxStates, $roleConditions, $requiredStates, $leftEncoding, $rightEncoding)
{
$success = false;
foreach (initialMapBruteforce($requiredStates, $roleConditions) as [$tm, $conditions, $stateMap]) {
if ($tm["states"] > $maxStates) {
continue;
}
$tms = grow($tm, $maxStates, $stateMap, $conditions, [], $leftEncoding, $rightEncoding);
if (count($tms) > 0) {
$success = true;
outputMeta($stateMap, $leftEncoding, $rightEncoding);
foreach ($tms as $compiledTm) {
if (isset($stateMap["LA"])) {
$compiledTm["start"] = $stateMap["LA"];
} else {
$compiledTm["start"] = $stateMap["RA"];
}
output($compiledTm);
}
// var_dump($roleConditions, $conditions, $stateMap); die;
}
}
return $success;
}
// commented are some methods, that give only one of the shortest combinations of subTMs
// this might be required to save memory, if there are many.
// function combine($stateTms)
// {
// $stateMap = [];
// $tm = ["states" => 0, "symbols" => 2];
// [$tm, $stateMap] = expand($tm, $stateMap, $stateTms);
// return [[$tm], $stateMap];
// }
// function expand($tm, $stateMap, $stateTms)
// {
// if (count($stateTms) === 0) {
// foreach ($tm as $key => $value) {
// if (in_array($key,["states", "symbols"])) {
// continue;
// }
// $tm[$key] = array_map(function($transition) use ($stateMap) {
// if ($transition === "halt") {
// return "halt";
// }
// $state = $transition[2];
// if (isset($stateMap[$state])) {
// $transition[2] = $stateMap[$state];
// }
// return $transition;
// }, $value);
// }
// $shrunk = shrink($tm);
// return [$shrunk, $stateMap];
// }
// [$nextTms, $nextStateMap] = array_shift($stateTms);
// $usedStates = $tm["states"];
// foreach ($nextStateMap as $role => $state) {
// $stateMap[$role] = $state + $usedStates;
// }
// foreach ($nextTms as $newTm) {
// $newStates = $newTm["states"];
// unset($newTm["states"],$newTm["symbols"]);
// $incCopy = [];
// foreach ($newTm as $i=>$symbolTransitions) {
// $incCopy[$i + $usedStates] = array_map(function($transition) use ($usedStates) {
// if ($transition === "halt") {
// return "halt";
// }
// if (preg_match("/^\d+$/", $transition[2])) {
// $transition[2] = $transition[2] + $usedStates;
// }
// return $transition;
// }, $symbolTransitions);
// }
// $tm["states"] = $tm["states"] + $newStates;
// foreach ($incCopy as $key => $value) {
// $tm[$key] = $value;
// }
// [$grownTm, $grownStateMap] = expand($tm, $stateMap, $stateTms);
// if (!isset($bestTm) || $bestTm["states"] > $grownTm["states"]) {
// $bestTm = $grownTm;
// $bestMap = $grownStateMap;
// }
// }
// return [$bestTm, $bestMap];
// }
function combine($stateTms)
{
[$tms, $stateMap] = array_shift($stateTms);
return expand($tms, $stateMap, $stateTms);
}
function expand($tms, $stateMap, $stateTms)
{
if (count($stateTms) === 0) {
$shrunk = [];
foreach ($tms as $tm) {
foreach ($tm as $key => $value) {
if (in_array($key,["states", "symbols"])) {
continue;
}
$tm[$key] = array_map(function($transition) use ($stateMap) {
if ($transition === "halt") {
return "halt";
}
$state = $transition[2];
if (isset($stateMap[$state])) {
$transition[2] = $stateMap[$state];
}
return $transition;
}, $value);
}
$shrunk[] = shrink($tm);
}
return [$shrunk, $stateMap];
}
[$nextTms, $nextStateMap] = array_shift($stateTms);
$usedStates = $tms[0]["states"];
foreach ($nextStateMap as $role => $state) {
$stateMap[$role] = $state + $usedStates;
}
$prodTms = [];
foreach ($nextTms as $newTm) {
$newStates = $newTm["states"];
unset($newTm["states"],$newTm["symbols"]);
$incCopy = [];
foreach ($newTm as $i=>$symbolTransitions) {
$incCopy[$i + $usedStates] = array_map(function($transition) use ($usedStates) {
if ($transition === "halt") {
return "halt";
}
if (preg_match("/^\d+$/", $transition[2])) {
$transition[2] = $transition[2] + $usedStates;
}
return $transition;
}, $symbolTransitions);
}
foreach ($tms as $oldTm) {
$oldTm["states"] = $oldTm["states"] + $newStates;
foreach ($incCopy as $key => $value) {
$oldTm[$key] = $value;
}
$prodTms[] = $oldTm;
}
}
return expand($prodTms, $stateMap, $stateTms);
}
function shrink($tm)
{
unset($tm["states"], $tm["symbols"]);
$tm = recursiveShrink($tm);
$tm["states"] = count($tm);
$tm["symbols"] = 2;
return $tm;
}
function recursiveShrink($tm) {
$compatibleStates = array_map(function($stateData) use ($tm) {
return array_combine(array_keys($tm),array_keys($tm));
},$tm);
$change = true;
while ($change === true) {
$change = false;
foreach ($compatibleStates as $state1 => $options) {
foreach ($options as $state2) {
if (compatibleState($tm, $state1, $state2, $compatibleStates)) {
continue;
}
unset($compatibleStates[$state1][$state2], $compatibleStates[$state2][$state1]);
$change = true;
}
}
}
foreach ($compatibleStates as $state => $options) {
if (count($options) <= 1) {
unset($compatibleStates[$state]);
continue;
}
$compatibleStates[$state] = array_diff($options, [$state]);
}
$bestTm = $tm;
foreach ($compatibleStates as $state1 => $options) {
foreach ($options as $state2) {
$try = tryCollapse($tm, [[$state1, $state2]]);
if ($try !== false) {
$try = recursiveShrink($try);
if (count($try) < count($bestTm)) {
$bestTm = $try;
}
}
}
}
return $bestTm;
}
function tryCollapse($tm, $todo) {
if (count($todo)=== 0) {
return $tm;
}
[$state1, $state2] = array_shift($todo);
//after this loop is done all transitions from state 1
//are mirrored in state 2. Additional state equalities
//that have to hold are appended to $todo.
foreach ($tm[$state1] as $symbol => $trans1) {
//continue if this transition is fine
//return false if it is incompatible
if (!isset($tm[$state2][$symbol])) {
$tm[$state2][$symbol] = $trans1;
continue;
}
$trans2 = $tm[$state2][$symbol];
if ($trans1 === "halt") {
if ($trans2 !== "halt") {
return false;
}
continue;
}
if ($trans2 === "halt") {
if ($trans1 !== "halt") {
return false;
}
continue;
}
[$sym1, $dir1, $next1] = $trans1;
[$sym2, $dir2, $next2] = $trans2;
if ($sym1 !== $sym2) {
return false;
}
if ($dir1 !== $dir2) {
return false;
}
if ($next1 === $next2) {
continue;
}
$todo[] = [$next1, $next2];
}
unset($tm[$state1]);
//redirect all transitions into state1 to state2
foreach ($tm as &$transitions) {
foreach ($transitions as &$trans) {
if ($trans === "halt") {
continue;
}
if ($trans[2] === $state1) {
$trans[2] = $state2;
}
}
}
//clean up $todo
foreach ($todo as $i => [$todo1, $todo2]) {
if ($todo1 === $state1) {
$todo1 = $state2;
}
if ($todo2 === $state1) {
$todo2 = $state2;
}
if ($todo1 === $todo2) {
unset($todo[$i]);
continue;
}
$todo[$i] = [$todo1, $todo2];
}
return tryCollapse($tm, $todo);
}
function compatibleState($tm, $state1, $state2, $compatibleStates)
{
foreach ($tm[$state1] as $symbol => $transition1) {
if (!isset($tm[$state2][$symbol])) {
continue;
}
$transition2 = $tm[$state2][$symbol];
if (!compatibleTransition($transition1, $transition2, $compatibleStates)) {
return false;
}
}
return true;
}
function compatibleTransition($trans1, $trans2, $compatibleStates)
{
if ($trans1 === "halt") {
return ($trans2 === "halt");
}
if ($trans2 === "halt") {
return ($trans1 === "halt");
}
[$sym1, $dir1, $state1] = $trans1;
[$sym2, $dir2, $state2] = $trans2;
if ($sym1 !== $sym2) {
return false;
}
if ($dir1 !== $dir2) {
return false;
}
return in_array($state2, $compatibleStates[$state1]);
}
function initialMap($requiredStates, $roleConditions, $focusedState)
{
$state = 0;
$stateMap = [];
foreach (array_keys($requiredStates) as $role) {
if (strpos($role, intToState($focusedState)) === false) {
continue;
}
$stateMap[$role] = $state;
$state ++;
}
$tm = ["states" => $state, "symbols" => 2];
$conditions = [];
$targetRoles = [];
foreach($roleConditions as $config => $goal) {
if (strpos($config, intToState($focusedState)) === false) {
continue;
}
[$config, $goal] = str_replace(array_keys($stateMap), array_values($stateMap), [$config, $goal]);
$conditions[$config] = $goal;
if ($goal === "HALT") {
continue;
}
$goalState = decodeConfig($goal)[0];
if (preg_match("/^\d+$/",$goalState) || in_array($goalState, $targetRoles)) {
continue;
}
$targetRoles[] = $goalState;
}
return [$tm, $conditions, $targetRoles, $stateMap];
}
function initialMapBruteforce($requiredStates, $roleConditions)
{
$leftStates = [];
$rightStates = [];
foreach ($requiredStates as $role => [$fromDir, ]) {
switch ($fromDir) {
case "L":
$leftStates[] = $role;
break;
case "R":
$rightStates[] = $role;
break;
}
}
$possibileMaps = [];
foreach (partialBijections($leftStates, $rightStates) as $roleCollapse) {
$state = 0;
$stateMap = [];
foreach (array_keys($requiredStates) as $role) {
if (isset($stateMap[$role])) {
continue;
}
$stateMap[$role] = $state;
if (isset($roleCollapse[$role])) {
$stateMap[$roleCollapse[$role]] = $state;
}
$state ++;
}
$tm = ["states" => $state, "symbols" => 2];
$conditions = [];
foreach($roleConditions as $config => $goal) {
[$config, $goal] = str_replace(array_keys($stateMap), array_values($stateMap), [$config, $goal]);
if (isset($conditions[$config])) {
if ($conditions[$config] !== $goal) {
continue 2;
}
}
$conditions[$config] = $goal;
}
$possibileMaps[] = [$tm, $conditions, $stateMap];
}
return $possibileMaps;
}
function partialBijections($set1, $set2, $tail=[[]])
{
if (count($set1) === 0) {
return $tail;
}
$elem1 = array_shift($set1);
$pbs = [];
foreach ($tail as $partial) {
$pbs[] = $partial;
foreach ($set2 as $elem2) {
if (in_array($elem2, $partial)) {
continue;
}
$partial[$elem1] = $elem2;
$pbs[] = $partial;
}
}
return partialBijections($set1, $set2, $pbs);
}
function grow($tm, $maxStates, $stateMap, $conditions, $targetRoles, $leftEncoding, $rightEncoding)
{
$todo = check($tm, $conditions);
switch ($todo) {
case "works":
return [$tm];
case "contra":
return [];
}
//grow
while (true) {
foreach ($conditions as $config => $goal) {
[$nextConfig, $status] = step($tm, $config);
switch ($status) {
case "step":
unset($conditions[$config]);
$conditions[$nextConfig] = $goal;
continue 2;
case "halt":
case "done":
unset($conditions[$config]);
continue 2;
}
//undef
[$state, $pos, $tape] = decodeConfig($nextConfig);
return growAt($state, $tape[$pos], $tm, $maxStates, $stateMap, $conditions, $targetRoles, $leftEncoding, $rightEncoding);
}
}
done("nowhere to grow");
}
function growAt($state, $symbol, $tm, $maxStates, $stateMap, $conditions, $targetRoles, $leftEncoding, $rightEncoding)
{
$possibleTms = [];
$tm[$state][$symbol] = "halt";
$possibleTms = array_merge($possibleTms, grow($tm, $maxStates, $stateMap, $conditions, $targetRoles, $leftEncoding, $rightEncoding));
foreach ($targetRoles as $newState) {
foreach ([["L",0],["L",1],["R",0],["R",1]] as [$dir, $newSymbol]) {
$tm[$state][$symbol] = [$newSymbol, $dir, $newState];
$possibleTms = array_merge($possibleTms, grow($tm, $maxStates, $stateMap, $conditions, $targetRoles, $leftEncoding, $rightEncoding));
}
}
$curStates = $tm["states"];
for ($newState = 0; $newState <= $curStates; $newState++) {
if ($newState == $curStates) {
$tm["states"] = $newState + 1;
if ($tm["states"] > $maxStates) {
continue;
}
}
foreach ([["L",0],["L",1],["R",0],["R",1]] as [$dir, $newSymbol]) {
$tm[$state][$symbol] = [$newSymbol, $dir, $newState];
$possibleTms = array_merge($possibleTms, grow($tm, $maxStates, $stateMap, $conditions, $targetRoles, $leftEncoding, $rightEncoding));
}
}
return $possibleTms;
}
function check($tm, $conditions)
{
foreach ($conditions as $config => $goal) {
[$finConfig, $status] = ffwd($tm, $config);
if ($status === "done") {
if ($finConfig === $goal) {
unset($conditions[$config]);
continue;
}
return "contra";
}
if (isset($conditions[$finConfig])) {
if ($conditions[$finConfig] !== $goal) {
return "contra";
}
}
if (!preg_match("/^\d+$/", decodeConfig($finConfig)[0])) {
return "contra";
}
unset($conditions[$config]);
$conditions[$finConfig] = $goal;
}
if (count($conditions) === 0) {
return "works";
}
return "grow";
}
function step($tm, $configString)
{
[$state, $pos, $tape] = decodeConfig($configString);
if (!isset($tape[$pos])) {
return [$configString, "done"];
}
if (!isset($tm[$state][$tape[$pos]])) {
return [$configString, "undef"];
}
$transition = $tm[$state][$tape[$pos]];
if ($transition === "halt") {
return [$configString, "halt"];
}
[$tape[$pos], $dir, $state] = $transition;
$pos = ["L" => ["L",0] , "R" => [1,"R"]][$dir][$pos];
$configString = encodeConfig([$state, $pos, $tape]);
return [$configString, "step"];
}
function ffwd($tm, $configString)
{
$history = [];
$status = "step";
while ($status === "step") {
if (in_array($configString, $history)) {
return ["CYCLE", "done"];
}
$history[]=$configString;
[$configString, $status] = step($tm, $configString);
}
if ($status === "halt") {
return ["HALT", "done"];
}
return [$configString, $status];
}
function encodeConfig($config)
{
$config[2] = implode(",", $config[2]);
return implode(";",$config);
}
function decodeConfig($configString)
{
$config = explode(";", $configString);
$config[2] = explode(",", $config[2]);
return $config;
}
function extractConditions($tm, $requiredStates, $leftEncoding, $rightEncoding)
{
$encoding = ["L" => $rightEncoding, "R" => $leftEncoding];
unset($tm["states"]);
unset($tm["symbols"]);
$conds = [];
foreach ($requiredStates as [$fromDir, $fromState]) {
foreach ($tm[$fromState] as $fromSymbol => [$toSymbol, $toDir, $toState]) {
if (!isset($encoding[$fromDir][$fromSymbol])) {
continue;
}
$config = encodeCondition($fromState, $fromDir, $encoding[$fromDir][$fromSymbol]);
$goal = "HALT";
if (isset($tm[$toState])) {
$goal = encodeGoal($toState, $toDir, $encoding[$toDir][$toSymbol]);
}
$conds[$config] = $goal;
}
}
return $conds;
}
function encodeCondition($fromState, $fromDir, $tape)
{
return implode(";", [encodeState($fromDir, $fromState), ["R"=>1,"L"=>0][$fromDir], implode(",",$tape)]);
}
function encodeGoal($toState, $toDir, $tape)
{
return implode(";", [encodeState(m($toDir), $toState), $toDir, implode(",",$tape)]);
}
function encodeState($dir, $state)
{
return $dir . $state;
}
function getRequiredStatesAndSymbols($tm)
{
unset($tm["states"], $tm["symbols"]);
$reqs = [];
$reqL = ["0"];
$reqR = ["0"];
foreach ($tm as $symbolTransitions) {
if (!is_array($symbolTransitions)) {
continue;
}
foreach ($symbolTransitions as $transition) {
if (!is_array($transition)) {
continue;
}
[$symbol, $dir, $state] = $transition;
if (!isset($tm[$state])) {
continue;
}
$dir = m($dir);
$reqs[encodeState($dir, $state)] = [$dir, $state];
if ($dir === "L" && !in_array($symbol, $reqL)) {
$reqL[] = $symbol;
}
if ($dir === "R" && !in_array($symbol, $reqR)) {
$reqR[] = $symbol;
}
}
}
if (isset($reqs[encodeState("L", "A")]) || isset($reqs[encodeState("R", "A")]) ) {
return [[$reqs, $reqL, $reqR]];
}
$reqsL = $reqs;
$reqsL[encodeState("L", "A")] = ["L", "A"];
$reqsR = $reqs;
$reqsR[encodeState("R", "A")] = ["R", "A"];
return [[$reqsL, $reqL, $reqR], [$reqsR, $reqL, $reqR]];
}
function m($dir)
{
return ["L"=>"R","R"=>"L"][$dir];
}
//--------------------main-------------------------------
if (!isset($argv[1])) {
done("Usage: php compiler.php <StdTmString> mode\nmode % 2 = 1 -> bruteforce\nmode/2 % 2 = 1 -> different side encodings\n");
}
global $mode;
$mode = 0;
if (isset($argv[2])) {
$mode = $argv[2];
}
$tmString = $argv[1];
$tm = readTm($tmString);
compile($tm);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment