model.py 31 KB

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