model.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. import sys
  2. import time
  3. import uuid
  4. sys.path.append("kernel/")
  5. sys.path.append("state/")
  6. sys.path.append("interface/HUTN")
  7. from modelverse_state.main import ModelverseState as MvS
  8. from modelverse_kernel.main import ModelverseKernel as MvK
  9. from modelverse_kernel.primitives import SleepKernel
  10. from hutn_compiler.compiler import main as do_compile
  11. from pypdevs.minimal import AtomicDEVS, CoupledDEVS, Simulator
  12. PROFILE = False
  13. import json
  14. import random
  15. random.seed(1)
  16. COMPILER_PATH = "interface/HUTN"
  17. sys.path.append(COMPILER_PATH)
  18. from hutn_compiler.compiler import main as do_compile
  19. import os
  20. def clean_code(code):
  21. if code == "":
  22. return code
  23. code_fragments = code.split("\n")
  24. code_fragments = [i.rstrip() for i in code_fragments if i.strip() != ""]
  25. code_fragments = [i.replace(" ", "\t") for i in code_fragments]
  26. initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments])
  27. code_fragments = [i[initial_tabs:] for i in code_fragments]
  28. code_fragments.append("")
  29. code = "\n".join(code_fragments)
  30. return code.encode('ascii', 'replace')
  31. def compile_model(temp_file):
  32. compiled = do_compile(temp_file, COMPILER_PATH + "/grammars/modelling.g", "M")
  33. return ["__LOCAL__"] + compiled
  34. def translate(operation):
  35. return {
  36. "CN": "create_node",
  37. "CE": "create_edge",
  38. "CNV": "create_nodevalue",
  39. "CD": "create_dict",
  40. "RV": "read_value",
  41. "RO": "read_outgoing",
  42. "RI": "read_incoming",
  43. "RE": "read_edge",
  44. "RD": "read_dict",
  45. "RDN": "read_dict_node",
  46. "RDNE": "read_dict_node_edge",
  47. "RDE": "read_dict_edge",
  48. "RRD": "read_reverse_dict",
  49. "RR": "read_root",
  50. "RDK": "read_dict_keys",
  51. "DE": "delete_edge",
  52. "DN": "delete_node",
  53. }[operation]
  54. class MvSState(object):
  55. def __init__(self):
  56. self.queue = []
  57. self.output = None
  58. self.mvs = MvS("bootstrap/bootstrap.m.gz")
  59. self.timer = float("inf")
  60. class ModelverseState(AtomicDEVS):
  61. def __init__(self,
  62. read_root,
  63. create_node,
  64. create_edge,
  65. create_nodevalue,
  66. create_dict,
  67. read_value,
  68. read_outgoing,
  69. read_incoming,
  70. read_edge,
  71. read_dict,
  72. read_dict_keys,
  73. read_dict_edge,
  74. read_dict_node,
  75. read_dict_node_edge,
  76. read_reverse_dict,
  77. delete_node,
  78. delete_edge):
  79. AtomicDEVS.__init__(self, "MvS")
  80. self.timings = {
  81. "read_root": read_root,
  82. "create_node": create_node,
  83. "create_edge": create_edge,
  84. "create_nodevalue": create_nodevalue,
  85. "create_dict": create_dict,
  86. "read_value": read_value,
  87. "read_outgoing": read_outgoing,
  88. "read_incoming": read_incoming,
  89. "read_edge": read_edge,
  90. "read_dict": read_dict,
  91. "read_dict_keys": read_dict_keys,
  92. "read_dict_edge": read_dict_edge,
  93. "read_dict_node": read_dict_node,
  94. "read_dict_node_edge": read_dict_node_edge,
  95. "read_reverse_dict": read_reverse_dict,
  96. "delete_node": delete_node,
  97. "delete_edge": delete_edge,
  98. }
  99. self.state = MvSState()
  100. self.from_mvk = self.addInPort("from_MvK")
  101. self.to_mvk = self.addOutPort("to_MvK")
  102. def extTransition(self, inputs):
  103. self.state.timer -= self.elapsed
  104. empty = len(self.state.queue) == 0
  105. self.state.queue.extend(inputs[self.from_mvk])
  106. if empty:
  107. # First message, so set the timer
  108. # And already compute the result so it is ready to output
  109. self.state.output = []
  110. self.state.timer = 0.0
  111. for v in self.state.queue[0]:
  112. f = getattr(self.state.mvs, translate(v[0]))
  113. start = time.time()
  114. self.state.output.append(f(*v[1]))
  115. if PROFILE:
  116. print("%s: %.17f" % (translate(v[0]), time.time() - start))
  117. self.state.timer += self.timings[translate(v[0])]
  118. else:
  119. # Just append the message to process
  120. pass
  121. return self.state
  122. def outputFnc(self):
  123. return {self.to_mvk: [self.state.output]}
  124. def intTransition(self):
  125. self.state.queue.pop(0)
  126. self.state.output = []
  127. if len(self.state.queue) > 0:
  128. self.state.timer = 0.0
  129. # Value contains a list of operations to do
  130. # So do them and calculate how long it takes
  131. for v in self.state.queue[0]:
  132. f = getattr(self.state.mvs, translate(v[0]))
  133. start = time.time()
  134. self.state.output.append(f(*v[1]))
  135. if PROFILE:
  136. print("%s: %.17f" % (translate(v[0]), time.time() - start))
  137. self.state.timer += self.timings[translate(v[0])]
  138. else:
  139. self.state.timer = float("inf")
  140. return self.state
  141. def timeAdvance(self):
  142. return self.state.timer
  143. class MvKState(object):
  144. def __init__(self, rule_generation):
  145. self.mvk = None
  146. self.waiting = False
  147. self.inputs = {}
  148. self.outputs = {}
  149. self.tasks = []
  150. self.reply = None
  151. self.phase = None
  152. self.commands = None
  153. self.root = None
  154. self.current_task = None
  155. self.loaded_primitives = False
  156. self.execution_counter = 0
  157. self.rule_generation = rule_generation
  158. self.current_time = 0.0
  159. self.start_task_time = 0.0
  160. def __str__(self):
  161. return "\nMvK: %s\n" % self.mvk + \
  162. "waiting: %s\n" % self.waiting + \
  163. "inputs: %s\n" % self.inputs + \
  164. "outputs: %s\n" % self.outputs + \
  165. "tasks: %s\n" % self.tasks + \
  166. "reply: %s\n" % self.reply + \
  167. "phase: %s\n" % self.phase + \
  168. "commands: %s\n" % self.commands + \
  169. "root: %s\n" % self.root + \
  170. "current task: %s\n" % self.current_task + \
  171. "execution counter: %s\n"
  172. class ModelverseKernel(AtomicDEVS):
  173. def __init__(self, time_per_phase, rule_generation):
  174. AtomicDEVS.__init__(self, "MvK")
  175. self.state = MvKState(rule_generation)
  176. self.from_mvi = self.addInPort("from_MvI")
  177. self.from_mvs = self.addInPort("from_MvS")
  178. self.to_mvi = self.addOutPort("to_MvI")
  179. self.to_mvs = self.addOutPort("to_MvS")
  180. self.time_per_phase = time_per_phase
  181. def extTransition(self, inputs):
  182. self.state.current_time += self.elapsed
  183. if self.from_mvi in inputs:
  184. # Got input from MvI, so we queue it
  185. for inp in inputs[self.from_mvi]:
  186. taskname = inp[0]
  187. data = inp[1]
  188. if data is not None:
  189. self.state.inputs.setdefault(taskname, []).extend(data)
  190. else:
  191. self.state.outputs.setdefault(taskname, []).append(None)
  192. if self.from_mvs in inputs:
  193. # Got input from MvS, so we can continue processing
  194. #print(" --> " + str(inputs[self.from_mvs]))
  195. for mvs_input in inputs[self.from_mvs]:
  196. if self.state.mvk is None:
  197. # No MvK, so set it with the root we have just received (or should have received)
  198. self.state.root = mvs_input[0]
  199. self.state.mvk = MvK(self.state.root)
  200. else:
  201. self.state.reply = mvs_input
  202. self.state.waiting = False
  203. return self.state
  204. def intTransition(self):
  205. self.state.current_time += self.timeAdvance()
  206. was_empty = len(self.state.tasks) == 0
  207. if self.state.commands is not None:
  208. self.state.commands = None
  209. return self.state
  210. if self.state.mvk is not None:
  211. self.state.mvk.returnvalue = None
  212. if self.state.mvk is None:
  213. # Initializing
  214. self.state.waiting = True
  215. elif not self.state.loaded_primitives:
  216. commands = self.state.mvk.execute_yields("", "load_primitives", [], self.state.reply)
  217. if commands is None:
  218. self.state.loaded_primitives = True
  219. self.state.reply = None
  220. else:
  221. self.state.waiting = True
  222. self.state.commands = commands
  223. else:
  224. # Are initialized and have work to do
  225. if len(self.state.tasks) == 0:
  226. # Read out new set of tasks first
  227. if self.state.reply is None:
  228. commands = [("RDK", [self.state.root])]
  229. else:
  230. self.state.tasks = self.state.reply[0]
  231. commands = None
  232. elif self.state.phase == "init_task":
  233. if self.state.reply is None:
  234. commands = [("RV", [self.state.tasks[0]])]
  235. else:
  236. self.state.current_task = self.state.reply[0]
  237. #print("Processing task %s at time %s" % (self.state.current_task, self.time_last))
  238. self.state.start_task_time = self.state.current_time
  239. if self.state.current_task.startswith("__"):
  240. # Don't process this task and force termination of task
  241. self.state.phase = "output"
  242. commands = None
  243. elif self.state.phase == "input":
  244. # Process inputs
  245. if self.state.inputs.get(self.state.current_task, None):
  246. value = self.state.inputs[self.state.current_task][0]
  247. start = time.time()
  248. commands = self.state.mvk.execute_yields(self.state.current_task, "set_input", [value], self.state.reply)
  249. if PROFILE:
  250. print("rule_generation: %.17f" % ((time.time() - start)))
  251. #self.state.rule_generation = time.time() - start
  252. self.state.mvk.returnvalue = None
  253. if commands is None:
  254. self.state.inputs[self.state.current_task].pop(0)
  255. else:
  256. commands = None
  257. elif self.state.phase == "computation":
  258. try:
  259. start = time.time()
  260. commands = self.state.mvk.execute_yields(self.state.current_task, "execute_rule", [], self.state.reply)
  261. if PROFILE:
  262. print("rule_generation: %.17f" % ((time.time() - start)))
  263. #self.state.rule_generation = time.time() - start
  264. except SleepKernel:
  265. commands = None
  266. self.state.mvk.success = False
  267. else:
  268. self.state.mvk.success = True
  269. elif self.state.phase == "output":
  270. start = time.time()
  271. commands = self.state.mvk.execute_yields(self.state.current_task, "get_output", [], self.state.reply)
  272. if PROFILE:
  273. print("rule_generation: %.17f" % ((time.time() - start)))
  274. #self.state.rule_generation = time.time() - start
  275. else:
  276. raise Exception("Phase: " + str(self.state.phase))
  277. # Advance phase
  278. if commands is None:
  279. if was_empty:
  280. self.state.phase = "init_task"
  281. elif self.state.phase == "init_task":
  282. self.state.phase = "input"
  283. elif self.state.phase == "input":
  284. self.state.phase = "computation"
  285. elif self.state.phase == "computation":
  286. if not self.state.mvk.success or (self.state.current_time - self.state.start_task_time > self.time_per_phase):
  287. self.state.phase = "output"
  288. elif self.state.phase == "output":
  289. self.state.tasks.pop(0)
  290. self.state.phase = "init_task"
  291. self.state.waiting = False
  292. self.state.reply = None
  293. else:
  294. self.state.waiting = True
  295. # Send the commands to the MvS
  296. self.state.commands = commands
  297. #print(" <-- " + str(commands))
  298. return self.state
  299. def outputFnc(self):
  300. outputs = {}
  301. if self.state.mvk is None:
  302. # Ask the root first
  303. outputs[self.to_mvs] = [[("RR", [])]]
  304. elif self.state.waiting:
  305. outputs[self.to_mvs] = [self.state.commands]
  306. if self.state.mvk and self.state.mvk.returnvalue is not None:
  307. outputs[self.to_mvi] = [(self.state.current_task, self.state.mvk.returnvalue)]
  308. return outputs
  309. def timeAdvance(self):
  310. if self.state.commands is not None:
  311. return self.state.rule_generation
  312. elif self.state.waiting:
  313. return float("inf")
  314. elif self.state.mvk is None:
  315. return 0
  316. else:
  317. return 0
  318. class MvIState():
  319. def __init__(self):
  320. self.operations = []
  321. self.additional_operations = []
  322. self.keyed_operations = {}
  323. self.task_to_spawner = {}
  324. self.task_to_operation = {}
  325. self.output = {}
  326. self.blocked = True
  327. self.finished = False
  328. self.send_operations = {}
  329. class ModelverseInterface(AtomicDEVS):
  330. def __init__(self, taskname, operations, finish_on, additional_operations=[], keyed_operations={}):
  331. AtomicDEVS.__init__(self, "MvI_%s" % taskname)
  332. self.state = MvIState()
  333. if taskname == "task_manager":
  334. self.state.blocked = False
  335. self.state.operations = operations
  336. self.state.additional_operations = additional_operations
  337. self.state.keyed_operations = keyed_operations
  338. self.state.create_additional_task = []
  339. self.taskname = taskname
  340. self.finish_on = finish_on
  341. self.to_mvk = self.addOutPort("to_MvK")
  342. self.from_mvk = self.addInPort("from_MvK")
  343. def intTransition(self):
  344. self.state.create_additional_task = []
  345. if not self.state.send_operations:
  346. self.state.operations.pop(0)
  347. else:
  348. for k in self.state.send_operations.keys():
  349. if self.state.send_operations[k]:
  350. self.state.send_operations[k][0] = None
  351. self.state.blocked = True
  352. return self.state
  353. def extTransition(self, inputs):
  354. for inp in inputs[self.from_mvk]:
  355. print("Got input: " + str(inp))
  356. self.state.blocked = False
  357. self.state.output.setdefault(inp[0], []).append(inp[1])
  358. if inp[0] == self.taskname and inp[1] == self.finish_on:
  359. self.state.finished = True
  360. elif inp[0] == self.taskname and self.state.operations[0] is None:
  361. # We have to block for now, and modify a model first...
  362. print("Blocking for now...")
  363. prev_output = self.state.output[inp[0]][-1]
  364. if prev_output.startswith("Please edit this model before sending next input: "):
  365. _, model_name = prev_output.split("Please edit this model before sending next input: ", 1)
  366. new_taskname = str(uuid.uuid4())
  367. self.state.send_operations[new_taskname] = [[], ["admin"], ["admin"], ["quiet"], ["model_modify", model_name, ""]] + self.state.additional_operations[0] + [["exit"]]
  368. print("Modifying model " + str(model_name))
  369. print("On taskname " + str(new_taskname))
  370. self.state.create_additional_task.append(new_taskname)
  371. self.state.task_to_operation[new_taskname] = None
  372. self.state.task_to_spawner[new_taskname] = None
  373. elif prev_output.startswith("Spawned activity on task: "):
  374. print("Spawned activity")
  375. _, task_name = prev_output.split("Spawned activity on task: ", 1)
  376. self.state.blocked = True
  377. self.state.task_to_spawner[task_name] = None
  378. # NOTE We now know that there is something to do on an other task, so we just wait for that event to come in
  379. print("Adding 3 empty lists")
  380. self.state.operations.insert(0, None)
  381. self.state.operations.insert(0, None)
  382. self.state.operations.insert(0, None)
  383. elif prev_output.startswith("Finished task: "):
  384. self.state.blocked = True
  385. elif " : " in prev_output:
  386. task_name, _ = prev_output.split(" : ", 1)
  387. print("Got new task to monitor: " + task_name)
  388. print("Adding 3 empty lists")
  389. self.state.blocked = True
  390. self.state.task_to_spawner[task_name] = None
  391. # NOTE We now know that there is something to do on an other task, so we just wait for that event to come in
  392. self.state.operations.insert(0, None)
  393. self.state.operations.insert(0, None)
  394. self.state.operations.insert(0, None)
  395. else:
  396. print("UNKNOWN: " + str(prev_output))
  397. elif inp[0] != self.taskname:
  398. # Got some output on another task
  399. # If the task is not registered yet, it is likely not important to communicate with it, so ignore it
  400. if inp[0] in self.state.send_operations:
  401. self.state.send_operations[inp[0]].pop(0)
  402. if inp[1].startswith("Please edit this model before sending next input: "):
  403. _, model_name = inp[1].split("Please edit this model before sending next input: ", 1)
  404. new_taskname = str(uuid.uuid4())
  405. self.state.send_operations[new_taskname] = [[], ["admin"], ["admin"], ["quiet"], ["model_modify", model_name, ""]] + self.state.keyed_operations.get(self.state.task_to_operation[inp[0]], []) + [["exit"]]
  406. print("Modifying model " + str(model_name))
  407. print("On taskname " + str(new_taskname))
  408. self.state.create_additional_task.append(new_taskname)
  409. self.state.task_to_spawner[new_taskname] = inp[0]
  410. elif inp[1].startswith("Please perform manual operation "):
  411. _, op_name = inp[1].split("Please perform manual operation ", 1)
  412. self.state.task_to_operation[inp[0]] = op_name[1:-1]
  413. if inp[0] in self.state.send_operations and not self.state.send_operations[inp[0]]:
  414. del self.state.send_operations[inp[0]]
  415. # At the end of these operations, so finish up!
  416. if inp[0] in self.state.task_to_spawner:
  417. if self.state.task_to_spawner[inp[0]] is not None:
  418. self.state.keyed_operations.pop(self.state.task_to_operation[self.state.task_to_spawner[inp[0]]], None)
  419. self.state.additional_operations.insert(0, [])
  420. self.state.send_operations[self.state.task_to_spawner[inp[0]]] = ["__continue__"]
  421. else:
  422. self.state.additional_operations.pop(0)
  423. self.state.operations.pop(0)
  424. print("Clear up to the normal task!")
  425. return self.state
  426. def outputFnc(self):
  427. if self.state.send_operations:
  428. outp = []
  429. if self.state.create_additional_task:
  430. outp.append(('task_manager', self.state.create_additional_task))
  431. for k, v in self.state.send_operations.items():
  432. if v and v[0] is not None:
  433. outp.append((k, v[0]))
  434. print("REQUEST special: " + str(outp))
  435. if outp:
  436. return {self.to_mvk: outp}
  437. else:
  438. return {}
  439. elif self.state.operations and self.state.operations[0] is not None:
  440. print("REQUEST: " + str(self.state.operations[0]))
  441. return {self.to_mvk: [(self.taskname, self.state.operations[0])]}
  442. else:
  443. return {}
  444. def timeAdvance(self):
  445. if self.state.blocked:
  446. return float("inf")
  447. else:
  448. return 0.0
  449. class NetworkState(object):
  450. def __init__(self):
  451. self.processing = []
  452. self.timer = float("inf")
  453. class Network(AtomicDEVS):
  454. def __init__(self, name, latency, bandwidth):
  455. AtomicDEVS.__init__(self, name)
  456. self.state = NetworkState()
  457. self.input_port = self.addInPort("input_port")
  458. self.output_port = self.addOutPort("output_port")
  459. self.latency = latency
  460. self.bandwidth = bandwidth
  461. def intTransition(self):
  462. self.state.processing.pop(0)
  463. if self.state.processing:
  464. self.state.timer = (len(self.state.processing[0]) * 8 / float(self.bandwidth) + self.latency)
  465. else:
  466. self.state.timer = float("inf")
  467. return self.state
  468. def extTransition(self, inputs):
  469. self.state.timer -= self.elapsed
  470. if self.state.timer == float("inf"):
  471. self.state.timer = 0
  472. for v in inputs[self.input_port]:
  473. self.state.processing.append(json.dumps(v))
  474. # NOTE data is in bytes, while bandwidth is in bits, so multiply by 8
  475. if len(self.state.processing) > 0:
  476. self.state.timer = (len(self.state.processing[0]) * 8 / float(self.bandwidth) + self.latency)
  477. return self.state
  478. def outputFnc(self):
  479. return {self.output_port: [json.loads(self.state.processing[0])]}
  480. def timeAdvance(self):
  481. #print("Timer: " + str(self.state.timer))
  482. return self.state.timer
  483. class System(CoupledDEVS):
  484. def __init__(self,
  485. taskname,
  486. operations,
  487. mvi_additional,
  488. mvi_keyed,
  489. finish_on,
  490. rule_generation,
  491. time_per_phase,
  492. mvi2mvk_latency,
  493. mvi2mvk_bandwidth,
  494. mvk2mvs_latency,
  495. mvk2mvs_bandwidth,
  496. mvs2mvk_latency,
  497. mvs2mvk_bandwidth,
  498. mvk2mvi_latency,
  499. mvk2mvi_bandwidth,
  500. read_root,
  501. create_node,
  502. create_edge,
  503. create_nodevalue,
  504. create_dict,
  505. read_value,
  506. read_outgoing,
  507. read_incoming,
  508. read_edge,
  509. read_dict,
  510. read_dict_keys,
  511. read_dict_edge,
  512. read_dict_node,
  513. read_dict_node_edge,
  514. read_reverse_dict,
  515. delete_node,
  516. delete_edge):
  517. CoupledDEVS.__init__(self, "System")
  518. self.mvi_manager = self.addSubModel(ModelverseInterface(\
  519. taskname = "task_manager",
  520. operations = [[taskname]],
  521. finish_on = None,
  522. ))
  523. self.mvi = self.addSubModel(ModelverseInterface(\
  524. taskname = taskname,
  525. operations = operations,
  526. finish_on = finish_on,
  527. additional_operations = mvi_additional,
  528. keyed_operations = mvi_keyed,
  529. ))
  530. self.mvk = self.addSubModel(ModelverseKernel(\
  531. time_per_phase = time_per_phase,
  532. rule_generation = rule_generation,
  533. ))
  534. self.mvs = self.addSubModel(ModelverseState(\
  535. read_root = read_root,
  536. create_node = create_node,
  537. create_edge = create_edge,
  538. create_nodevalue = create_nodevalue,
  539. create_dict = create_dict,
  540. read_value = read_value,
  541. read_outgoing = read_outgoing,
  542. read_incoming = read_incoming,
  543. read_edge = read_edge,
  544. read_dict = read_dict,
  545. read_dict_keys = read_dict_keys,
  546. read_dict_edge = read_dict_edge,
  547. read_dict_node = read_dict_node,
  548. read_dict_node_edge = read_dict_node_edge,
  549. read_reverse_dict = read_reverse_dict,
  550. delete_node = delete_node,
  551. delete_edge = delete_edge,
  552. ))
  553. self.mvi2mvk = self.addSubModel(Network(\
  554. name = "mvi2mvk",
  555. latency = mvi2mvk_latency,
  556. bandwidth = mvi2mvk_bandwidth,
  557. ))
  558. self.mvk2mvs = self.addSubModel(Network(\
  559. name = "mvk2mvs",
  560. latency = mvk2mvs_latency,
  561. bandwidth = mvk2mvs_bandwidth,
  562. ))
  563. self.mvs2mvk = self.addSubModel(Network(\
  564. name = "mvs2mvk",
  565. latency = mvs2mvk_latency,
  566. bandwidth = mvs2mvk_bandwidth,
  567. ))
  568. self.mvk2mvi = self.addSubModel(Network(\
  569. name = "mvk2mvi",
  570. latency = mvk2mvi_latency,
  571. bandwidth = mvk2mvi_bandwidth,
  572. ))
  573. self.connectPorts(self.mvi_manager.to_mvk, self.mvk.from_mvi)
  574. self.connectPorts(self.mvi.to_mvk, self.mvi2mvk.input_port)
  575. self.connectPorts(self.mvi2mvk.output_port, self.mvk.from_mvi)
  576. self.connectPorts(self.mvk.to_mvs, self.mvk2mvs.input_port)
  577. self.connectPorts(self.mvk2mvs.output_port, self.mvs.from_mvk)
  578. self.connectPorts(self.mvs.to_mvk, self.mvs2mvk.input_port)
  579. self.connectPorts(self.mvs2mvk.output_port, self.mvk.from_mvs)
  580. self.connectPorts(self.mvk.to_mvi, self.mvk2mvi.input_port)
  581. self.connectPorts(self.mvk2mvi.output_port, self.mvi.from_mvk)
  582. taskname = "test_task"
  583. operations = json.loads(open("model/operations", 'r').read())
  584. #operations = json.loads(open("model/operations_simple", 'r').read())
  585. additional_operations = [[], # revise_req
  586. [], # revise_environment
  587. [], # revise_plant
  588. [], # revise_control
  589. [], # revise_query
  590. [], # revise_architecture
  591. [], # make_initial_models
  592. [["instantiate_edge", "Association", "PLANT2EPN_link", "PW_Plant/State", "Encapsulated_PetriNet/Place"], ["instantiate_edge", "Association", "PLANT2EPN_tlink", "PW_Plant/Transition", "Encapsulated_PetriNet/Transition"]], # plant_to_EPN
  593. [["instantiate_edge", "Association", "CTRL2EPN_link", "PW_Control/State", "Encapsulated_PetriNet/Place"], ["instantiate_edge", "Association", "CTRL2EPN_tlink", "PW_Control/Transition", "Encapsulated_PetriNet/Transition"]], # control_to_EPN
  594. [["instantiate_edge", "Association", "ENV2EPN_link", "PW_Environment/Event", "Encapsulated_PetriNet/Place"]], # environment_to_EPN
  595. [["instantiate_edge", "Association", "EPN2PN_place_link", "Encapsulated_PetriNet/Place", "PetriNet/Place"], ["instantiate_edge", "Association", "EPN2PN_transition_link", "Encapsulated_PetriNet/Transition", "PetriNet/Transition"]], # EPN_to_PN
  596. [], # match
  597. [], # reachability
  598. [], # bfs
  599. [], # merge
  600. ]
  601. #additional_operations = [[]]
  602. keyed_operations = {"models/revise_req": [["upload"], compile_model("models/requirements_model.mvc")],
  603. "models/revise_plant": [["upload"], compile_model("models/plant_model.mvc")],
  604. "models/revise_environment": [["upload"], compile_model("models/environment_model.mvc")],
  605. "models/revise_control": [["upload"], compile_model("models/control_model.mvc")],
  606. "models/revise_query": [["upload"], compile_model("models/query_model.mvc")],
  607. "models/revise_architecture": [["upload"], compile_model("models/architecture_model.mvc")],
  608. }
  609. #keyed_operations = {"models/modify_lang": [["instantiate_node", "PN/Class", ""]]}
  610. finish_on = "FINISHED"
  611. args = {
  612. "taskname": taskname,
  613. "operations": operations,
  614. "finish_on": finish_on,
  615. "mvi_additional": additional_operations,
  616. "mvi_keyed": keyed_operations,
  617. "mvi2mvk_latency": 0.0000001,
  618. "mvi2mvk_bandwidth": 50000000000,
  619. "mvk2mvs_latency": 0.0000001,
  620. "mvk2mvs_bandwidth": 50000000000,
  621. "mvs2mvk_latency": 0.0000001,
  622. "mvs2mvk_bandwidth": 50000000000,
  623. "mvk2mvi_latency": 0.0000001,
  624. "mvk2mvi_bandwidth": 50000000000,
  625. "time_per_phase": 0.05,
  626. # Automatically filled in from calibration results, just here to prevent crashes (results for my UA desktop)
  627. "read_root": 0.00001406669616699,
  628. "create_node": 0.00000379181167487,
  629. "create_edge": 0.00000601282282066,
  630. "create_nodevalue": 0.00000501364247391,
  631. "create_dict": 0.00001028065706205,
  632. "read_value": 0.00000388661630500,
  633. "read_outgoing": 0.00000520600098073,
  634. "read_incoming": 0.00000645903181994,
  635. "read_edge": 0.00000449162172644,
  636. "read_dict": 0.00000460127038355,
  637. "read_dict_keys": 0.00001678063432883,
  638. "read_dict_node": 0.00001020808859528,
  639. "read_dict_edge": 0.00000642558526942,
  640. "read_dict_node_edge": 0.0,
  641. "read_reverse_dict": 0.00002557890755790,
  642. "delete_node": 0.00004755891187096,
  643. "delete_edge": 0.00000683382081240,
  644. "rule_generation": 0.00001543215873893,
  645. }
  646. with open("calibration/averages", 'r') as param_file:
  647. for l in param_file:
  648. op, t = l.split(": ")
  649. op = op.strip()
  650. args[op] = float(t)
  651. model = System(**args)
  652. sim = Simulator(model)
  653. sim.setTerminationCondition(lambda t, m: m.mvi.state.finished)
  654. #sim.setVerbose()
  655. tn = sim.simulate()
  656. print("Simulation finished at time %s" % tn)