model.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  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. 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. #print(" --> " + str(inputs[self.from_mvs]))
  199. for mvs_input in inputs[self.from_mvs]:
  200. if self.state.mvk is None:
  201. # No MvK, so set it with the root we have just received (or should have received)
  202. self.state.root = mvs_input[0]
  203. self.state.mvk = MvK(self.state.root)
  204. else:
  205. self.state.reply = mvs_input
  206. self.state.waiting = False
  207. return self.state
  208. def intTransition(self):
  209. self.state.current_time += self.timeAdvance()
  210. was_empty = len(self.state.tasks) == 0
  211. if self.state.commands is not None:
  212. self.state.commands = None
  213. return self.state
  214. if self.state.mvk is not None:
  215. self.state.mvk.returnvalue = None
  216. if self.state.mvk is None:
  217. # Initializing
  218. self.state.waiting = True
  219. elif not self.state.loaded_primitives:
  220. commands = self.state.mvk.execute_yields("", "load_primitives", [], self.state.reply)
  221. if commands is None:
  222. self.state.loaded_primitives = True
  223. self.state.reply = None
  224. else:
  225. self.state.waiting = True
  226. self.state.commands = commands
  227. else:
  228. # Are initialized and have work to do
  229. if len(self.state.tasks) == 0:
  230. # Read out new set of tasks first
  231. if self.state.reply is None:
  232. self.state.execution_rounds += 1
  233. commands = [("RDK", [self.state.root])]
  234. if self.state.execution_rounds > 10000:
  235. commands.append(("GC", []))
  236. self.state.execution_rounds = 0
  237. else:
  238. self.state.tasks = self.state.reply[0]
  239. commands = None
  240. elif self.state.phase == "init_task":
  241. if self.state.reply is None:
  242. commands = [("RV", [self.state.tasks[0]])]
  243. else:
  244. self.state.current_task = self.state.reply[0]
  245. #print("Processing task %s at time %s" % (self.state.current_task, self.time_last))
  246. self.state.start_task_time = self.state.current_time
  247. if self.state.current_task.startswith("__"):
  248. # Don't process this task and force termination of task
  249. self.state.phase = "output"
  250. commands = None
  251. elif self.state.phase == "input":
  252. # Process inputs
  253. if self.state.inputs.get(self.state.current_task, None):
  254. value = self.state.inputs[self.state.current_task][0]
  255. start = time.time()
  256. commands = self.state.mvk.execute_yields(self.state.current_task, "set_input", [value], self.state.reply)
  257. if PROFILE:
  258. print("rule_generation: %.17f" % ((time.time() - start)))
  259. #self.state.rule_generation = time.time() - start
  260. self.state.mvk.returnvalue = None
  261. if commands is None:
  262. self.state.inputs[self.state.current_task].pop(0)
  263. else:
  264. commands = None
  265. elif self.state.phase == "computation":
  266. try:
  267. start = time.time()
  268. commands = self.state.mvk.execute_yields(self.state.current_task, "execute_rule", [], self.state.reply)
  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. if PROFILE:
  281. print("rule_generation: %.17f" % ((time.time() - start)))
  282. #self.state.rule_generation = time.time() - start
  283. else:
  284. raise Exception("Phase: " + str(self.state.phase))
  285. # Advance phase
  286. if commands is None:
  287. if was_empty:
  288. self.state.phase = "init_task"
  289. elif self.state.phase == "init_task":
  290. self.state.phase = "input"
  291. elif self.state.phase == "input":
  292. self.state.phase = "computation"
  293. elif self.state.phase == "computation":
  294. if not self.state.mvk.success or (self.state.current_time - self.state.start_task_time > self.time_per_phase):
  295. self.state.phase = "output"
  296. elif self.state.phase == "output":
  297. self.state.tasks.pop(0)
  298. self.state.phase = "init_task"
  299. self.state.waiting = False
  300. self.state.reply = None
  301. else:
  302. self.state.waiting = True
  303. # Send the commands to the MvS
  304. self.state.commands = commands
  305. #print(" <-- " + str(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("Got input: " + str(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. print("Blocking for now...")
  371. prev_output = self.state.output[inp[0]][-1]
  372. if prev_output.startswith("Please edit this model before sending next input: "):
  373. _, model_name = prev_output.split("Please edit this model before sending next input: ", 1)
  374. new_taskname = str(uuid.uuid4())
  375. self.state.send_operations[new_taskname] = [[], ["admin"], ["admin"], ["quiet"], ["model_modify", model_name, ""]] + self.state.additional_operations[0] + [["exit"]]
  376. print("Modifying model " + str(model_name))
  377. print("On taskname " + str(new_taskname))
  378. self.state.create_additional_task.append(new_taskname)
  379. self.state.task_to_operation[new_taskname] = None
  380. self.state.task_to_spawner[new_taskname] = None
  381. elif prev_output.startswith("Spawned activity on task: "):
  382. print("Spawned activity")
  383. _, task_name = prev_output.split("Spawned activity on task: ", 1)
  384. self.state.blocked = True
  385. self.state.task_to_spawner[task_name] = None
  386. # NOTE We now know that there is something to do on an other task, so we just wait for that event to come in
  387. print("Adding 3 empty lists")
  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. elif prev_output == "Success":
  402. print("Remaining operations: " + str(self.state.operations))
  403. self.state.operations.pop(0)
  404. self.state.blocked = False
  405. else:
  406. print("UNKNOWN: " + str(prev_output))
  407. elif inp[0] != self.taskname:
  408. # Got some output on another task
  409. # If the task is not registered yet, it is likely not important to communicate with it, so ignore it
  410. if inp[0] in self.state.send_operations:
  411. self.state.send_operations[inp[0]].pop(0)
  412. if inp[1].startswith("Please edit this model before sending next input: "):
  413. _, model_name = inp[1].split("Please edit this model before sending next input: ", 1)
  414. new_taskname = str(uuid.uuid4())
  415. 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"]]
  416. print("Modifying model " + str(model_name))
  417. print("On taskname " + str(new_taskname))
  418. self.state.create_additional_task.append(new_taskname)
  419. self.state.task_to_spawner[new_taskname] = inp[0]
  420. elif inp[1].startswith("Please perform manual operation "):
  421. _, op_name = inp[1].split("Please perform manual operation ", 1)
  422. self.state.task_to_operation[inp[0]] = op_name[1:-1]
  423. if inp[0] in self.state.send_operations and not self.state.send_operations[inp[0]]:
  424. del self.state.send_operations[inp[0]]
  425. # At the end of these operations, so finish up!
  426. if inp[0] in self.state.task_to_spawner:
  427. if self.state.task_to_spawner[inp[0]] is not None:
  428. self.state.keyed_operations.pop(self.state.task_to_operation[self.state.task_to_spawner[inp[0]]], None)
  429. self.state.additional_operations.insert(0, [])
  430. self.state.send_operations[self.state.task_to_spawner[inp[0]]] = ["__continue__"]
  431. else:
  432. self.state.additional_operations.pop(0)
  433. self.state.operations.pop(0)
  434. print("Clear up to the normal task!")
  435. return self.state
  436. def outputFnc(self):
  437. if self.state.send_operations:
  438. outp = []
  439. if self.state.create_additional_task:
  440. outp.append(('task_manager', self.state.create_additional_task))
  441. for k, v in self.state.send_operations.items():
  442. if v and v[0] is not None:
  443. outp.append((k, v[0]))
  444. print("REQUEST special: " + str(outp))
  445. if outp:
  446. return {self.to_mvk: outp}
  447. else:
  448. return {}
  449. elif self.state.operations and self.state.operations[0] is not None:
  450. print("REQUEST: " + str(self.state.operations[0]))
  451. return {self.to_mvk: [(self.taskname, self.state.operations[0])]}
  452. else:
  453. return {}
  454. def timeAdvance(self):
  455. if self.state.blocked:
  456. return float("inf")
  457. else:
  458. return 0.0
  459. class NetworkState(object):
  460. def __init__(self):
  461. self.processing = []
  462. self.timer = float("inf")
  463. class Network(AtomicDEVS):
  464. def __init__(self, name, latency, bandwidth):
  465. AtomicDEVS.__init__(self, name)
  466. self.state = NetworkState()
  467. self.input_port = self.addInPort("input_port")
  468. self.output_port = self.addOutPort("output_port")
  469. self.latency = latency
  470. self.bandwidth = bandwidth
  471. def intTransition(self):
  472. self.state.processing.pop(0)
  473. if self.state.processing:
  474. self.state.timer = (len(json.dumps(self.state.processing[0])) * 8 / float(self.bandwidth) + self.latency)
  475. else:
  476. self.state.timer = float("inf")
  477. return self.state
  478. def extTransition(self, inputs):
  479. self.state.timer -= self.elapsed
  480. if self.state.timer == float("inf"):
  481. self.state.timer = 0
  482. for v in inputs[self.input_port]:
  483. self.state.processing.append(v)
  484. # NOTE data is in bytes, while bandwidth is in bits, so multiply by 8
  485. if len(self.state.processing) > 0:
  486. self.state.timer = (len(json.dumps(self.state.processing[0])) * 8 / float(self.bandwidth) + self.latency)
  487. return self.state
  488. def outputFnc(self):
  489. return {self.output_port: [self.state.processing[0]]}
  490. def timeAdvance(self):
  491. #print("Timer: " + str(self.state.timer))
  492. return self.state.timer
  493. class System(CoupledDEVS):
  494. def __init__(self,
  495. taskname,
  496. operations,
  497. mvi_additional,
  498. mvi_keyed,
  499. finish_on,
  500. rule_generation,
  501. time_per_phase,
  502. mvi2mvk_latency,
  503. mvi2mvk_bandwidth,
  504. mvk2mvs_latency,
  505. mvk2mvs_bandwidth,
  506. mvs2mvk_latency,
  507. mvs2mvk_bandwidth,
  508. mvk2mvi_latency,
  509. mvk2mvi_bandwidth,
  510. read_root,
  511. create_node,
  512. create_edge,
  513. create_nodevalue,
  514. create_dict,
  515. read_value,
  516. read_outgoing,
  517. read_incoming,
  518. read_edge,
  519. read_dict,
  520. read_dict_keys,
  521. read_dict_edge,
  522. read_dict_node,
  523. read_dict_node_edge,
  524. read_reverse_dict,
  525. delete_node,
  526. delete_edge):
  527. CoupledDEVS.__init__(self, "System")
  528. self.mvi_manager = self.addSubModel(ModelverseInterface(\
  529. taskname = "task_manager",
  530. operations = [[taskname]],
  531. finish_on = None,
  532. ))
  533. self.mvi = self.addSubModel(ModelverseInterface(\
  534. taskname = taskname,
  535. operations = operations,
  536. finish_on = finish_on,
  537. additional_operations = mvi_additional,
  538. keyed_operations = mvi_keyed,
  539. ))
  540. self.mvk = self.addSubModel(ModelverseKernel(\
  541. time_per_phase = time_per_phase,
  542. rule_generation = rule_generation,
  543. ))
  544. self.mvs = self.addSubModel(ModelverseState(\
  545. read_root = read_root,
  546. create_node = create_node,
  547. create_edge = create_edge,
  548. create_nodevalue = create_nodevalue,
  549. create_dict = create_dict,
  550. read_value = read_value,
  551. read_outgoing = read_outgoing,
  552. read_incoming = read_incoming,
  553. read_edge = read_edge,
  554. read_dict = read_dict,
  555. read_dict_keys = read_dict_keys,
  556. read_dict_edge = read_dict_edge,
  557. read_dict_node = read_dict_node,
  558. read_dict_node_edge = read_dict_node_edge,
  559. read_reverse_dict = read_reverse_dict,
  560. delete_node = delete_node,
  561. delete_edge = delete_edge,
  562. ))
  563. self.mvi2mvk = self.addSubModel(Network(\
  564. name = "mvi2mvk",
  565. latency = mvi2mvk_latency,
  566. bandwidth = mvi2mvk_bandwidth,
  567. ))
  568. self.mvk2mvs = self.addSubModel(Network(\
  569. name = "mvk2mvs",
  570. latency = mvk2mvs_latency,
  571. bandwidth = mvk2mvs_bandwidth,
  572. ))
  573. self.mvs2mvk = self.addSubModel(Network(\
  574. name = "mvs2mvk",
  575. latency = mvs2mvk_latency,
  576. bandwidth = mvs2mvk_bandwidth,
  577. ))
  578. self.mvk2mvi = self.addSubModel(Network(\
  579. name = "mvk2mvi",
  580. latency = mvk2mvi_latency,
  581. bandwidth = mvk2mvi_bandwidth,
  582. ))
  583. self.connectPorts(self.mvi_manager.to_mvk, self.mvk.from_mvi)
  584. self.connectPorts(self.mvi.to_mvk, self.mvi2mvk.input_port)
  585. self.connectPorts(self.mvi2mvk.output_port, self.mvk.from_mvi)
  586. self.connectPorts(self.mvk.to_mvs, self.mvk2mvs.input_port)
  587. self.connectPorts(self.mvk2mvs.output_port, self.mvs.from_mvk)
  588. self.connectPorts(self.mvs.to_mvk, self.mvs2mvk.input_port)
  589. self.connectPorts(self.mvs2mvk.output_port, self.mvk.from_mvs)
  590. self.connectPorts(self.mvk.to_mvi, self.mvk2mvi.input_port)
  591. self.connectPorts(self.mvk2mvi.output_port, self.mvi.from_mvk)
  592. taskname = "test_task"
  593. operations = json.loads(open("model/operations", 'r').read())
  594. #operations = json.loads(open("model/operations_simple", 'r').read())
  595. additional_operations = [[], # revise_req
  596. [], # revise_environment
  597. [], # revise_plant
  598. [], # revise_control
  599. [], # revise_query
  600. [], # revise_architecture
  601. [], # make_initial_models
  602. [["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
  603. [["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
  604. [["instantiate_edge", "Association", "ENV2EPN_link", "PW_Environment/Event", "Encapsulated_PetriNet/Place"]], # environment_to_EPN
  605. [["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
  606. [], # match
  607. [], # reachability
  608. [], # bfs
  609. [], # merge
  610. ]
  611. #additional_operations = [[]]
  612. keyed_operations = {"models/revise_req": [["upload"], compile_model("models/requirements_model.mvc")],
  613. "models/revise_plant": [["upload"], compile_model("models/plant_model.mvc")],
  614. "models/revise_environment": [["upload"], compile_model("models/environment_model.mvc")],
  615. "models/revise_control": [["upload"], compile_model("models/control_model.mvc")],
  616. "models/revise_query": [["upload"], compile_model("models/query_model.mvc")],
  617. "models/revise_architecture": [["upload"], compile_model("models/architecture_model.mvc")],
  618. }
  619. #keyed_operations = {"models/modify_lang": [["instantiate_node", "PN/Class", ""]]}
  620. finish_on = "FINISHED"
  621. args = {
  622. "taskname": taskname,
  623. "operations": operations,
  624. "finish_on": finish_on,
  625. "mvi_additional": additional_operations,
  626. "mvi_keyed": keyed_operations,
  627. "mvi2mvk_latency": 0.0000001,
  628. "mvi2mvk_bandwidth": 50000000000,
  629. "mvk2mvs_latency": 0.0000001,
  630. "mvk2mvs_bandwidth": 50000000000,
  631. "mvs2mvk_latency": 0.0000001,
  632. "mvs2mvk_bandwidth": 50000000000,
  633. "mvk2mvi_latency": 0.0000001,
  634. "mvk2mvi_bandwidth": 50000000000,
  635. "time_per_phase": 0.05,
  636. # Automatically filled in from calibration results, just here to prevent crashes (results for my UA desktop)
  637. "read_root": 0.00001406669616699,
  638. "create_node": 0.00000379181167487,
  639. "create_edge": 0.00000601282282066,
  640. "create_nodevalue": 0.00000501364247391,
  641. "create_dict": 0.00001028065706205,
  642. "read_value": 0.00000388661630500,
  643. "read_outgoing": 0.00000520600098073,
  644. "read_incoming": 0.00000645903181994,
  645. "read_edge": 0.00000449162172644,
  646. "read_dict": 0.00000460127038355,
  647. "read_dict_keys": 0.00001678063432883,
  648. "read_dict_node": 0.00001020808859528,
  649. "read_dict_edge": 0.00000642558526942,
  650. "read_dict_node_edge": 0.0,
  651. "read_reverse_dict": 0.00002557890755790,
  652. "delete_node": 0.00004755891187096,
  653. "delete_edge": 0.00000683382081240,
  654. "rule_generation": 0.00001543215873893,
  655. }
  656. with open("calibration/averages", 'r') as param_file:
  657. for l in param_file:
  658. op, t = l.split(": ")
  659. op = op.strip()
  660. args[op] = float(t)
  661. model = System(**args)
  662. sim = Simulator(model)
  663. sim.setTerminationCondition(lambda t, m: m.mvi.state.finished)
  664. #sim.setVerbose()
  665. tn = sim.simulate()
  666. print("Simulation finished at time %s" % tn)