From 2bf3502654aa45abc57ef1ff5e0b82a2b1b71f01 Mon Sep 17 00:00:00 2001
From: imcovangent <I.vanGent@tudelft.nl>
Date: Fri, 23 Nov 2018 16:33:35 +0100
Subject: [PATCH] Small bug fix in BLISS-2000 and included sleep_time for
 mathematical functions.

Former-commit-id: 0200ad6b308e15a7b0001dc9bfe1f1b3155a54c4
---
 examples/scripts/sellar_problem.py | 12 ++++----
 kadmos/graph/graph_data.py         | 45 +++++++++++++++---------------
 kadmos/graph/graph_kadmos.py       |  6 +++-
 kadmos/graph/mixin_equation.py     |  4 ++-
 kadmos/utilities/xmls.py           |  5 ++--
 setup.py                           |  2 +-
 6 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/examples/scripts/sellar_problem.py b/examples/scripts/sellar_problem.py
index 1718e8cf0..ab50a3069 100644
--- a/examples/scripts/sellar_problem.py
+++ b/examples/scripts/sellar_problem.py
@@ -43,14 +43,14 @@ rcg = RepositoryConnectivityGraph(name='Sellar problem graph')
 # A description is added to the graph
 rcg.graph['description'] = 'Repository graph of tools where a subset can be used to solve the Sellar problem'
 # All function nodes are defined
-rcg.add_node('A', category='function', function_type='regular')
-rcg.add_node('D1', category='function', function_type='regular')
-rcg.add_node('D2', category='function', function_type='regular')
+rcg.add_node('A', category='function', function_type='regular', sleep_time=1.)
+rcg.add_node('D1', category='function', function_type='regular', sleep_time=0.)
+rcg.add_node('D2', category='function', function_type='regular', sleep_time=0.)
 rcg.add_node('D3', category='function')
-rcg.add_node('F1', category='function', function_type='regular')
+rcg.add_node('F1', category='function', function_type='regular', sleep_time=0.)
 rcg.add_node('F2', category='function')
-rcg.add_node('G1', category='function', function_type='regular')
-rcg.add_node('G2', category='function', function_type='regular')
+rcg.add_node('G1', category='function', function_type='regular', sleep_time=0.)
+rcg.add_node('G2', category='function', function_type='regular', sleep_time=0.)
 # All variable nodes are defined
 rcg.add_node('/dataSchema/settings/a', category='variable', label='a')
 rcg.add_node('/dataSchema/settings/c', category='variable', label='c')
diff --git a/kadmos/graph/graph_data.py b/kadmos/graph/graph_data.py
index c72a4ffca..6673b178f 100644
--- a/kadmos/graph/graph_data.py
+++ b/kadmos/graph/graph_data.py
@@ -4910,7 +4910,8 @@ class FundamentalProblemGraph(DataGraph, KeChainMixin):
                 external_group_couplings_copies_group, local_group_couplings_copies_group, \
                 mapping_locals = mdg.localize_group_couplings(subsys_functions, external_group_couplings_group +
                                                               prev_local_group_couplings_copies,
-                                                              local_group_couplings_group, instances_for_externals=True)
+                                                              local_group_couplings_group, instances_for_externals=True,
+                                                              make_copies_des_vars=True)
 
                 # Check for the uncoupled-DVD functions if they depend on the local design variables, if not, make them
                 # uncoupled-DVI
@@ -4979,8 +4980,6 @@ class FundamentalProblemGraph(DataGraph, KeChainMixin):
                 for weight_node in weight_nodes:
                     weight_node2 = mdg.add_instance(weight_node)
                     sm_inps.append(weight_node2)
-                    mdg.mark_as_design_variable(weight_node2, lower_bound=-2.0, nominal_value=0.0, upper_bound=2.0,
-                                                ignore_outdegree=True)
                     weight_nodes2.append(weight_node2)
                 for node in external_group_couplings_copies_group:
                     # Check for hole node for instance = 1, otherwise add instance
@@ -5025,8 +5024,8 @@ class FundamentalProblemGraph(DataGraph, KeChainMixin):
                         if rel_node in sms_outs_related:
                             sm_node = sms_outs[sms_outs_related.index(rel_node)]
                             # Reconnect the source to the SM node
+                            mdg.copy_edge((source, func), (sm_node, func))
                             mdg.remove_edge(source, func)
-                            mdg.add_edge(sm_node, func)
 
             # Create and connect the consistency constraint function
             sms_outs_couplings = [node for node in sms_outs if mdg.nodes[node]['related_to_schema_node'] in
@@ -5569,7 +5568,8 @@ class MdaoDataGraph(DataGraph, MdaoMixin):
                                                                   architecture_role
         xpath_nodes = node.split('/')
         root = xpath_nodes[1]
-        additional_attributes = dict()
+        node_data_dict = copy.deepcopy(dict(self.nodes[node]))
+
         if architecture_role == self.ARCHITECTURE_ROLES_VARS[6]:  # consistency constraint variable
             new_node = '/' + root + '/architectureNodes/' + make_camel_case(architecture_role) + 's' + \
                        '/' + root + 'Copy/' + '/'.join(xpath_nodes[2:-1]) + '/gc_' + xpath_nodes[-1]
@@ -5609,37 +5609,35 @@ class MdaoDataGraph(DataGraph, MdaoMixin):
         else:
             raise IOError('Label extension could not be found.')
 
-        node_data_dict = dict(self.nodes[node])
-
         # Determine the related schema node
-        if 'related_to_schema_node' in node_data_dict:
-            related_schema_node = node_data_dict['related_to_schema_node']
-        else:
-            related_schema_node = node
+        if 'related_to_schema_node' not in node_data_dict:
+            node_data_dict['related_to_schema_node'] = node
 
         if architecture_role == self.ARCHITECTURE_ROLES_VARS[9]:
-            additional_attributes = {'problem_role': self.PROBLEM_ROLES_VARS[0]}
-            if 'valid_ranges' in node_data_dict:
-                additional_attributes['valid_ranges'] = node_data_dict['valid_ranges']
-            if 'nominal_value' in node_data_dict:
-                additional_attributes['nominal_value'] = node_data_dict['nominal_value']
+            node_data_dict.update({'problem_role': self.PROBLEM_ROLES_VARS[0]})
 
         if not self.has_node(new_node):
+            node_data_dict['label'] = label_prefix + get_correctly_extended_latex_label(node_data_dict['label'], label_suffix)
+            node_data_dict['architecture_role'] = architecture_role
+            node_data_dict['instance'] = 1
             self.add_node(new_node,
-                          category=node_data_dict['category'],
-                          related_to_schema_node=related_schema_node,
-                          architecture_role=architecture_role,
-                          label=label_prefix+get_correctly_extended_latex_label(node_data_dict['label'], label_suffix),
-                          instance=1, attr_dict=additional_attributes)
+                          #category=node_data_dict['category'],
+                          #related_to_schema_node=related_schema_node,
+                          #architecture_role=architecture_role,
+                          #label=,
+                          #instance=1,
+                          attr_dict=node_data_dict)
         elif self.has_node(new_node):
             if not ignore_duplicates:
                 raise AssertionError('Node {} that is created as copy already exists in the graph.'.format(new_node))
             elif add_instance_if_exists:
                 highest_instance = self.get_highest_instance(new_node)
+                node_data_dict['instance'] = highest_instance+1
                 self.copy_node_with_suffix(new_node, self.INSTANCE_SUFFIX + str(highest_instance+1),
                                            '^{i' + str(highest_instance+1) + '}',
-                                           instance=highest_instance+1, related_to_schema_node=node,
-                                           attr_dict=additional_attributes)
+                                           #instance=highest_instance+1,
+                                           #related_to_schema_node=node,
+                                           attr_dict=node_data_dict)
                 new_node = new_node + self.INSTANCE_SUFFIX + str(highest_instance+1)
         return new_node
 
@@ -5768,6 +5766,7 @@ class MdaoDataGraph(DataGraph, MdaoMixin):
             eq_lab2 = 'w{}'.format(idx)
             self.add_edge(var1, new_function_node, equation_label=eq_lab1)
             self.add_edge(var2, new_function_node, equation_label=eq_lab2)
+            self.mark_as_design_variable(var2, lower_bound=-2., upper_bound=2., nominal_value=1.)
             if idx == 0:
                 math_expression = '{}*{}'.format(eq_lab2, eq_lab1)
             else:
diff --git a/kadmos/graph/graph_kadmos.py b/kadmos/graph/graph_kadmos.py
index 5a4b5b042..c27e15489 100644
--- a/kadmos/graph/graph_kadmos.py
+++ b/kadmos/graph/graph_kadmos.py
@@ -3632,16 +3632,20 @@ class KadmosGraph(nx.DiGraph, EquationMixin, VistomsMixin):
             original_node = node
 
         node_data_dict = dict(self.nodes[node])
+        cleaned_data_dict = copy.deepcopy(node_data_dict)
+        del cleaned_data_dict['instance']
 
         # Determine the related schema node
         if 'related_to_schema_node' in node_data_dict:
             related_schema_node = node_data_dict['related_to_schema_node']
+            del cleaned_data_dict['related_to_schema_node']
         else:
             related_schema_node = node
 
         self.copy_node_with_suffix(original_node, self.INSTANCE_SUFFIX + str(new_instance),
                                    '^{i' + str(new_instance) + '}',
-                                   instance=new_instance, related_to_schema_node=related_schema_node)
+                                   instance=new_instance, related_to_schema_node=related_schema_node,
+                                   attr_dict=cleaned_data_dict)
         return '{}{}{}'.format(original_node, self.INSTANCE_SUFFIX, new_instance)
 
     def add_function_instance(self, node, serves, instance=None):
diff --git a/kadmos/graph/mixin_equation.py b/kadmos/graph/mixin_equation.py
index a731a7475..59119fdf3 100644
--- a/kadmos/graph/mixin_equation.py
+++ b/kadmos/graph/mixin_equation.py
@@ -232,6 +232,7 @@ class EquationMixin(object):
             cmdows_math_func = cmdows_math_funcs.add('mathematicalFunction', uID=graph_math_func)
             cmdows_math_func.add('label', self.node[graph_math_func].get('label', graph_math_func))
             cmdows_math_func.add('functionType', self.node[graph_math_func].get('function_type', graph_math_func))
+            cmdows_math_func.add('sleepTime', self.node[graph_math_func].get('sleep_time', graph_math_func))
 
             # Create mathematicalFunctions/mathematicalFunction/inputs with children
             cmdows_inputs = cmdows_math_func.add('inputs')
@@ -277,7 +278,8 @@ class EquationMixin(object):
                           category='function',
                           shape='s',
                           label=function.findtext('label'),
-                          function_type=function.findtext('functionType'))
+                          function_type=function.findtext('functionType'),
+                          sleep_time=float(function.findtext('sleepTime')))
             for inp in function.findall('inputs/input'):
                 self.add_edge(inp.findtext('parameterUID').replace("'", '"'), function.get('uID'),
                               equation_label=inp.findtext('equationLabel'),
diff --git a/kadmos/utilities/xmls.py b/kadmos/utilities/xmls.py
index 58bd37056..442b58dee 100644
--- a/kadmos/utilities/xmls.py
+++ b/kadmos/utilities/xmls.py
@@ -7,8 +7,7 @@ from collections import OrderedDict
 from lxml import etree
 from lxml.etree import SubElement
 
-from general import make_camel_case, unmake_camel_case, make_singular
-
+from general import make_camel_case, unmake_camel_case, make_singular, get_list_entries
 
 # Settings for the logger
 logger = logging.getLogger(__name__)
@@ -185,7 +184,7 @@ class ExtendedElement(etree.ElementBase):
         # Add loopElements and functionElements for getting the right order
         for idx, element in enumerate(process_hierarchy):
             if isinstance(element, basestring):
-                if mpg.nodes[element]['architecture_role'] in mpg.ARCHITECTURE_ROLES_FUNS[0:4]:
+                if mpg.nodes[element]['architecture_role'] in get_list_entries(mpg.ARCHITECTURE_ROLES_FUNS, 0, 1, 2, 3, 10):
                     if self.find('loopElements') is None:
                         self.add('loopElements')
                     loop_elements = self.find('loopElements')
diff --git a/setup.py b/setup.py
index 912de6db2..e9745fc3f 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ version = '0.8.2'
 
 
 def readme():
-    with open('readme.md') as f:
+    with open('README.md') as f:
         return f.read()
 
 
-- 
GitLab