Pārlūkot izejas kodu

Added block map

Randy Paredis 4 gadi atpakaļ
vecāks
revīzija
d549159d0a

+ 21 - 21
src/CBD/converters/latexify/CBD2Latex.py

@@ -1,7 +1,4 @@
-from CBD.converters.latexify.functions import Fnc, Eq
-
-# TODO: fill this + move to 'functions.py'?
-_BLOCK_MAP = {}
+from CBD.converters.latexify.functions import Fnc, Eq, _BLOCK_MAP, ConstantFnc
 
 # TODO: test eq generation, printing and simplifications
 class CBD2Latex:
@@ -103,15 +100,12 @@ class CBD2Latex:
 			name = name.replace("_", r"\_")
 		return name
 
-	def construct_func(self, block):
-		inputs = [block.getPath(self.config["path_sep"]) + self.config['path_sep'] + x for x in block.getInputPortNames()]
-		return [Fnc(block.getFunctionName(), *inputs)]
-
 	def get_block_equation(self, block):
-		# TODO: do this for all block types; split into (+, *), (-, /, !), (>, >=, ==, and, or, %, sqrt, ^), (constant),
-		#       (generic), (delay), (der), (integrator)
-		bdata = _BLOCK_MAP.get(block.getBlockType(), self.construct_func)
+		inputs = [block.getPath(self.config["path_sep"]) + self.config['path_sep'] + x for x in block.getInputPortNames()]
+		bdata = _BLOCK_MAP.get(block.getBlockType(), lambda b: [Fnc(b.getFunctionName())])
 		fncs = bdata(block)
+		for f in fncs:
+			f.args = inputs[:]
 		eqs = []
 		outputs = [block.getPath(self.config["path_sep"]) + self.config['path_sep'] + x for x in block.getSignals().keys()]
 		for i, fnc in enumerate(fncs):
@@ -128,20 +122,24 @@ class CBD2Latex:
 		"""
 		# Add all blocks
 		for block in self.model.getBlocks():
-			# if block.getBlockType() not in ["OutputPortBlock", "InputPortBlock", "WireBlock"]:
-			eq = self.get_block_equation(block)
-			for e in eq:
-				self.equations[e.lhs] = e
+			if block.getBlockType() not in ["OutputPortBlock", "InputPortBlock", "WireBlock"]:
+				eq = self.get_block_equation(block)
+				for e in eq:
+					self.equations[e.lhs] = e
 
 		# Add all connections
 		for block in self.model.getBlocks():
-			tp = block.getBlockType()
+			# tp = block.getBlockType()
 			path = block.getPath(self.config['path_sep'])
 			for k, v in block.getLinksIn().items():
-				if tp == "OutputPortBlock":
-					self.equations[self._rename(path)] = [self._rename(v.block.getPath(self.config['path_sep']) + self.config['path_sep'] + v.output_port)]
-				else:
-					self.equations[self._rename(path + self.config['path_sep'] + k)] = self._rename(v.block.getPath(self.config['path_sep']) + self.config['path_sep'] + v.output_port)
+				# if tp == "OutputPortBlock":
+				# 	lhs = self._rename(path)
+				# 	rhs = ConstantFnc("C", self._rename(v.block.getPath(self.config['path_sep']) + self.config['path_sep'] + v.output_port))
+				# 	self.equations[lhs] = Eq(lhs, rhs)
+				# else:
+				lhs = self._rename(path + self.config['path_sep'] + k)
+				rhs = ConstantFnc("C", self._rename(v.block.getPath(self.config['path_sep']) + self.config['path_sep'] + v.output_port))
+				self.equations[lhs] = Eq(lhs, rhs)
 
 	def render(self, rl=True):
 		"""
@@ -209,7 +207,7 @@ class CBD2Latex:
 		"""
 		res = ""
 		for k, v in self.equations.items():
-			res += "{} = {}\n".format(k, str(v))
+			res += "{}\n".format(repr(v))
 		return res
 
 	def create_ic(self):
@@ -387,3 +385,5 @@ if __name__ == '__main__':
 	model.addConnection("C1", "test")
 	model.addConnection("test", "OUT1")
 	c2l = CBD2Latex(model, ignore_path=False)
+
+	print(c2l.eq())

+ 85 - 3
src/CBD/converters/latexify/functions.py

@@ -96,15 +96,14 @@ class Fnc:
 
 	Args:
 		name (str):     The name for the function.
-		*args (Fnc):    A list of arguments for the function.
 
 	Keyword Args:
 		time (Time):    The current time for this function.
 		eq_time (Time): The current equation time for this function.
 	"""
-	def __init__(self, name, *args, time=Time.now(), eq_time=Time.now()):
+	def __init__(self, name, time=Time.now(), eq_time=Time.now()):
 		self.name = name
-		self.args = args
+		self.args = []
 
 		# Time properties
 		self.time = time
@@ -189,6 +188,89 @@ class Fnc:
 		return res
 
 
+class MultiFnc(Fnc):
+	"""
+	Collection function for both the adder and the product blocks
+	"""
+	def __init__(self, name, symbol, time=Time.now(), eq_time=Time.now()):
+		Fnc.__init__(self, name, time=time, eq_time=eq_time)
+		self.symbol = symbol
+
+	def eq(self):
+		return "(" + (" " + self.name + " ").join([a.eq() for a in self.args]) + ")"
+
+	def latex(self):
+		return "(" + (" " + self.name + " ").join([a.latex() for a in self.args]) + ")"
+
+
+class UnaryFnc(Fnc):
+	"""
+	Collection function for unary input functions
+	"""
+	def __init__(self, name, symbol, time=Time.now(), eq_time=Time.now()):
+		Fnc.__init__(self, name, time=time, eq_time=eq_time)
+		self.symbol = symbol
+
+	def eq(self):
+		return "(" + self.name + self.args[0].eq() + ")"
+
+	def latex(self):
+		return "(" + self.symbol + self.args[0].latex() + ")"
+
+
+class BinaryFnc(Fnc):
+	"""
+	Collection function for binary input functions
+	"""
+	def __init__(self, name, symbol, time=Time.now(), eq_time=Time.now()):
+		Fnc.__init__(self, name, time=time, eq_time=eq_time)
+		self.symbol = symbol
+
+	def eq(self):
+		return "(" + self.args[0].eq() + self.name + self.args[1].eq() + ")"
+
+	def latex(self):
+		return "(" + self.symbol.format(a=self.args[0].latex(), b=self.args[1].latex()) + ")"
+
+
+class ConstantFnc(Fnc):
+	"""
+	Function that represents a constant value
+	"""
+	def __init__(self, name, val, time=Time.now(), eq_time=Time.now()):
+		Fnc.__init__(self, name, time=time, eq_time=eq_time)
+		self.val = val
+
+	def __str__(self):
+		return str(self.val)
+
+	def eq(self):
+		return str(self.val)
+
+	def latex(self):
+		return str(self.val)
+
+# TODO: der, delay, integrator
+_BLOCK_MAP = {
+	"ConstantBlock": lambda block: [ConstantFnc("C", block.getValue())],
+	"NegatorBlock": lambda block: [UnaryFnc("-", "-")],
+	"InverterBlock": lambda block: [UnaryFnc("~", "1 / ")],
+	"AdderBlock": lambda block: [MultiFnc("+", "+")],
+	"ProductBlock": lambda block: [MultiFnc("*", "\\cdot")],
+	"ModuloBlock": lambda block: [BinaryFnc("mod", "{a} % {b}")],
+	"RootBlock": lambda block: [BinaryFnc("root", "{a}^(1/{b})")],
+	"PowerBlock": lambda block: [BinaryFnc("pow", "{a}^{b}")],
+	"GenericBlock": lambda block: [Fnc(block.getBlockOperator())],
+	"LessThanBlock": lambda block: [BinaryFnc("<", "{a} < {b}")],
+	"LessThanOrEqualsBlock": lambda block: [BinaryFnc("<=", "{a} \\lte {b}")],
+	"EqualsBlock": lambda block: [BinaryFnc("==", "{a} \\leftrightarrow {b}")],
+	"NotBlock": lambda block: [UnaryFnc("!", "\\neg")],
+	"OrBlock": lambda block: [BinaryFnc("or", "{a} \\wedge {b}")],
+	"AndBlock": lambda block: [BinaryFnc("and", "{a} \\vee {b}")],
+	"TimeBlock": lambda block: [ConstantFnc("time", "i")],
+}
+
+
 if __name__ == '__main__':
 	l1 = [Fnc('+', Fnc('h', time=Time(-1, True)), Fnc('time', time=Time(-1, True))), Fnc('IC1', time=Time(0), eq_time=Time(0))]
 	l2 = [Fnc('IC2')]