def test_main(self): n_iter = 1000 s = dl.lib.StateSaver(int) gen = dl.lib.make_generator(1, reps=n_iter) @dl.DeltaBlock(allow_const=True) def return10_const() -> int: return 10 @dl.DeltaBlock(allow_const=False) def return10_non_const() -> int: return 10 @dl.DeltaBlock() def adder(a: dl.DOptional(int), b: int) -> int: if a is None: return b else: return a + b @dl.Interactive([('a', int)], int) def aggregator(node): result = 0 for _ in range(n_iter): a = node.receive('a') result += a node.send(result) # Case 1: const nodes always provide an input for optional ports with dl.DeltaGraph() as graph: total = adder(return10_const(), gen.call()) s.save_and_exit(aggregator.call(a=total)) dl.DeltaPySimulator(graph).run() self.assertEqual(s.saved[-1], 11 * n_iter) # Case 2: due to uncontrolled delays non-const nodes not always # provide an input for optional ports s.reset() gen = dl.lib.make_generator(1, reps=n_iter) with dl.DeltaGraph() as graph: total = adder(return10_non_const(), gen.call()) s.save_and_exit(aggregator.call(a=total)) dl.DeltaPySimulator(graph).run() self.assertLessEqual(s.saved[-1], 11 * n_iter)
def test_exit_all_const_nodes(self): """Test that runtime runs correctly if all nodes are constant.""" with dl.DeltaGraph() as graph: self.const_save_exit(n=add(n1=1, n2=2)) with self.assertRaises(RuntimeError): dl.DeltaPySimulator(graph).run(100)
def main(simple): if simple: graph, _ = generate_graph_constant_input() else: graph, _ = generate_graph_interactive_input() rt = dl.DeltaPySimulator(graph, lvl=logging.ERROR) rt.run()
def test_queue_optionality(self): """Test that queues inhere correct optionality depending on the type of the destination node. """ graph = getg_optional_queues() dl.DeltaPySimulator(graph) self.assertEqual(graph.nodes[0].out_queues['output'].optional, True) self.assertEqual(graph.nodes[1].out_queues['output'].optional, False)
def test_queue_size(self): """If both queue_size and in_port_size are defined, the minimum is chosen.""" @dl.DeltaBlock(allow_const=False, in_port_size=2) def receive_then_sleep(n: int) -> dl.Void: time.sleep(SLEEPTIME) with dl.DeltaGraph() as graph: n = send_and_check_time.call() receive_then_sleep(n) # 1 < 2 dl.DeltaPySimulator(graph, queue_size=1) self.assertEqual(n.out_queues[None].maxsize, 1) # 2 < 3 dl.DeltaPySimulator(graph, queue_size=3) self.assertEqual(n.out_queues[None].maxsize, 2)
def test_exit_const_node(self): """Test that a DeltaRuntimeExit in a constant node does not cause an error. """ with dl.DeltaGraph() as graph: do_nothing(n=self.const_save_exit(n=add(n1=1, n2=2))) with self.assertRaises(RuntimeError): dl.DeltaPySimulator(graph).run()
def test_no_message_logging(self): """Messages should not be logged at all if msg_lvl is not reset""" rt = dl.DeltaPySimulator(self.test_graph) rt.run() message_times = [msg.clk for node, _, msg in rt.msg_log.messages if node.startswith("save")] self.assertEqual(message_times, [])
def test_error_async_nodes(self): """Test that an error in a node is re-thrown.""" with dl.DeltaGraph() as graph: n = SomeClass().method() async_err_if_4(n) rt = dl.DeltaPySimulator(graph, lvl=logging.FATAL) with self.assertRaises(RuntimeError): rt.run() self.assertFalse(rt.running)
def test_clock_updates(self): """Messages should be displayed at end of run in logical clock order. """ rt = dl.DeltaPySimulator(self.test_graph, msg_lvl=logging.DEBUG) rt.run() message_times = [msg.clk for node, _, msg in rt.msg_log.messages if node.startswith("save")] self.assertGreater(len(message_times), 0) for time_1, time_2 in zip(message_times, message_times[1:]): self.assertLess(time_1, time_2)
def test_exit_(self): """Test that an DeltaRuntimeExit does not cause an error.""" s = dl.lib.StateSaver(int, condition=lambda x: x == 4) with dl.DeltaGraph() as graph: n = SomeClass().method() s.save_and_exit_if(n) rt = dl.DeltaPySimulator(graph) rt.run() self.assertFalse(rt.running) self.assertEqual(s.saved, [1, 2, 3, 4])
def main(simple): verbose = False if verbose: verbosity = 3 else: verbosity = 0 if simple: graph, shaper = generate_graph_constant_input() else: graph, shaper = generate_graph_interactive_input(verbose) rt = dl.DeltaPySimulator(graph, lvl=logging.ERROR) rt.run()
def check_executes(self, graph, expect, exception, mock_stdout, excluded_body_tags=None, preferred_body_tags=None): """DeltaPySimulator executes the graph execution. Parameters ---------- graph : dl.DeltaGraph The graph to execute. expect : str The exact multistring expression we expect on stdout (excluding any housekeeping messages). exception : Exception Exception thrown by a runtime/simulator at _any_ stage (includes building, deployment, execution, etc.). mock_stdout ``unittest.mock`` captures stdout and refers to this object. excluded_body_tags Body tags to exclude. preferred_body_tags Body tags to prefer. """ graph.select_bodies(exclusions=excluded_body_tags, preferred=preferred_body_tags) if exception: with self.assertRaises(exception): dl.DeltaPySimulator(graph).run() else: dl.DeltaPySimulator(graph).run() if expect: self.assertMultiLineEqual( mock_stdout.getvalue(), self.python_output_prefix + textwrap.dedent(expect) + self.python_output_suffix )
def test_queue_types(self): """Test that queues of correct types are created (or not) depending on the type of the source and destination nodes. """ graph = getg_const_chain() dl.DeltaPySimulator(graph) self.assertEqual(len(graph.nodes[0].out_queues), 0) self.assertEqual(len(graph.nodes[1].out_queues), 1) self.assertEqual(len(graph.nodes[2].out_queues), 1) self.assertEqual(type(graph.nodes[1].out_queues['output']), dl.runtime.ConstQueue) self.assertEqual(type(graph.nodes[2].out_queues['output']), dl.runtime.DeltaQueue)
def test_blocking_queue_queue_size(self): """The queue size is defined globally by queue_size.""" @dl.DeltaBlock(allow_const=False) def receive_then_sleep(n: int) -> dl.Void: time.sleep(SLEEPTIME) for _ in range(100): with dl.DeltaGraph() as graph: n = send_and_check_time.call() receive_then_sleep(n) dl.DeltaPySimulator(graph, queue_size=1).run(100 * SLEEPTIME) self.assertGreaterEqual(TIME_DIFF, SLEEPTIME) self.assertEqual(n.out_queues[None].maxsize, 1)
def setUp(self): """ Create the graph: return_4 -> add -> add_member -> print -> saver / return_2 / """ self.saver = dl.lib.StateSaver(int) with dl.DeltaGraph() as graph: inst = OtherClass(2) const = add(return_4(), return_2()) num = inst.add_member(const) self.saver.save_and_exit(num) self.graph = graph self.runtime = dl.DeltaPySimulator(graph)
def test_interactive_node_with_only_optional_input(self): """Test that an interactive node with an only optional input and no outputs or outputs that can be reached only in a special case wouldn't block the simulation. This is implemented via addition of a 1 ns wait when a node attempts to receive an input and it's trivial. Note that non-interactive nodes with such behaviour won't block as they always call ``send``. """ @dl.Interactive(inputs=[('a', dl.Optional(int))]) def node_to_investigate(node): while True: a = node.receive('a') if a is not None: STORE.append(a) raise dl.DeltaRuntimeExit @dl.Interactive(outputs=[('output', int)]) def rest_of_graph(node): """This node imitates the rest of the graph that does some computations and occasionally provides an input.""" i = 0 while True: i += 1 a = 40 b = 2 a, b = b, a if i % 1000 == 0: node.send(10) else: node.send(None) with dl.DeltaGraph() as graph: opt_input = rest_of_graph.call() node_to_investigate.call(a=opt_input) start_time = time.time() dl.DeltaPySimulator(graph).run() total_time = time.time() - start_time self.assertEqual(STORE, [10]) self.assertLessEqual(total_time, 1)
def setUp(self): r"""Build the following graph ``` add_1 / \ || || || || \ / increment ----------> saver ``` """ self.saver = dl.lib.StateSaver(int) with dl.DeltaGraph() as graph: add_1_placeholder = dl.placeholder_node_factory() incr_node = opt_increment.call(n=add_1_placeholder) self.saver.save_and_exit(incr_node.y) add_one = add1_or0(incr_node.x) add_1_placeholder.specify_by_node(add_one) self.graph = graph self.rt = dl.DeltaPySimulator(graph)
def test_interactive_node_without_input(self): """Similar to the test above, but here the tests node does not have inputs. """ @dl.Interactive(inputs=[], outputs=int) def unstoppable(node): i = 0 while True: node.send(i) i = i + 1 exit_if = dl.lib.StateSaver(int, condition=lambda x: x > 10) with dl.DeltaGraph() as graph: exit_if.save_and_exit_if(unstoppable.call()) rt = dl.DeltaPySimulator(graph) rt.run() unstoppable = graph.find_node_by_name("unstoppable") self.assertFalse(rt.threads[unstoppable.name].is_alive()) self.assertEqual(exit_if.saved, list(range(12)))
def test_portless_node(self): """This test has a node without inputs nor outputs. We test that DeltaPySimulator does not get stuck on running just this node and instead runs every node (the order is not determined). This is implemented via addition of a 1 ns wait when a node attempts to send an output. """ N_ITER = 1000 @dl.DeltaBlock(allow_const=False) def foo() -> dl.Void: a = 40 b = 2 a, b = b, a gen = dl.lib.make_generator(1, reps=N_ITER) s = dl.lib.StateSaver(int) @dl.Interactive([('a', int)], int) def aggregator(node): result = 0 for _ in range(N_ITER): a = node.receive('a') result += a node.send(result) with dl.DeltaGraph() as graph: foo() s.save_and_exit(aggregator.call(a=gen.call())) start_time = time.time() dl.DeltaPySimulator(graph).run() total_time = time.time() - start_time self.assertEqual(s.saved, [N_ITER]) self.assertLessEqual(total_time, 1)
b : int Another argument the user can access node : Optional[PythonFuncNode] The node this block is running on. Used so that the user can send & receive messages in the interactive console. """ c = 9 d = 10 code.interact(local=dict(globals(), **locals())) @dl.DeltaBlock() def printer(n: int) -> dl.Void: if n == -1: print("Exiting Deltaflow example") print("Exit the console via" + " Ctrl-D on Linux/MacOS or Ctrl-Z on Windows") raise dl.DeltaRuntimeExit print(n) if __name__ == "__main__": # define our DeltaGraph with dl.DeltaGraph() as test_graph: n = interact(7, 8) printer(n) # make a runtime and run the graph rt = dl.DeltaPySimulator(test_graph) rt.run()
"""This file exists for purely testing of Deltaflow-on-ARTIQ. For an explanation please read the notebook, which has much more details. """ import deltalanguage as dl from examples.rabi_demo.exp_graph import get_graph from examples.rabi_demo.aggregator import REPETITIONS, RESOLUTION graph, result_storage, cmds_storage = get_graph() q_sim = dl.lib.HardwareAbstractionLayerNode( dl.lib.ProjectqQuantumSimulator(register_size=1)) template_node = graph.find_node_by_name('template_QSim') template_node.add_body(q_sim.accept_command) print(graph) rt = dl.DeltaPySimulator(graph) rt.run() # basic checks assert len(result_storage.saved) == 2**RESOLUTION, \ f"{len(result_storage.saved)} /= {2**RESOLUTION}" assert len(cmds_storage.saved) == 3 * 2**RESOLUTION * REPETITIONS, \ f"{len(cmds_storage.saved)} /= {3 * 2**RESOLUTION * REPETITIONS}" assert all(map(lambda x: x <= REPETITIONS, result_storage.saved))
def test_run(self): dl.DeltaPySimulator(self.graph).run() self.assertEqual(self.saver.saved, [1])