自动机实验:NFA到DFA的转换

一、实验目的

1)设计确定有穷自动机DFA和非确定有穷自动机NFA描述的对象模型或数据结构,实现DFA和NFA的基本操作(输入和输出)。

2)设计一个将NFA确定化成DFA的方法,加深对自动机的理解。

二、实验内容

需要实现的功能:

1)设计一个函数(方法),实现把NFA确定化成一个DFA;

2)输入一个NFA:NFA描述存储在文本文件中,文件名作为命令行参数输入;

3)输出等价的DFA到标准输出设备。

三、实验要求

1)NFA描述文件的格式参见文档《实验用文件结构.doc》;

2)要求文本文件编码格式是ANSI。

四、附件

描述

NFA M=(Q,∑,S,Z,F)

其中:

Q={0,1,2,3,4,5,6,7,8,9,10}

∑={1,2}

F: F(0,0)={1,7}     F(1,0)={2,4}

   F(2,1)={3}      F(3,0)={6}

F(4,2)={5}      F(5,0)={6}

F(6,0)={1,7}     F(7,1)={8}

F(8,2)={9}      F(9,2)={10}

S={0}

Z={10}

输入(NFA描述文件):

11

2

0 0 1 7 -1

1 0 2 4 -1

2 1 3 -1

3 0 6 -1

4 2 5 -1

5 0 6 -1

6 0 1 7 -1

7 1 8 -1

8 2 9 -1

9 2 10 -1

-1

0 -1

10 -1

输出(标准输出设备):

DFA

  状态个数:5

  字符个数:2

  状态转换:

    (0,1)->1

    (0,2)->2

    (1,1)->1

    (1,2)->3

    (2,1)->1

    (2,2)->2

    (3,1)->1

    (3,2)->4

    (4,1)->1

    (4,2)->2

  开始状态:0

  结束状态集:{ 4 }

五、代码

#include <sstream>
#include "vector"
#include "iostream"
#include "fstream"
#include "string"
#include "map"
#include "set"
#include <algorithm>
#ifndef BIANYI_DFA_H
#define BIANYI_DFA_H
using namespace std;

class Q{    //NFA状态集
private:
    int n;  //状态个数
    set<int> q;
public:
    int getN() const {
        return n;
    }

    void setN(int n) {
        Q::n = n;
    }

    const set<int> &getQ() const {
        return q;
    }

    void setQ(const set<int> &q) {
        Q::q = q;
    }
};

class Z{    //NFA字符集
private:
    int n;  //字符个数
    set<int> z;
public:
    int getN() const {
        return n;
    }

    void setN(int n) {
        Z::n = n;
    }

    const set<int> &getZ() const {
        return z;
    }

    void setZ(const set<int> &z) {
        Z::z = z;
    }
};

class T{    //NFA转换函数
private:
    int n;  //NFA转换函数个数
    map<pair<int,int>,set<int>> t;  //NFA转换函数集
public:
    int getN() const {
        return n;
    }

    const map<pair<int, int>, set<int>> &getT() const {
        return t;
    }

    void setT(const map<pair<int, int>, set<int>> &t) {
        T::t = t;
    }

    void setN(int n) {
        T::n = n;
    }

};

class S{    //NFA初态集
private:
    set<int> s;
public:
    const set<int> &getS() const {
        return s;
    }

    void setS(const set<int> &s) {
        S::s = s;
    }
};

class F{
private:
    set<int> f; //NFA终态集
public:
    const set<int> &getF() const {
        return f;
    }

    void setF(const set<int> &f) {
        F::f = f;
    }
};
class DFA{
private:
    int n1; //状态个数
    int n2; //字符个数
    map<pair<int,int>,int> dt;     //转换函数
    int ds;    //初态
    set<int> df;    //终态集
public:
    int getN1() const {
        return n1;
    }

    int getN2() const {
        return n2;
    }

    void setN2(int n2) {
        DFA::n2 = n2;
    }

    const map<pair<int, int>, int> &getDt() const {
        return dt;
    }

    void setDt(const map<pair<int, int>, int> &dt) {
        DFA::dt = dt;
    }

    void setN1(int n1) {
        DFA::n1 = n1;
    }

    const int &getDs() const {
        return ds;
    }

    void setDs(const int &ds) {
        DFA::ds = ds;
    }

    const set<int> &getDf() const {
        return df;
    }

    void setDf(const set<int> &df) {
        DFA::df = df;
    }

    void outdfa(){
        cout<<"state number:"<<n1<<endl;
        cout<<"character nember:"<<n2<<endl;
        for(map<pair<int,int>,int>::iterator it=dt.begin();it!=dt.end();it++){
            cout<<"("<<it->first.first<<","<<it->first.second<<"->"<<it->second<<endl;
        }
        cout<<"initial state:"<<ds<<endl;
        cout<<"final state:";
        for(set<int>::iterator it=df.begin();it!=df.end();it++){
            cout<<*it<<" ";
        }
    }
};

class NFA{  //NFA转换为DFA
private:
    Q setq;
    Z setz;
    T mapt;
    S sets;
    F setf;
    DFA dfa;
    string filename;
public:
    void setFilename(const string &filename) {
        NFA::filename = filename;
    }

public:
    void fileop(){  //读文件,输入NFA
        vector<int> tr;
        vector<vector<int>> trr;
        map<pair<int,int>,set<int>> mmap;
        set<int> mset;
        pair<int,int> mpair;
        string s;
        ifstream fout(filename);
        stringstream buffer;
        buffer << fout.rdbuf();
        string contents(buffer.str());//将文件读入一个字符串
        istringstream istringstream1(contents);
        for(int i=0;istringstream1 >> s;i++){
            if(i==0){
                tr.push_back(atoi(s.c_str()));
                trr.push_back(tr);
                tr.clear();
            } else if(i==1){
                tr.push_back(atoi(s.c_str()));
                trr.push_back(tr);
                tr.clear();
            }
            else if(i==2){

                tr.push_back(atoi(s.c_str()));
                trr.push_back(tr);
                tr.clear();
            }
            else {

                if(atoi(s.c_str())==-1){

                    trr.push_back(tr);
                    tr.clear();
                } else{
                    tr.push_back(atoi(s.c_str()));
                }
            }
        }
        for(int i=0;i<trr.size();i++){
            if(i==0){
                setq.setN(trr[i][0]);
            } else if(i==1){
                setz.setN(trr[i][0]);
            } else if(i==2){
                mapt.setN(trr[i][0]);
            }else if(i==trr.size()-2){
                for(int j=0;j<trr[i].size();j++){
                    mset.insert(trr[i][j]);
                }
                sets.setS(mset);
                mset.clear();

            }
            else if(i==trr.size()-1){
                for(int j=0;j<trr[i].size();j++){
                    mset.insert(trr[i][j]);
                }
                setf.setF(mset);
                mset.clear();
            }
            else {
                for(int j=0;j<trr[i].size();j++){
                    if(j==0){
                        mpair.first=trr[i][j];
                    } else if(j==1){
                        mpair.second=trr[i][j];
                    } else{
                        mset.insert(trr[i][j]);
                    }
                }
                mmap.emplace(mpair,mset);
                mset.clear();
            }
        }
        mapt.setT(mmap);
        for(int i=0;i<setq.getN();i++){
            mset.insert(i);
        }
        setq.setQ(mset);
        for(int i=0;i<=setz.getN();i++){
            mset.insert(i);
        }
        setz.setZ(mset);
    }

    set<int> closoure1(int n){//求每个元素的0闭包
        set<int> ter;
        vector<int> tt;
        tt.push_back(n);
        map<pair<int,int>,set<int>> mapc;
        mapc=mapt.getT();

        for(int i=0;i<tt.size();i++){
            for(map<pair<int,int>,set<int>>::iterator it=mapc.begin();it!=mapc.end();it++){
                if(it->first.first==tt[i]&&it->first.second==0){
                    for(set<int>::iterator itt=it->second.begin();itt!=it->second.end();itt++){
                        tt.push_back(*itt);
                    }
                }
            }
        }
        for(int i=0;i<tt.size();i++){
            ter.insert(tt[i]);
        }
        return ter;
    }

    set<int> move(set<int> j,int m) {   //转态A,经过a到达的状态
        set<int> u;
        map<pair<int,int>,set<int>> mapc;
        mapc=mapt.getT();
        for (set<int>::iterator i = j.begin(); i != j.end(); i++) {
            for (map<pair<int, int>, set<int>>::iterator it = mapc.begin(); it != mapc.end(); it++) {
                if (it->first.first == *i && it->first.second == m) {
                    u.insert(it->second.begin(), it->second.end());
                }
            }
        }
        return u;
    }
    set<int> closoure2(set<int> move){  //集合的闭包
        map<int,set<int>> clo;
        set<int> ret;
        for(set<int>::iterator i=setq.getQ().begin();i!=setq.getQ().end();i++){
            clo.emplace(*i, closoure1(*i));
        }
        for(set<int>::iterator i=move.begin();i!=move.end();i++){
            ret.insert(clo[*i].begin(),clo[*i].end());
        }
        return ret;
    }

    bool  isff(set<int> a,set<int> b){  //判断两个集合是否有交集
        set<int> c;
        c.insert(a.begin(),a.end());
        c.insert(b.begin(),b.end());
        if(c.size()==a.size()+b.size()){
            return 0;
        } else return 1;

    }
    bool isnotinmap(map<int,set<int>> I,set<int> ter){  //判断集合是否在字典内
        int i=1;
        for(map<int,set<int>>::iterator it=I.begin();it!=I.end();it++){
            if(it->second==ter){
                i=0;
            }
        }
        return i;
    }

    void tran(){    //转换为DFA
        map<int,set<int>> I;
        set<int> closoure;
        closoure= closoure2(sets.getS());
        I.emplace(0,closoure);
        int k=1;
        for(int i=0;i<I.size();i++){
            for(int j=1;j<=setz.getN();j++){
                closoure=closoure2(move(I[i],j));
                if(isnotinmap(I,closoure)){

                    I.emplace(k,closoure);k++;
                }
            }
        }
        //生成DFA
        map<pair<int,int>,int> dtt;
        pair<int,int> s;
        set<int> ff;
        dfa.setN1(I.size());
        dfa.setN2(setz.getN());
        dfa.setDs(0);
        for(int i=0;i<I.size();i++){
            for(int j=1;j<=setz.getN();j++){
                s.first=i;
                s.second =j;
                for(map<int,set<int>>::iterator it=I.begin();it!=I.end();it++){
                    if(it->second==closoure2(move(I[i],j))){
                        dtt.emplace(s,it->first);
                    }
                }
            }
            if(isff(I[i],setf.getF())){
                ff.insert(i);
            }
        }
        dfa.setDt(dtt);
        dfa.setDf(ff);

        dfa.outdfa();
    }
};
#endif //BIANYI_DFA_H
int main() {
    NFA nfa;
    string filename;
    cout<<"Please input file(absolute path; eg: D://filename.txt):"<<endl;
    cin>>filename;
    nfa.setFilename(filename);//"E://by//NFA.txt"
    nfa.fileop();
    nfa.tran();
//    输入文件格式
//    11
//    2
//    10
//    0 0 1 7 -1
//    1 0 2 4 -1
//    2 1 3 -1
//    3 0 6 -1
//    4 2 5 -1
//    5 0 6 -1
//    6 0 1 7 -1
//    7 1 8 -1
//    8 2 9 -1
//    9 2 10 -1
//    0 -1
//    10 -1
}

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值