一、实验目的
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
}