Adding optimisation on LD expression generated
authorlbessard
Wed, 27 Aug 2008 16:55:16 +0200
changeset 242 5b3e1c4569e6
parent 241 64e584348a5b
child 243 c5da8b706cde
Adding optimisation on LD expression generated
PLCGenerator.py
plcopen/structures.py
--- a/PLCGenerator.py	Wed Aug 27 13:33:08 2008 +0200
+++ b/PLCGenerator.py	Wed Aug 27 16:55:16 2008 +0200
@@ -714,14 +714,9 @@
         elif body_type == "LD":
             for instance in body.getcontentInstances():
                 if isinstance(instance, plcopen.ldObjects_coil):
-                    paths = self.GenerateLDPaths(instance.connectionPointIn.getconnections(), body)
-                    if len(paths) > 0:
-                        paths = tuple(paths)
-                    else:
-                        paths = paths[0]
+                    expression = self.ComputeLDExpression(body, instance.connectionPointIn.getconnections())
                     coil_info = (self.TagName, "coil", instance.getlocalId())
                     variable = self.ExtractModifier(instance, [(instance.getvariable(), coil_info + ("reference",))], coil_info)
-                    expression = self.ComputeLDExpression(paths, True)
                     self.Program += [(self.CurrentIndent, ())] + variable
                     self.Program += [(" := ", ())] + expression + [(";\n", ())]
         elif body_type == "SFC":
@@ -770,6 +765,28 @@
                             return expression
             raise PLCGenException, "No connector found corresponding to \"%s\" continuation in \"%s\" POU"%(name, self.Name)
 
+    def FactorizeLDPaths(self, paths):
+        same_paths = {}
+        uncomputed_index = range(len(paths))
+        factorized_paths = []
+        for num, path in enumerate(paths):
+            if type(path) == ListType:
+                for i in xrange(1, len(path)):
+                    str_path = str(path[i:])
+                    same_paths.setdefault(str_path, [])
+                    same_paths[str_path].append((path[:i], num))
+            else:
+                factorized_paths.append(path)
+                uncomputed_index.remove(num)
+        for same_path, elements in same_paths.items():
+            if len(elements) > 1:
+                factorized_paths.append([tuple([path for path, num in elements])] + eval(same_path))        
+                for path, num in elements:
+                    uncomputed_index.remove(num)
+        for num in uncomputed_index:
+            factorized_paths.append(paths[num])
+        return factorized_paths
+
     def GenerateLDPaths(self, connections, body):
         paths = []
         for connection in connections:
@@ -787,31 +804,47 @@
                 variable = str(self.ExtractModifier(next, [(next.getvariable(), contact_info + ("reference",))], contact_info))
                 result = self.GenerateLDPaths(next.connectionPointIn.getconnections(), body)
                 if len(result) > 1:
-                    paths.append([variable, tuple(result)])
+                    factorized_paths = self.FactorizeLDPaths(result)
+                    if len(factorized_paths) > 1:
+                        paths.append([variable, tuple(factorized_paths)])
+                    else:
+                        paths.append([variable] + factorized_paths)
                 elif type(result[0]) == ListType:
                     paths.append([variable] + result[0])
-                elif result[0]:
+                elif result[0] is not None:
                     paths.append([variable, result[0]])
                 else:
                     paths.append(variable)
         return paths
 
-    def ComputeLDExpression(self, paths, first = False):
+    def ComputeLDPaths(self, paths, first = False):
         if type(paths) == TupleType:
             if None in paths:
                 return [("TRUE", ())]
             else:
-                vars = [self.ComputeLDExpression(path) for path in paths]
+                vars = [self.ComputeLDPaths(path) for path in paths]
                 if first:
                     return JoinList([(" OR ", ())], vars)
                 else:
                     return [("(", ())] + JoinList([(" OR ", ())], vars) + [(")", ())]
         elif type(paths) == ListType:
-            vars = [self.ComputeLDExpression(path) for path in paths]
+            vars = [self.ComputeLDPaths(path) for path in paths]
             return JoinList([(" AND ", ())], vars)
         else:
             return eval(paths)
 
+    def ComputeLDExpression(self, body, connections):
+        paths = self.GenerateLDPaths(connections, body)
+        if len(paths) > 1:
+            factorized_paths = self.FactorizeLDPaths(paths)
+            if len(factorized_paths) > 1:
+                paths = tuple(factorized_paths)
+            else:
+                paths = factorized_paths[0]
+        else:
+            paths = paths[0]
+        return self.ComputeLDPaths(paths, True)
+
     def ExtractModifier(self, variable, expression, var_info):
         if variable.getnegated():
             return [("NOT(", var_info + ("negated",))] + expression + [(")", ())]
@@ -1003,8 +1036,7 @@
                 elif transitionType == "LD":
                     for instance in transitionBody.getcontentInstances():
                         if isinstance(instance, plcopen.ldObjects_coil):
-                            paths = self.GenerateLDPaths(instance.connectionPointIn.getconnections(), transitionBody)
-                            expression = self.ComputeLDExpression(paths, True)
+                            expression = self.ComputeLDExpression(transitionBody, instance.connectionPointIn.getconnections())
                             transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ())] + expression + [(";\n", ())]
                             self.SFCComputedBlocks += self.Program
                             self.Program = []
@@ -1016,8 +1048,7 @@
                 if network_type == None:
                     raise PLCGenException, "Type of network connected to transition impossible to define in \"%s\" POU"%self.Name
                 if len(connections) > 1 or network_type == "LD":
-                    paths = self.GenerateLDPaths(connections, body)
-                    expression = self.ComputeLDExpression(paths, True)
+                    expression = self.ComputeLDExpression(body, connections)
                 else:
                     expression = self.ComputeFBDExpression(body, connections[0])
                 transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ())] + expression + [(";\n", ())]
--- a/plcopen/structures.py	Wed Aug 27 13:33:08 2008 +0200
+++ b/plcopen/structures.py	Wed Aug 27 16:55:16 2008 +0200
@@ -63,12 +63,7 @@
                     if body_type == "FBD" or body_type == "SFC":
                         value = generator.ComputeFBDExpression(body, connections[0], executionOrderId > 0)
                     elif body_type == "LD":
-                        paths = generator.GenerateLDPaths(variable.connectionPointIn.getConnections(), body)
-                        if len(paths) > 0:
-                            paths = tuple(paths)
-                        else:
-                            paths = paths[0] 
-                        value = generator.ComputeLDExpression(paths, True)
+                        value = generator.ComputeLDExpression(body, variable.connectionPointIn.getConnections())
                     vars.append(generator.ExtractModifier(variable, value, input_info))
             generator.Program += [(generator.CurrentIndent, ()),
                                   (output_name, output_info),
@@ -90,12 +85,7 @@
                     if body_type == "FBD" or body_type == "SFC":
                         value = generator.ComputeFBDExpression(body, connections[0], executionOrderId > 0)
                     elif body_type == "LD":
-                        paths = generator.GenerateLDPaths(variable.connectionPointIn.getconnections(), body)
-                        if len(paths) > 0:
-                            paths = tuple(paths)
-                        else:
-                            paths = paths[0] 
-                        value = generator.ComputeLDExpression(paths, True)
+                        value = generator.ComputeLDExpression(body, variable.connectionPointIn.getconnections())
                     vars.append([(parameter, input_info),
                                  (" := ", ())] + generator.ExtractModifier(variable, value, input_info))
             generator.Program += [(generator.CurrentIndent, ()),