通用程序的实现

2020-07-10  本文已影响0人  嬴小政今天好好吃饭了吗

计算理论导引作业2020/7/9日交。

1. 通用程序的定义

image.png

即:以z,x为输入,将z转换成程序(指令),去处理x形成的图灵机的带,最后输出y。

2. 通用程序伪码表示

TO E IF ~PROG(Z)
v=1
I=1
A 
    TO G IF (I=0) ∨(I>Lt(Z))
    TO R IF r((Z) I )=1
    TO L IF r((Z) I )=2
    TO F IF r((Z) I )=3
    TO B IF r((Z) I )=4
    TO T IF R(r((Z) I , 2) =1
    TO C IF (X) V =2
D
    I=I+1
    TO A
C 
    W=[(r((Z) I )-3)/2]
    I= MIN t≤Lt(Z) L((Z) t ) =W
    TO A
T 
    TO C IF (X) V =1
    TO D
B 
    TO D IF (X) V =1
    X=[X/P V ]
    TO D
F 
    TO D IF (X) V =2
    X=X·P V { 算术运算}
    TO D
L 
    TO M IF V≠1
    X=2*X {Gödel 乘}
    TO D
M 
    V=V-1
    TO D
R 
    TO S IF V ≠ Lt(X)
    X=X*2 {Gödel 乘}
S 
    V=V+1
    TO D
G 
    Y=#(2 ,X) -1

3. 通用程序的实现

注:结合前面的30个程序的实现。

#include <iostream>
#include <vector>
#include <Cmath> 
using namespace std;
//定义cantor矩阵查询规模
#define NUM 10
unsigned int aCantor[NUM][NUM];
//求余
unsigned int R(unsigned long long int x, unsigned long long int y) {
    unsigned int res;
    res = (x % y);
    return res;
}
//求x - y
unsigned long long int sub(unsigned long long int x, unsigned long long int y) {
    unsigned long long int res;
    if (x >= y)
        res = x - y;
    else
        res = 0;
    return res;
}
//求反
unsigned int alpha(unsigned long long int x) {
    unsigned int res;
    res = sub(1, x);
    return res;
}
//y可以整除x
unsigned int ycanx(unsigned long long int x, unsigned long long int y) {
    unsigned int res;
    for (int i = 0; i <= x; i++) {
        if (i * y == x) {
            res = 0;
            break;
        }
        else
            res = 1;
    }
    return res;
}
//prim:判断x是否是素数(0:是;1:否)
unsigned int prim(unsigned long long int x) {
    unsigned int res = 0;
    if (x <= 1)
        res = 1;
    else {
        for (int t = 2; t < x; t++) {
            res += alpha(ycanx(x, t));
        }
        res = alpha(alpha(res));
    }
    return res;
}
//p:求第x个素因子
unsigned int p(unsigned long long int x) {
    unsigned int res = 0;
    int i = 0, j = 1;//第1个素数是2
    while (i != x) {
        j++;
        if (prim(j) == 0) {
            i++;
        }
    }
    res = j;
    return res;
}
//Lt:x的最大非零指数素因子的序号
unsigned int Lt(unsigned long long int x) {
    //cout << "已经入Lt" << endl;
    unsigned int res = 0, i = 1, count = 0;
    while (x != 1) {//x一直对素数相除
        if (x % p(i) == 0) {//如果可以被这个素数整除
            while (x % p(i) == 0) {//就一直整除下去
                x = x / p(i);
            }
            res = i;
        }
        i++;
    }
    //cout << "已经退出Lt" << endl;
    return res;
}
//an(x):求得x的哥德尔数
vector<unsigned int> an(unsigned long long int x) {
    vector<unsigned int> res;
    unsigned int  i = 1;//注意第一个素数才是2,不是第0个
    while (x != 1) {//x一直对素数相除
        unsigned int count = 0;
        if (x % p(i) == 0) {//如果可以被这个素数整除
            while (x % p(i) == 0) {//就一直整除下去
                x = x / p(i);
                count++;
                //cout << "验证x:" << x << endl;
            }
        }
        res.push_back(count);
        i++;
    }
    return res;
}
//PROG(x):求x是否为pt程序
unsigned int PROG(unsigned long long int x) {
    unsigned int res = 0;//默认谓词为真
    //cout << "验证未计算出an" << endl;
    vector<unsigned int> rn = an(x);
    //cout << "验证已计算出an" << endl;
    vector<unsigned int> in;//存左部
    vector<unsigned int> jn;//存右部
    vector <unsigned int>::iterator tmp0;
    vector <unsigned int>::iterator tmp1;
    for (tmp0 = rn.begin(); tmp0 != rn.end(); tmp0++) {
        for (int i = 0; i < NUM; i++) {
            for (int j = 0; j < NUM - i; j++) {
                if (aCantor[i][j] == *tmp0) {
                    if (j == 0)//如果出现j为0就一定不成立
                    {
                        return 1;
                    }
                    else {//没有的话就继续执行
                        in.push_back(i);
                        jn.push_back(j);
                    }
                }
            }
        }
    }
    //已经得到了指令左右部“二维”数组
    for (tmp0 = in.begin(); tmp0 == in.end(); tmp0++) {
        for (tmp1 = jn.begin(); tmp1 == jn.end(); tmp1++) {
            //如果两者都不为0
            if (in[*tmp0] != 0 && in[*tmp1] != 0) {
                if (in[*tmp0] == in[*tmp1]) {//两者相等
                    return 1;
                }
            }
        }
    }
    return res;
}
//给定x,y给出对应位置数
unsigned int match(unsigned int x, unsigned int y) {
    unsigned int res = 0;
    return res = aCantor[x][y];
}
//求指令zi的右部
unsigned int r(unsigned int z) {
    //cout << "已经入r" << endl;
    unsigned int res = 0;
    for (int i = 0; i < NUM; i++) {
        for (int j = 0; j < NUM - i; j++) {
            if (match(i, j) == z)
                res = j;
        }
    }
    return res;
}
//求指令zi的左部
unsigned int l(unsigned int z) {
    //cout << "已经入l" << endl;
    unsigned int res = 0;
    for (int i = 0; i < NUM; i++) {
        for (int j = 0; j < NUM - i; j++) {
            if (match(i, j) == z)
                res = i;
        }
    }
    return res;
}
//哥德尔乘
vector<unsigned int> XGodelY(vector<unsigned int> X, vector<unsigned int> Y) {
    vector<unsigned int> res;
    vector <unsigned int>::iterator tmp;
    for (tmp = Y.begin(); tmp != Y.end(); tmp++) {
        X.push_back(*tmp);
    }
    //a.insert(a.end(), b, begin(), b.end());其实用insert更好
    return res = X;
}
//x哥德尔数的第i个
unsigned int xi(unsigned long long int x, unsigned int i) {
    unsigned int res = 0, j = 1, count = 0;
    if (i >= 0) {
        while (x != 1) {//x一直对素数相除
            if (x % p(j) == 0) {//如果可以被这个素数整除
                while (x % p(j) == 0) {//就一直整除下去
                    x = x / p(j);
                    if (j == i)
                        count++;
                }
            }
            j++;
        }
        res = count;
    }
    else
        res = 0;
    return res;
}
//给出哥德尔数,求整数
unsigned long long int XZ(vector<unsigned int> x_vector) {
    unsigned long long int res = 1;
    unsigned int i = 1;
    vector <unsigned int>::iterator tmp;
    for (tmp = x_vector.begin(); tmp != x_vector.end(); tmp++) {
        res *= pow(p(i), *tmp);
        i++;
    }
    return res;
}
//求x的素因子分解式中指数为a的个数
unsigned int sharpax(unsigned long long int x, unsigned int a) {
    cout << "已经入sharpx" << endl;
    unsigned int res = 0;
    cout << "进入an" << endl;
    vector<unsigned int> anRes = an(x);
    cout << "完成an" << endl;
    vector <unsigned int>::iterator tmp;
    for (tmp = anRes.begin(); tmp != anRes.end(); tmp++) {
        if (*tmp == a)
            res++;
    }
    return res;
}
//通用程序
int program() {
    //输入数据
    int x, y, w, t, choice;
    unsigned long long int z;
    cout << "请输入z 和 x" << endl;
    cin >> z >> x;

    //一个vector只存储一个2,用于计算X的哥德尔
    vector<unsigned int> xG2;
    xG2.push_back(2);
    //cout << "xG2输入完毕!" << endl;

    //将x放到带上,并计算出它的哥德尔数
    vector<unsigned int> x_Godel;
    for (int x_i = 0; x_i <= x; x_i++) {
        x_Godel.push_back(2); //输入1(godel为2)
    }
    x_Godel.push_back(1); //最后要输入B(godel为1),可加可不加
    //cout << "tape(x)输入完毕!" << endl;

    //通过tape(x)哥德尔数,求出X
    unsigned long long int X = XZ(x_Godel);
    //cout << "tape(x)转换成X输入完毕!" << endl;

    //创造cantor矩阵
    int cantor_count0 = 0, cantor_count1 = 0;
    int cantor_i = 0, cantor_j = 0;
    for (cantor_count0 = 0; cantor_count0 < NUM; cantor_count0++) {
        for (cantor_j = 0; cantor_j <= cantor_count0; cantor_j++) {
            cantor_i = cantor_count0 - cantor_j;
            aCantor[cantor_i][cantor_j] = cantor_count1++;
            //验证cantor矩阵的正确性
            //cout << cantor_i << "    " << cantor_j << endl;
            //cout << aCantor[cantor_i][cantor_j] << endl;;

        }
    }
    //cout << "cantor输入完毕!" << endl;

    //输出z哥德尔数对一个的cantor矩阵的位置,用于检验
    cout << "z在cantor矩阵中对应的编码为:" << endl;
    for (int i = 1; i <= Lt(z); i++) {
        cout << "Z(" << i << ") = " << xi(z, i) << endl;
        cout << "<" << l(xi(z, i)) << ", " << r(xi(z, i)) << ">" << endl;
    }

    //输出tape(x)
    cout << "tape(x) = ";
    vector <unsigned int>::iterator tmp;
    for (tmp = x_Godel.begin(); tmp != x_Godel.end(); tmp++) {
        cout << *tmp << " ";
    }
    cout << endl;

    //输出哥德尔数X
    cout << "X = " << X << endl;

    //第一步,验证z是否是某一pt程序的哥德尔数
    if (PROG(z) == 1) {//如果不是
        cout << "z不是某pt程序的哥德尔数!" << endl;
        return 0;//就返回
    }
    else {//如果是
        int v = 1, I = 1; //初始化带计数器,指令计数器
        //cout << "v,I输入完毕!" << endl;
    A:
        cout << "已进入A!" << endl;
        if (I == 0 || I > Lt(z))
            goto G;
        else if (r(xi(z, I)) == 1)
            goto R;//右移
        else if (r(xi(z, I)) == 2)
            goto L;//左移
        else if (r(xi(z, I)) == 3)
            goto F;//写1
        else if (r(xi(z, I)) == 4)
            goto B;//写B
        else if (R(r(xi(z, I)), 2) == 1)
            goto T;
        else if (xi(X, v) == 2)//指向1
            goto C;

    D:
        cout << "已进入D!" << endl;
        I = I + 1;
        goto A;

    C:
        cout << "已进入C!" << endl;
        w = (r(xi(z, I)) - 3) / 2;
        for (t = 1; t <= Lt(z); t++)
            if (l(xi(z, t) == w)) {
                I = t;//跳转
                break;
            }
        goto A;

    T:
        cout << "已进入T!" << endl;
        if (xi(X, v) == 1)
            goto C;
        goto D;

    B:
        cout << "已进入B!" << endl;
        if (xi(X, v) == 1)
            goto D;
        X = X / p(v);
        goto D;

    F:
        cout << "已进入F!" << endl;
        if (xi(X, v) == 2)//如果带上这格是1
            goto D;
        X = X * p(v);//不是的话就写1
        goto D;

    L:
        cout << "已进入L!" << endl;
        if (v != 1)
            goto M;
        x_Godel = XGodelY(xG2, x_Godel);
        X = XZ(x_Godel);
        goto D;

    M:
        cout << "已进入M!" << endl;
        v = v - 1;
        goto D;

    R:
        cout << "已进入R!" << endl;
        if (v != Lt(X))
            goto S;
        x_Godel = XGodelY(x_Godel, xG2);

    S:
        cout << "已进入S!" << endl;
        v = v + 1;
        goto D;

    G:
        cout << "已进入G!" << endl;
        y = sharpax(X, 2) - 1;
    }
    cout << "y = " << y << endl;
}

int main()
{
    int choice = 1;//选项
    while (choice == 1) {
        program();
        cout << endl;
        cout << "1:继续输入;0:终止程序!" << endl;
        cin >> choice;
        cout << endl;
    }
    getchar();
    return 0;
}

4. 测试实例

image.png

z实现右移一位write 1的操作,将改变0转化成的带上的1的个数。

上一篇下一篇

猜你喜欢

热点阅读