Browse Source

Finish Processor Priority

Willi Zschiebsch 5 years atrás
parent
commit
e3273ff3f8

+ 2 - 1
lib/include/IModule.h

@@ -22,7 +22,8 @@ namespace mdd {
         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 std::vector <std::shared_ptr<IOutput>> getInputConnections() = 0;
+        virtual std::vector <std::vector <std::shared_ptr<IInput>>> getOutputConnections() = 0;
         virtual state update() = 0;
         virtual ~IModule() = default;
     };

+ 2 - 1
lib/include/ModuleBase.h

@@ -39,7 +39,8 @@ class ModuleBase : public  IModule{
         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::vector<std::shared_ptr<IOutput>> getInputConnections() override;
+        std::vector <std::vector <std::shared_ptr<IInput>>> getOutputConnections() 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;

+ 2 - 1
lib/include/ProcessorBase.h

@@ -67,7 +67,8 @@ namespace mdd {
         std::vector<state> getInputStates() override;
         std::vector<state> getOutputStates() override;
 
-        std::vector<std::shared_ptr<IOutput>> getConnections() override;
+        std::vector<std::shared_ptr<IOutput>> getInputConnections() override;
+        std::vector <std::vector <std::shared_ptr<IInput>>> getOutputConnections() override;
 
         std::shared_ptr<IOutput> getOutput(std::string output_id) override;
         std::shared_ptr<IInput> getInput(std::string input_id) override;

+ 4 - 3
lib/include/ProcessorStandard.h

@@ -15,10 +15,11 @@ namespace mdd {
     private:
         struct module_priority{
             std::shared_ptr<IModule> module_ptr;
-            size_t connectionCounter;
+            size_t inputCounter;
             size_t changeCounter;
-            std::chrono::milliseconds runtime;
-            module_priority(std::shared_ptr<IModule> module, size_t connection = 0, size_t change = 0);
+            size_t outputCounter;
+            int time_priority;
+            module_priority(std::shared_ptr<IModule> module, size_t inputs = 0, size_t outputs = 0, size_t change = 0);
         };
         std::vector<module_priority> _priority_list;
 

+ 10 - 1
lib/src/ModuleBase.cpp

@@ -60,7 +60,7 @@ namespace mdd {
         return ret;
     }
 
-    std::vector<std::shared_ptr<IOutput>> ModuleBase::getConnections()
+    std::vector<std::shared_ptr<IOutput>> ModuleBase::getInputConnections()
     {
         std::vector<std::shared_ptr<IOutput>> ret;
         for (auto& input : _inputs) {
@@ -77,6 +77,15 @@ namespace mdd {
     }
 
 
+    std::vector<std::vector<std::shared_ptr<IInput>>> ModuleBase::getOutputConnections()
+    {
+        std::vector<std::vector<std::shared_ptr<IInput>>> ret;
+        for (auto& output : _outputs) {
+            ret.push_back(output->getConnections());
+        }
+        return ret;
+    }
+
     std::shared_ptr<IOutput> ModuleBase::getOutput(std::string output_id) {
         for(auto& output : _outputs){
                 if (output->getID() == output_id) {

+ 13 - 1
lib/src/ProcessorBase.cpp

@@ -212,7 +212,7 @@ namespace mdd{
         return ret;
     }
 
-    std::vector<std::shared_ptr<IOutput>> ProcessorBase::getConnections()
+    std::vector<std::shared_ptr<IOutput>> ProcessorBase::getInputConnections()
     {
         std::vector<std::shared_ptr<IOutput>> ret;
         for (auto& input : _processor_inputs) {
@@ -224,6 +224,18 @@ namespace mdd{
         return ret;
     }
 
+    std::vector<std::vector<std::shared_ptr<IInput>>> ProcessorBase::getOutputConnections()
+    {
+        std::vector<std::vector<std::shared_ptr<IInput>>> ret;
+        for (auto& output : _processor_outputs) {
+            ret.push_back(output->getConnections());
+        }
+        for (auto& output : _module_outputs) {
+            ret.push_back(output.accessHandler->getConnections());
+        }
+        return ret;
+    }
+
     std::shared_ptr<IOutput> ProcessorBase::getOutput(std::string output_id){
         for (auto& output : _processor_outputs) {
             if(output->getID() == output_id){

+ 53 - 14
lib/src/ProcessorStandard.cpp

@@ -40,20 +40,34 @@ namespace mdd {
     state ProcessorStandard::update() {
         if (priorityEvaluation != MANUAL)
         {
-            //sort by connections
+            //update priorities
             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) {
+                //collect connected inputs
+                auto input_connections = it->module_ptr->getInputConnections();
+                it->inputCounter = 0;
+                for (auto it_c = input_connections.begin(); it_c != input_connections.end(); ++it_c) {
                     if ((*it_c) != nullptr)
                     {
-                        ++(it->connectionCounter);
+                        ++(it->inputCounter);
+                    }
+                }
+                //collect connected outputs
+                auto output_connections = it->module_ptr->getOutputConnections();
+                it->outputCounter = 0;
+                for (auto it_c = output_connections.begin(); it_c != output_connections.end(); ++it_c) {
+                    if (!(*it_c).empty())
+                    {
+                        ++(it->outputCounter);
                     }
                 }
             }
             //sort by connections
             std::sort(_priority_list.begin(), _priority_list.end(), [](module_priority a, module_priority b) {
-                return a.connectionCounter < b.connectionCounter;
+                if (a.inputCounter == b.inputCounter)
+                {
+                    return a.outputCounter > b.outputCounter;
+                }
+                return a.inputCounter < b.inputCounter;
             });
         }
         
@@ -61,21 +75,30 @@ namespace mdd {
         //update
         state ret = state::UNCHANGED;
         state group_state = state::CHANGED;
+        size_t restart = 0;
         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) {
+            for (int i = restart; 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 (priorityEvaluation == TIME)
+                {
+                    _priority_list[i].time_priority = std::round(std::log10(std::chrono::duration_cast<std::chrono::milliseconds>(t_end - t_start).count()));
+                }
                 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)
+                // ignore modules which have to initilize once in the future
+                if (_priority_list[i].inputCounter == 0 && priorityEvaluation != MANUAL) {
+                    restart = i;
+                }
+                if ((priorityEvaluation == DYNAMIC || priorityEvaluation == TIME) && _priority_list.size() < i+1) {
+                    if (_priority_list[i + 1].inputCounter == _priority_list[i].inputCounter && _priority_list[i + 1].inputCounter != 0)
                     {
+                        //collect changes
                         for (auto it = _priority_list.begin() + i + 1; it != _priority_list.end(); ++it) {
                             auto input_states = it->module_ptr->getInputStates();
                             it->changeCounter = 0;
@@ -87,10 +110,24 @@ namespace mdd {
                             }
                         }
                         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);
+                            if (a.inputCounter == b.inputCounter)
+                            {
+                                if (a.time_priority == b.time_priority)
+                                {
+                                    if ((a.inputCounter - a.changeCounter) == (b.inputCounter - b.changeCounter)) {
+                                        if (a.changeCounter == b.changeCounter) {
+                                            return a.outputCounter > b.outputCounter;
+                                        }
+                                        return a.changeCounter > b.changeCounter;
+                                    }
+                                    return (a.inputCounter - a.changeCounter) < (b.inputCounter - b.changeCounter);
+                                }
+                                return a.time_priority < b.time_priority;
+                            }
+                            return a.inputCounter < b.inputCounter;
+                            
                         });
                     }
-                    //optimize by computational time
                 }
             }
             if (maxIterations != -1 && getProcessorOutput(0)->getValueInternal()["value"].get<int>() >= maxIterations)
@@ -104,10 +141,12 @@ namespace mdd {
     std::shared_ptr<IOutput> ProcessorStandard::getIteration(){
         return getProcessorOutput(0);
     }
-    ProcessorStandard::module_priority::module_priority(std::shared_ptr<IModule> module, size_t connection, size_t change)
+    ProcessorStandard::module_priority::module_priority(std::shared_ptr<IModule> module, size_t inputs, size_t outputs, size_t change)
     {
         module_ptr = module;
-        connectionCounter = connection;
+        inputCounter = inputs;
+        outputCounter = outputs;
         changeCounter = change;
+        time_priority = 0;
     }
 }

+ 77 - 1
lib/test/test_ProcessorStandard.cpp

@@ -79,7 +79,7 @@ TEST(ProcessorStandard, CalculateAdvancedFormula){
     test->addModule(f1);
     test->addModuleOutput(f4, f4->getOutput(f4->getOutputIDs()[0]));
     test->update();
-
+    //std::cout << test->getOutput(test->getOutputIDs()[1])->getValue()["value"].dump() << std::endl;
     EXPECT_EQ(test->getOutput(test->getOutputIDs()[1])->getValue()["value"].get<int>(), 3);
 }
 
@@ -103,4 +103,80 @@ TEST(ProcessorStandard, CalculateExtremeFormula){
     processor->update();
 
     EXPECT_FLOAT_EQ(processor->getOutput(processor->getOutputIDs()[1])->getValue()["value"].get<double>(), 0.0);
+}
+
+TEST(ProcessorStandard, CalculateAdvancedFormulaWithSTATIC) {
+    //f4:(f3:(f1:(5*3)-f2:(4+5))/2)==(15-9)/2==6/2==3
+    std::vector<std::string> inputs;
+    std::shared_ptr<ModuleMath> f1 = std::make_shared<ModuleMath>(MathOperation::MULTIPLY);
+    inputs = f1->getInputIDs();
+    f1->getInput(inputs[0])->setDefaultValue()["value"] = 5;
+    f1->getInput(inputs[1])->setDefaultValue()["value"] = 3;
+
+    std::shared_ptr<ModuleMath> f2 = std::make_shared<ModuleMath>(MathOperation::ADD);
+    inputs = f2->getInputIDs();
+    f2->getInput(inputs[0])->setDefaultValue()["value"] = 4;
+    f2->getInput(inputs[1])->setDefaultValue()["value"] = 5;
+
+    std::shared_ptr<ModuleMath> f3 = std::make_shared<ModuleMath>(MathOperation::SUBTRACT);
+    inputs = f3->getInputIDs();
+    f3->getInput(inputs[0])->connect(f1->getOutput(f1->getOutputIDs()[0]));
+    f3->getInput(inputs[1])->connect(f2->getOutput(f2->getOutputIDs()[0]));
+
+    std::shared_ptr<ModuleMath> f4 = std::make_shared<ModuleMath>(MathOperation::DIVIDE);
+    inputs = f4->getInputIDs();
+    f4->getInput(inputs[0])->connect(f3->getOutput(f3->getOutputIDs()[0]));
+    f4->getInput(inputs[1])->setDefaultValue()["value"] = 2;
+
+    std::shared_ptr<ProcessorStandard> process_static = std::make_shared<ProcessorStandard>(STATIC);
+    process_static->addModule(f4);
+    process_static->addModule(f3);
+    process_static->addModule(f2);
+    process_static->addModule(f1);
+    process_static->addModuleOutput(f4, f4->getOutput(f4->getOutputIDs()[0]));
+    process_static->update();
+    //std::cout << test->getOutput(test->getOutputIDs()[1])->getValue()["value"].dump() << std::endl;
+    EXPECT_EQ(process_static->getOutput(process_static->getOutputIDs()[1])->getValue()["value"].get<int>(), 3);
+}
+
+TEST(ProcessorStandard, PrioritySTATIC) {
+    //f4:(f3:(f1:(5*3)-f2:(4+5))/2)==(15-9)/2==6/2==3
+    std::vector<std::string> inputs;
+    std::shared_ptr<ModuleMath> f1 = std::make_shared<ModuleMath>(MathOperation::MULTIPLY);
+    inputs = f1->getInputIDs();
+    f1->getInput(inputs[0])->setDefaultValue()["value"] = 5;
+    f1->getInput(inputs[1])->setDefaultValue()["value"] = 3;
+
+    std::shared_ptr<ModuleMath> f2 = std::make_shared<ModuleMath>(MathOperation::ADD);
+    inputs = f2->getInputIDs();
+    f2->getInput(inputs[0])->setDefaultValue()["value"] = 4;
+    f2->getInput(inputs[1])->setDefaultValue()["value"] = 5;
+
+    std::shared_ptr<ModuleMath> f3 = std::make_shared<ModuleMath>(MathOperation::SUBTRACT);
+    inputs = f3->getInputIDs();
+    f3->getInput(inputs[0])->connect(f1->getOutput(f1->getOutputIDs()[0]));
+    f3->getInput(inputs[1])->connect(f2->getOutput(f2->getOutputIDs()[0]));
+
+    std::shared_ptr<ModuleMath> f4 = std::make_shared<ModuleMath>(MathOperation::DIVIDE);
+    inputs = f4->getInputIDs();
+    f4->getInput(inputs[0])->connect(f3->getOutput(f3->getOutputIDs()[0]));
+    f4->getInput(inputs[1])->setDefaultValue()["value"] = 2;
+
+    std::shared_ptr<ProcessorStandard> process_manual = std::make_shared<ProcessorStandard>();
+    process_manual->addModule(f1);
+    process_manual->addModule(f2);
+    process_manual->addModule(f3);
+    process_manual->addModule(f4);
+    process_manual->addModuleOutput(f4, f4->getOutput(f4->getOutputIDs()[0]));
+    process_manual->update();
+
+    std::shared_ptr<ProcessorStandard> process_static = std::make_shared<ProcessorStandard>(STATIC);
+    process_static->addModule(f4);
+    process_static->addModule(f3);
+    process_static->addModule(f2);
+    process_static->addModule(f1);
+    process_static->addModuleOutput(f4, f4->getOutput(f4->getOutputIDs()[0]));
+    process_static->update();
+    //std::cout << process_static->getOutput(process_static->getOutputIDs()[1])->getValue()["value"].dump() << std::endl;
+    EXPECT_TRUE(process_static->getIteration()->getValue()["value"].get<int>() <= process_manual->getIteration()->getValue()["value"].get<int>());
 }