用户操作
[即时聊天] [发私信] [加为好友]
sonkysID:sonkys
1697次访问,排名2万外,好友0人,关注者0人。
sonkys的文章
原创 2 篇
翻译 0 篇
转载 0 篇
评论 24 篇
最近评论
loffiz:有意思的是,我们却要另外两个指针的空间,而这在32位机器中将需要8个字节。所以,实际上一共占用了13+8个字节。
Sonkys:看点计算理论就懂了:)
Deiva:我懂就好了
文章分类
收藏
    相册
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 用C#模拟Post-Turing程序的运行收藏

    新一篇: 使用字符树(Trie)方法节省内存 | 

    近期在学习计算理论,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;  //存储无标号指令代码
        }
    }

    发表于 @ 2005年11月24日 15:49:00|评论(loading...)|编辑

    新一篇: 使用字符树(Trie)方法节省内存 | 

    评论

    #Sonkys 发表于2005-11-29 20:00:00  IP: 202.104.245.*
    看点计算理论就懂了:)
    #Deiva 发表于2005-11-29 17:34:00  IP: 61.241.77.*
    我懂就好了
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © sonkys