// ***************************************************************** // ***************************************************************** // SAT Problem Solving Self-Replicating Rules // written by Hui-Hsien Chou // ***************************************************************** // ***************************************************************** // // ***************************************************************** // *********** The SAT Predicate Encoding Section *************** // ***************************************************************** // A SAT predicate is encoded using the following four arrays, pos1[] // pos2[], code1[], and code2[]. The position arrays listed the // index of the variables in a SAT predicate, and the code arrays // listed the expected boolean values of the variable. For example, // as set in the following arrays, the predicate // // (x_1 and not x_3) or (not x_1 and x_2) or (not x_2 and x_3) // // are encoded. // This variable denotes the number of SAT clauses. int noclauses = 6; // First condition position for each clause. The number is the index // of the binary bit within each SAT sequence. int pos1[] = { 0, 1, 1, 2, 4, 4, 5}; // First condition listing for each clause. int code1[] = { 0, '1:code', '0:code', '0:code', '0:code', '1:code', '0:code'}; // Second condition position for each clause. The number is the index // of the binary bit within each SAT sequence. int pos2[] = { 0, 3, 2, 3, 4, 5, 6}; // Second condition listing for each clause. int code2[] = { 0, '0:code', '1:code', '1:code', '0:code', '1:code', '1:code'}; // ***************************************************************** // ***************** Default Rules ******************* // ***************************************************************** // The default action is to maintain no change if none of the rule // changes the next state value for each field. Therefore, the current // value is copied over to the next state for each field. default code=code; default pos=pos; default direc=direc; default clause=clause; default special=special; default color=color; // ***************************************************************** // ********* Direction to Neighbor Position Conversion ************* // ***************************************************************** // This function maps a directional pointer in the 'direc' field to // a neighbor position. nbr PointTo(int x) { rot if (x=='<:direc') return ea:; else return ce:; } // ***************************************************************** // ***************** Virus Broadcasting Rules ********************** // ***************************************************************** // If there is no virus in a cell, thus clause==0, then copy the virus // value from either the north or west neighbor, if any of them exists, // then modify the value by one modulo the total number of the clauses. // This modified virus value is then stored in the cell. if (clause==0) if (no:clause) clause=no:clause%noclauses+1; else if (we:clause) clause=we:clause%noclauses+1; // ***************************************************************** // ************ The SAT Rules for Setting Flags ******************** // ***************************************************************** // If special is set at any of the destruction flags, reset it. if (special=='#' || special=='!') special='.'; // If current cell is bound (thus direc!=0) and there is a destruction // flag nearby, set the destruction flag in the current cell. else rot if (direc && no:special=='#') special='#'; // This rule retracts the replicating arm once a collision is found // (thus the '!' flag is set). It will copy the retraction flag // until the end of the corner (judged by we:direc=='<') is reached, // where the retraction flag is converted to the arm extrusion // flag '*'. else rot if (no:direc=='<,1' && no:special=='!') if (we:direc=='<') special='*'; else special='!'; // This rule determines if else rot if (code && direc=='<,2' && (special=='.' || special=='?') && (ea:code=='D' || we:code=='D')) special='+'; // The arm extrusion failure checking. A failed attempt at new arm // extrusion will result in flag '*' being set in the corner, which // allows further attemps at the other direction later. else rot if (code=='F' && direc=='<,1' && no:direc==0 && we:code=='o') special='*'; // This rule resets flag '+' to '-' after seeing L. else if (special=='+' && code=='L') special='-'; // Code E will always clear the special field. else if (code=='E') special='.'; // This rule resets the special flags '+' or '-' to either quiescent // state or flag '*', depending the condition else if (special=='+' || special=='-') { if (PointTo(direc):code=='o') special='.'; else if (code=='A' || code=='B') special='*'; // The virus checking codes. If a SAT bit is on the current cell (thus // pos!=0)... } else if (pos) { // see if it violates the first variable expectation of the virus if (special=='.' && pos==pos1[clause] && code==code1[clause]) special='?'; // yes, set the alarm flag ? // if alarm flag has been set, see if it violates the second // variable expectation. If both are violated, set the destruction // flag '#' to infect the loop. Otherwise, reset to normal, the // loop is not infected. else if (special=='?' && pos==pos2[clause]) if (code==code2[clause]) special='#'; else special='.'; } // ***************************************************************** // *************** Rules for Bound Cells ***************** // ***************************************************************** if (direc) { // if any of the destruction flag is set, reset everything to 0 if (special=='#' || special=='!') { direc=0; code=0; pos=0; color=0; // do checking for real codes only } else if (code) // if D sees a '+' flag nearby, it disappears if (code=='D') { rot if (ea:special=='+') { code='.'; direc='.'; color=0; } // if the closing of loop is detected, set Code D } else rot if (direc=='<,2' && nw:direc=='<,1' && nw:code && ne:direc=='<,3' && ne:code) { code='D'; pos=0; // the rule to close the loop in the child loop } else if (PointTo(direc):code=='D') { rot if (direc=='<,2') { direc='<,3'; code=no:code; } // the rule to generate the EF sequence seeing flag '*' } else if (code!='o' && PointTo(direc):code=='o' && code!='E' && special=='*') { code='E'; pos='0'; } else if (code=='E') code='F'; //****************** // This turns a new arm element into a temporarily inactive signal when around the U turns else rot if(we:code=='E' && we:direc=='<,3' && we:special=='*' && no:direc=='<,1' && direc=='<,2') code='N'; // This turns a new arm element into a temporarily inactive signal when around the U turns else rot if(we:code=='F' && we:direc=='<,3' && code=='N' && no:direc=='<,1' && direc=='<,2') code='N'; // This turns the inactive signal back to a growth after encountering the U turns else rot if(we:code=='N' && nw:code=='N' && ea:direc=='.' && no:direc=='<,1' && direc=='<,2') code='E'; // This turns the inactive signal back to a growth after encountering the U turns else rot if(we:code=='N' && code== 'E' && ea:direc=='.' && no:direc=='<,1' && direc=='<,2') code='F'; // the rule to prevent signal E getting copied beyound corner else rot if (direc=='<' && ea:code=='E' && ea:direc=='<,1' && (se:code=='F' || se:code=='N')) { code='o'; pos='0'; // same rule to prevent signal F getting copied beyound corner } else if (code=='o' && PointTo(direc):code=='F') code='o'; // rules to explore binary bit A or B to 0 or 1 when seeing '+' else if (PointTo(direc):special=='+') { if (PointTo(direc):code=='A') code='0'; else if (PointTo(direc):code=='B') code='1'; else code=PointTo(direc):code; pos=PointTo(direc):pos; // rules to explore binary bit A or B to 1 or 0 when seeing '+' } else if (PointTo(direc):special=='-') { if (PointTo(direc):code=='A') code='1'; else if (PointTo(direc):code=='B') code='0'; else code=PointTo(direc):code; pos=PointTo(direc):pos; // ****Mike rules } else rot if(we:code=='M' && we:direc=='<,3' && no:direc=='.' && nw:direc=='<,3' && direc=='<,2') code='N'; //******* else rot if(direc=='<,2' && we:code=='N' && we:direc=='<,3' && no:direc=='.') code='P'; //******** else rot if(we:code=='M' && we:direc=='<,1' && ea:code=='.'){ if(so:direc=='.') code='P'; else code='N'; // normal copying rules for signal flow in the loop }else { code=PointTo(direc):code; pos=PointTo(direc):pos; } // quiescent state changes to 'o' when seeing signal G else if (PointTo(direc):code=='G') code='o'; // ***************************************************************** // *************** Rules for Unbound Cells ***************** // ***************************************************************** } else { rot if(se:direc=='<' && so:direc=='<,1' && so:code=='G') code='.'; // quiescent state changes to 'o' when seeing signal G or M else rot if ((no:code=='G' || no:code=='M') && (no:special==0 || no:special=='?') && no:direc=='<,3' && ne:direc!='<,2' && nw:direc!='<') { direc='<,3'; //fix // check to see if collision occurs if (so:direc==0 || so:color==no:color) {// no collision code='o'; color=no:color; } else // yes, collision, set special='!'; // flag '!' to retract arm // ***make a U turn } else rot if(no:code=='P' && ne:code=='G' && ne:direc=='<,1' && no:direc=='<' && nw:direc=='.'){ code='o'; direc='<,3'; color=no:color; } else rot if(so:code=='P' &&se:direc=='<,3' && ea:direc=='<,3' && sw:direc=='.'){ code='o'; direc='<,1'; color=so:color; // ****turn right to make a u U turn } else rot if(so:direc=='<,2' && ea:code=='L' && ea:direc=='<,3' && we:code=='.'){ code='o'; direc='<'; color=ea:color; // EF sequence extruding a new branch } else rot if (so:code=='E' && so:direc=='<,1' && (so:special==0 || so:special=='?') && no:direc==0) { direc='<,1'; code='G'; color='^'; // The rule to set turn the signal flowing direction // when seeing signal L } else rot if (no:code=='L' && (no:special==0 || no:special=='?') && no:direc=='<' && nw:direc==0) { direc='<,3'; code='o'; if (so:direc==0 || so:color==no:color) color=no:color; else special='!'; } }