大连海事大学智能科学与技术专业课程设计,代码福利

写法说明

该程序可处理任意函数名,任意常量名的多语句归结。且有较优秀的效率以及十分完备的封装结构,今后的进一步维护将非常方便。

实际基本结构如下:

首先采用暴力bfs的形式扩展出每一个有可能组合形成的“horn语句”(后面称之为结点),在bfs的过程中维护一个set用来表示已经扩展完成的结点。用当前扩展结点和set中的每一个结点都进行一次组合,这样就保证了可以生成所有结点,即一定可以找到一组归结解法。

扩展过程用了很多小技巧,比如用二重hash方法将每条语句信息进行提取,通过一颗红黑树维护好每个语句的压缩信息是否已经出现,这样就保证了每一个结点都只被扩展出一次。节约了时间。同时存储所有生成边,形成一颗树结构。

之后再通过在这棵树上,从“->”结点返向dfs搜索,输出归结结果。

附代码:

//定义数字1~100表示变量,101~200表示常量,201~300表示函数名
#include<bits/stdc++.h>
using namespace std;
typedef long long int qq;
#define maxn 10005
const qq bas1 = 721;
const qq bas2 = 737;
const qq bas3 = 1767;
const qq bas4 = 797;
const qq MOD1 = 1000000007;
const qq MOD2 = 998244353;
#define mod1(x) ((x)%MOD1)
#define mod2(x) ((x)%MOD2)

map<string,int>nameid;    //将名字(函数名,变量名)映射成编号
string name[300];
int numf,numx,numc;  //函数和变量的个数
struct point    //原子式
{
    ///id(a1,a2,a3...am);
    int id;   //该原子式函数名的标号
    vector<int>a;   //该原子式内所有变量的编号
    void clear(){a.clear();}
    pair<qq,qq> hash()
    {
        pair<qq,qq>ret;
        ret.first=ret.second=0;
        for(int i=0;i<a.size();i++)
        {
            ret.first = ret.first*bas1+a[i] ;
            ret.second = ret.second*bas2+a[i];
        }
        ret.first*=id;
        ret.second*=id;
        return ret;
    }
    void output()
    {
        cout<<name[id];
        printf("(");
        for(int i=0;i<a.size();i++)
        {
            if(i!=0)printf(",");
            cout<<name[a[i]];
        }
        printf(")");
    }
};
operator < (point a,point b)
{
    if(a.id==b.id)
    {
        if(a.a.size()!=b.a.size())return a.a.size()<b.a.size();
        int i=0,len=a.a.size();
        while(i<len-1&&a.a[i]==b.a[i])i++;
        return a.a[i]<b.a[i];
    }
    return a.id<b.id;
}
operator == (point a,point b)
{
    if(a.id!=b.id||a.a.size()!=b.a.size())return 0;
    int i=0,len=a.a.size();
    while(i<len&&a.a[i]==b.a[i])i++;
    if(i==len)return 1;
    else return 0;
}
struct horn
{
    /// s <- t
    int id;//结点标号从0开始
    vector<point>s;
    vector<point>t;
    pair<qq,qq>hast;
    void clear(){s.clear();t.clear();}
    pair<qq,qq> hash()
    {
        pair<qq,qq>ret,temp;
        ret.first=ret.second=0;
        for(int i=0;i<s.size();i++)
        {
            temp=s[i].hash();
            ret.first = (ret.first+temp.first)*bas1 ;
            ret.second = (ret.second+temp.second)*bas2;
        }
        for(int i=0;i<t.size();i++)
        {
            temp=t[i].hash();
            ret.first = (ret.first+temp.first)*bas3;
            ret.second =(ret.second+temp.second)*bas4;
        }
        return hast=ret;
    }
    void leg()//范式化
    {
        sort(s.begin(),s.end());
        sort(t.begin(),t.end());
        vector<point>ns,nt; ns.clear();nt.clear();
        map<pair<qq,qq>,bool>appears; appears.clear();
        map<pair<qq,qq>,bool>appeart; appeart.clear();
        for(int i=0;i<s.size();i++)
            if(i==0||!(s[i]==s[i-1]))
            {
                appears[s[i].hash()]=1;
                ns.push_back(s[i]);
            }
        for(int i=0;i<t.size();i++)
            if(i==0||!(t[i]==t[i-1]))
            {
                appeart[t[i].hash()]=1;
                nt.push_back(t[i]);
            }
        s.clear(),t.clear();
        for(int i=0;i<ns.size();i++)
        {
            if(appeart.count(ns[i].hash())==0)s.push_back(ns[i]);
        }
        for(int i=0;i<nt.size();i++)
        {
            if(appears.count(nt[i].hash())==0)t.push_back(nt[i]);
        }
        hast=hash();
    }
    horn add(int x,int k)//将变量 x 赋值成常量 k
    {
        horn ret;ret.clear();
        for(int i=0;i<s.size();i++)
        {
            point temp; temp.clear();
            temp.id=s[i].id;
            for(int j=0;j<s[i].a.size();j++)
                if(s[i].a[j]==x) temp.a.push_back(k);
                else temp.a.push_back(s[i].a[j]);
            ret.s.push_back(temp);
        }
        for(int i=0;i<t.size();i++)
        {
            point temp; temp.clear();
            temp.id=t[i].id;
            for(int j=0;j<t[i].a.size();j++)
                if(t[i].a[j]==x) temp.a.push_back(k);
                else temp.a.push_back(t[i].a[j]);
            ret.t.push_back(temp);
        }
        ret.leg();
        return ret;
    }
    void output(bool op)
    {
        for(int i=0;i<s.size();i++)
        {
            if(i!=0)printf(",");
            s[i].output();
        }
        printf(" <- ");
        for(int i=0;i<t.size();i++)
        {
            if(i!=0)printf(",");
            t[i].output();
        }
        if(op)printf("\n");
    }
    void input()
    {
        char temp[500]={0},c;
        int len=0;
        while(scanf("%c",&c))
        {
            if(c=='\n')break;
            temp[len++]=c;
        }
        //AT(dog,x1) <- AT(zhangsan,x1),AT(zhangsan,train)
        int now=0;
        point add;
        ///---------------------Get_s--------------------------------
        while(now<len)
        {
            if(temp[now]=='<'){now+=2;break;}
            if(temp[now]==' '||temp[now]=='-'){now++;continue;}
            string xcx; xcx.clear();
            while(now<len)
            {
                if(temp[now]=='('||temp[now]==')'||temp[now]==','){now++;break;}
                if(temp[now]==' '){now++;continue;}
                xcx+=temp[now++];
            }
            if(xcx.length()==0){continue;}
            if(temp[now-1]!='(')//是变量或常量
            {
                if(nameid.count(xcx)==0)
                {
                    if(xcx[0]=='x') nameid[xcx]=++numx;
                    else nameid[xcx]=(++numc+200);
                    name[nameid[xcx]]=xcx;
                }
                add.a.push_back(nameid[xcx]);
            }
            else//是函数名
            {
                if(nameid.count(xcx)==0)
                {
                    nameid[xcx]=(++numf+100);
                    name[nameid[xcx]]=xcx;
                }
                add.id=nameid[xcx];
            }
            if(temp[now-1]==')'){s.push_back(add);add.clear();}
        }
        ///---------------------Get_t--------------------------------
        while(now<len)
        {
            if(temp[now]=='<'){now+=2;break;}
            if(temp[now]==' '||temp[now]=='-'){now++;continue;}
            string xcx; xcx.clear();
            while(now<len)
            {
                if(temp[now]=='('||temp[now]==')'||temp[now]==','){now++;break;}
                if(temp[now]==' '){now++;continue;}
                xcx+=temp[now++];
            }
            if(xcx.length()==0){continue;}
            if(temp[now-1]!='(')//是变量或常量
            {
                if(nameid.count(xcx)==0)
                {
                    if(xcx[0]=='x') nameid[xcx]=++numx;
                    else nameid[xcx]=(++numc+200);
                    name[nameid[xcx]]=xcx;
                }
                add.a.push_back(nameid[xcx]);
            }
            else//是函数名
            {
                if(nameid.count(xcx)==0)
                {
                    nameid[xcx]=(++numf+100);
                    name[nameid[xcx]]=xcx;
                }
                add.id=nameid[xcx];
            }
            if(temp[now-1]==')'){t.push_back(add);add.clear();}
        }
        leg();
    }
};
struct edge
{
    int op;
    int op2;
    int u;//下一节点的标号
    ///op2=-1表示该节点可由u结点与op结点结合生成
    ///否则表示该节点可由u结点的变量变成op2常量产生
};
vector<edge>tr[100052];
vector<horn>a;
queue<horn>q;
map<pair<qq,qq>,bool>vis;
vector<horn>rule;    //事实结点(叶子节点)
int trs;///结点个数
int pos[100052];//结点id为i的结点a中为a[pos[i]]
horn oi;
int e=0,root;
bool is_aim(horn x)
{
    if(x.s.size()==0)return 1;
    else return 0;
}
bool is_rule(horn x)
{
    if(x.t.size()==0)return 1;
    else return 0;
}
horn merge(horn a,horn b)
{
    horn ret; ret.clear();
    bool vsa[100]={0},vta[100]={0},vsb[100]={0},vtb[100]={0};
    for(int i=0;i<a.s.size();i++)
    for(int j=0;j<b.t.size();j++)
        if(a.s[i]==b.t[j]) vsa[i]=vtb[j]=1;
    for(int i=0;i<a.t.size();i++)
    for(int j=0;j<b.s.size();j++)
        if(a.t[i]==b.s[j]) vta[i]=vsb[j]=1;

    for(int i=0;i<a.s.size();i++)
        if(vsa[i]==0)ret.s.push_back(a.s[i]);
    for(int i=0;i<b.s.size();i++)
        if(vsb[i]==0)ret.s.push_back(b.s[i]);
    for(int i=0;i<a.t.size();i++)
        if(vta[i]==0)ret.t.push_back(a.t[i]);
    for(int i=0;i<b.t.size();i++)
        if(vtb[i]==0)ret.t.push_back(b.t[i]);
    vector<point>temp;
    //temp=ret.s;ret.s=ret.t;ret.t=temp;
    ret.leg();
    return ret;
}
void bfs(horn aim)
{
    while(!q.empty())q.pop();
    a.clear();
    vis.clear();
    trs=0;

    for(int i=0;i<rule.size();i++)
    {
        rule[i].id=trs++;
        q.push(rule[i]);
        vis[rule[i].hast]=1;
    }
    aim.id=trs++;
    q.push(aim);vis[aim.hast]=1;
    while(!q.empty())
    {
        horn now=q.front();
        //now.output();
        for(int i=0;i<a.size();i++)//当前结点now与a集合中所有组合
        {
            horn add=merge(a[i],now);
            if(vis.count(add.hast)!=0)continue;
            if(add.s.size()>max(a[i].s.size(),now.s.size())
            || add.t.size()>max(a[i].t.size(),now.t.size()))continue;
            vis[add.hast]=1;

            edge temp1,temp2;
            temp1.op2=temp2.op2=-1;
            temp1.op=a[i].id;   temp1.u=now.id;
            temp2.op=now.id;    temp2.u=a[i].id;
            tr[trs].push_back(temp1);
            tr[trs].push_back(temp2);

            add.id=trs++;
            q.push(add);
        }

        bool posx[105]={0};//now中出现过的变量
        for(int i=0;i<now.s.size();i++)
            for(int j=0;j<now.s[i].a.size();j++)
            {
                if(now.s[i].a[j]>numx)continue;
                posx[now.s[i].a[j]]=1;
            }
        for(int i=0;i<now.t.size();i++)
            for(int j=0;j<now.t[i].a.size();j++)
            {
                if(now.t[i].a[j]>100)continue;
                posx[now.t[i].a[j]]=1;
            }
        //if(a.size()==317){printf("--- ");now.output();}
        for(int i=1;i<=numx;i++)
        {
            if(!posx[i])continue;
            for(int j=201;j<=numc+200;j++)
            {

                horn add=now.add(i,j);

                if(vis.count(add.hast)!=0)continue;
                vis[add.hast]=1;

                edge temp;
                temp.op2=i;
                temp.op=j;
                temp.u=now.id;
                tr[trs].push_back(temp);
                //printf("trs2=%d ",trs);
                add.id=trs++;
                q.push(add);
            }
        }
        pos[now.id]=a.size();
        if(is_aim(now)&&is_rule(now))root=now.id;
        if(now.hast==oi.hast)e=oi.id;
        a.push_back(now);
        q.pop();
    }
    printf("xcx\n");
    /*for(int i=0;i<a.size();i++) { if(is_rule(a[i])||is_aim(a[i])) { printf("%d ",i); a[i].output(); } }*/
}
stack<edge>way;
int op_num;
void dfs(int x)
{
    //printf("%d ",x);
    //a[pos[x]].output();
    //dfs(tr[x][0].u);
    if(tr[x].size()==0)
    {
        printf("%d.\n",op_num++);
        printf("(%d) ",a[pos[x]].id);
        a[pos[x]].output(1);
        return;
    }
    if(tr[x][0].op2==-1)///说明是合并的
    {
        dfs(tr[x][0].u);
        dfs(tr[x][0].op);
        printf("%d.\n",op_num++);
        printf("(%d) ",a[pos[x]].id);
        a[pos[x]].output(0);
        printf("(%d)+(%d) \n",tr[x][0].u,tr[x][0].op);
    }
    else//是转换的
    {
        dfs(tr[x][0].u);
        printf("%d.\n",op_num++);
        printf("(%d) ",a[pos[x]].id);
        a[pos[x]].output(0);
        printf(" (%d): ",tr[x][0].u);
        cout<<name[tr[x][0].op2]<<" --> "<<name[tr[x][0].op]<<endl;
    }
}
void init()
{
    numf=numx=numc=0;
    rule.clear();
    nameid.clear();
    a.clear();
    while(!q.empty())q.pop();
    vis.clear();
}
int main()
{
    init();
    //freopen("in3.txt","r",stdin);
    //freopen("out2.txt","w",stdout);
    int T,cnt=1;    ///cnt 为 horn 语句个数
    printf("请输入事实个数:");
    scanf("%d",&T);printf(" %d\n",T);getchar();

    while(T--)
    {
        horn temp;temp.clear();
        temp.input();
        temp.output(1);
        rule.push_back(temp);
        cnt++;
    }
    printf("自动识别:\n变量个数:%d\n常量个数:%d\n函数个数:%d\n",numx,numc,numf);
    printf("请输入目标个数:");
    scanf("%d",&T);printf(" %d\n",T);getchar();
    int aim_num=1;
    while(T--)
    {
        for(int i=0;i<100052;i++)tr[i].clear();
        horn temp;  temp.clear();
        temp.input();
        oi=temp;
        temp.output(1);
        trs=0;
        op_num=1;
        bfs(temp);///广搜出图
        dfs(root);///深搜出路径
        //printf("归结完成\n");
        while(1)getchar();
    }
    return 0;
}
/* 程序功能: 输入: n表示有n个规则或事实 接下来n行表示每一个规则或事实 如: AT(zhangsan,x),AT(pp,x) -> AT(dog,x) AT(zhangsan,train) <- 接下来输入m 表示有m个目标: 如: <-AT(dog,train) 输入样例: 样例一: 2 AT(dog,x1)<- AT(zhangsan,x1) AT(zhangsan,train)<- 1 <-AT(dog,train) 样例二: 3 Father(Bob,Allan)<- Brother(x2,x3)<-Father(x1,x2),Father(x1,x3) Father(Bob,Nick)<- 1 <-Brother(Allan,Nick) */