• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Quang00 / dqsweep / 15299256377

28 May 2025 11:43AM UTC coverage: 85.15% (-0.2%) from 85.379%
15299256377

push

github

Quang00
fix build

625 of 734 relevant lines covered (85.15%)

2.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

53.97
/experiments/run_simulation.py
1
"""
2
Dqsweep
3
=======================================================
4

5
Overview:
6
---------
7
This script simulates distributed quantum experiments using a configurable
8
setup. It allows to sweep one or more parameters over defined ranges and then
9
execute multiple simulation runs in parallel for each parameter combination.
10
For every run, it calculates two performance metrics: the average fidelity
11
(as a percentage) and the average simulation time (in milliseconds).
12

13
Process:
14
--------
15
1. Parameter Sweep:
16
   - Generates all combinations of values for the specified parameters.
17
   - For each combination, it executes the simulation a certain amount of times
18
    which is configurable by the user and computes the mean fidelity and
19
    simulation time.
20

21
2. Data Generation:
22
   - Raw results and computed averages for each parameter combination are
23
    stored in a pandas DataFrame and saved as a CSV file.
24
   - Parameter–Performance Correlation txt file is provided and shows the
25
    correlations between the input parameters and the performance metrics.
26

27
3. Visualization:
28
   - 2D Heatmaps: These are generated for each performance metric based on
29
    each unique pair of swept parameters.
30

31
Usage:
32
------
33
Run the script with the following command-line arguments:
34

35
  --config         Path to the YAML config file that defines the network setup
36
  --experiment     Experiment to simulate (e.g., cnot, pingpong, dgrover2, ...)
37
  --epr_rounds     Number of EPR rounds per simulation
38
  --num_experiments Number of simulation runs per parameter combination
39
  --sweep_params   Comma-separated list of parameter names for the sweep.
40
  --ranges         For each swept parameter, provide a range in the format
41
                   "start,end,points", where start is the initial value, end
42
                   is the final value, and points is the number of values
43
                   (or steps) to generate between start and end.
44
  --output_dir     Directory where the CSV file, txt file and generated plots
45
                   will be saved.
46
"""
47

48
import argparse
3✔
49
import itertools
3✔
50
import os
3✔
51
from concurrent.futures import ProcessPoolExecutor
3✔
52
from functools import partial
3✔
53

54
import pandas as pd
3✔
55

56
from experiments.dgrover import GroverControl, GroverTarget
3✔
57
from experiments.dgrover_2 import AliceDGrover2, BobDGrover2
3✔
58
from experiments.dqft_2 import AliceDQFT2, BobDQFT2
3✔
59
from experiments.nonlocal_cnot_teledata import (
3✔
60
    Alice2Teleportations,
61
    Bob2Teleportations,
62
)
63
from experiments.nonlocal_cnot_telegate import AliceProgram, BobProgram
3✔
64
from experiments.nonlocal_toffoli import (
3✔
65
    AliceToffoli,
66
    BobToffoli,
67
    CharlieToffoli
68
)
69
from experiments.pingpong import (
3✔
70
    AlicePingpongTeleportation,
71
    BobPingpongTeleportation
72
)
73
from squidasm.run.stack.config import StackNetworkConfig
3✔
74
from utils.helper import (
3✔
75
    check_sweep_params_input,
76
    create_subdir,
77
    metric_correlation,
78
    parallelize_comb,
79
    parse_range,
80
)
81
from utils.plots import plot_combined_heatmaps
3✔
82

83

84
# =============================================================================
85
# Parameter Sweep Function
86
# =============================================================================
87
def sweep_parameters(
3✔
88
    cfg: StackNetworkConfig,
89
    rounds: int,
90
    num_experiments: int,
91
    sweep_params: list,
92
    ranges: list,
93
    experiment: str,
94
    output_dir: str,
95
) -> pd.DataFrame:
96
    """Performs a parameter sweep, runs simulations, and stores results.
97

98
    Args:
99
        cfg (StackNetworkConfig): Network configuration.
100
        rounds (int): Number of EPR rounds.
101
        num_experiments (int): Number of experiments per configuration.
102
        sweep_params (list): Parameters to sweep.
103
        ranges (list): Ranges for each parameter.
104
        experiment (str): Experiment name.
105
        output_dir (str): Directory to save results.
106

107
    Returns:
108
        pd.DataFrame: DataFrame of results.
109
    """
110
    os.makedirs(output_dir, exist_ok=True)
3✔
111

112
    # Parse parameter ranges.
113
    param_ranges = {
3✔
114
        param: parse_range(rng_str, param)
115
        for param, rng_str in zip(sweep_params, ranges, strict=False)
116
    }
117
    # Create all combinations of parameters.
118
    comb_list = list(
3✔
119
        itertools.product(*(param_ranges[param] for param in sweep_params))
120
    )
121

122
    # Map experiments to their program classes.
123
    experiment_map = {
3✔
124
        "cnot_teledata": (Alice2Teleportations, Bob2Teleportations),
125
        "dgrover": (GroverControl, GroverTarget),
126
        "dgrover2": (AliceDGrover2, BobDGrover2),
127
        "dqft2": (AliceDQFT2, BobDQFT2),
128
        "pingpong": (AlicePingpongTeleportation, BobPingpongTeleportation),
129
        "toffoli": (AliceToffoli, BobToffoli, CharlieToffoli),
130
    }
131
    classes = experiment_map.get(experiment, (AliceProgram, BobProgram))
3✔
132
    names = ["Alice", "Bob"] + (["Charlie"] if len(classes) > 2 else [])
3✔
133

134
    if experiment == "dgrover":
3✔
135
        peers = names[:-1]
×
136
        trgt_peer = names[-1]
×
137
        programs = {peer: GroverControl(trgt_peer, rounds) for peer in peers}
×
138
        programs[trgt_peer] = GroverTarget(peers, rounds)
×
139
        # TODO: Generalize to n qubits
140
        programs = {
×
141
            "Alice": GroverControl("Charlie", rounds),
142
            "Bob": GroverControl("Charlie", rounds),
143
            "Charlie": GroverTarget(["Alice", "Bob"], rounds),
144
        }
145
    else:
146
        programs = {
3✔
147
            name: cls(num_epr_rounds=rounds)
148
            for name, cls in zip(names, classes, strict=False)
149
        }
150

151
    func = partial(
3✔
152
        parallelize_comb,
153
        cfg=cfg,
154
        sweep_params=sweep_params,
155
        num_experiments=num_experiments,
156
        programs=programs,
157
    )
158

159
    # Use ProcessPoolExecutor to parallelize the combinations.
160
    with ProcessPoolExecutor() as executor:
3✔
161
        results = list(executor.map(func, comb_list))
3✔
162

163
    df = pd.DataFrame(results)
3✔
164
    csv_path = os.path.join(output_dir, f"{experiment}_results.csv")
3✔
165
    df.to_csv(csv_path, index=False)
3✔
166
    return df
3✔
167

168

169
def main():
3✔
170
    """Main entry point for the Distributed Quantum Experiments Script.
171

172
    This function launches the simulation, starting from the parsing
173
    command-line arguments to generating performance plots (Heat maps),
174
    raw results (csv file), and correlation analysis (txt file).
175

176
    """
177
    parser = argparse.ArgumentParser(
×
178
        description="Performance analysis of several distributed quantum"
179
        "computing experiments by sweeping given parameters."
180
    )
181
    parser.add_argument(
×
182
        "--config",
183
        type=str,
184
        default="configurations/perfect.yaml",
185
        help="Path to the configuration."
186
        "(Default: configurations/perfect.yaml)",
187
    )
188
    parser.add_argument(
×
189
        "--experiment",
190
        type=str,
191
        default="cnot",
192
        help="Distributed experiments (cnot_teledata, cnot_telegate,"
193
        "dgrover, dgrover2, dqft2, pingpong, toffoli...)."
194
        "(Default: cnot_teledata).",
195
    )
196
    parser.add_argument(
×
197
        "--epr_rounds",
198
        type=int,
199
        default=10,
200
        help="Number of EPR rounds. (Default: 10).",
201
    )
202
    parser.add_argument(
×
203
        "--num_experiments",
204
        type=int,
205
        default=10,
206
        help="Number of experiments per combination. (Default: 10).",
207
    )
208
    parser.add_argument(
×
209
        "--sweep_params",
210
        type=str,
211
        default="single_qubit_gate_depolar_prob,two_qubit_gate_depolar_prob",
212
        help="Comma-separated list of configuration parameter names to sweep."
213
        "(Default single_qubit_gate_depolar_prob,two_qubit_gate_depolar_prob)",
214
    )
215
    parser.add_argument(
×
216
        "--ranges",
217
        nargs="+",
218
        type=str,
219
        default=["0.0,0.8,10", "0.0,0.8,10"],
220
        help="One range string per parameter (format: 'start,end,points')."
221
        "(Default: \"0.0,0.8,10 \"0.0,0.8,10\")",
222
    )
223
    parser.add_argument(
×
224
        "--output_dir",
225
        type=str,
226
        default="results",
227
        help="Path to the output directory. (Default: results)"
228
    )
229
    args = parser.parse_args()
×
230

231
    output_dir = create_subdir(
×
232
        args.output_dir,
233
        args.experiment,
234
        args.sweep_params
235
    )
236
    print(f"Using output directory: {output_dir}")
×
237

238
    cfg = StackNetworkConfig.from_file(args.config)
×
239

240
    check_sweep_params_input(cfg, args.sweep_params)
×
241

242
    if args.sweep_params and args.ranges:
×
243
        # Ensure the number of parameters matches the number of ranges
244
        sweep_params = [p.strip() for p in args.sweep_params.split(",")]
×
245
        if len(sweep_params) != len(args.ranges):
×
246
            raise ValueError(
×
247
                "Number of sweep parameters must match number of range strings"
248
            )
249

250
        # Run parameter sweep and generate results
251
        df = sweep_parameters(
×
252
            cfg,
253
            args.epr_rounds,
254
            args.num_experiments,
255
            sweep_params,
256
            args.ranges,
257
            args.experiment,
258
            output_dir=output_dir,
259
        )
260
        print("Sweep completed. Preview of results:")
×
261
        print(df.head())
×
262

263
        # Generate a txt file with the correlation values
264
        metric_correlation(
×
265
            df,
266
            sweep_params,
267
            ["Average Fidelity", "Average Simulation Time (ms)"],
268
            output_dir,
269
            args.experiment,
270
        )
271

272
        # Build parameter range dictionary
273
        param_range_dict = {
×
274
            param: parse_range(rng_str, param)
275
            for param, rng_str in zip(sweep_params, args.ranges, strict=False)
276
        }
277

278
        # Generate heat maps for each metrics or a combined heat map
279
        plot_combined_heatmaps(
×
280
            df,
281
            sweep_params,
282
            param_range_dict,
283
            output_dir,
284
            args.experiment,
285
            args.epr_rounds,
286
            separate_files=True,
287
        )
288

289

290
if __name__ == "__main__":
3✔
291
    main()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc