rparedis 4 лет назад
Родитель
Сommit
e73af19b24

Разница между файлами не показана из-за своего большого размера
+ 46 - 36
examples/notebook/.ipynb_checkpoints/HybridTrain-checkpoint.ipynb


Разница между файлами не показана из-за своего большого размера
+ 1121 - 0
examples/notebook/.ipynb_checkpoints/Linear-checkpoint.ipynb


Разница между файлами не показана из-за своего большого размера
+ 46 - 36
examples/notebook/HybridTrain.ipynb


Разница между файлами не показана из-за своего большого размера
+ 1119 - 0
examples/notebook/Linear.ipynb


+ 49 - 57
src/CBD/converters/hybrid.py

@@ -28,22 +28,23 @@ class CBDRunner(AtomicDEVS):
 							progress. Useful when in combination with
 							multiple ODEs. Defaults to :code:`False`.
 	"""
-	def __init__(self, name, cbd, initials, stopped=False, crossings=None):
+	def __init__(self, name, cbd, initials=None, stopped=False, crossings=None):
 		AtomicDEVS.__init__(self, name)
-		self.initials = initials
+		self.initials = {} if initials is None else initials
 		self.original_model, self.Hname = prepare_cbd(cbd.clone(), initials)
 		self.crossings = {} if crossings is None else crossings
 
 		self.state = {
 			"CBD": None,
+			"curIt": 0,
 			"delta_t": 0.0,
-			"initials": initials,
+			"initials": self.initials,
 			"request_output": False,
 			"request_compute": True,
 			"zero_crossing": None,
 			"time": 0.0,
 			"stopped": stopped,
-			"zcd": { k: None for k in self.crossings }
+			# "zcd": { k: None for k in self.crossings }
 		}
 
 		self.simulator = None
@@ -63,7 +64,7 @@ class CBDRunner(AtomicDEVS):
 	def timeAdvance(self):
 		if self.state["stopped"]:
 			return INFINITY
-		if self.state["request_output"] or self.state["request_compute"]:
+		if self.state["request_compute"]:
 			return 0.0
 		return max(0.0, self.state["delta_t"])
 
@@ -82,55 +83,60 @@ class CBDRunner(AtomicDEVS):
 		return res
 
 	def intTransition(self):
+		ta = self.timeAdvance()
+		self.state["time"] += ta
 		if self.state["request_output"]:
 			self.state["request_output"] = False
+			self.state["request_compute"] = True
 			return self.state
 
-		ta = self.timeAdvance()
-
-		self.state["time"] += ta
+		self.state["request_output"] = True
 		self.state["request_compute"] = False
 		self.state["zero_crossing"] = None
 
+		self.state["curIt"] += 1
+		if self.state["curIt"] == 1:
+			self.simulator._do_single_step()
+			self.state["request_output"] = True
+			return self.state
+
+		old = {}
+		for c in self.crossings:
+			# print("PRE", c, self.state["CBD"].getBlockByName(c).getSignal("OUT1")[-1])
+			old[c] = self.get_signal(c)
+
+		self.state["delta_t"] = self.get_delta()
 		self.simulator._do_single_step()
 
-		crsc = {}
+		cds = {}
 		for z, y in self.crossings.items():
 			value = self.get_signal(z)
-			if self.state["zcd"][z] is None:
-				self.state["zcd"][z] = value
-			else:
-				old = self.state["zcd"][z]
-				if (old - y) * (value - y) < 0:
-					cd = self.crossing_detection(z, y, ta)
-					if cd in crsc:
-						crsc[cd].append(z)
-					else:
-						crsc[cd] = [z]
-
-		if len(tzc) > 0:
+			# print("POST", z, self.state["CBD"].getBlockByName(z).getSignal("OUT1")[-1])
+			if (old[z] - y) * (value - y) < 0:
+				# A crossing will happen!
+				# print("CROSSING:", old[z], value, y)
+				cds.setdefault(self.crossing_detection(z, y, old[z]), []).append(z)
+		if len(cds) > 0:
+			oh = self.get_delta()
+			self.simulator._rewind()
 			self.simulator._rewind()
-			self.state["time"] -= ta
-			mtzc = min(crsc)
-			h = mtzc[1] - self.state["time"]
+			fzc = min(cds)
+			self.state["zero_crossing"] = cds[fzc]
+			h = fzc - self.state["time"]
+			self.state["delta_t"] = h
 			self.set_delta(h)
+			p = self.simulator.getClock().getBlockByName("Past")
+			p.setValue(p.getValue() + oh)
 			self.simulator._do_single_step()
-			self.state["time"] += h
+			p.setValue(p.getValue() + oh)
+			self.simulator._do_single_step()
+			# print("CROSSING:", self.state["CBD"].getBlockByName("v").getSignal("OUT1")[-1])
+		else:
 			self.set_delta(float('inf'))
-			self.state["request_output"] = True
-			self.state["request_compute"] = True
-			self.state["zero_crossing"] = crsc[mtzc]
-			# self.simulator._do_single_step()
-
-		self.state["delta_t"] = self.get_delta()
-		self.set_delta(self.state["delta_t"])
-
-		self.state["request_output"] = True
 		return self.state
 
 	def extTransition(self, inputs):
 		self.state["time"] += self.elapsed
-		self.state["delta_t"] -= self.elapsed
 
 		if not self.state["stopped"]:
 			self.state["delta_t"] -= self.elapsed
@@ -143,31 +149,16 @@ class CBDRunner(AtomicDEVS):
 			self.state["stopped"] = True
 			return self.state
 
-		# if self.rewind in inputs:
-		# 	H = self.state["delta_t"]
-		# 	h = inputs[self.rewind]
-		# 	self.simulator._rewind()
-		# 	# TODO: set delay to h
-		# 	self.simulator._do_single_step()
-		# 	# TODO: set delay to H - h
-		# 	self.simulator._do_single_step()
-		# 	# TODO: set delay to H
-		# else:
 		for inport, value in inputs.items():
 			if inport.name in self.initials:
 				self.state["initials"][inport.name] = value
 
 		self.reinit()
-		self.set_delta(self.state["delta_t"])
 
-		self.simulator._do_single_step()
-
-		self.set_delta(float('inf'))
-
-		###
-		self.state["request_compute"] = False
-		self.state["request_output"] = True
+		self.state["request_compute"] = True
+		self.state["request_output"] = False
 		self.state["stopped"] = False
+		self.state["curIt"] = 0
 		return self.state
 
 	def __del__(self):
@@ -177,6 +168,8 @@ class CBDRunner(AtomicDEVS):
 		self.state["CBD"] = self.original_model.clone()
 		self.apply_initials()
 		self.simulator = Simulator(self.state["CBD"])
+		self.simulator.getClock().setStartTime(self.state["time"])
+		self.set_delta(float('inf'))
 
 	def apply_initials(self):
 		for k, v in self.state["initials"].items():
@@ -185,10 +178,9 @@ class CBDRunner(AtomicDEVS):
 	def get_signal(self, pname):
 		return self.state["CBD"].getBlockByName(pname).getSignal("OUT1")[-1].value
 
-	def crossing_detection(self, signal, y, ta):
-		t2 = self.state["time"]
-		t1 = t2 - ta
-		y1 = self.state["zcd"][signal]
+	def crossing_detection(self, signal, y, y1):
+		t1 = self.state["time"]
+		t2 = t1 + self.state["delta_t"]
 		y2 = self.get_signal(signal)
 		return (t2 - t1) / (y2 - y1) * (y - y1) + t1
 

+ 8 - 2
src/CBD/lib/std.py

@@ -586,7 +586,7 @@ class Clock(CBD):
 	"""
 	def __init__(self, block_name, start_time=0.0):
 		# TODO: simplify if start_time is 0
-		CBD.__init__(self, block_name, ["h"], ["time", "rel_time"])
+		CBD.__init__(self, block_name, ["h"], ["time", "rel_time", "delta"])
 		self.__start_time = start_time
 
 		self.addBlock(ConstantBlock("IC", start_time))
@@ -611,6 +611,8 @@ class Clock(CBD):
 		self.addConnection("STNeg", "STSum")
 		self.addConnection("STSum", "rel_time")
 
+		self.addConnection("h", "delta")
+
 	def getTime(self, curIt):
 		"""
 		Gets the current time of the clock.
@@ -626,9 +628,13 @@ class Clock(CBD):
 		"""
 		return self.getTime(curIt) - self.__start_time
 
+	def setStartTime(self, start_time=0.0):
+		self.__start_time = start_time
+		self.getBlockByName("IC").setValue(start_time)
+
 	def _rewind(self):
 		CBD._rewind(self)
-		time = self.getInputSignal(-1, "h")
+		time = self.getInputSignal(-1, "h").value
 		c = self.getBlockByName("Past")
 		c.setValue(c.getValue() - time)