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

Quang00 / dqsweep / 19392284119

15 Nov 2025 04:09PM UTC coverage: 85.007% (+0.09%) from 84.918%
19392284119

push

github

Quang00
generalize distributed grover

20 of 25 new or added lines in 2 files covered. (80.0%)

1 existing line in 1 file now uncovered.

635 of 747 relevant lines covered (85.01%)

2.55 hits per line

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

54.55
/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
from tqdm import tqdm
3✔
56

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

84

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

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

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

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

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

135
    if experiment == "dgrover":
3✔
NEW
136
        node_names = [stack.name for stack in cfg.stacks]
×
NEW
137
        control_peers = node_names[:-1]
×
NEW
138
        target_peer = node_names[-1]
×
NEW
139
        num_qubits = len(node_names)
×
140

UNCOV
141
        programs = {
×
142
            peer: GroverControl(target_peer, rounds, num_qubits)
143
            for peer in control_peers
144
        }
NEW
145
        programs[target_peer] = GroverTarget(
×
146
            control_peers, rounds, num_qubits
147
        )
148
    else:
149
        programs = {
3✔
150
            name: cls(num_epr_rounds=rounds)
151
            for name, cls in zip(names, classes, strict=False)
152
        }
153

154
    func = partial(
3✔
155
        parallelize_comb,
156
        cfg=cfg,
157
        sweep_params=sweep_params,
158
        num_experiments=num_experiments,
159
        programs=programs,
160
    )
161

162
    # Use ProcessPoolExecutor to parallelize the combinations.
163
    with ProcessPoolExecutor() as executor:
3✔
164
        iterator = executor.map(func, comb_list)
3✔
165
        results = list(
3✔
166
            tqdm(
167
                iterator,
168
                total=len(comb_list),
169
                desc="Parameter combinations",
170
            )
171
        )
172

173
    df = pd.DataFrame(results)
3✔
174
    csv_path = os.path.join(output_dir, f"{experiment}_results.csv")
3✔
175
    df.to_csv(csv_path, index=False)
3✔
176
    return df
3✔
177

178

179
def main():
3✔
180
    """Main entry point for the Distributed Quantum Experiments Script.
181

182
    This function launches the simulation, starting from the parsing
183
    command-line arguments to generating performance plots (Heat maps),
184
    raw results (csv file), and correlation analysis (txt file).
185

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

241
    output_dir = create_subdir(
×
242
        args.output_dir,
243
        args.experiment,
244
        args.sweep_params
245
    )
246
    print(f"Using output directory: {output_dir}")
×
247

248
    cfg = StackNetworkConfig.from_file(args.config)
×
249

250
    check_sweep_params_input(cfg, args.sweep_params)
×
251

252
    if args.sweep_params and args.ranges:
×
253
        # Ensure the number of parameters matches the number of ranges
254
        sweep_params = [p.strip() for p in args.sweep_params.split(",")]
×
255
        if len(sweep_params) != len(args.ranges):
×
256
            raise ValueError(
×
257
                "Number of sweep parameters must match number of range strings"
258
            )
259

260
        # Run parameter sweep and generate results
261
        df = sweep_parameters(
×
262
            cfg,
263
            args.epr_rounds,
264
            args.num_experiments,
265
            sweep_params,
266
            args.ranges,
267
            args.experiment,
268
            output_dir=output_dir,
269
        )
270
        print("Sweep completed. Preview of results:")
×
271
        print(df.head())
×
272

273
        # Generate a txt file with the correlation values
274
        metric_correlation(
×
275
            df,
276
            sweep_params,
277
            ["Average Fidelity", "Average Simulation Time (ms)"],
278
            output_dir,
279
            args.experiment,
280
        )
281

282
        # Build parameter range dictionary
283
        param_range_dict = {
×
284
            param: parse_range(rng_str, param)
285
            for param, rng_str in zip(sweep_params, args.ranges, strict=False)
286
        }
287

288
        # Generate heat maps for each metrics or a combined heat map
289
        plot_combined_heatmaps(
×
290
            df,
291
            sweep_params,
292
            param_range_dict,
293
            output_dir,
294
            args.experiment,
295
            args.epr_rounds,
296
            separate_files=True,
297
        )
298

299

300
if __name__ == "__main__":
3✔
301
    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