Skip to content
Snippets Groups Projects
Commit c3ce7780 authored by Martin Hanzik's avatar Martin Hanzik Committed by Jan Trávníček
Browse files

Add basic algorithm discovery

parent 0dafc008
No related branches found
No related tags found
No related merge requests found
...@@ -37,6 +37,10 @@ include_directories( ...@@ -37,6 +37,10 @@ include_directories(
link_directories(${ALIB_PATH}/bin-debug) link_directories(${ALIB_PATH}/bin-debug)
   
add_executable(${PROJECT_NAME} add_executable(${PROJECT_NAME}
src/Algorithm/Algorithm.cpp
src/Algorithm/Algorithm.hpp
src/Algorithm/Registry.cpp
src/Algorithm/Registry.hpp
src/Converter.cpp src/Converter.cpp
src/Converter.hpp src/Converter.hpp
src/Graphics/Connection/Connection.cpp src/Graphics/Connection/Connection.cpp
......
#include <Algorithm/Algorithm.hpp>
#include <cassert>
#include <stdexcept>
#include <regex>
#include <utility>
Algorithm::Algorithm(std::string name)
: name(std::move(name)) {}
uint8_t Algorithm::getInputCount() const {
return static_cast<uint8_t>(this->overloads[0].parameterTypes.size());
}
void Algorithm::addOverload(Algorithm::Overload overload) {
if (!this->overloads.empty() && this->overloads.back().parameterTypes.size() != overload.parameterTypes.size())
throw std::runtime_error { std::string("Inconsistent number of parameters for algorithm ") + this->name };
this->overloads.push_back(overload);
}
std::string Algorithm::getPrettyName() const {
auto pos = this->name.rfind(':');
assert(pos != std::string::npos && pos != this->name.size() - 1);
std::string name = this->name.substr(pos + 1);
return std::regex_replace(name, std::regex {"([a-z])([A-Z])"}, "$1 $2");
}
Algorithm::Overload::Overload(std::string returnType,
std::vector<std::string> parameterTypes)
: returnType(std::move(returnType))
, parameterTypes(std::move(parameterTypes)) {}
#pragma once
#include <string>
#include <vector>
class Algorithm {
friend class Registry;
public:
struct Overload {
Overload(std::string returnType, std::vector<std::string> parameterTypes);
std::string returnType;
std::vector<std::string> parameterTypes;
};
explicit Algorithm(std::string name);
const std::string& getName() const { return this->name; }
std::string getPrettyName() const;
uint8_t getInputCount() const;
private:
void addOverload(Overload overload);
std::string name;
std::vector<Overload> overloads;
};
#include <Algorithm/Registry.hpp>
#include <registry/AlgorithmRegistry.hpp>
void Registry::initialize() {
auto& in = Registry::getInstance();
for (const auto& group: {"automaton::determinize", "automaton::simplify", "automaton::transform"}) {
for (const auto& item: abstraction::AlgorithmRegistry::listGroup(group)) {
const auto& name = item.first;
auto algorithm = std::make_unique<Algorithm>(name);
for (const auto& overload: abstraction::AlgorithmRegistry::listOverloads(name, item.second)) {
const std::string& resultType = std::get<1>(overload).first;
std::vector<std::string> paramNames;
for (const auto& param: std::get<2>(overload)) {
paramNames.push_back(std::get<0>(param));
}
algorithm->addOverload({ resultType, paramNames });
}
in.algorithms[name] = std::move(algorithm);
}
}
}
Registry& Registry::getInstance() {
static Registry instance;
return instance;
}
Algorithm* Registry::getAlgorithm(const std::string& name) {
auto& in = Registry::getInstance();
auto it = in.algorithms.find(name);
if (it == in.algorithms.end())
return nullptr;
return it->second.get();
}
#pragma once
#include <map>
#include <memory>
#include <string>
#include <Algorithm/Algorithm.hpp>
class Registry {
public:
static void initialize();
static Algorithm* getAlgorithm(const std::string& name);
private:
Registry() = default;
static Registry& getInstance();
std::map<std::string, std::unique_ptr<Algorithm>> algorithms;
};
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
   
#include <exception/CommonException.h> #include <exception/CommonException.h>
   
#include <Algorithm/Registry.hpp>
#include <Converter.hpp> #include <Converter.hpp>
#include <Graphics/Dialogs/InputDialog.hpp> #include <Graphics/Dialogs/InputDialog.hpp>
#include <Graphics/Dialogs/ResultDialog.hpp> #include <Graphics/Dialogs/ResultDialog.hpp>
...@@ -24,6 +25,8 @@ MainWindow::MainWindow() ...@@ -24,6 +25,8 @@ MainWindow::MainWindow()
ui->setupUi(this); ui->setupUi(this);
ui->graphicsView->setScene(this->scene.get()); ui->graphicsView->setScene(this->scene.get());
   
Registry::initialize();
this->scene->addItem(WrapperFactory::createNew(WrapperFactory::INPUT, 0, 200)); this->scene->addItem(WrapperFactory::createNew(WrapperFactory::INPUT, 0, 200));
outputBox = WrapperFactory::createNew(WrapperFactory::OUTPUT, 400, 200); outputBox = WrapperFactory::createNew(WrapperFactory::OUTPUT, 400, 200);
this->scene->addItem(outputBox); this->scene->addItem(outputBox);
......
...@@ -6,44 +6,9 @@ ...@@ -6,44 +6,9 @@
#include <common/AlgorithmHelper.h> #include <common/AlgorithmHelper.h>
#include <exception/CommonException.h> #include <exception/CommonException.h>
   
AlgorithmModelBox::AlgorithmModelBox(Algorithm* algorithm)
namespace { : ModelBox(ModelType::Algorithm, algorithm->getInputCount())
uint8_t determineNumberOfInputs(const std::string& name) { , algorithm(algorithm) {}
ext::set<ext::tuple<abstraction::AlgorithmCategories::AlgorithmCategory,
ext::pair<std::string,
ext::set<abstraction::ParamQualifiers::ParamQualifier>>,
ext::vector<ext::tuple<std::string,
ext::set<abstraction::ParamQualifiers::ParamQualifier>,
std::string>>>> data = abstraction::AlgorithmRegistry::listOverloads(name, {});
for (const auto& tup: data) {
const auto& out = std::get<1>(tup).first;
if (out.find("automaton::DFA") == 0 || out.find("automaton::NFA") == 0)
{
bool ok = true;
for (const auto& tup2: std::get<2>(tup))
{
const auto& in = std::get<0>(tup2);
if (in.find("automaton::DFA") != 0 && in.find("automaton::NFA") != 0)
{
ok = false;
break;
}
}
if (!ok)
continue;
return static_cast<uint8_t>(std::get<2>(tup).size());
}
}
Q_ASSERT(false && "Failed to determine proper overload.");
return 0;
}
}
AlgorithmModelBox::AlgorithmModelBox(std::string name)
: ModelBox(ModelType::Algorithm, determineNumberOfInputs(name))
, name(std::move(name)) {
Q_ASSERT(!this->name.empty());
}
   
std::shared_ptr<abstraction::OperationAbstraction> AlgorithmModelBox::run() { std::shared_ptr<abstraction::OperationAbstraction> AlgorithmModelBox::run() {
ext::vector<std::shared_ptr<abstraction::OperationAbstraction>> params; ext::vector<std::shared_ptr<abstraction::OperationAbstraction>> params;
...@@ -57,7 +22,7 @@ std::shared_ptr<abstraction::OperationAbstraction> AlgorithmModelBox::run() { ...@@ -57,7 +22,7 @@ std::shared_ptr<abstraction::OperationAbstraction> AlgorithmModelBox::run() {
} }
   
std::vector<bool> moves(params.size(), true); std::vector<bool> moves(params.size(), true);
return abstraction::AlgorithmHelper::eval(this->name, return abstraction::AlgorithmHelper::eval(this->algorithm->getName(),
{}, {},
params, params,
moves, moves,
......
#pragma once #pragma once
#include <Algorithm/Algorithm.hpp>
#include <Models/ModelBox.hpp> #include <Models/ModelBox.hpp>
   
class AlgorithmModelBox : public ModelBox { class AlgorithmModelBox : public ModelBox {
public: public:
explicit AlgorithmModelBox(std::string name); explicit AlgorithmModelBox(Algorithm* algorithm);
   
std::shared_ptr<abstraction::OperationAbstraction> run() override; std::shared_ptr<abstraction::OperationAbstraction> run() override;
   
private: private:
std::string name; Algorithm* algorithm;
}; };
   
   
...@@ -3,15 +3,12 @@ ...@@ -3,15 +3,12 @@
#include <QChar> #include <QChar>
#include <QString> #include <QString>
   
#include <Algorithm/Registry.hpp>
#include <Graphics/InputGraphicsBox.hpp> #include <Graphics/InputGraphicsBox.hpp>
#include <Models/InputModelBox.hpp> #include <Graphics/GraphicsBox.hpp>
#include <Models/OutputModelBox.hpp>
#include <Models/AlgorithmModelBox.hpp> #include <Models/AlgorithmModelBox.hpp>
#include <Models/InputModelBox.hpp> #include <Models/InputModelBox.hpp>
#include <Models/OutputModelBox.hpp> #include <Models/OutputModelBox.hpp>
#include <Graphics/GraphicsBox.hpp>
#include <Graphics/InputGraphicsBox.hpp>
   
GraphicsBox* WrapperFactory::createNew(WrapperFactory::Algorithms algorithm, qreal x = 0, qreal y = 0) GraphicsBox* WrapperFactory::createNew(WrapperFactory::Algorithms algorithm, qreal x = 0, qreal y = 0)
{ {
...@@ -27,49 +24,49 @@ GraphicsBox* WrapperFactory::createNew(WrapperFactory::Algorithms algorithm, qre ...@@ -27,49 +24,49 @@ GraphicsBox* WrapperFactory::createNew(WrapperFactory::Algorithms algorithm, qre
   
// Single simplify // Single simplify
case DETERMINIZE: case DETERMINIZE:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::determinize::Determinize"), "Determinize", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::determinize::Determinize")), "Determinize", {x, y});
case TOTAL: case TOTAL:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::Total"), "Total", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::simplify::Total")), "Total", {x, y});
case MINIMIZE: case MINIMIZE:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::Minimize"), "Minimize", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::simplify::Minimize")), "Minimize", {x, y});
case NORMALIZE: case NORMALIZE:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::Normalize"), "Normalize", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::simplify::Normalize")), "Normalize", {x, y});
case SINGLE_INITIAL: case SINGLE_INITIAL:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::SingleInitialState"), "Single Initial", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::simplify::SingleInitialState")), "Single Initial", {x, y});
case EPSILON_REMOVE_IN: case EPSILON_REMOVE_IN:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::EpsilonRemoverIncoming"), eps.append("-Remove In"), {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::simplify::EpsilonRemoverIncoming")), eps.append("-Remove In"), {x, y});
case EPSILON_REMOVE_OUT: case EPSILON_REMOVE_OUT:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::EpsilonRemoverOutgoing"), eps.append("-Remove Out"), {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::simplify::EpsilonRemoverOutgoing")), eps.append("-Remove Out"), {x, y});
case RENAME: case RENAME:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::Rename"), "Rename", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::simplify::Rename")), "Rename", {x, y});
case TRIM: case TRIM:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::Trim"), "Trim", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::simplify::Trim")), "Trim", {x, y});
case REMOVE_USELES: case REMOVE_USELES:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::UselessStatesRemover"), "Remove Useless", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::simplify::UselessStatesRemover")), "Remove Useless", {x, y});
case REMOVE_UNREACHABLE: case REMOVE_UNREACHABLE:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::simplify::UnreachableStatesRemover"), "Remove Unreachable", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::simplify::UnreachableStatesRemover")), "Remove Unreachable", {x, y});
   
// Single transform // Single transform
case COMPACT: case COMPACT:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::Compaction"), "Compact", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::transform::Compaction")), "Compact", {x, y});
case REVERSE: case REVERSE:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::Reverse"), "Reverse", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::transform::Reverse")), "Reverse", {x, y});
case ITERATE: case ITERATE:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomatonIteration"), "Iterate", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::transform::AutomatonIteration")), "Iterate", {x, y});
case ITERATE_EPSILON: case ITERATE_EPSILON:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomatonIterationEpsilonTransition"), eps.append("-Iterate"), {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::transform::AutomatonIterationEpsilonTransition")), eps.append("-Iterate"), {x, y});
   
//Double //Double
case CONCATENATE: case CONCATENATE:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomataConcatenation"), "Concatenate", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::transform::AutomataConcatenation")), "Concatenate", {x, y});
case CONCATENATE_EPSILON: case CONCATENATE_EPSILON:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomataConcatenationEpsilonTransition"), eps.append("-Concatenate"), {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::transform::AutomataConcatenationEpsilonTransition")), eps.append("-Concatenate"), {x, y});
case UNION: case UNION:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomataUnionCartesianProduct"), "Union", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::transform::AutomataUnionCartesianProduct")), "Union", {x, y});
case UNION_EPSILON: case UNION_EPSILON:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomataUnionEpsilonTransition"), eps.append("-Union"), {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::transform::AutomataUnionEpsilonTransition")), eps.append("-Union"), {x, y});
case INTERSECT: case INTERSECT:
return new GraphicsBox(std::make_unique<AlgorithmModelBox>("automaton::transform::AutomataIntersectionCartesianProduct"), "Intersect", {x, y}); return new GraphicsBox(std::make_unique<AlgorithmModelBox>(Registry::getAlgorithm("automaton::transform::AutomataIntersectionCartesianProduct")), "Intersect", {x, y});
default: default:
return nullptr; return nullptr;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment