initial commit

This commit is contained in:
2018-05-05 21:03:14 +08:00
parent 3484525181
commit 78417b99cc
14 changed files with 920 additions and 0 deletions
+109
View File
@@ -0,0 +1,109 @@
{
"name": "0n1n",
"description": "{ 0^{n}1^{n} | n>0 }",
"grammar": {
"states": {
"states": [
"q0",
"q1",
"q2",
"q3",
"q4"
],
"initial": "q0",
"finial": [
"q4"
]
},
"input": [
"0",
"1"
],
"alphabet": [
"0",
"1",
"B",
"X",
"Y"
],
"blank": "B",
"transition": {
"q0": {
"0": [
"q1",
"X",
"R"
],
"Y": [
"q3",
"Y",
"R"
]
},
"q1": {
"Y": [
"q1",
"Y",
"R"
],
"0": [
"q1",
"0",
"R"
],
"1": [
"q2",
"Y",
"L"
]
},
"q2": {
"Y": [
"q2",
"Y",
"L"
],
"0": [
"q2",
"0",
"L"
],
"X": [
"q0",
"X",
"R"
]
},
"q3": {
"Y": [
"q3",
"Y",
"R"
],
"B": [
"q4",
"B",
"L"
]
},
"q4": {
"X": [
"q4",
"0",
"L"
],
"Y": [
"q4",
"1",
"L"
],
"B": [
"q4",
"B",
"R"
]
}
}
},
"demo": "000111"
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

+42
View File
@@ -0,0 +1,42 @@
#-------------------------------------------------
#
# Project created by QtCreator 2018-05-03T23:17:18
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = TuringMachine
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp \
turingmachine.cpp \
centralwidget.cpp \
papertape.cpp
HEADERS += \
mainwindow.h \
turingmachine.h \
centralwidget.h \
papertape.h
FORMS += \
mainwindow.ui
RC_ICONS = Alan_Turing.ico
+178
View File
@@ -0,0 +1,178 @@
#include "centralwidget.h"
CentralWidget::CentralWidget(QWidget *parent) : QWidget(parent)
{
machine = new TuringMachine(this);
// nameEdit = new QLineEdit(this);
// nameEdit->setReadOnly(true);
autoCheckTimer = new QTimer(this);
connect(autoCheckTimer, QTimer::timeout, this, [this](){
checkByStep->click();
});
teststrEdit = new QLineEdit(this);
allStatesEdit = new QLineEdit(this);
allStatesEdit->setReadOnly(true);
inputEdit = new QLineEdit(this);
inputEdit->setReadOnly(true);
alphabetEdit = new QLineEdit(this);
alphabetEdit->setReadOnly(true);
initialStateEdit = new QLineEdit(this);
initialStateEdit->setReadOnly(true);
blankEdit = new QLineEdit(this);
blankEdit->setReadOnly(true);
finialStatesEdit = new QLineEdit(this);
finialStatesEdit->setReadOnly(true);
listWidget = new QListWidget(this);
importButton = new QPushButton(tr("导入配置"), this);
connect(importButton, QPushButton::clicked, this, importJson);
checkByStep = new QPushButton(tr("单步检查"), this);
checkByStep->setDisabled(true);
connect(checkByStep, QPushButton::clicked, this, stepCheck);
autoCheckButton = new QPushButton(tr("自动模式"), this);
autoCheckButton->setDisabled(true);
connect(autoCheckButton, QPushButton::clicked, this, autoCheck);
loadButton = new QPushButton(tr("装载纸带"), this);
loadButton->setDisabled(true);
connect(loadButton, QPushButton::clicked, this, loadTape);
resetButton = new QPushButton(tr("重置"), this);
connect(resetButton, QPushButton::clicked, this, [this](){
machine->reset();
loadButton->setEnabled(true);
autoCheckButton->setDisabled(true);
checkByStep->setDisabled(true);
checkByStep->setChecked(false);
});
tape = new PaperTape();
scene = new QGraphicsScene(this);
scene->setSceneRect(-250, -65, 500, 130);
scene->addItem(tape);
scene->addLine(0,0,0,40,QPen(Qt::red));
view = new QGraphicsView(scene ,this);
formlayout = new QFormLayout();
// formlayout->setSpacing(10);
// formlayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
// formlayout->addRow(tr("Name"), nameEdit);
formlayout->addRow(tr("状态集合"), allStatesEdit);
formlayout->addRow(tr("输入字符"), inputEdit);
formlayout->addRow(tr("字符表"), alphabetEdit);
formlayout->addRow(tr("初始状态"), initialStateEdit);
formlayout->addRow(tr("空白符"), blankEdit);
formlayout->addRow(tr("终止状态"), finialStatesEdit);
formlayout->addRow(tr("Test string"), teststrEdit);
// formlayout->addRow(loadButton);
// formlayout->addRow(checkByStep);
vsublayout = new QVBoxLayout();
vsublayout->addWidget(importButton);
vsublayout->addWidget(resetButton);
vsublayout->addWidget(loadButton);
vsublayout->addWidget(autoCheckButton);
vsublayout->addWidget(checkByStep);
hlayout = new QHBoxLayout();
hlayout->addLayout(formlayout);
hlayout->addWidget(listWidget);
hlayout->addLayout(vsublayout);
// hlayout->addWidget(importButton);
mainlayout = new QVBoxLayout(this);
mainlayout->addLayout(hlayout);
mainlayout->addWidget(view);
setLayout(mainlayout);
}
CentralWidget::~CentralWidget()
{
delete machine;
delete tape;
}
void CentralWidget::importJson()
{
QString filename = QFileDialog::getOpenFileName(this, tr("import json"),
".",tr("json(*.json)"));
if(filename.isEmpty())
return;
if(!machine->setGrammar(filename))
{
setStatus("请检查文件格式");
return;
};
setStatus(tr("导入成功"));
if(machine->hasGrammar())
{
loadButton->setEnabled(true);
// checkByStep->setEnabled(true);
}
else
loadButton->setDisabled(false);
// nameEdit->setText(machine->getName());
allStatesEdit->setText(machine->getAllStates().join(", "));
alphabetEdit->setText(machine->getAlphabet().split("", QString::SkipEmptyParts).join(", "));
inputEdit->setText(machine->getInput().split("", QString::SkipEmptyParts).join(", "));
initialStateEdit->setText(machine->getInitialState());
blankEdit->setText(machine->getBlank());
finialStatesEdit->setText(machine->getFinialStates().join(", "));
listWidget->clear();
listWidget->addItems(machine->getTransition());
if(teststrEdit->text().isEmpty())
{
teststrEdit->setText(machine->getRawStr());
}
tape->adjustPos();
}
void CentralWidget::loadTape()
{
machine->setTestStr(teststrEdit->text());
machine->reset();
tape->setStr(machine->getTestStr());
tape->standBy(1);
checkByStep->setEnabled(true);
autoCheckButton->setEnabled(true);
machineReady = true;
}
void CentralWidget::stepCheck()
{
machineReady = machine->checkByStep();
if(machineReady)
{
loadButton->setDisabled(true);
tape->standBy(machine->getCurrentIndex());
tape->setStr(machine->getTestStr());
listWidget->setCurrentRow(machine->getTransitionIndex());
}
else
{
loadButton->setEnabled(true);
autoCheckButton->setDisabled(true);
checkByStep->setDisabled(true);
checkByStep->setChecked(false);
autoCheckTimer->stop();
if(machine->getFinialStates().contains(machine->getCurrentState()))
{
emit setStatus("Correct!");
}
else
{
emit setStatus("Not OK!");
}
}
}
void CentralWidget::autoCheck()
{
autoCheckTimer->start(300);
}
+56
View File
@@ -0,0 +1,56 @@
#ifndef CENTRALWIDGET_H
#define CENTRALWIDGET_H
#include <QWidget>
#include <QFormLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QFileDialog>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QListWidget>
#include <QTimer>
#include "turingmachine.h"
#include "papertape.h"
class CentralWidget : public QWidget
{
Q_OBJECT
public:
explicit CentralWidget(QWidget *parent = nullptr);
~CentralWidget();
signals:
void setStatus(QString message);
public slots:
void importJson();
void loadTape();
void stepCheck();
void autoCheck();
private:
QVBoxLayout *mainlayout, *vsublayout;
QFormLayout *formlayout;
QHBoxLayout *hlayout;
QLineEdit *nameEdit, *teststrEdit;
QLineEdit *allStatesEdit, *alphabetEdit, *inputEdit, *initialStateEdit, *blankEdit, *finialStatesEdit;
QPushButton *importButton;
QPushButton *loadButton, *checkByStep, *resetButton, *autoCheckButton;
QListWidget *listWidget;
QGraphicsScene *scene;
QGraphicsView *view;
PaperTape *tape;
QTimer *autoCheckTimer;
TuringMachine *machine;
bool machineReady = true;
};
#endif // CENTRALWIDGET_H
+126
View File
@@ -0,0 +1,126 @@
{
"name": "m-n",
"description": "calculate m-n",
"grammar": {
"states": {
"states": [
"q0",
"q1",
"q2",
"q3",
"q4",
"q5",
"q6"
],
"initial": "q0",
"finial": [
"q6"
]
},
"input": [
"0",
"1"
],
"alphabet": [
"0",
"1",
"B"
],
"blank": "B",
"transition": {
"q0": {
"0": [
"q1",
"B",
"R"
],
"1": [
"q5",
"B",
"R"
]
},
"q1": {
"0": [
"q1",
"0",
"R"
],
"1": [
"q2",
"1",
"R"
]
},
"q2": {
"1": [
"q2",
"1",
"R"
],
"B": [
"q3",
"B",
"L"
],
"0": [
"q4",
"1",
"L"
]
},
"q3": {
"0": [
"q3",
"0",
"L"
],
"1": [
"q3",
"B",
"L"
],
"B": [
"q6",
"0",
"S"
]
},
"q4": {
"0": [
"q4",
"0",
"L"
],
"1": [
"q4",
"1",
"L"
],
"B": [
"q0",
"B",
"R"
]
},
"q5": {
"0": [
"q5",
"B",
"R"
],
"1": [
"q5",
"B",
"R"
],
"B": [
"q6",
"B",
"S"
]
}
}
},
"demo": "00000100"
}
+21
View File
@@ -0,0 +1,21 @@
#include "mainwindow.h"
#include <QApplication>
#include "turingmachine.h"
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setFont(QFont("Microsoft YaHei UI",9));
MainWindow w;
w.show();
// TuringMachine tm;
// tm.setGrammar("0n1n.json");
// tm.setTestStr("");
// if(tm.run())
// qDebug()<<"OK";
// else
// qDebug()<<"not ok";
return a.exec();
}
+41
View File
@@ -0,0 +1,41 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
// ui(new Ui::MainWindow)
{
// ui->setupUi(this);
cw = new CentralWidget(this);
helpMenu = new QMenu(this);
aboutAction = new QAction(tr("关于"), this);
connect(aboutAction, QAction::triggered, this, showAbout);
helpMenu->setTitle(tr("帮助(&H)"));
helpMenu->addAction(aboutAction);
setCentralWidget(cw);
menuBar()->addMenu(helpMenu);
statusBar()->showMessage("欢迎使用环保图灵机!");
connect(cw, CentralWidget::setStatus, this,[this](QString message)
{
statusBar()->showMessage(message, 0);
});
}
MainWindow::~MainWindow()
{
delete cw;
}
void MainWindow::showAbout()
{
QMessageBox *aboutWindow = new QMessageBox(this);
aboutWindow->setStandardButtons(QMessageBox::Ok);
aboutWindow->setText(tr("<h1>TuringMachine</h1>"
"<p>Based on Qt 5.10.1 (MinGW 5.3.0, 32bit)</p>"
"Source Code: <a href=\"https://github.com/c-my/TuringMachine\">https://github.com/c-my/TuringMachine</a><br/>"
"Email: "
"<address><a href=\"mailto:cmy1113@outlook.com?subject=TuringMachine Feedback\">cmy1113@outlook.com</a>"
"</address>"));
aboutWindow->show();
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMenu>
#include <QAction>
#include <QMessageBox>
#include "centralwidget.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
CentralWidget *cw;
QMenu *helpMenu;
QAction *aboutAction;
void showAbout();
};
#endif // MAINWINDOW_H
+24
View File
@@ -0,0 +1,24 @@
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle" >
<string>MainWindow</string>
</property>
<widget class="QMenuBar" name="menuBar" />
<widget class="QToolBar" name="mainToolBar" />
<widget class="QWidget" name="centralWidget" />
<widget class="QStatusBar" name="statusBar" />
</widget>
<layoutDefault spacing="6" margin="11" />
<pixmapfunction></pixmapfunction>
<resources/>
<connections/>
</ui>
+64
View File
@@ -0,0 +1,64 @@
#include "papertape.h"
PaperTape::PaperTape(QGraphicsItem *parent): QGraphicsObject(parent)
{
ani = new QPropertyAnimation(this, "pos");
this->setStr("hello");
this->adjustPos();
}
QRectF PaperTape::boundingRect() const
{
return QRectF(0 ,0 ,str.size()*width, height);
}
void PaperTape::setStr(QString str)
{
this->str = str;
lastLenth = lenth;
lenth = str.size();
// this->adjustPos();
this->update();
}
int PaperTape::getWidth()
{
return lenth*width;
}
void PaperTape::standBy(int index)
{
// ani->setStartValue(this->pos());
ani->setEndValue(QPointF(-(index+0.5)*width, this->pos().y()));
ani->setDuration(230);
ani->start();
}
void PaperTape::adjustPos()
{
setPos(-str.size()*width/2, -height);
}
void PaperTape::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setBackground(QBrush(Qt::white));
painter->eraseRect(/*-lastLenth*width/2, -height, width*1000, height*/boundingRect());
painter->setBrush(QBrush("lightblue"));
painter->setPen(Qt::NoPen);
painter->drawRect(0, 0, lenth*width, height);
painter->setPen(Qt::black);
painter->setPen(Qt::DotLine);
painter->setFont(QFont("Microsoft Yahei", 13));
for(int i=0; i<lenth; i++)
{
if(i!=0)
{
// 画分割线
painter->drawLine(0+i*width, 0, 0+i*width, height);
}
// 画字符
painter->drawText(i*width+width/2-4, height/2+8, str.at(i));
}
setToolTip(this->str);
// setPos(-str.size()*width/2, -height);
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef PAPERTAPE_H
#define PAPERTAPE_H
#include <QGraphicsObject>
#include <QPainter>
#include <QPropertyAnimation>
class PaperTape : public QGraphicsObject
{
Q_PROPERTY(QPoinF pos READ pos WRITE setPos)
public:
PaperTape(QGraphicsItem *parent = Q_NULLPTR);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR);
QRectF boundingRect() const;
void setStr(QString str);
int getWidth();
void standBy(int index);
void adjustPos();
private:
int height = 50;
int width = 50;
QString str;
int lenth=0, lastLenth=0;
QPropertyAnimation *ani;
};
#endif // PAPERTAPE_H
+146
View File
@@ -0,0 +1,146 @@
#include "turingmachine.h"
TuringMachine::TuringMachine(QObject *parent) : QObject(parent)
{
currentIndex = 1;
isRunning = true;
}
bool TuringMachine::setGrammar(QString filename)
{
QFile jsonFile(filename);
if(!jsonFile.exists())
return false;
jsonFile.open(QIODevice::ReadOnly|QIODevice::Text);
jsonobj = QJsonDocument::fromJson(jsonFile.readAll()).object();
jsonFile.close();
if(jsonobj.isEmpty()||!jsonobj.contains("grammar"))
return false;
grammar = jsonobj.value("grammar").toObject();
if(!grammar.contains("states")
||!grammar.contains("input")
||!grammar.contains("alphabet")
||!grammar.contains("blank")
||!grammar.contains("transition"))
return false;
//获取初始状态
initialState = grammar.value("states").toObject().value("initial").toString();
currentState = initialState;
//获取终止状态
finialStates.clear();
QJsonArray array = grammar.value("states").toObject().value("finial").toArray();
for(auto item: array)
finialStates.append(item.toString());
//获取状态集合
allStates.clear();
array = grammar.value("states").toObject().value("states").toArray();
for(auto item: array)
allStates.append(item.toString());
//获取空白符
blank = grammar.value("blank").toString().at(0);
//获取字符表
alphabet.clear();
array = grammar.value("alphabet").toArray();
for(auto item: array)
alphabet += (item.toString());
//获取接受字符
input.clear();
array = grammar.value("input").toArray();
for(auto item: array)
input += (item.toString());
//获取转移字符
transition.clear();
QStringList keys = grammar.value("transition").toObject().keys();
for(auto key: keys)
{
QJsonObject subobject = grammar.value("transition").toObject().value(key).toObject();
QStringList subkeys = subobject.keys();
for(auto subkey: subkeys)
{
QJsonArray array = subobject.value(subkey).toArray();
QString tmp = "δ(" + key +", " + subkey + ") = (";
for(auto item: array)
tmp += item.toString()+", ";
tmp.remove(tmp.length()-2, 2);
tmp+=")";
transition.append(tmp);
}
}
setTestStr(jsonobj.value("demo").toString());
name = jsonobj.value("name").toString();
return true;
}
void TuringMachine::setTestStr(QString str)
{
rawStr = str;
testStr = blank + str + blank;
isRunning = true;
}
bool TuringMachine::checkByStep()
{
QJsonValue value = grammar.value("transition").toObject().value(currentState)
.toObject().value(testStr.at(currentIndex));
if(!value.isUndefined())
{
QString listItem;
listItem = "δ(" +currentState + ", " + testStr.at(currentIndex) + ") = (";
currentState = value.toArray()[0].toString(); //更新当前状态
testStr[currentIndex] = value.toArray()[1].toString()[0]; //更新当前字符
QString move = value.toArray()[2].toString();
listItem += currentState +", " + testStr[currentIndex] + ", " + move+")";
transitionIndex = transition.indexOf(listItem);
if(move == "L")
currentIndex = (currentIndex - 1 >= 0) ? (currentIndex - 1) : 0;
else if(move == "R")
currentIndex = (currentIndex + 1 < testStr.size()) ?
(currentIndex + 1) : testStr.size()-1;
else if(move == "S")
currentIndex = currentIndex;
return true;
}
else
return false;
}
bool TuringMachine::run()
{
while (isRunning) {
checkByStep();
}
if(finialStates.contains(currentState))
return true;
else
return false;
}
bool TuringMachine::hasGrammar()
{
return !this->jsonobj.isEmpty();
}
bool TuringMachine::isStopped()
{
return !isRunning;
}
void TuringMachine::reset()
{
currentIndex = 1;
currentState = initialState;
// transition.clear();
// input.clear();
// alphabet.clear();
// finialStates.clear();
// allStates.clear();
}
+57
View File
@@ -0,0 +1,57 @@
#ifndef TURINGMACHINE_H
#define TURINGMACHINE_H
#include <QObject>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <QVector>
#include <QDebug>
class TuringMachine : public QObject
{
Q_OBJECT
public:
TuringMachine(QObject *parent = nullptr);
bool setGrammar(QString filename);
void setTestStr(QString str);
QString getTestStr() { return testStr; }
QString getRawStr() { return rawStr; }
QString getName() { return name; }
QString getInitialState() { return initialState; }
QChar getBlank() { return blank; }
QStringList getFinialStates() { return finialStates; }
QStringList getAllStates() { return allStates; }
QString getAlphabet() { return alphabet; }
QString getInput() { return input; }
int getCurrentIndex() { return currentIndex; }
QStringList getTransition() { return transition; }
int getTransitionIndex() { return transitionIndex; }
QString getCurrentState() { return currentState; }
bool checkByStep();
bool run();
bool hasGrammar();
bool isStopped();
void reset();
private:
QJsonObject jsonobj;
QJsonObject grammar;
QString name;
QString rawStr, testStr;
QChar blank; //空白符
QString currentState; //当前状态
int currentIndex; //当前字符索引号
int transitionIndex;
QString initialState;
QStringList finialStates;
QStringList allStates;
QString input;
QString alphabet;
QStringList transition;
bool isRunning;
};
#endif // TURINGMACHINE_H