Skip to content

Commit c03da87

Browse files
committed
Merge remote-tracking branch 'origin/main' into layout_and_route_disjoint_coupling_maps
2 parents f0a498e + eb4c5cb commit c03da87

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+629
-518
lines changed

.azure/lint-linux.yml

+5-4
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ jobs:
2121
python -m pip install --upgrade pip setuptools wheel virtualenv
2222
virtualenv test-job
2323
source test-job/bin/activate
24-
pip install -U -r requirements.txt -r requirements-dev.txt -c constraints.txt
25-
pip install -U -c constraints.txt -e .
26-
pip install -U "qiskit-aer" -c constraints.txt
27-
pip install -e .
24+
pip install -U \
25+
-c constraints.txt \
26+
-r requirements.txt \
27+
-r requirements-dev.txt \
28+
-e .
2829
displayName: 'Install dependencies'
2930
env:
3031
SETUPTOOLS_ENABLE_FEATURES: "legacy-editable"

.azure/test-linux.yml

+19-7
Original file line numberDiff line numberDiff line change
@@ -60,27 +60,37 @@ jobs:
6060
# Use stable Rust, rather than MSRV, to spot-check that stable builds properly.
6161
rustup override set stable
6262
source test-job/bin/activate
63-
pip install -U -r requirements.txt -r requirements-dev.txt -c constraints.txt
6463
# Install setuptools-rust for building sdist
6564
pip install -U -c constraints.txt setuptools-rust
6665
python setup.py sdist
67-
pip install -U -c constraints.txt dist/qiskit-terra*.tar.gz
66+
pip install -U \
67+
-c constraints.txt \
68+
-r requirements.txt \
69+
-r requirements-dev.txt \
70+
dist/qiskit-terra*.tar.gz
6871
displayName: "Install Terra from sdist"
6972
7073
- ${{ if eq(parameters.installFromSdist, false) }}:
7174
- bash: |
7275
set -e
7376
source test-job/bin/activate
74-
pip install -U -r requirements.txt -r requirements-dev.txt -c constraints.txt
75-
pip install -U -c constraints.txt -e .
77+
pip install -U \
78+
-c constraints.txt \
79+
-r requirements.txt \
80+
-r requirements-dev.txt \
81+
-e .
7682
displayName: "Install Terra directly"
7783
env:
7884
SETUPTOOLS_ENABLE_FEATURES: "legacy-editable"
7985
8086
- bash: |
8187
set -e
8288
source test-job/bin/activate
83-
pip install -U "cplex;python_version < '3.11'" "qiskit-aer" "z3-solver" -c constraints.txt
89+
pip install -U \
90+
-c constraints.txt \
91+
"cplex;python_version < '3.11'" \
92+
"qiskit-aer" \
93+
"z3-solver"
8494
mkdir -p /tmp/terra-tests
8595
cp -r test /tmp/terra-tests/.
8696
cp .stestr.conf /tmp/terra-tests/.
@@ -162,8 +172,10 @@ jobs:
162172
- bash: |
163173
set -e
164174
virtualenv image_tests
165-
image_tests/bin/pip install -U -r requirements.txt -c constraints.txt
166-
image_tests/bin/pip install -U -c constraints.txt -e ".[visualization]"
175+
image_tests/bin/pip install -U \
176+
-c constraints.txt \
177+
-r requirements.txt \
178+
-e ".[visualization]"
167179
sudo apt-get update
168180
sudo apt-get install -y graphviz pandoc
169181
image_tests/bin/pip check

.azure/test-macos.yml

+5-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@ jobs:
3434
python -m pip install --upgrade pip setuptools wheel virtualenv
3535
virtualenv test-job
3636
source test-job/bin/activate
37-
pip install -U -r requirements.txt -r requirements-dev.txt -c constraints.txt
38-
pip install -U -c constraints.txt -e .
37+
pip install -U \
38+
-c constraints.txt \
39+
-r requirements.txt \
40+
-r requirements-dev.txt \
41+
-e .
3942
pip check
4043
displayName: 'Install dependencies'
4144
env:

.azure/test-windows.yml

+6-3
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@ jobs:
3333
python -m pip install --upgrade pip setuptools wheel virtualenv
3434
virtualenv test-job
3535
source test-job/Scripts/activate
36-
pip install -r requirements.txt -r requirements-dev.txt -c constraints.txt
37-
pip install -c constraints.txt -e .
38-
pip install "z3-solver" -c constraints.txt
36+
pip install -U \
37+
-c constraints.txt \
38+
-r requirements.txt \
39+
-r requirements-dev.txt \
40+
"z3-solver" \
41+
-e .
3942
pip check
4043
displayName: 'Install dependencies'
4144
env:

.azure/tutorials-linux.yml

+14-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,20 @@ jobs:
2222
set -e
2323
git clone https://github.com/Qiskit/qiskit-tutorials --depth=1
2424
python -m pip install --upgrade pip
25-
pip install -U -r requirements.txt -r requirements-dev.txt -c constraints.txt
26-
pip install -c constraints.txt -e .
27-
pip install "qiskit-ibmq-provider" "qiskit-aer" "z3-solver" "networkx" "matplotlib>=3.3.0" sphinx nbsphinx sphinx_rtd_theme cvxpy -c constraints.txt
25+
pip install -U \
26+
-c constraints.txt \
27+
-r requirements.txt \
28+
-r requirements-dev.txt \
29+
"qiskit-ibmq-provider" \
30+
"qiskit-aer" \
31+
"z3-solver" \
32+
"networkx" \
33+
"matplotlib>=3.3.0" \
34+
sphinx \
35+
nbsphinx \
36+
sphinx_rtd_theme \
37+
cvxpy \
38+
-e .
2839
sudo apt-get update
2940
sudo apt-get install -y graphviz pandoc
3041
pip check

.mergify.yml

+1-15
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,5 @@
1-
queue_rules:
2-
- name: automerge
3-
conditions:
4-
- check-success=Qiskit.qiskit-terra
5-
1+
---
62
pull_request_rules:
7-
- name: automatic merge on CI success and review
8-
conditions:
9-
- check-success=Qiskit.qiskit-terra
10-
- "#approved-reviews-by>=1"
11-
- label=automerge
12-
- label!=on hold
13-
actions:
14-
queue:
15-
name: automerge
16-
method: squash
173
- name: backport
184
conditions:
195
- label=stable backport potential

azure-pipelines.yml

+8-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ trigger:
88
include:
99
- 'main'
1010
- 'stable/*'
11+
- 'gh-readonly-queue/*'
1112
tags:
1213
include:
1314
- '*'
@@ -126,8 +127,10 @@ stages:
126127
id: 7864
127128
comment: Nightly test job failed at commit $(Build.SourceVersion). View the logs at $(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId).
128129

129-
# Full PR suite.
130-
- ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
130+
# Full PR suite. This also needs to apply to the merge queue, which appears
131+
# as a push event. The queue won't get cron triggered because the schedule
132+
# trigger doesn't have it as a target.
133+
- ${{ if or(eq(variables['Build.Reason'], 'PullRequest'), contains(variables['Build.SourceBranch'], 'gh-readonly-queue')) }}:
131134
# The preliminary stage should be small in both total runtime (including
132135
# provisioning) and resources required. About half of PR commits result in
133136
# a CI failure, and over 90% of these are in linting, documention or a test
@@ -188,9 +191,9 @@ stages:
188191
parameters:
189192
pythonVersion: ${{ parameters.maximumPythonVersion }}
190193

191-
# Push to main or the stable branches. The triggering branches are set in the
192-
# triggers at the top of this file.
193-
- ${{ if and(eq(variables['Build.Reason'], 'IndividualCI'), startsWith(variables['Build.SourceBranch'], 'refs/heads/')) }}:
194+
# Push to main or the stable branches. The triggering branches also need to
195+
# be in the triggers at the top of this file.
196+
- ${{ if and(eq(variables['Build.Reason'], 'IndividualCI'), or(startsWith(variables['Build.SourceBranch'], 'refs/heads/main'), startsWith(variables['Build.SourceBranch'], 'refs/heads/stable/'))) }}:
194197
- stage: "Push"
195198
jobs:
196199
- template: ".azure/test-linux.yml"

crates/accelerate/src/dense_layout.rs

-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,6 @@ pub fn best_subset(
198198
.reduce(reduce_identity_fn, reduce_fn)
199199
} else {
200200
(0..coupling_shape[0])
201-
.into_iter()
202201
.map(map_fn)
203202
.reduce(reduce_fn)
204203
.unwrap()

crates/accelerate/src/euler_one_qubit_decomposer.rs

+46-25
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ fn circuit_kak(
155155
// NOTE: The following normalization is safe, because the gphase correction below
156156
// fixes a particular diagonal entry to 1, which prevents any potential phase
157157
// slippage coming from _mod_2pi injecting multiples of 2pi.
158-
lam = mod_2pi(lam);
158+
lam = mod_2pi(lam, atol);
159159
if lam.abs() > atol {
160160
circuit.push((String::from(k_gate), vec![lam]));
161161
global_phase += lam / 2.;
@@ -170,18 +170,18 @@ fn circuit_kak(
170170
lam -= phi;
171171
phi = 0.;
172172
}
173-
if mod_2pi(lam + PI).abs() < atol || mod_2pi(phi + PI).abs() < atol {
173+
if mod_2pi(lam + PI, atol).abs() < atol || mod_2pi(phi + PI, atol).abs() < atol {
174174
lam += PI;
175175
theta = -theta;
176176
phi += PI;
177177
}
178-
lam = mod_2pi(lam);
178+
lam = mod_2pi(lam, atol);
179179
if lam.abs() > atol {
180180
global_phase += lam / 2.;
181181
circuit.push((String::from(k_gate), vec![lam]));
182182
}
183183
circuit.push((String::from(a_gate), vec![theta]));
184-
phi = mod_2pi(phi);
184+
phi = mod_2pi(phi, atol);
185185
if phi.abs() > atol {
186186
global_phase += phi / 2.;
187187
circuit.push((String::from(k_gate), vec![phi]));
@@ -201,12 +201,12 @@ fn circuit_u3(
201201
atol: Option<f64>,
202202
) -> OneQubitGateSequence {
203203
let mut circuit = Vec::new();
204-
let phi = mod_2pi(phi);
205-
let lam = mod_2pi(lam);
206204
let atol = match atol {
207205
Some(atol) => atol,
208206
None => DEFAULT_ATOL,
209207
};
208+
let phi = mod_2pi(phi, atol);
209+
let lam = mod_2pi(lam, atol);
210210
if !simplify || theta.abs() > atol || phi.abs() > atol || lam.abs() > atol {
211211
circuit.push((String::from("u3"), vec![theta, phi, lam]));
212212
}
@@ -233,14 +233,20 @@ fn circuit_u321(
233233
atol = -1.0;
234234
}
235235
if theta.abs() < atol {
236-
let tot = mod_2pi(phi + lam);
236+
let tot = mod_2pi(phi + lam, atol);
237237
if tot.abs() > atol {
238238
circuit.push((String::from("u1"), vec![tot]));
239239
}
240240
} else if (theta - PI / 2.).abs() < atol {
241-
circuit.push((String::from("u2"), vec![mod_2pi(phi), mod_2pi(lam)]));
241+
circuit.push((
242+
String::from("u2"),
243+
vec![mod_2pi(phi, atol), mod_2pi(lam, atol)],
244+
));
242245
} else {
243-
circuit.push((String::from("u3"), vec![theta, mod_2pi(phi), mod_2pi(lam)]));
246+
circuit.push((
247+
String::from("u3"),
248+
vec![theta, mod_2pi(phi, atol), mod_2pi(lam, atol)],
249+
));
244250
}
245251
OneQubitGateSequence {
246252
gates: circuit,
@@ -264,8 +270,8 @@ fn circuit_u(
264270
if !simplify {
265271
atol = -1.0;
266272
}
267-
let phi = mod_2pi(phi);
268-
let lam = mod_2pi(lam);
273+
let phi = mod_2pi(phi, atol);
274+
let lam = mod_2pi(lam, atol);
269275
if theta.abs() > atol || phi.abs() > atol || lam.abs() > atol {
270276
circuit.push((String::from("u"), vec![theta, phi, lam]));
271277
}
@@ -323,7 +329,7 @@ where
323329
phi -= lam;
324330
lam = 0.;
325331
}
326-
if mod_2pi(lam + PI).abs() < atol || mod_2pi(phi).abs() < atol {
332+
if mod_2pi(lam + PI, atol).abs() < atol || mod_2pi(phi, atol).abs() < atol {
327333
lam += PI;
328334
theta = -theta;
329335
phi += PI;
@@ -338,7 +344,7 @@ where
338344
// emit circuit
339345
pfun(&mut circuit, lam);
340346
match xpifun {
341-
Some(xpifun) if mod_2pi(theta).abs() < atol => xpifun(&mut circuit),
347+
Some(xpifun) if mod_2pi(theta, atol).abs() < atol => xpifun(&mut circuit),
342348
_ => {
343349
xfun(&mut circuit);
344350
pfun(&mut circuit, theta);
@@ -372,9 +378,15 @@ fn circuit_rr(
372378
};
373379
}
374380
if (theta - PI).abs() > atol {
375-
circuit.push((String::from("r"), vec![theta - PI, mod_2pi(PI / 2. - lam)]));
376-
}
377-
circuit.push((String::from("r"), vec![PI, mod_2pi(0.5 * (phi - lam + PI))]));
381+
circuit.push((
382+
String::from("r"),
383+
vec![theta - PI, mod_2pi(PI / 2. - lam, atol)],
384+
));
385+
}
386+
circuit.push((
387+
String::from("r"),
388+
vec![PI, mod_2pi(0.5 * (phi - lam + PI), atol)],
389+
));
378390
OneQubitGateSequence {
379391
gates: circuit,
380392
global_phase: phase,
@@ -408,7 +420,7 @@ pub fn generate_circuit(
408420
inner_atol = -1.0;
409421
}
410422
let fnz = |circuit: &mut OneQubitGateSequence, phi: f64| {
411-
let phi = mod_2pi(phi);
423+
let phi = mod_2pi(phi, inner_atol);
412424
if phi.abs() > inner_atol {
413425
circuit.gates.push((String::from("p"), vec![phi]));
414426
}
@@ -438,7 +450,7 @@ pub fn generate_circuit(
438450
inner_atol = -1.0;
439451
}
440452
let fnz = |circuit: &mut OneQubitGateSequence, phi: f64| {
441-
let phi = mod_2pi(phi);
453+
let phi = mod_2pi(phi, inner_atol);
442454
if phi.abs() > inner_atol {
443455
circuit.gates.push((String::from("rz"), vec![phi]));
444456
circuit.global_phase += phi / 2.;
@@ -468,7 +480,7 @@ pub fn generate_circuit(
468480
inner_atol = -1.0;
469481
}
470482
let fnz = |circuit: &mut OneQubitGateSequence, phi: f64| {
471-
let phi = mod_2pi(phi);
483+
let phi = mod_2pi(phi, inner_atol);
472484
if phi.abs() > inner_atol {
473485
circuit.gates.push((String::from("u1"), vec![phi]));
474486
}
@@ -498,7 +510,7 @@ pub fn generate_circuit(
498510
inner_atol = -1.0;
499511
}
500512
let fnz = |circuit: &mut OneQubitGateSequence, phi: f64| {
501-
let phi = mod_2pi(phi);
513+
let phi = mod_2pi(phi, inner_atol);
502514
if phi.abs() > inner_atol {
503515
circuit.gates.push((String::from("rz"), vec![phi]));
504516
circuit.global_phase += phi / 2.;
@@ -608,11 +620,14 @@ pub fn compute_error_list(
608620
}
609621

610622
#[pyfunction]
623+
#[pyo3(signature = (unitary, target_basis_list, qubit, error_map=None, simplify=true, atol=None))]
611624
pub fn unitary_to_gate_sequence(
612625
unitary: PyReadonlyArray2<Complex64>,
613626
target_basis_list: Vec<&str>,
614627
qubit: usize,
615628
error_map: Option<&OneQubitGateErrorMap>,
629+
simplify: bool,
630+
atol: Option<f64>,
616631
) -> PyResult<Option<OneQubitGateSequence>> {
617632
const VALID_BASES: [&str; 12] = [
618633
"U321", "U3", "U", "PSX", "ZSX", "ZSXX", "U1X", "RR", "ZYZ", "ZXZ", "XYX", "XZX",
@@ -629,7 +644,7 @@ pub fn unitary_to_gate_sequence(
629644
.iter()
630645
.map(|target_basis| {
631646
let [theta, phi, lam, phase] = angles_from_unitary(unitary_mat, target_basis);
632-
generate_circuit(target_basis, theta, phi, lam, phase, true, None).unwrap()
647+
generate_circuit(target_basis, theta, phi, lam, phase, simplify, atol).unwrap()
633648
})
634649
.min_by(|a, b| {
635650
let error_a = compare_error_fn(a, &error_map, qubit);
@@ -649,12 +664,18 @@ fn complex_phase(x: Complex64) -> f64 {
649664
x.im.atan2(x.re)
650665
}
651666

667+
/// Wrap angle into interval [-π,π). If within atol of the endpoint, clamp to -π
652668
#[inline]
653-
fn mod_2pi(angle: f64) -> f64 {
669+
fn mod_2pi(angle: f64, atol: f64) -> f64 {
654670
// f64::rem_euclid() isn't exactly the same as Python's % operator, but because
655671
// the RHS here is a constant and positive it is effectively equivalent for
656672
// this case
657-
(angle + PI).rem_euclid(2. * PI) - PI
673+
let wrapped = (angle + PI).rem_euclid(2. * PI) - PI;
674+
if (wrapped - PI).abs() < atol {
675+
-PI
676+
} else {
677+
wrapped
678+
}
658679
}
659680

660681
fn params_zyz_inner(mat: ArrayView2<Complex64>) -> [f64; 4] {
@@ -722,8 +743,8 @@ fn params_xyx_inner(mat: ArrayView2<Complex64>) -> [f64; 4] {
722743
],
723744
]);
724745
let [theta, phi, lam, phase] = params_zyz_inner(mat_zyz.view());
725-
let new_phi = mod_2pi(phi + PI);
726-
let new_lam = mod_2pi(lam + PI);
746+
let new_phi = mod_2pi(phi + PI, 0.);
747+
let new_lam = mod_2pi(lam + PI, 0.);
727748
[
728749
theta,
729750
new_phi,

0 commit comments

Comments
 (0)