Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into sabre-layout-rust
Browse files Browse the repository at this point in the history
  • Loading branch information
mtreinish committed Nov 21, 2022
2 parents 87f7a57 + b82a89d commit 488c447
Show file tree
Hide file tree
Showing 90 changed files with 1,467 additions and 585 deletions.
8 changes: 8 additions & 0 deletions .azure/lint-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,25 @@ jobs:
- bash: |
set -e
source test-job/bin/activate
echo "Running black, any errors reported can be fixed with 'tox -eblack'"
black --check qiskit test tools examples setup.py
echo "Running rustfmt check, any errors reported can be fixed with 'cargo fmt'"
cargo fmt --check
displayName: "Formatting"
- bash: |
set -e
source test-job/bin/activate
echo "Running pylint"
pylint -rn qiskit test tools
echo "Running Cargo Clippy"
cargo clippy -- -D warnings
echo "Running license header check"
tools/verify_headers.py qiskit test
echo "Running check for optional imports on bare 'import qiskit'"
python tools/find_optional_imports.py
echo "Running check for release notes in incorrect directories"
tools/find_stray_release_notes.py
echo "Running reno lint"
reno lint
displayName: 'Lint'
37 changes: 25 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ name = "qiskit_accelerate"
crate-type = ["cdylib"]

[dependencies]
rayon = "1.5"
rayon = "1.6"
numpy = "0.17.2"
rand = "0.8"
rand_pcg = "0.3"
rand_distr = "0.4.3"
ahash = "0.8.0"
num-complex = "0.4"
num-bigint = "0.4"
retworkx-core = "0.11"
rustworkx-core = "0.12"

[dependencies.pyo3]
version = "0.17.3"
features = ["extension-module", "hashbrown", "num-complex", "num-bigint"]
features = ["extension-module", "hashbrown", "num-complex", "num-bigint", "indexmap"]

[dependencies.ndarray]
version = "^0.15.6"
Expand All @@ -33,7 +33,7 @@ version = "0.12.3"
features = ["rayon"]

[dependencies.indexmap]
version = "1.9.1"
version = "1.7"
features = ["rayon"]

[profile.release]
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Qiskit Terra
[![License](https://img.shields.io/github/license/Qiskit/qiskit-terra.svg?style=popout-square)](https://opensource.org/licenses/Apache-2.0)<!--- long-description-skip-begin -->[![Build Status](https://img.shields.io/travis/com/Qiskit/qiskit-terra/master.svg?style=popout-square)](https://travis-ci.com/Qiskit/qiskit-terra)[![Release](https://img.shields.io/github/release/Qiskit/qiskit-terra.svg?style=popout-square)](https://github.com/Qiskit/qiskit-terra/releases)[![Downloads](https://img.shields.io/pypi/dm/qiskit-terra.svg?style=popout-square)](https://pypi.org/project/qiskit-terra/)[![Coverage Status](https://coveralls.io/repos/github/Qiskit/qiskit-terra/badge.svg?branch=main)](https://coveralls.io/github/Qiskit/qiskit-terra?branch=main)[![Minimum rustc 1.56.1](https://img.shields.io/badge/rustc-1.56.1+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)<!--- long-description-skip-end -->
[![License](https://img.shields.io/github/license/Qiskit/qiskit-terra.svg?style=popout-square)](https://opensource.org/licenses/Apache-2.0)<!--- long-description-skip-begin -->[![Release](https://img.shields.io/github/release/Qiskit/qiskit-terra.svg?style=popout-square)](https://github.com/Qiskit/qiskit-terra/releases)[![Downloads](https://img.shields.io/pypi/dm/qiskit-terra.svg?style=popout-square)](https://pypi.org/project/qiskit-terra/)[![Coverage Status](https://coveralls.io/repos/github/Qiskit/qiskit-terra/badge.svg?branch=main)](https://coveralls.io/github/Qiskit/qiskit-terra?branch=main)[![Minimum rustc 1.56.1](https://img.shields.io/badge/rustc-1.56.1+-blue.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)<!--- long-description-skip-end -->

**Qiskit** is an open-source framework for working with noisy quantum computers at the level of pulses, circuits, and algorithms.

Expand Down
2 changes: 2 additions & 0 deletions qiskit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
sys.modules["qiskit._accelerate.results"] = qiskit._accelerate.results
sys.modules["qiskit._accelerate.optimize_1q_gates"] = qiskit._accelerate.optimize_1q_gates
sys.modules["qiskit._accelerate.sampled_exp_val"] = qiskit._accelerate.sampled_exp_val
sys.modules["qiskit._accelerate.vf2_layout"] = qiskit._accelerate.vf2_layout
sys.modules["qiskit._accelerate.error_map"] = qiskit._accelerate.error_map


# Extend namespace for backwards compat
Expand Down
65 changes: 55 additions & 10 deletions qiskit/algorithms/gradients/finite_diff_estimator_gradient.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from __future__ import annotations

import sys
from typing import Sequence

import numpy as np
Expand All @@ -28,29 +29,55 @@
from .base_estimator_gradient import BaseEstimatorGradient
from .estimator_gradient_result import EstimatorGradientResult

if sys.version_info >= (3, 8):
# pylint: disable=no-name-in-module, ungrouped-imports
from typing import Literal
else:
from typing_extensions import Literal


class FiniteDiffEstimatorGradient(BaseEstimatorGradient):
"""
Compute the gradients of the expectation values by finite difference method.
"""

def __init__(self, estimator: BaseEstimator, epsilon: float, options: Options | None = None):
"""
def __init__(
self,
estimator: BaseEstimator,
epsilon: float,
options: Options | None = None,
*,
method: Literal["central", "forward", "backward"] = "central",
):
r"""
Args:
estimator: The estimator used to compute the gradients.
epsilon: The offset size for the finite difference gradients.
options: Primitive backend runtime options used for circuit execution.
The order of priority is: options in ``run`` method > gradient's
default options > primitive's default setting.
Higher priority setting overrides lower priority setting
method: The computation method of the gradients.
- ``central`` computes :math:`\frac{f(x+e)-f(x-e)}{2e}`,
- ``forward`` computes :math:`\frac{f(x+e) - f(x)}{e}`,
- ``backward`` computes :math:`\frac{f(x)-f(x-e)}{e}`
where :math:`e` is epsilon.
Raises:
ValueError: If ``epsilon`` is not positive.
TypeError: If ``method`` is invalid.
"""
if epsilon <= 0:
raise ValueError(f"epsilon ({epsilon}) should be positive.")
self._epsilon = epsilon
self._base_parameter_values_dict = {}
if method not in ("central", "forward", "backward"):
raise TypeError(
f"The argument method should be central, forward, or backward: {method} is given."
)
self._method = method
super().__init__(estimator, options)

def _run(
Expand All @@ -74,12 +101,25 @@ def _run(
metadata_.append({"parameters": [circuit.parameters[idx] for idx in indices]})

offset = np.identity(circuit.num_parameters)[indices, :]
plus = parameter_values_ + self._epsilon * offset
minus = parameter_values_ - self._epsilon * offset
n = 2 * len(indices)
job = self._estimator.run(
[circuit] * n, [observable] * n, plus.tolist() + minus.tolist(), **options
)
if self._method == "central":
plus = parameter_values_ + self._epsilon * offset
minus = parameter_values_ - self._epsilon * offset
n = 2 * len(indices)
job = self._estimator.run(
[circuit] * n, [observable] * n, plus.tolist() + minus.tolist(), **options
)
elif self._method == "forward":
plus = parameter_values_ + self._epsilon * offset
n = len(indices) + 1
job = self._estimator.run(
[circuit] * n, [observable] * n, [parameter_values_] + plus.tolist(), **options
)
elif self._method == "backward":
minus = parameter_values_ - self._epsilon * offset
n = len(indices) + 1
job = self._estimator.run(
[circuit] * n, [observable] * n, [parameter_values_] + minus.tolist(), **options
)
jobs.append(job)

# combine the results
Expand All @@ -90,8 +130,13 @@ def _run(

gradients = []
for result in results:
n = len(result.values) // 2 # is always a multiple of 2
gradient_ = (result.values[:n] - result.values[n:]) / (2 * self._epsilon)
if self._method == "central":
n = len(result.values) // 2 # is always a multiple of 2
gradient_ = (result.values[:n] - result.values[n:]) / (2 * self._epsilon)
elif self._method == "forward":
gradient_ = (result.values[1:] - result.values[0]) / self._epsilon
elif self._method == "backward":
gradient_ = (result.values[0] - result.values[1:]) / self._epsilon
gradients.append(gradient_)
opt = self._get_local_options(options)
return EstimatorGradientResult(gradients=gradients, metadata=metadata_, options=opt)
Loading

0 comments on commit 488c447

Please sign in to comment.