<jupyter_start><jupyter_text>An example of how to run GST on a 2-qubit systemThis example gives an overview of the typical steps used to perform an end-to-end (i.e. experimental-data-to-report) Gate Set Tomography analysis on a 2-qubit system.  The steps are very similar to the single-qubit case described in the tutorials, but we thought 2Q-GST is an important enough topic to deserve a separate example.<jupyter_code>import pygsti<jupyter_output><empty_output><jupyter_text>Step 1: Construct the desired 2-qubit modelSince the purpose of this example is to show how to *run* 2Q-GST, we'll just use a built-in "standard" 2-qubit model.  (Another example covers how to create a custom 2-qubit model.)<jupyter_code>from pygsti.modelpacks import smq2Q_XYICNOT
target_model = smq2Q_XYICNOT.target_model()<jupyter_output><empty_output><jupyter_text>Step 2: create an experiment designAn experiment design is a object containing all the information needed to perform and later interpret the data from a set of circuits.  In the case of GST, lists of fiducial and germ sub-circuits are the building blocks of the circuits performed in the experiment. Typically, these lists are either provided by pyGSTi because you're using a "standard" model (as we are here), or computed using the "fiducial selection" and "germ selection" algorithms which are a part of pyGSTi and covered in the tutorials.  As an additional input, we'll need a list of lengths indicating the maximum length circuits to use on each successive GST iteration.  Since 2Q-GST can take a while, only use short sequences (`max_max_lengths=1`) with fiducial-pair reduction (`fpr=True`) to demonstrate 2Q-GST more quickly (because we know you have important stuff to do).<jupyter_code>exp_design = smq2Q_XYICNOT.create_gst_experiment_design(max_max_length=2, fpr=True)<jupyter_output><empty_output><jupyter_text>Step 3: Data generationNow that we have an experment design we can generate the list of experiments needed to run GST, just like in the 1-qubit case.<jupyter_code>#Create an empty dataset file at example_files/My2QExample/data/dataset.txt, which stores the
# list of experiments and zerod-out columns where data should be inserted.
pygsti.io.write_empty_protocol_data("example_files/My2QExample", exp_design, clobber_ok=True)
#Generate some "fake" (simulated) data based on a depolarized version of the target model.  In actual
# situations, you'd fill in dataset.txt with real data.
mdl_datagen = target_model.depolarize(op_noise=0.1, spam_noise=0.01)
pygsti.io.fill_in_empty_dataset_with_fake_data("example_files/My2QExample/data/dataset.txt",
                                               mdl_datagen, num_samples=1000, seed=2020)

# ---- NOTE: you can stop and restart the python session at this point; everything you need is saved to disk ---- 

#Load in the "data object" which packages together the dataset and experiment design
data = pygsti.io.read_data_from_dir("example_files/My2QExample")<jupyter_output><empty_output><jupyter_text>Step 4: Run GSTJust like for 1-qubit GST, we use the `StandardGST` protocol to compute the GST estimates.  Usually for two qubits this could take a long time (hours on a single cpu) based on the number of operation sequences used, and running on multiple processors is a good idea (see the MPI example).  Here, we set the tolerance to a high value ($10^{-3}$) so that it only takes around 30 minutes to run.Some notes about the options/arguments here that are particularly relevant to 2-qubit GST:  - `memlimit` gives an estimate of how much memory is available to use on your system (in bytes).  This is currently *not* a hard limit, and pyGSTi may require slightly more memory than this "limit".  So you'll need to be conservative in the value you place here: if your machine has 10GB of RAM, set this to 6 or 8 GB initially and increase it as you see how much memory is actually used using a separate OS performance monitor tool.  If you're running on multiple processors, this should be the memory available *per processor*.  - `verbosity` tells the routine how much detail to print to stdout.  If you don't mind waiting a while without getting any output, you can leave this at its default value (2).  If you can't standing wondering whether GST is still running or has locked up, set this to 3.<jupyter_code>import time
start = time.time()
protocol = pygsti.protocols.StandardGST("CPTP", optimizer={'tol': 1e-3}, verbosity=4)
results = protocol.run(data, memlimit=5*(1024)**3)
end = time.time()
print("Total time=%f hours" % ((end - start) / 3600.0))<jupyter_output><empty_output><jupyter_text>Step 5: Create report(s) using the returned `ModelEstimateResults` objectThe `ModelEstimateResults` object returned from `run` can be used to generate a "general" HTML report, just as in the 1-qubit case:<jupyter_code>report = pygsti.report.construct_standard_report(
    results, title="Example 2Q-GST Report", verbosity=2)
report.write_html('example_files/easy_2q_report', verbosity=2)<jupyter_output><empty_output><jupyter_text>Now open [example_files/easy_2q_report/main.html](example_files/easy_2q_report/main.html) to see the results.  You've run 2-qubit GST!You can save the `ModelEstimateResults` object to the same directory as the data and experiment design:<jupyter_code>results.write()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07133495600074892, 'fraction_numerical': 0.013480621606440741, 'mean_word_length': 5.204413472706156, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '452825', 'license': 'Apache-2.0', 'n_tokens_mistral': 1613, 'n_tokens_neox': 1512, 'n_words': 666, 'path': 'jupyter_notebooks/Examples/2QGST-RunningIt.ipynb', 'repo_name': 'maij/pyGSTi', 'size': '5341'}