用C#模拟Post-Turing程序的运行

近期在学习计算理论,C#还是入门,利用它来实现计算理论的Post-Turing程序的运行,作为练习。

有关概念:

[Post-Turing程序]

数据:一条带,两端无穷,数据只有1和空(B表示);

指令集只有六条

(1)RIGHT     (指令代码为1)

(2)LEFT        (2)

(3)WRITE 1  (3)

(4)WRITE B  (4)

(5)TO Ai IF 1 (指令代码2i+4)

(6)TO Ai IF B (指令代码2i+3)

数的表示:比如3在带上表示为 1111B

[Godel数(歌德尔数)]

歌德尔数[a1,a2,...,an]表示 (P1^a1)*(P2^a2)*...*(Pn^an),其中P1,P2,...,Pn为素数列(2,3,5,7...);

[Cantor(康托)配对函数]

<X,Y> =( (X+Y)*(X+Y+1))/2 + Y

[程序说明]

给出一个歌德尔数,比如[7,20,44,13,2,9],数字表示指令代码。或者输入一个长整数,进行质因子分解得到一个歌德尔数。然后进行有效性判断:

1、歌德尔数中不能有0;

2、用Cantor配对函数对歌德尔数进行反向计算求到X,Y(如7=<2,1>),说得到的X和Y集合中,Y>0,而且X中不能有不为0且相同的数;否则歌德尔数不是能够转换为P-T程序的有效序列。

分解得到的X表示标号代码,Y无标号指令代码,比如:

7 -  <2,1> 表示程序语句:A2   RIGHT

20 - <0,5> 表示程序语句:TO A1 IF B

44 - <0,8> 表示程序语句:TO A2 IF 1

13 - <1,3>  A1 WRITE 1

2 - <0,1>  RIGHT

9 - <0,3> WRITE 1

根据歌德尔数得到P-T程序后,输入变量X,运行P-T程序对X进行计算。

[结论]

任意给定一个P-T程序,则一定对应一个唯一的歌德尔数;反之,任意给定一个整数得到的歌德尔数不一定有P-T程序与之对应。

另外,在P4 3G的机器上,如果整数超过8位,分解的时间太长,所以直接输入歌德尔序列更加有效。

[程序]

/*
 * Project : Post-Turing
 * Author : Sonky Jiang
 * Description : 任意输入一个正整数,得到Godel数,并模拟Post-Turing程序运行
 * Date : November,2005
 */

using System;
using System.Text;
using System.Collections;

namespace Computation
{
    class PostTuring
    {
        public static void Main(String[] args)
        {
            PostTuringMachine ptm = new PostTuringMachine();
            PostTuring gn = new PostTuring();
                    
         LabelReadChoose:
            try
            {
                while (true)
                {
                    Console.WriteLine("<Menu>");
                    Console.WriteLine("1 : Use default GodelList [7,20,44,13,2,9]");  //选择功能运行
                    Console.WriteLine("2 : Enter a long number to gain Godel Number");
                    Console.WriteLine("3 : Enter a Godel Number");
                    Console.WriteLine("Q : Exit System");
                    Console.Write("[Main Menu]Enter 1, 2, 3 or Q:");

                    string functionChar = Console.ReadLine();

                    if (functionChar.ToUpper().Equals("Q")) break;

                    int chooseInt = Convert.ToInt16(functionChar);     //读入功能选择

                    switch (chooseInt)
                    {
                        case 1:
                            ArrayList defaultGodelArrayList = new ArrayList();  //用来测试程序的默认Godel数

                            defaultGodelArrayList.Add(7);
                            defaultGodelArrayList.Add(20);
                            defaultGodelArrayList.Add(44);
                            defaultGodelArrayList.Add(13);
                            defaultGodelArrayList.Add(2);
                            defaultGodelArrayList.Add(9);

                            ptm.PrintPostTuringMachine(defaultGodelArrayList);
                            break;

                        case 2:   //如果选择2,则用户输入一个长整数,并分解质因子,得到一个歌德尔数。
                            Console.Write("[Menu 2]Enter a long number(such as 147456/629856) to gain GodelNumber:");

                        LabelReadTheLong:
                            string s = Console.ReadLine();
                            try
                            {
                                long theLong = Convert.ToInt64(s);
                               
                                if (!ptm.PrintPostTuringMachine(gn.OuputGodelNumber(theLong))) //如果输入的Godel数不能转化为有效的P-T程序,则重新输入,否则调用PostTuringMachine函数,运行post-turing机                            
                                {
                                     Console.Write("[Menu 2]Enter a new long number to gain Godel Number:");
                                     goto LabelReadTheLong;
                                }                                                                   
                            }
                            catch
                            {
                                Console.Write("Enter error,enter a new long number to gain GodelNumber:");
                                goto LabelReadTheLong;
                            }
                            break;
                        case 3:   //自行输入Godel数
                            Console.Write("[Menu 3]Enter a Godel Number:");

                        LabelReadGodelList:
                            string enterGodelString = Console.ReadLine();
                            try
                            {
                                if (!ptm.PrintPostTuringMachine(gn.GetEnterGodel(enterGodelString))) //如果输入的Godel数不能转化为有效的P-T程序,则重新输入
                                {
                                    Console.Write("[Menu 3]Enter a new Godel Number:");
                                    goto LabelReadGodelList;
                                }
                            }
                            catch
                            {
                                Console.WriteLine("Enter error,enter Godel Number again:");
                                goto LabelReadGodelList;
                            }
                            break;

                        default:
                            Console.Write("Error,just enter 1, 2 or 3:");
                            goto LabelReadChoose;
                    }
                }               
            }
            catch
            {
                Console.Write("Enter wrong,please enter 1, 2, 3 or Q:");
                goto LabelReadChoose;
            }       
        }       


        public ArrayList GetEnterGodel(string enterGodelString)  //得到输入的字符串,分割获得各个数字
        {
            ArrayList GodelListArrayList = new ArrayList();

            enterGodelString = enterGodelString.Trim();
            string[] split = enterGodelString.Split(new Char[] { ' ', ',' });//Split函数分割String中以空格或者‘,’为标志的字符串

            foreach (string s in split)
            {
                if (s.Trim() != "")
                {
                    int i = Convert.ToInt32(s);
                    GodelListArrayList.Add(i);
                }
            }
            return GodelListArrayList;
        }

        public ArrayList OuputGodelNumber(long theLong)
        {
            Prime p = new Prime();   
            ArrayList L = p.MakeoutPrimes(theLong);    //分解出长整数thelong以内的素数集,并存入ArrayList中
            ArrayList godelList = new ArrayList();    
            long godelNumberTemp = theLong;
            if (L.Count != 0)
            {
                int i = 0;
                int index = 0;

                while (i < L.Count) //计算godelNumberTemp在各个素数位上的指数,直到最后一个素数计算完毕
                {
                    if (godelNumberTemp % Convert.ToInt64(L[i].ToString()) == 0)
                    {
                        index++;        //如果正整数godelNumberTemp能够被L.get(i)中的素数整除,则该素数位的指数index加1;
                        godelNumberTemp = godelNumberTemp / Convert.ToInt64(L[i].ToString());
                        continue;     //算出godelNumberTemp/该素数的值,返回到循环体前部,继续计算这个值是否还可以被该素数整除
                    }
                    else   //如果不能整除,该素数位计算结束,输出它的指数index值。index赋值为0,计算下一个素数
                    {
                        godelList.Add(index);
                        index = 0;
                        i++;
                        if (godelNumberTemp == 1) break;  //如果godelNumberTemp已经=1,结束计算
                    }
                }

                Console.Write("The Primes Number is ");
                PrintValues(L, 0, i);
                Console.Write("The Godel Number of {0} is ", theLong);
                PrintValues(godelList);               
            }
            return godelList;
        }

        public void PrintValues(ArrayList myList)   //打印ArrayList中的所有object
        {
            Console.Write("[");
            for (int i = 0; i < myList.Count; i++)
            {
                if (i == myList.Count - 1)
                    Console.Write(myList[i].ToString());
                else
                    Console.Write(myList[i].ToString());
            }
            Console.WriteLine("]");
        }

        public void PrintValues(ArrayList myList, int index, int count)    //打印ArrayList中的从index开始的count个object
        {
            Console.Write("[");
            for (int i = index; i < (count + index); i++)
            {
                if (i == (count + index-1))
                    Console.Write(myList[i].ToString());
                else
                    Console.Write(myList[i].ToString());
            }
            Console.WriteLine("]");
        } 
    }

    class Prime
    {
        public bool IsPrime(long n)   //判断输入的数是否是素数
        {
            bool isPrime = true;
            if (n == 1) isPrime = false;
            for (long i = 2; i <= Math.Sqrt(n); i++)
            {
                if (n % i == 0)
                {
                    isPrime = false;
                    break;
                }
            }
            return isPrime;
        }

        public ArrayList MakeoutPrimes(long n)   //输出N以内的所有素数,以ArrayList形式输出
        {
            ArrayList pa = new ArrayList();

            for (long i = 1; i <= n; i++)
            {
                if (IsPrime(i)) pa.Add(i);
            }
            return pa;
        }
    }
   
    public class Cantor   //康托配对函数
    {
        public long CantorNumber(int x, int y)   //算出配对函数<x,y>的值
        {
            return ((x + y) * (x + y + 1)) / 2 + y;
        }

        public void ReCantorNumber(long c, out int x, out int y)  //算出一个数所对应的配对函数,不一定能够得到结果,如果没有得到有效的配对函数,则输出(0,0)
        {
            bool IsCantorNumber = false;
            x = 0;
            y = 0;

            for (int x1 = 0; ; x1++)  //穷举算出配对函数,如果找不到,退出的条件是<x1,1>的配对函数值大于c
            {
                if (CantorNumber(x1, 1) > c)
                {
                    x = 0;
                    y = 0;
                    break;
                }
                for (int y1 = 1; ; y1++)
                {
                    if (CantorNumber(x1, y1) > c) break;
                    if (CantorNumber(x1, y1) == c)
                    {
                        x = x1;
                        y = y1;

                        IsCantorNumber = true;                       
                    }
                }
                if (IsCantorNumber) break;                                                                    
            }
        }
    }

    public class PostTuringMachine    //Post-Turing机器
    {       
        public string PrintCode(int tab, int notab)    //打印程序代码,tab是标号代码,notab是无标号指令代码
        {
            string codeString;

            if (tab != 0)
            {
                codeString = "A" + tab.ToString() + " ";
            }
            else codeString = "   ";

            switch (notab)
            {
                case 1:
                    codeString += " RIGHT  ";
                    break;
               
                case 2:
                    codeString += " LEFT  ";
                    break;
                   
                case 3:
                    codeString += " WRITE 1  ";
                    break;
               
                case 4:
                    codeString += " WRITE B  ";
                    break;
               
                default:   //如果notab大于5
                    if (notab % 2 == 0)   //如果notab的值是偶数,则根据(2i+4)算出标号i的值
                    {
                        notab = (notab - 4) / 2;
                        codeString += " TO A" + notab.ToString() + " IF 1  ";
                    }
                    else   如果notab的值是奇数,则根据(2i+3)算出标号i的值
                    {
                        notab = (notab - 3) / 2;
                        codeString += " TO A" + notab.ToString() + " IF B  ";
                    }
                    break;
            }

            return codeString;
        }

        public bool PrintPostTuringMachine(ArrayList godelArrayList)   //打印出整个P-T程序
        {
            Cantor ct = new Cantor();
            int x;
            int y;

            ArrayList tempArrayList = new ArrayList();

            bool IsValidGodelList = true;

            //下面的语句判断输入的GodelList是否有效,即可以转化为一个P-T程序
            for (int i = 0; i < godelArrayList.Count; i++)
            {
                if (Convert.ToInt32(godelArrayList[i].ToString()) == 0)
                {
                    IsValidGodelList = false;
                    break;
                }

                ct.ReCantorNumber(Convert.ToInt64(godelArrayList[i].ToString()), out x, out y);

                if (y == 0)  //如果配对函数中的Y=0,则不是有效的godellist
                {
                    IsValidGodelList = false;
                    break;
                }

                for (int j = 0; j < tempArrayList.Count; j++)
                {

                    if ((x != 0) && (x == ((CantorCode)tempArrayList[j]).labelCodeInt)) //如果有不为0且相等的X,则不是有效的godelist
                    {
                        IsValidGodelList = false;
                        break;
                    }
                }

                CantorCode c1 = new CantorCode();
                c1.labelCodeInt = x;
                c1.operateCodeInt = y;
                tempArrayList.Add(c1);
            }

            if (IsValidGodelList)   //如果是有效的可转化为P-T程序的Godel,则运行
            {
                Console.WriteLine();
                Console.WriteLine("The P-T Program is:");
                Console.WriteLine("---------------------------------------");

                ArrayList programArrayList = new ArrayList();

                for (int i = 0; i < godelArrayList.Count; i++)              //将指令代码和标号代码存入programArrayList中
                {
                    ct.ReCantorNumber(Convert.ToInt64(godelArrayList[i].ToString()), out x, out y);   //得到一个数的配对函数〈x,y〉中的x,y值

                    CantorCode cc = new CantorCode();
                    cc.labelCodeInt = x;
                    cc.operateCodeInt = y;

                    programArrayList.Add(cc);

                    Console.WriteLine("{0,3}  --  <{1,2},{2,2}>  --  " + PrintCode(x, y), Convert.ToInt64(godelArrayList[i].ToString()), x, y);
                }

                Console.WriteLine("---------------------------------------");

                Console.Write("/nPlease enter the value of X to run the program:");

            LabelReadX:
                try
                {
                    int X = Convert.ToInt32(Console.ReadLine());    //读入X的值
                    RunPostTuringMachin(programArrayList, X);       //运行P-T程序
                }
                catch
                {
                    Console.Write("Enter wrong,please enter a int number:");
                    goto LabelReadX;
                }
            }
            else Console.WriteLine("Error : The GodelList can't change to a valid P-T program!!");

            return IsValidGodelList;
        }

        public StringBuilder PrintTuringStrap(StringBuilder sb,int index)   //格式turing带的表示格式,如:[1]1 1 1 1 B
        {
            StringBuilder tempStringBuilder = new StringBuilder();

            for (int i = 0; i < sb.Length; i++)
            {
                if (i == index)
                {
                    tempStringBuilder.Append('[');
                    tempStringBuilder.Append(sb[i].ToString());
                    tempStringBuilder.Append(']');
                }
                else
                {
                    tempStringBuilder.Append(sb[i].ToString());
                    if (i != (sb.Length - 1)) tempStringBuilder.Append(' ');
                }
            }
            return tempStringBuilder;
        }

        public void RunPostTuringMachin(ArrayList programArrayList, int x)    //根据输入的指令集和x的值进行模拟运行
        {
            StringBuilder turingStringBuilder = new StringBuilder();    //turing带

            for (int i = 0; i <= x; i++)   //将x转化为turing带
            {
                turingStringBuilder.Append('1');
            }
            turingStringBuilder.Append('B');
           
            Console.WriteLine("The initial TuringStrap is " + PrintTuringStrap(turingStringBuilder,0) + ",Running.../n");
            Console.WriteLine("--------------------------------------------");

            for (int i = 0; i < programArrayList.Count; i++)
            {
                CantorCode c2 = (CantorCode)programArrayList[i];
            }

            int turingIndexInt = 0;
            int programIndexInt = 0;
            int runIndex = 1;

            while (!(programIndexInt > programArrayList.Count-1))   //如果指令序号大于指令集的总数,程序结束
            {
                CantorCode cc = (CantorCode)programArrayList[programIndexInt];
                switch (cc.operateCodeInt)
                {
                    case 1:   //指令代码是1,Turing带进行右移操作:RIGHT
                        turingIndexInt++;    //turing带右移
                       
                        if (turingIndexInt >= turingStringBuilder.Length)
                            turingStringBuilder.Append(' ');

                        programIndexInt++;   //读取下一条指令
                        Console.Write(runIndex.ToString("D2") + " -> RIGHT                ");
                        Console.WriteLine(PrintTuringStrap(turingStringBuilder, turingIndexInt));
                        runIndex++;      //运行指令数加1;
                        break;
                    case 2:   //指令代码是2,则Turing带进行左移操作
                        turingIndexInt--;   //turing带左移

                        if (turingIndexInt < 0 )
                        {
                            turingStringBuilder.Insert(0, ' ');
                            turingIndexInt = 0;
                        }

                        programIndexInt++;  //读取下一条指令
                        Console.Write(runIndex.ToString("D2") + " -> Left                  ");
                        Console.WriteLine(PrintTuringStrap(turingStringBuilder, turingIndexInt));
                        runIndex++;
                        break;
                    case 3:   //指令代码是3,则进行“写1”操作
                        if (turingIndexInt > (turingStringBuilder.Length - 1))  //如果指针超过turingStringBuilder的长度,则需要执行Append(在后面插入值)
                        {
                            turingStringBuilder.Append('1');
                        }
                        else
                        {
                            if (turingIndexInt < 0)   //如果指针小于0,则需要执行Insert(在制定位置插入值)
                            {
                                turingStringBuilder.Insert(0, '1');
                                turingIndexInt = 0;
                            }
                            else turingStringBuilder[turingIndexInt] = '1';
                        }

                        programIndexInt++;
                        Console.Write(runIndex.ToString("D2") + " -> Write 1              ");
                        Console.WriteLine(PrintTuringStrap(turingStringBuilder, turingIndexInt));
                        runIndex++;
                        break;
                    case 4:   //指令代码是3,则进行“写B”操作
                        if (turingIndexInt > (turingStringBuilder.Length - 1))
                            turingStringBuilder.Append('B');
                        else
                        {
                            if (turingIndexInt < 0)
                            {
                                turingStringBuilder.Insert(0, 'B');
                                turingIndexInt = 0;
                            }
                            else turingStringBuilder[turingIndexInt] = 'B';
                        }
                       
                        programIndexInt++;
                        Console.Write(runIndex.ToString("D2") + " -> Write B              ");
                        Console.WriteLine(PrintTuringStrap(turingStringBuilder, turingIndexInt));
                        runIndex++;
                        break;
                    default:
                        if ((turingStringBuilder[turingIndexInt]=='1') && (cc.operateCodeInt % 2 ==0))   //如果当前读到的数是1,且读到的指令代码是偶数
                        {                           
                            int labelCode = (cc.operateCodeInt - 4) / 2;   //获取跳转的标号代码
                            programIndexInt = SearchLabelCode(programArrayList, labelCode);  //找到标号代码所在程序指令的序号
                            Console.Write(runIndex.ToString("D2") + " -> To A{0} IF 1           ", labelCode);
                            Console.WriteLine(PrintTuringStrap(turingStringBuilder, turingIndexInt));
                            runIndex++;
                        }
                        else
                            if ((turingStringBuilder[turingIndexInt] == 'B') && (cc.operateCodeInt % 2 != 0)) //如果当前读到的数是B,且读到的指令代码是奇数
                            {
                                int labelCode = (cc.operateCodeInt - 3) / 2;
                                programIndexInt = SearchLabelCode(programArrayList, labelCode);
                                Console.Write(runIndex.ToString("D2") + " -> To A{0} IF B           ", labelCode);
                                Console.WriteLine(PrintTuringStrap(turingStringBuilder, turingIndexInt));
                                runIndex++;
                            }
                            else programIndexInt++;
                        break;
                }               
            }

            Console.WriteLine("--------------------------------------------");
            Console.WriteLine("/nThe result is " + PrintTuringStrap(turingStringBuilder,-1)+"({0})/n",ValueOfTuringStrap(turingStringBuilder));           
        }

        public int ValueOfTuringStrap(StringBuilder turingStrapStringBuilder)   //得到Turing带上的值
        {
            int sum = 0;
           
            for (int i = 0; i < turingStrapStringBuilder.Length; i++)
            {
                if (turingStrapStringBuilder[i] == '1')
                    sum++;
            }
            return --sum;
        }

        public int SearchLabelCode(ArrayList al, int lcIndex)   //在指令集中搜索标号代码为lcIndex相对应的指令序号
        {
            CantorCode c = new CantorCode();
            int index = 0;

            for (int i = 0; i < al.Count; i++)
            {
                c = (CantorCode)al[i];
                if (c.labelCodeInt == lcIndex)
                {
                    index = i;
                    break;
                }
            }
            return index;
        }
    }

    public class CantorCode
    {
        public int labelCodeInt;   //存储标号代码
        public int operateCodeInt;  //存储无标号指令代码
    }
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值