model.py 31 KB

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