Willi Zschiebsch před 5 roky
rodič
revize
4e327b02f5

+ 2 - 2
lib/CMakeLists.txt

@@ -24,7 +24,7 @@ add_library(${PROJECT_NAME} STATIC
         include/Output.h
         include/ProcessorBase.h
         include/ProcessorEvolution.h
-	include/ProcessorManual.h
+	include/ProcessorStandard.h
 	include/state.h
 
         src/Input.cpp
@@ -39,7 +39,7 @@ add_library(${PROJECT_NAME} STATIC
         src/Output.cpp
         src/ProcessorBase.cpp
 	src/ProcessorEvolution.cpp
-        src/ProcessorManual.cpp
+        src/ProcessorStandard.cpp
         )
 
 target_include_directories(${PROJECT_NAME} PUBLIC

+ 1 - 0
lib/include/IInput.h

@@ -12,6 +12,7 @@ namespace mdd{
         virtual json& setDefaultValue() = 0;
         virtual bool verify(const json & data) = 0;
         virtual bool connect(std::shared_ptr<IOutput> output) = 0;
+        virtual std::shared_ptr<IOutput> getConnection() = 0;
         virtual ~IInput() = default;
     };
 }

+ 3 - 0
lib/include/IModule.h

@@ -18,8 +18,11 @@ namespace mdd {
         virtual std::vector<std::string> getOutputs() = 0;
         virtual std::vector<std::string> getInputIDs() = 0;
         virtual std::vector<std::string> getOutputIDs() = 0;
+        virtual std::vector<state> getInputStates() = 0;
+        virtual std::vector<state> getOutputStates() = 0;
         virtual std::shared_ptr<IOutput> getOutput(std::string output_id) = 0;
         virtual std::shared_ptr<IInput> getInput(std::string input_id) = 0;
+        virtual std::vector <std::shared_ptr<IOutput>> getConnections() = 0;
         virtual state update() = 0;
         virtual ~IModule() = default;
     };

+ 1 - 0
lib/include/IProcessor.h

@@ -9,6 +9,7 @@ namespace mdd
     class IProcessor: public  IModule{
     public:
         virtual std::string  addModule(std::shared_ptr<IModule> module) = 0;
+        virtual void  removeModule(std::shared_ptr<IModule> module) = 0;
         virtual std::vector<std::string> getModules() = 0;
         virtual std::vector<std::string> getModuleIDs() = 0;
         virtual std::shared_ptr<IModule> getModule(std::string module_id) = 0;

+ 1 - 0
lib/include/Input.h

@@ -33,6 +33,7 @@ namespace mdd {
         void resetState() override;
 
         const json& getValue() override;
+        std::shared_ptr<IOutput> getConnection() override;
         json& setDefaultValue() override;
         bool verify(const json & data) override;
         bool connect(std::shared_ptr<IOutput> output) override;

+ 3 - 0
lib/include/ModuleBase.h

@@ -37,6 +37,9 @@ class ModuleBase : public  IModule{
         std::vector<std::string> getInputIDs() override;
         std::vector<std::string> getOutputs() override;
         std::vector<std::string> getOutputIDs() override;
+        std::vector<state> getInputStates() override;
+        std::vector<state> getOutputStates() override;
+        std::vector<std::shared_ptr<IOutput>> getConnections() override;
         std::shared_ptr<IOutput> getOutput(std::string output_id) override;
         std::shared_ptr<IInput> getInput(std::string input_id) override;
         std::string setType(std::string type) override;

+ 21 - 4
lib/include/ProcessorBase.h

@@ -5,11 +5,22 @@
 #include "Input.h"
 #include "Output.h"
 #include "IProcessor.h"
-#include "HandlerModule.h"
 
 namespace mdd {
     class ProcessorBase : public IProcessor{
     private:
+
+        template<class T>
+        class HandlerModule {
+        public:
+            std::shared_ptr<IModule> moduleHandler;
+            std::shared_ptr<T> accessHandler;
+            HandlerModule(std::shared_ptr<IModule> module, std::shared_ptr<T> access) {
+                moduleHandler = module;
+                accessHandler = access;
+            }
+        };
+
         std::string _prefix;
         std::string _type;
         int _appendix;
@@ -39,6 +50,7 @@ namespace mdd {
         void updateID() override ;
 
         std::string addModule(std::shared_ptr<IModule> module) override ;
+        void removeModule(std::shared_ptr<IModule> module) override;
         std::string addModuleInput(std::string module_ID, std::string input_ID);
         std::string addModuleInput(std::shared_ptr<IModule> module, std::shared_ptr<IInput> input);
         std::string addModuleOutput(std::string module_ID, std::string output_ID);
@@ -48,9 +60,14 @@ namespace mdd {
         std::vector<std::string> getOutputs() override;
         std::vector<std::string> getModules() override;
 
-        std::vector<std::string> getInputIDs();
-        std::vector<std::string> getOutputIDs();
-        std::vector<std::string> getModuleIDs();
+        std::vector<std::string> getInputIDs() override;
+        std::vector<std::string> getOutputIDs() override;
+        std::vector<std::string> getModuleIDs() override;
+
+        std::vector<state> getInputStates() override;
+        std::vector<state> getOutputStates() override;
+
+        std::vector<std::shared_ptr<IOutput>> getConnections() override;
 
         std::shared_ptr<IOutput> getOutput(std::string output_id) override;
         std::shared_ptr<IInput> getInput(std::string input_id) override;

+ 0 - 14
lib/include/ProcessorManual.h

@@ -1,14 +0,0 @@
-#ifndef MDD_PROCESSORMANUAL_H
-#define MDD_PROCESSORMANUAL_H
-#include "ProcessorBase.h"
-#include "Output.h"
-namespace mdd {
-    class ProcessorManual : public ProcessorBase {
-    public:
-        ProcessorManual();
-        state update() override;
-        std::shared_ptr<IOutput> getIteration();
-    };
-}
-
-#endif //MDD_PROCESSORMANUAL_H

+ 38 - 0
lib/include/ProcessorStandard.h

@@ -0,0 +1,38 @@
+#ifndef MDD_PROCESSORSTANDARD_H
+#define MDD_PROCESSORSTANDARD_H
+#include "ProcessorBase.h"
+#include "Output.h"
+#include <chrono>
+namespace mdd {
+    enum priority {
+        MANUAL,
+        STATIC,
+        DYNAMIC,
+        TIME
+    };
+
+    class ProcessorStandard : public ProcessorBase {
+    private:
+        struct module_priority{
+            std::shared_ptr<IModule> module_ptr;
+            size_t connectionCounter;
+            size_t changeCounter;
+            std::chrono::milliseconds runtime;
+        };
+        std::vector<module_priority> _priority_list;
+
+        priority _prioritization;
+    public:
+        int maxIterations;
+        priority priorityEvaluation;
+
+        ProcessorStandard(priority priorityEvaluation = MANUAL, int maxIterations = -1);
+        std::string addModule(std::shared_ptr<IModule> module) override;
+        void removeModule(std::shared_ptr<IModule> module) override;
+        std::vector<std::shared_ptr<IModule>> getModulePriority();
+        state update() override;
+        std::shared_ptr<IOutput> getIteration();
+    };
+}
+
+#endif //MDD_PROCESSORMANUAL_H

+ 2 - 0
lib/src/Input.cpp

@@ -52,6 +52,8 @@ namespace mdd{
         }
     }
 
+    std::shared_ptr<IOutput> Input::getConnection() { return _output; }
+
     json& Input::setDefaultValue(){
         return _value;
     }

+ 25 - 0
lib/src/ModuleBase.cpp

@@ -44,6 +44,31 @@ namespace mdd {
         return ret;
     }
 
+    std::vector<state> ModuleBase::getInputStates() {
+        std::vector<state> ret;
+        for (auto& input : _inputs) {
+            ret.push_back(input->getState());
+        }
+        return ret;
+    }
+
+    std::vector<state> ModuleBase::getOutputStates() {
+        std::vector<state> ret;
+        for (auto& output : _outputs) {
+            ret.push_back(output->getState());
+        }
+        return ret;
+    }
+
+    std::vector<std::shared_ptr<IOutput>> ModuleBase::getConnections()
+    {
+        std::vector<std::shared_ptr<IOutput>> ret;
+        for (auto& input : _inputs) {
+            ret.push_back(input->getConnection());
+        }
+        return ret;
+    }
+
     int ModuleBase::addInput(const std::string& type , const json& value,
                              const std::function<bool(const json&)>& verification) {
         _inputs.emplace_back(std::make_shared<Input>(type, _inputs.size(), value, verification));

+ 58 - 0
lib/src/ProcessorBase.cpp

@@ -77,6 +77,30 @@ namespace mdd{
         return _modules.back()->getID();
     }
 
+    void ProcessorBase::removeModule(std::shared_ptr<IModule> module)
+    {
+        for (auto it = _module_inputs.begin(); it != _module_inputs.end(); ++it) {
+            if (it->accessHandler == module)
+            {
+                _module_inputs.erase(it);
+            }
+        }
+
+        for (auto it = _module_outputs.begin(); it != _module_outputs.end(); ++it) {
+            if (it->accessHandler == module)
+            {
+                _module_outputs.erase(it);
+            }
+        }
+
+        for (auto it = _modules.begin(); it != _modules.end(); ++it) {
+            if ((*it) == module)
+            {
+                _modules.erase(it);
+            }
+        }
+    }
+
     std::string ProcessorBase::addModuleInput(std::string module_ID, std::string input_ID){
         int ret = _processor_inputs.size();
         for (auto& module : _modules) {
@@ -166,6 +190,40 @@ namespace mdd{
         return ret;
     }
 
+    std::vector<state> ProcessorBase::getInputStates() {
+        std::vector<state> ret;
+        for (auto& input : _processor_inputs) {
+            ret.push_back(input->getState());
+        }
+        for (auto& input : _module_inputs) {
+            ret.push_back(input.accessHandler->getState());
+        }
+        return ret;
+    }
+    
+    std::vector<state> ProcessorBase::getOutputStates() {
+        std::vector<state> ret;
+        for (auto& output : _processor_outputs) {
+            ret.push_back(output->getState());
+        }
+        for (auto& output : _module_outputs) {
+            ret.push_back(output.accessHandler->getState());
+        }
+        return ret;
+    }
+
+    std::vector<std::shared_ptr<IOutput>> ProcessorBase::getConnections()
+    {
+        std::vector<std::shared_ptr<IOutput>> ret;
+        for (auto& input : _processor_inputs) {
+            ret.push_back(input->getConnection());
+        }
+        for (auto& input : _module_inputs) {
+            ret.push_back(input.accessHandler->getConnection());
+        }
+        return ret;
+    }
+
     std::shared_ptr<IOutput> ProcessorBase::getOutput(std::string output_id){
         for (auto& output : _processor_outputs) {
             if(output->getID() == output_id){

+ 0 - 30
lib/src/ProcessorManual.cpp

@@ -1,30 +0,0 @@
-#include "ProcessorManual.h"
-#include <iostream>
-
-namespace mdd {
-    ProcessorManual::ProcessorManual()
-    {
-        addProcessorOutput("Iterator", "{ \"value\": 0 }"_json);
-    }
-
-    state ProcessorManual::update() {
-        state ret = state::UNCHANGED;
-        state group_state = state::CHANGED;
-        while(group_state == state::CHANGED){
-            getProcessorOutput(0)->getValueInternal()["value"]= getProcessorOutput(0)->getValue()["value"].get<int>()+1;
-            group_state = state::UNCHANGED;
-            for (int i = 0; i < getModules().size(); ++i) {
-                state module_state = getModule(i)->update();
-                if(module_state == state::CHANGED){
-                    group_state = state::CHANGED;
-                    ret = state::CHANGED;
-                }
-            }
-        }
-        return ret;
-    }
-
-    std::shared_ptr<IOutput> ProcessorManual::getIteration(){
-        return getProcessorOutput(0);
-    }
-}

+ 106 - 0
lib/src/ProcessorStandard.cpp

@@ -0,0 +1,106 @@
+#include "ProcessorStandard.h"
+#include <iostream>
+
+namespace mdd {
+    ProcessorStandard::ProcessorStandard(priority priorityEvaluation = MANUAL, int maxIterations = -1):
+        priorityEvaluation(priorityEvaluation),
+        maxIterations(maxIterations)
+    {
+        addProcessorOutput("Iterator", "{ \"value\": 0 }"_json);
+    }
+
+    std::string ProcessorStandard::addModule(std::shared_ptr<IModule> module)
+    {
+        std::string id = ProcessorBase::addModule(module);
+        _priority_list.emplace_back(module);
+        return id;
+    }
+
+    void ProcessorStandard::removeModule(std::shared_ptr<IModule> module)
+    {
+        ProcessorBase::removeModule(module);
+        for (auto it = _priority_list.begin(); it != _priority_list.end(); ++it) {
+            if (it->module_ptr == module)
+            {
+                _priority_list.erase(it);
+                return;
+            }
+        }
+    }
+
+    std::vector<std::shared_ptr<IModule>> ProcessorStandard::getModulePriority()
+    {
+        std::vector <std::shared_ptr<IModule>> ret;
+        for (auto& p : _priority_list) {
+            ret.push_back(p.module_ptr);
+        }
+        return ret;
+    }
+
+    state ProcessorStandard::update() {
+        if (priorityEvaluation != MANUAL)
+        {
+            //sort by connections
+            for (auto it = _priority_list.begin(); it != _priority_list.end(); ++it) {
+                auto connections = it->module_ptr->getConnections();
+                it->connectionCounter = 0;
+                for (auto it_c = connections.begin(); it_c != connections.end(); ++it_c) {
+                    if ((*it_c) != nullptr)
+                    {
+                        ++(it->connectionCounter);
+                    }
+                }
+            }
+            std::sort(_priority_list.begin(), _priority_list.end(), [](module_priority a, module_priority b) {
+                return a.connectionCounter < b.connectionCounter;
+            });
+        }
+        
+        typedef std::chrono::high_resolution_clock Time;
+        //update
+        state ret = state::UNCHANGED;
+        state group_state = state::CHANGED;
+        while (group_state == state::CHANGED) {
+            getProcessorOutput(0)->getValueInternal()["value"] = getProcessorOutput(0)->getValue()["value"].get<int>() + 1;
+            group_state = state::UNCHANGED;
+            for (int i = 0; i < _priority_list.size(); ++i) {
+                auto t_start = Time::now();
+                state module_state = _priority_list[i].module_ptr->update();
+                auto t_end = Time::now();
+                _priority_list[i].runtime = std::chrono::duration_cast<std::chrono::milliseconds>(t_end - t_start);
+                if (module_state == state::CHANGED) {
+                    group_state = state::CHANGED;
+                    ret = state::CHANGED;
+                }
+                if (priorityEvaluation == DYNAMIC || priorityEvaluation == TIME) {
+                    if (_priority_list[i + 1].connectionCounter == _priority_list[i].connectionCounter)
+                    {
+                        for (auto it = _priority_list.begin() + i + 1; it != _priority_list.end(); ++it) {
+                            auto input_states = it->module_ptr->getInputStates();
+                            it->changeCounter = 0;
+                            for (auto it_c = input_states.begin(); it_c != input_states.end(); ++it_c) {
+                                if ((*it_c) == state::CHANGED)
+                                {
+                                    ++(it->changeCounter);
+                                }
+                            }
+                        }
+                        std::sort(_priority_list.begin() + i + 1, _priority_list.end(), [](module_priority a, module_priority b) {
+                            return (a.connectionCounter - a.changeCounter) < (b.connectionCounter - b.changeCounter);
+                        });
+                    }
+                    //optimize by computational time
+                }
+            }
+            if (maxIterations != -1 && getProcessorOutput(0)->getValueInternal()["value"].get<int>() >= maxIterations)
+            {
+                return state::STATE_ERROR;
+            }
+        }
+        return ret;
+    }
+
+    std::shared_ptr<IOutput> ProcessorStandard::getIteration(){
+        return getProcessorOutput(0);
+    }
+}

+ 3 - 3
lib/test/test_ProcessorManual.cpp

@@ -30,7 +30,7 @@ TEST(ProcessorManual, CalculateSimpleFormula){
     f4->getInput(inputs[0])->connect(f3->getOutput(f3->getOutputIDs()[0]));
     f4->getInput(inputs[1])->setDefaultValue()["value"] = 2;
 
-    std::shared_ptr<ProcessorManual> test = std::make_shared<ProcessorManual>();
+    std::shared_ptr<ProcessorStandard> test = std::make_shared<ProcessorStandard>();
     test->addModule(f1);
     test->addModule(f2);
     test->addModule(f3);
@@ -72,7 +72,7 @@ TEST(ProcessorManual, CalculateAdvancedFormula){
     f4->getInput(inputs[0])->connect(f3->getOutput(f3->getOutputIDs()[0]));
     f4->getInput(inputs[1])->setDefaultValue()["value"] = 2;
 
-    std::shared_ptr<ProcessorManual> test = std::make_shared<ProcessorManual>();
+    std::shared_ptr<ProcessorStandard> test = std::make_shared<ProcessorStandard>();
     test->addModule(f4);
     test->addModule(f3);
     test->addModule(f2);
@@ -87,7 +87,7 @@ TEST(ProcessorManual, CalculateExtremeFormula){
     //x_0=8, x_i=x_{i-1}/2
     std::shared_ptr<ModuleSwitch> switchModule =  std::make_shared<ModuleSwitch>();
     std::shared_ptr<ModuleMath> calcModule = std::make_shared<ModuleMath>(MathOperation::DIVIDE);
-    std::shared_ptr<ProcessorManual> processor = std::make_shared<ProcessorManual>();
+    std::shared_ptr<ProcessorStandard> processor = std::make_shared<ProcessorStandard>();
     processor->addModule(switchModule);
     processor->addModule(calcModule);