diff --git a/README.md b/README.md index 5574bd1..1442cb3 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# AutoDepGraph +# AutoDepGraph -[![PyPI](https://img.shields.io/pypi/v/adaptive.svg)](https://pypi.python.org/pypi/autodepgraph) +[![PyPI](https://img.shields.io/pypi/v/autodepgraph.svg)](https://pypi.python.org/pypi/autodepgraph) [![Build Status](https://travis-ci.org/AdriaanRol/AutoDepGraph.svg?branch=master)](https://travis-ci.org/AdriaanRol/AutoDepGraph) -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/ae46c58617ff45df9ac98446b3dc34ac)](https://www.codacy.com/app/adriaan-rol/AutoDepGraph?utm_source=github.com&utm_medium=referral&utm_content=AdriaanRol/AutoDepGraph&utm_campaign=Badge_Grade) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/ae46c58617ff45df9ac98446b3dc34ac)](https://www.codacy.com/app/adriaan-rol/AutoDepGraph?utm_source=github.com&utm_medium=referral&utm_content=AdriaanRol/AutoDepGraph&utm_campaign=Badge_Grade) [![Coverage Status](https://coveralls.io/repos/github/AdriaanRol/AutoDepGraph/badge.svg?branch=master)](https://coveralls.io/github/AdriaanRol/AutoDepGraph?branch=master) [![DOI](https://zenodo.org/badge/85987885.svg)](https://zenodo.org/badge/latestdoi/85987885) -AutoDepGraph is a framework for using dependency graphs to calibrate a system. It is heavily inspired by ["Physical qubit calibration on a directed acyclic graph"](https://arxiv.org/abs/1803.03226). +AutoDepGraph is a framework for using dependency graphs to calibrate a system. It is heavily inspired by ["Physical qubit calibration on a directed acyclic graph"](https://arxiv.org/abs/1803.03226). ## Overview AutoDepGraph consists of two main classes, the CalibrationNode and the Graph. @@ -21,11 +21,11 @@ A CalibrationNode contains: + Bad (red): calibration or check has failed + unknown (grayed): checks of the node should be run + active (blue): calibration or check in progress - - parents: the nodes it depends on + - parents: the nodes it depends on - children: nodes that depend on this node - check_function : name of function to be executed when check is called. This can be a method of another instrument. - calibrate_function : name of function to be executed when calibrate is called. This can be a method of another instrument. - - calibration_timeout: time in (s) after which a calibration times out. + - calibration_timeout: time in (s) after which a calibration times out. - function - execute or call @@ -35,8 +35,8 @@ A CalibrationNode contains: - calibrate + Executes the calibration routines of the node -A Graph is a container of nodes, it is used for: -- new graphs can be created by instantiating a graph and then using the add_node method to define new nodes. +A Graph is a container of nodes, it is used for: +- new graphs can be created by instantiating a graph and then using the add_node method to define new nodes. - loading and saving the graph - real-time visualization using pyqtgraph - state of the node determines color of a node @@ -45,7 +45,7 @@ A Graph is a container of nodes, it is used for: ![Example calibration graph](docs/example_graph.png) -## Examples +## Examples For an introductory example see the example notebook. If you want to see how to use a specific function, see the tests located in the autodepgraph/tests folder. ## Installation @@ -54,8 +54,8 @@ For an introductory example see the example notebook. If you want to see how to - navigate to the repository and run `pip install -e .` - verify success of installation by running `py.test` -#### N.B. windows can be "problematic" -Installation on windows is a bit more difficult, this relates mostly to the installation of pygraphviz. To install graphviz and pygraphviz on windows follow these steps: +#### N.B. windows can be "problematic" +Installation on windows is a bit more difficult, this relates mostly to the installation of pygraphviz. To install graphviz and pygraphviz on windows follow these steps: - get the 64 bit version of ![graphviz for windows](https://github.com/mahkoCosmo/GraphViz_x64/), copy it to e.g., program files and add the bin folder to the system path. - the 64 bit version lacks the libxml2.dll, you most likely have this from some other program. You can find this by searching for `libxml2.dll` in the program files folder. After that just copy paste it to the bin folder of graphviz. @@ -69,4 +69,4 @@ python setup.py install --include-path="C:\Program Files\graphviz-2.38_x64\inclu - then install autodepgraph and test the installation using `py.test` ## Acknowledgements -I would like to thank Julian Kelly for the idea of using a dependency graph for calibrations and for early discussions. I would like to thank Joe Weston for discussions and help in working out the initial design. I would like to acknowledge Livio Ciorciaro for disucssions and as a coauthor of this project. +I would like to thank Julian Kelly for the idea of using a dependency graph for calibrations and for early discussions. I would like to thank Joe Weston for discussions and help in working out the initial design. I would like to acknowledge Livio Ciorciaro for disucssions and as a coauthor of this project. diff --git a/autodepgraph/graph.py b/autodepgraph/graph.py index 5f92ef9..6058474 100644 --- a/autodepgraph/graph.py +++ b/autodepgraph/graph.py @@ -26,12 +26,12 @@ class AutoDepGraph_DAG(nx.DiGraph): """ - + Attributes: node_states: Allowed states for the nodes matplotlib_edge_properties: Properties passed to networkx plotting of edges matplotlib_label_properties: Properties passed to networkx plotting of labels - + """ node_states : List[str] = ['good', 'needs calibration', 'bad', 'unknown', 'active'] @@ -52,9 +52,6 @@ def __init__(self, name, cfg_plot_mode='svg', self.cfg_plot_mode = cfg_plot_mode self.cfg_plot_mode_args = {'fig': None} - _path_name = split(__file__)[:-1][0] - self.cfg_svg_filename = join(_path_name, 'svg_viewer', 'adg_graph.svg') - super().__init__(incoming_graph_data, **attr) # internal attributes @@ -66,7 +63,15 @@ def __init__(self, name, cfg_plot_mode='svg', self._exec_cnt = 0 self._calib_cnt = 0 self._check_cnt = 0 - + + + @property + def cfg_svg_filename(self): + """ + Default location for storing svg based visualizations of the DAG. + """ + _path_name = split(__file__)[:-1][0] + return join(_path_name, 'svg_viewer', 'adg_graph.svg') def fresh_copy(self): return AutoDepGraph_DAG(name=self.name, @@ -96,9 +101,6 @@ def add_node(self, node_for_adding, **attr): 'autodepgraph.node_functions.calibration_functions' + '.NotImplementedCalibration') - attr.setdefault('calibrate_function_kwargs', {}) - 'calibrate_function_kwargs', {}) - attr['check_function'] = attr.get( 'check_function', 'autodepgraph.node_functions.check_functions' + @@ -283,10 +285,8 @@ def calibrate_node(self, node : str, verbose : bool =False): self.set_node_state(node, 'active') func = _get_function(self.nodes[node]['calibrate_function']) - func_kwargs = self.nodes[node]['calibrate_function_kwargs'] - try: - result = func(**func_kwargs) + result = func() except Exception as e: self.set_node_state(node, 'bad') logging.warning(e) @@ -311,8 +311,6 @@ def set_all_node_states(self, state): def update_monitor(self): if self.cfg_plot_mode == 'matplotlib': self.update_monitor_mpl() - # elif self.cfg_plot_mode == 'pyqtgraph': - # self.draw_pg() elif self.cfg_plot_mode == 'svg': self.draw_svg() elif self.cfg_plot_mode is None or self.cfg_plot_mode == 'None': @@ -337,8 +335,7 @@ def _generate_node_positions(self, node_positions : Optional[dict] = None): nodes=self.nodes() if node_positions is None: - node_positions = {} - + node_positions = {} def position_generator(N=10, centre=[0,5]): """ Generate circle of positions around centre """ idx=0 @@ -350,9 +347,8 @@ def position_generator(N=10, centre=[0,5]): positions=position_generator(len(nodes)) pos=dict([ (node, node_positions.get(node, next(positions)) ) for node in nodes] ) - return pos - - + return pos + def draw_mpl(self, ax=None): if ax is None: f, ax = plt.subplots() @@ -376,17 +372,6 @@ def _format_mpl_plot(ax): ax.set_xticks([]) ax.set_yticks([]) - # def draw_pg(self, DiGraphWindow=None): - # """ - # draws the graph using an interactive pyqtgraph window - # """ - # if DiGraphWindow is None: - # DiGraphWindow = self._DiGraphWindow - # self._DiGraphWindow = vis.draw_graph_pyqt( - # self, DiGraphWindow=DiGraphWindow, - # window_title=self.name) - # return self._DiGraphWindow - def draw_svg(self, filename: str=None): """ """ @@ -446,7 +431,7 @@ def set_node_description(self, node, description): def calibration_state(self): """ Return dictionary with current calibration state """ - return dict(self.node) + return dict(self.nodes) def _update_drawing_attrs(self): for node_name, node_attrs in self.nodes(True): diff --git a/examples/Example notebook.ipynb b/examples/Example notebook.ipynb index ad1b221..cbebb4f 100644 --- a/examples/Example notebook.ipynb +++ b/examples/Example notebook.ipynb @@ -18,16 +18,7 @@ "cell_type": "code", "execution_count": 1, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/Adriaan/anaconda/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n", - " from ._conv import register_converters as _register_converters\n" - ] - } - ], + "outputs": [], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", @@ -49,24 +40,47 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ - "test_graph.add_node?" + "cal_True_delayed= 'autodepgraph.node_functions.calibration_functions.test_calibration_True_delayed'\n", + "test_graph = AutoDepGraph_DAG('test graph')\n", + "for node in ['A', 'B', 'C', 'D', 'E']:\n", + " test_graph.add_node(node, \n", + " calibrate_function=cal_True_delayed)" ] }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "\u001b[0;31mSignature:\u001b[0m \u001b[0mtest_graph\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_node\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnode_for_adding\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mattr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mDocstring:\u001b[0m\n", + "Adds a node to the graph, including starting attributes.\n", + "\n", + "attr:\n", + " name (type) = default_value\n", + "\n", + " calibrate_function = 'NotImplementedCalibration'\n", + " check_functions = 'return_fixed_value'\n", + " tolerance (float) = 0\n", + " timeout (float) = np.inf\n", + " state (str) = 'unknown'\n", + "\u001b[0;31mFile:\u001b[0m ~/GitHubRepos/Personal/AutoDepGraph/autodepgraph/graph.py\n", + "\u001b[0;31mType:\u001b[0m method\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "cal_True_delayed= 'autodepgraph.node_functions.calibration_functions.test_calibration_True_delayed'\n", - "test_graph = AutoDepGraph_DAG('test graph')\n", - "for node in ['A', 'B', 'C', 'D', 'E']:\n", - " test_graph.add_node(node, \n", - " calibrate_function=cal_True_delayed)" + "test_graph.add_node?" ] }, { @@ -78,7 +92,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -108,16 +122,16 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "'/Users/Adriaan/GitHubRepos/DiCarloLab_Repositories/AutoDepGraph/autodepgraph/svg_viewer/adg_graph.svg'" + "'/Users/adriaanrol/GitHubRepos/Personal/AutoDepGraph/autodepgraph/svg_viewer/adg_graph.svg'" ] }, - "execution_count": 43, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -129,13 +143,100 @@ "test_graph.update_monitor()\n", "\n", "# Updating the monitor overwrites an svg file whose location is determined by the attribute:\n", - "test_graph.cfg_svg_filename\n", - "# This attribute can safely be overwritten" + "test_graph.cfg_svg_filename" ] }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "test graph\n", + "\n", + "\n", + "\n", + "A\n", + "\n", + "A\n", + "\n", + "\n", + "\n", + "B\n", + "\n", + "B\n", + "\n", + "\n", + "\n", + "B->A\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "C\n", + "\n", + "C\n", + "\n", + "\n", + "\n", + "C->A\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "C->B\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "D\n", + "\n", + "D\n", + "\n", + "\n", + "\n", + "D->A\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "E\n", + "\n", + "E\n", + "\n", + "\n", + "\n", + "E->D\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from IPython.display import display, SVG\n", + "display(SVG(test_graph.cfg_svg_filename))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, "metadata": { "scrolled": true }, @@ -144,7 +245,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "/Users/Adriaan/GitHubRepos/DiCarloLab_Repositories/AutoDepGraph/autodepgraph/svg_viewer/svgviewer-6t2tj5gh.html\n" + "/Users/adriaanrol/GitHubRepos/Personal/AutoDepGraph/autodepgraph/svg_viewer/svgviewer-etruszyd.html\n" ] } ], @@ -164,12 +265,12 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 8, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -194,7 +295,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -203,7 +304,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -225,14 +326,81 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/svg+xml": [ + "\n", + "\n", + "test graph\n", + "\n", + "\n", + "\n", + "A\n", + "\n", + "A\n", + "\n", + "\n", + "\n", + "B\n", + "\n", + "B\n", + "\n", + "\n", + "\n", + "B->A\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "C\n", + "\n", + "C\n", + "\n", + "\n", + "\n", + "C->A\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "C->B\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "D\n", + "\n", + "D\n", + "\n", + "\n", + "\n", + "D->A\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "E\n", + "\n", + "E\n", + "\n", + "\n", + "\n", + "E->D\n", + "\n", + "\n", + "\n", + "\n", + "" + ], "text/plain": [ - "
" + "" ] }, "metadata": {}, @@ -240,12 +408,12 @@ } ], "source": [ - "test_graph.draw_mpl()" + "display(SVG(test_graph.cfg_svg_filename))" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -255,7 +423,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -264,7 +432,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -288,7 +456,7 @@ "'good'" ] }, - "execution_count": 13, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -297,6 +465,93 @@ "test_graph.maintain_node('E')" ] }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "test graph\n", + "\n", + "\n", + "\n", + "A\n", + "\n", + "A\n", + "\n", + "\n", + "\n", + "B\n", + "\n", + "B\n", + "\n", + "\n", + "\n", + "B->A\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "C\n", + "\n", + "C\n", + "\n", + "\n", + "\n", + "C->A\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "C->B\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "D\n", + "\n", + "D\n", + "\n", + "\n", + "\n", + "D->A\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "E\n", + "\n", + "E\n", + "\n", + "\n", + "\n", + "E->D\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "display(SVG(test_graph.cfg_svg_filename))" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -309,7 +564,7 @@ }, { "cell_type": "code", - "execution_count": 59, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ @@ -318,6 +573,783 @@ "DAG = nx.readwrite.read_yaml(fn)" ] }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "q2 DAG\n", + "\n", + "\n", + "\n", + "3 qubit device multiplexed readout\n", + "\n", + "3 qubit device multiplexed readout\n", + "\n", + "\n", + "\n", + "q0 optimal weights\n", + "\n", + "q0 optimal weights\n", + "\n", + "\n", + "\n", + "3 qubit device multiplexed readout->q0 optimal weights\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 optimal weights\n", + "\n", + "q1 optimal weights\n", + "\n", + "\n", + "\n", + "3 qubit device multiplexed readout->q1 optimal weights\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 optimal weights\n", + "\n", + "q2 optimal weights\n", + "\n", + "\n", + "\n", + "3 qubit device multiplexed readout->q2 optimal weights\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 pulse amplitude med\n", + "\n", + "q0 pulse amplitude med\n", + "\n", + "\n", + "\n", + "q0 optimal weights->q0 pulse amplitude med\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 pulse amplitude med\n", + "\n", + "q1 pulse amplitude med\n", + "\n", + "\n", + "\n", + "q1 optimal weights->q1 pulse amplitude med\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 pulse amplitude med\n", + "\n", + "q2 pulse amplitude med\n", + "\n", + "\n", + "\n", + "q2 optimal weights->q2 pulse amplitude med\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "3 qubit device resonator frequencies coarse\n", + "\n", + "3 qubit device resonator frequencies coarse\n", + "\n", + "\n", + "\n", + "AWG8 Flux-staircase\n", + "\n", + "AWG8 Flux-staircase\n", + "\n", + "\n", + "\n", + "AWG8 MW-staircase\n", + "\n", + "AWG8 MW-staircase\n", + "\n", + "\n", + "\n", + "CZ q0-q1\n", + "\n", + "CZ q0-q1\n", + "\n", + "\n", + "\n", + "Chevron q0-q1\n", + "\n", + "Chevron q0-q1\n", + "\n", + "\n", + "\n", + "CZ q0-q1->Chevron q0-q1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 cryo dist. corr.\n", + "\n", + "q0 cryo dist. corr.\n", + "\n", + "\n", + "\n", + "CZ q0-q1->q0 cryo dist. corr.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 cryo dist. corr.\n", + "\n", + "q1 cryo dist. corr.\n", + "\n", + "\n", + "\n", + "CZ q0-q1->q1 cryo dist. corr.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Chevron q0-q1->3 qubit device multiplexed readout\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Chevron q0-q1->AWG8 Flux-staircase\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 gates restless\n", + "\n", + "q0 gates restless\n", + "\n", + "\n", + "\n", + "Chevron q0-q1->q0 gates restless\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 gates restless\n", + "\n", + "q1 gates restless\n", + "\n", + "\n", + "\n", + "Chevron q0-q1->q1 gates restless\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 cryo dist. corr.->q0 gates restless\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 room temp. dist. corr.\n", + "\n", + "q0 room temp. dist. corr.\n", + "\n", + "\n", + "\n", + "q0 cryo dist. corr.->q0 room temp. dist. corr.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 cryo dist. corr.->q1 gates restless\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 room temp. dist. corr.\n", + "\n", + "q1 room temp. dist. corr.\n", + "\n", + "\n", + "\n", + "q1 cryo dist. corr.->q1 room temp. dist. corr.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "CZ q1-q2\n", + "\n", + "CZ q1-q2\n", + "\n", + "\n", + "\n", + "CZ q1-q2->q1 cryo dist. corr.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Chevron q1-q2\n", + "\n", + "Chevron q1-q2\n", + "\n", + "\n", + "\n", + "CZ q1-q2->Chevron q1-q2\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 cryo dist. corr.\n", + "\n", + "q2 cryo dist. corr.\n", + "\n", + "\n", + "\n", + "CZ q1-q2->q2 cryo dist. corr.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Chevron q1-q2->3 qubit device multiplexed readout\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Chevron q1-q2->AWG8 Flux-staircase\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Chevron q1-q2->q0 gates restless\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Chevron q1-q2->q1 gates restless\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 gates restless\n", + "\n", + "q2 gates restless\n", + "\n", + "\n", + "\n", + "q2 cryo dist. corr.->q2 gates restless\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 room temp. dist. corr.\n", + "\n", + "q2 room temp. dist. corr.\n", + "\n", + "\n", + "\n", + "q2 cryo dist. corr.->q2 room temp. dist. corr.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 gates restless->q0 optimal weights\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 gates restless->q1 optimal weights\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 T1\n", + "\n", + "q0 T1\n", + "\n", + "\n", + "\n", + "q0 pulse amplitude coarse\n", + "\n", + "q0 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "q0 T1->q0 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 pulse amplitude coarse->AWG8 MW-staircase\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 frequency coarse\n", + "\n", + "q0 frequency coarse\n", + "\n", + "\n", + "\n", + "q0 pulse amplitude coarse->q0 frequency coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 mixer offsets drive\n", + "\n", + "q0 mixer offsets drive\n", + "\n", + "\n", + "\n", + "q0 pulse amplitude coarse->q0 mixer offsets drive\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 mixer offsets readout\n", + "\n", + "q0 mixer offsets readout\n", + "\n", + "\n", + "\n", + "q0 pulse amplitude coarse->q0 mixer offsets readout\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 mixer skewness drive\n", + "\n", + "q0 mixer skewness drive\n", + "\n", + "\n", + "\n", + "q0 pulse amplitude coarse->q0 mixer skewness drive\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 T2-echo\n", + "\n", + "q0 T2-echo\n", + "\n", + "\n", + "\n", + "q0 T2-echo->q0 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 T2-star\n", + "\n", + "q0 T2-star\n", + "\n", + "\n", + "\n", + "q0 T2-star->q0 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 room temp. dist. corr.->AWG8 Flux-staircase\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 resonator frequency\n", + "\n", + "q0 resonator frequency\n", + "\n", + "\n", + "\n", + "q0 frequency coarse->q0 resonator frequency\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 resonator frequency->3 qubit device resonator frequencies coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 frequency fine\n", + "\n", + "q0 frequency fine\n", + "\n", + "\n", + "\n", + "q0 frequency fine->q0 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q0 pulse amplitude med->q0 frequency fine\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 T1\n", + "\n", + "q1 T1\n", + "\n", + "\n", + "\n", + "q1 pulse amplitude coarse\n", + "\n", + "q1 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "q1 T1->q1 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 pulse amplitude coarse->AWG8 MW-staircase\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 frequency coarse\n", + "\n", + "q1 frequency coarse\n", + "\n", + "\n", + "\n", + "q1 pulse amplitude coarse->q1 frequency coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 mixer offsets drive\n", + "\n", + "q1 mixer offsets drive\n", + "\n", + "\n", + "\n", + "q1 pulse amplitude coarse->q1 mixer offsets drive\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 mixer offsets readout\n", + "\n", + "q1 mixer offsets readout\n", + "\n", + "\n", + "\n", + "q1 pulse amplitude coarse->q1 mixer offsets readout\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 mixer skewness drive\n", + "\n", + "q1 mixer skewness drive\n", + "\n", + "\n", + "\n", + "q1 pulse amplitude coarse->q1 mixer skewness drive\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 T2-echo\n", + "\n", + "q1 T2-echo\n", + "\n", + "\n", + "\n", + "q1 T2-echo->q1 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 T2-star\n", + "\n", + "q1 T2-star\n", + "\n", + "\n", + "\n", + "q1 T2-star->q1 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 room temp. dist. corr.->AWG8 Flux-staircase\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 resonator frequency\n", + "\n", + "q1 resonator frequency\n", + "\n", + "\n", + "\n", + "q1 frequency coarse->q1 resonator frequency\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 resonator frequency->3 qubit device resonator frequencies coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 frequency fine\n", + "\n", + "q1 frequency fine\n", + "\n", + "\n", + "\n", + "q1 frequency fine->q1 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q1 pulse amplitude med->q1 frequency fine\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 T1\n", + "\n", + "q2 T1\n", + "\n", + "\n", + "\n", + "q2 pulse amplitude coarse\n", + "\n", + "q2 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "q2 T1->q2 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 pulse amplitude coarse->AWG8 MW-staircase\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 frequency coarse\n", + "\n", + "q2 frequency coarse\n", + "\n", + "\n", + "\n", + "q2 pulse amplitude coarse->q2 frequency coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 mixer offsets drive\n", + "\n", + "q2 mixer offsets drive\n", + "\n", + "\n", + "\n", + "q2 pulse amplitude coarse->q2 mixer offsets drive\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 mixer offsets readout\n", + "\n", + "q2 mixer offsets readout\n", + "\n", + "\n", + "\n", + "q2 pulse amplitude coarse->q2 mixer offsets readout\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 mixer skewness drive\n", + "\n", + "q2 mixer skewness drive\n", + "\n", + "\n", + "\n", + "q2 pulse amplitude coarse->q2 mixer skewness drive\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 T2-echo\n", + "\n", + "q2 T2-echo\n", + "\n", + "\n", + "\n", + "q2 T2-echo->q2 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 T2-star\n", + "\n", + "q2 T2-star\n", + "\n", + "\n", + "\n", + "q2 T2-star->q2 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 gates restless->q2 optimal weights\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 room temp. dist. corr.->AWG8 Flux-staircase\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 resonator frequency\n", + "\n", + "q2 resonator frequency\n", + "\n", + "\n", + "\n", + "q2 frequency coarse->q2 resonator frequency\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 resonator frequency->3 qubit device resonator frequencies coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 frequency fine\n", + "\n", + "q2 frequency fine\n", + "\n", + "\n", + "\n", + "q2 frequency fine->q2 pulse amplitude coarse\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "q2 pulse amplitude med->q2 frequency fine\n", + "\n", + "\n", + "\n", + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "test_graph.cfg_plot_mode = 'svg'\n", + "DAG.update_monitor()\n", + "# This graph is so big, the html visualization is more suitable. \n", + "display(SVG(DAG.cfg_svg_filename))" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'/Users/adriaanrol/GitHubRepos/Personal/AutoDepGraph/autodepgraph/svg_viewer/svgviewer-6e8wz0xh.html'" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "url = test_graph.open_html_viewer()\n", + "url" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -328,7 +1360,7 @@ }, { "cell_type": "code", - "execution_count": 60, + "execution_count": 25, "metadata": {}, "outputs": [ { @@ -347,18 +1379,18 @@ " 'tolerance': 0}" ] }, - "execution_count": 60, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "DAG.node['CZ q0-q1']" + "DAG.nodes['CZ q0-q1']" ] }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 26, "metadata": {}, "outputs": [], "source": [ @@ -369,7 +1401,7 @@ }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 27, "metadata": {}, "outputs": [], "source": [ @@ -378,10 +1410,8 @@ }, { "cell_type": "code", - "execution_count": 58, - "metadata": { - "scrolled": false - }, + "execution_count": 28, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -528,9 +1558,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.8.5" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 }