|
|
@@ -63,7 +63,10 @@ class LinearSolver(Solver):
|
|
|
self._logger.fatal("Cannot solve non-linear algebraic loop.\nSelf: {}\nComponents: {}".format(path, component))
|
|
|
|
|
|
def __isLinear(self, strongComponent):
|
|
|
- """Determines if an algebraic loop describes a linear equation or not
|
|
|
+ """Determines if an algebraic loop describes a linear equation or not.
|
|
|
+
|
|
|
+ For a block to comprise the strong component, at least one of its dependencies must be in the strong
|
|
|
+ component as well.
|
|
|
|
|
|
Args:
|
|
|
strongComponent (list): The detected loop, in a list (of BaseBlock instances)
|
|
|
@@ -74,10 +77,6 @@ class LinearSolver(Solver):
|
|
|
# TO IMPLEMENT
|
|
|
|
|
|
"""
|
|
|
- The strong component parameter is a list of blocks that comprise the strong component.
|
|
|
- For a block to comprise the strong component, at least one of its dependencies must be in the strong
|
|
|
- component as well.
|
|
|
-
|
|
|
A non-linear equation is generated when the following conditions occur:
|
|
|
(1) there is a multiplication operation being performed between two unknowns.
|
|
|
(2) there is an invertion operation being performed in an unknown.
|
|
|
@@ -91,21 +90,21 @@ class LinearSolver(Solver):
|
|
|
"""
|
|
|
|
|
|
# WON'T APPEAR: Constant, Sequence, Time, Logging
|
|
|
- # LINEAR: Negator, Adder, Delay, Input, Output, Wire, TimedGate
|
|
|
- # NON-LINEAR: Inverter, Modulo, Root, LT, EQ, LTE, Not, Or, And, MUX, Generic, ABS, Int
|
|
|
+ # LINEAR: Negator, Adder, Delay, Input, Output, Wire
|
|
|
+ # NON-LINEAR: Inverter, Modulo, Root, LT, EQ, LTE, Not, Or, And, MUX, Generic, ABS, Int, Power
|
|
|
# SEMI-LINEAR: Product
|
|
|
|
|
|
for block in strongComponent:
|
|
|
# condition (1)
|
|
|
if block.getBlockType() == "ProductBlock":
|
|
|
dependenciesUnknown = [x for x in block.getDependencies(0) if x in strongComponent]
|
|
|
- if len(dependenciesUnknown) == 2:
|
|
|
+ if len(dependenciesUnknown) >= 2:
|
|
|
return False
|
|
|
|
|
|
# condition (2) and (3)
|
|
|
if block.getBlockType() in ["InverterBlock", "ModuloBlock", "RootBlock", "LessThanBlock", "EqualsBlock",
|
|
|
"LessThanOrEqualsBlock", "NotBlock", "OrBlock", "AndBlock",
|
|
|
- "MultiplexerBlock", "GenericBlock", "AbsBlock", "IntBlock"]:
|
|
|
+ "MultiplexerBlock", "GenericBlock", "AbsBlock", "IntBlock", "PowerBlock"]:
|
|
|
return False
|
|
|
|
|
|
return True
|
|
|
@@ -163,7 +162,11 @@ class LinearSolver(Solver):
|
|
|
elif block.getBlockType() == "OutputPortBlock" or block.getBlockType() == "WireBlock":
|
|
|
# M2 can stay 0
|
|
|
M1[i, i] = 1
|
|
|
- M1[i, indexdict[block.getDependencies(0)[0]]] = - 1
|
|
|
+ dblock = block.getDependencies(0)[0]
|
|
|
+ if isinstance(dblock, CBD):
|
|
|
+ oport = block.getLinksIn()['IN1'].output_port
|
|
|
+ dblock = dblock.getBlockByName(oport).getLinksIn()['IN1'].block
|
|
|
+ M1[i, indexdict[dblock]] = - 1
|
|
|
elif block.getBlockType() == "DelayBlock":
|
|
|
# If a delay is in a strong component, this is the first iteration
|
|
|
assert curIteration == 0
|