Skip to content
This repository has been archived by the owner on Dec 7, 2021. It is now read-only.

Fix probability Hessians with the parameter shift method. #1367

Merged
merged 209 commits into from
Nov 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
209 commits
Select commit Hold shift + click to select a range
93116e5
clean PR with the current gradient state
Cryoris Sep 22, 2020
e75af3b
Update derivatives_base.py
Zoufalc Sep 22, 2020
7d09fa0
Update hessian.py
Zoufalc Sep 22, 2020
612b897
Update test_grad.py
Zoufalc Sep 22, 2020
10a6f07
add notebooks
Zoufalc Sep 22, 2020
54f3728
Typing, Linting
Zoufalc Sep 22, 2020
4fac4a9
Update gradient_framework.ipynb
Zoufalc Sep 22, 2020
84876d2
Merge pull request #69 from OUF/cleanup-ouf
Zoufalc Sep 22, 2020
20ebdc1
typing qfi
Zoufalc Sep 22, 2020
770dfd8
enable gradients for VQAlgorithms
Zoufalc Sep 22, 2020
8cdc127
remove old files and notes
t-imamichi Sep 23, 2020
c3f715c
enfoce num chars <= 100
t-imamichi Sep 23, 2020
42db468
fix an import
t-imamichi Sep 23, 2020
b3e4791
re-adjust import
t-imamichi Sep 23, 2020
e3ad154
fix other imports
t-imamichi Sep 23, 2020
4ad34a4
Merge pull request #71 from IMAMICHI/del-old
Zoufalc Sep 23, 2020
c17cb76
Merge pull request #72 from IMAMICHI/num-chars-100
Zoufalc Sep 23, 2020
85728c9
additional base classes
Zoufalc Sep 23, 2020
1101b3d
test cases pass and the core logic all works. Doc strings could use a…
BryceFuller Sep 23, 2020
ea6e1cf
Merge pull request #73 from OUF/gradients_additional_base_classes
Cryoris Sep 24, 2020
e7357dd
Update derivatives_base.py (#75)
BryceFuller Sep 24, 2020
d03e6ce
update ordering/naming
Zoufalc Sep 24, 2020
e0f81d0
Merge branch 'qfi_reorg_ouf' into gradients
Zoufalc Sep 24, 2020
9cf4991
Merge pull request #78 from OUF/gradients
Zoufalc Sep 24, 2020
2663c1a
reshuffle, rename
Zoufalc Sep 24, 2020
d730cd3
add VQE gradient unittest
Zoufalc Sep 24, 2020
7e6857b
add notebook B2Meeting
Zoufalc Sep 24, 2020
c0e6fc6
Update gradient_framework_reduced.ipynb
Zoufalc Sep 24, 2020
f139b15
removed a leftover notebook file
BryceFuller Sep 24, 2020
2349170
removed the notebooks (and am pushing them to a cleaned up QGradients…
BryceFuller Sep 24, 2020
acccf89
Update gradient.py
BryceFuller Sep 24, 2020
c168791
will be deleted need this to pull sry
Zoufalc Sep 25, 2020
e1270e8
Merge branch 'qfi_reorg_ouf' of https://github.ibm.com/OUF/qiskit-aqu…
Zoufalc Sep 25, 2020
d686baa
fix qfi docstring
Zoufalc Sep 25, 2020
84f12c0
Add retworkx version check
Zoufalc Sep 25, 2020
6599ab7
delete notebooks, fixed seed fin_diff circSampler, fix kwargs import …
Zoufalc Sep 25, 2020
8e6f7ff
Delete test_natural_gradient.py
Zoufalc Sep 25, 2020
aa13e54
Merge pull request #79 from OUF/qfi_reorg_ouf
Zoufalc Sep 25, 2020
fbb66b4
Merge pull request #82 from OUF/SummedOp-tiny-fix
Zoufalc Sep 25, 2020
7a7499a
fix symbol map in parameter expression grad
Cryoris Sep 27, 2020
0a4b62c
typing
Zoufalc Sep 28, 2020
19a7ec5
Merge pull request #84 from OUF/fix-parameter-expressionn-grad
Zoufalc Sep 28, 2020
dee059d
Update qfi.py
Zoufalc Sep 28, 2020
8bb7b5b
Merge branch 'gradients' of https://github.ibm.com/OUF/qiskit-aqua-gr…
Zoufalc Sep 28, 2020
b78ede9
typing
Zoufalc Sep 28, 2020
2dc76cb
Update test_grad.py
Zoufalc Sep 28, 2020
374a3df
added a docstring to unroll_operator
BryceFuller Sep 28, 2020
82efc33
Update hessian.py
Zoufalc Sep 28, 2020
c26430f
Update gradient.py
Zoufalc Sep 28, 2020
b0f2cab
Fix statevector check (not always a QuantumInstance)
Zoufalc Sep 28, 2020
bd2bd60
Update hessian.py
Zoufalc Sep 28, 2020
6a85ae0
fix lint of qiskit/aqua/operators/gradients/*.py
t-imamichi Sep 30, 2020
c51474f
fix lint of qiskit/aqua/operators/gradients/circuit_gradients/*.py
t-imamichi Sep 30, 2020
c74011c
Merge pull request #85 from IMAMICHI/lint
Zoufalc Sep 30, 2020
a4994ad
Merge branch 'master' into gradients
Zoufalc Sep 30, 2020
fe21c08
fix lint of qiskit/aqua/operators/gradients/circuit_qfis/*.py
t-imamichi Sep 30, 2020
5bec965
fix test_grad
t-imamichi Sep 30, 2020
4cf1056
Merge branch 'master' into gradients
Cryoris Oct 5, 2020
cef7f67
Copy folder
Zoufalc Oct 5, 2020
24136cc
remove unknown aqua changes
Zoufalc Oct 5, 2020
3078bec
fix ListOp, VQAlgorithms for gradients
Zoufalc Oct 5, 2020
5b5f429
VQE Gradients import
Zoufalc Oct 5, 2020
d891a87
update operators init
Zoufalc Oct 6, 2020
1295b09
rm some changes not related to gradients
Cryoris Oct 6, 2020
5c02bbd
Merge branch 'master' into gradients
Cryoris Oct 6, 2020
d4a9171
mypy fixes
Zoufalc Oct 6, 2020
71673a0
Merge branch 'gradients' of https://github.com/Zoufalc/qiskit-aqua in…
Zoufalc Oct 6, 2020
45441af
skip jax test if not installed
Cryoris Oct 6, 2020
d920d95
try to fix cyclic import
Cryoris Oct 6, 2020
86a34d8
fix lint in isinstance
Cryoris Oct 6, 2020
e1240fb
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Cryoris Oct 6, 2020
4044fe6
uncomment vqe tests + consistent HAS_JAX
Cryoris Oct 6, 2020
1dcf237
mypy fixes
Zoufalc Oct 6, 2020
55bb2d0
Merge branch 'gradients' of https://github.com/Zoufalc/qiskit-aqua in…
Zoufalc Oct 6, 2020
f4a52c8
ignore mypy warning from opbase.coeff
Cryoris Oct 6, 2020
229e24b
fix isinstance used w/ typehints
Cryoris Oct 6, 2020
a40d9f4
try fixing sphinx
Cryoris Oct 6, 2020
266162b
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Cryoris Oct 6, 2020
50fea6b
ignore cases mypy doesn't understand correctly
Cryoris Oct 6, 2020
1ec656e
fix unnecessary else after raise
Cryoris Oct 6, 2020
a966dfc
Add jax to github actions
manoelmarques Oct 6, 2020
e2236c4
fix spell
manoelmarques Oct 6, 2020
f2f090b
add jax dependency to actions lint
manoelmarques Oct 6, 2020
c708a97
fix spell
manoelmarques Oct 6, 2020
ae197b8
Reduce VQE Iterations in unittest
Zoufalc Oct 6, 2020
2e93a96
Use ImportError
manoelmarques Oct 6, 2020
7f57359
fix lint
manoelmarques Oct 6, 2020
42bdb7e
Merge branch 'master' into gradients
manoelmarques Oct 6, 2020
e3eef9d
Add gradient framework release note
Zoufalc Oct 7, 2020
4a97765
update gradient framework release note
Zoufalc Oct 7, 2020
a6ebb44
fix reno formatting errors
manoelmarques Oct 7, 2020
c97df57
Merge branch 'master' into gradients
manoelmarques Oct 7, 2020
69d2dd2
Merge branch 'master' into gradients
manoelmarques Oct 8, 2020
0e57112
Merge branch 'master' into gradients
manoelmarques Oct 8, 2020
6ff35a2
Update to documentation
woodsp-ibm Oct 8, 2020
864e8d4
Fix doctring to avoid warnings
woodsp-ibm Oct 8, 2020
977bc7b
update gradient init
Zoufalc Oct 9, 2020
e4ecbc5
update qaoa docstring
Zoufalc Oct 9, 2020
a432a45
remover retworkx check
Zoufalc Oct 9, 2020
1a4a583
update docstrings
Zoufalc Oct 9, 2020
3a4873b
lint fixes
Zoufalc Oct 9, 2020
11fcb27
update docstrings to hint max_evals_grouped deprecation if gradient i…
Zoufalc Oct 9, 2020
6870291
Merge branch 'master' into gradients
manoelmarques Oct 9, 2020
ce98aea
Update test_grad.py
BryceFuller Oct 9, 2020
cec4e10
Update test_grad.py
BryceFuller Oct 9, 2020
ba6156b
Merge branch 'master' into gradients
manoelmarques Oct 10, 2020
68a8926
Update lin_comb circuit gradients to fix hessian evaluation
Zoufalc Oct 11, 2020
6161e94
Move renamed gradient test into operator file
Zoufalc Oct 12, 2020
b5541b8
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Zoufalc Oct 12, 2020
bfbaf70
update lin_comb
Zoufalc Oct 12, 2020
28fb923
update lin_comb gradients
Zoufalc Oct 12, 2020
ba488c1
Merge branch 'master' into gradients
manoelmarques Oct 12, 2020
567213f
fix lint
manoelmarques Oct 12, 2020
4fa540f
Merge branch 'master' into gradients
manoelmarques Oct 12, 2020
9383b01
fix lin_comb
Zoufalc Oct 12, 2020
7f62834
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Zoufalc Oct 12, 2020
6a4bc63
fixed the bugs that were causing Hessian logic to fail with custom co…
BryceFuller Oct 12, 2020
98c2141
Merge pull request #1 from BryceFuller/hessian_fix
BryceFuller Oct 12, 2020
acff66b
increase coverage of natural gradient
t-imamichi Oct 13, 2020
456585a
Merge branch 'gradients' of https://github.com/Zoufalc/qiskit-aqua in…
Zoufalc Oct 13, 2020
9cda697
merge zoufalc gradients
Zoufalc Oct 13, 2020
17eb613
try all combinations of grad_method and qfi_method
t-imamichi Oct 13, 2020
b81f659
style fix
Zoufalc Oct 13, 2020
3b12e99
updates for hessians
Zoufalc Oct 13, 2020
3c854df
remove redundant line
Zoufalc Oct 13, 2020
4b81ec3
Merge pull request #2 from BryceFuller/patch-1
Zoufalc Oct 13, 2020
cf2ee0a
make fixes
Zoufalc Oct 13, 2020
0c853b8
remove hessian from grad
Zoufalc Oct 13, 2020
6163a69
relax VQE test
Zoufalc Oct 13, 2020
9a44398
remove redundant lambda
Zoufalc Oct 13, 2020
f3e003f
fix identation
Zoufalc Oct 13, 2020
3e600bd
fix spelling
Zoufalc Oct 13, 2020
17ec1b5
fix whitespace
Zoufalc Oct 13, 2020
ee724b3
Merge branch 'master' of https://github.com/Qiskit/qiskit-aqua into g…
Zoufalc Oct 13, 2020
e954ab7
revert qfi_method in test_natural_gradient
t-imamichi Oct 14, 2020
0da3848
Merge remote-tracking branch 'ouf/gradients' into natgrad
t-imamichi Oct 14, 2020
e75f288
revert param name
t-imamichi Oct 14, 2020
4d4d097
fix lint
Zoufalc Oct 14, 2020
8de66fd
remove redundant comment
Zoufalc Oct 14, 2020
34c71bd
Merge pull request #3 from t-imamichi/natgrad
Zoufalc Oct 14, 2020
33b2f3f
update identation
Zoufalc Oct 14, 2020
2bc9705
fix np.random.seed
t-imamichi Oct 14, 2020
c7600e1
Merge pull request #4 from t-imamichi/fix_seed
Zoufalc Oct 14, 2020
2ddfbf4
Merge branch 'master' into gradients
manoelmarques Oct 14, 2020
b0242bb
Merge branch 'master' of https://github.com/Qiskit/qiskit-aqua into g…
Zoufalc Oct 14, 2020
f4c44b4
increase coverage for lin_comb
Zoufalc Oct 14, 2020
934806c
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Zoufalc Oct 14, 2020
244ab01
fix lint
Zoufalc Oct 14, 2020
aba315d
lint
Zoufalc Oct 14, 2020
8522248
whitespace fix
Zoufalc Oct 14, 2020
385b138
docstring
Zoufalc Oct 14, 2020
ab10176
lint
Zoufalc Oct 14, 2020
b4a1a94
disable misspelling
Zoufalc Oct 14, 2020
d7404b6
add yy, zz to pylintdict
Zoufalc Oct 14, 2020
a20f35d
Merge branch 'master' into gradients
woodsp-ibm Oct 14, 2020
56b3dc0
Update __init__.py
BryceFuller Oct 14, 2020
27e9a08
fixed linting
BryceFuller Oct 14, 2020
087d206
Merge branch 'master' into gradients
Cryoris Oct 14, 2020
31ee118
update init file
Zoufalc Oct 15, 2020
82d5bd1
Merge pull request #6 from BryceFuller/patch-2
Zoufalc Oct 15, 2020
22b5b07
fix spell
Zoufalc Oct 15, 2020
7212624
fix spelling
Zoufalc Oct 15, 2020
1e37cf7
remove redundant import
Zoufalc Oct 15, 2020
09062b2
attempt to fix sphinx #1
Cryoris Oct 15, 2020
a1b594a
Update qiskit/aqua/operators/gradients/qfi.py
Zoufalc Oct 15, 2020
2d81a0c
try to fix sphinx no.2
Cryoris Oct 15, 2020
0012562
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Cryoris Oct 15, 2020
b5fba08
Merge branch 'master' into gradients
Cryoris Oct 15, 2020
2377c57
add words to pylintdict
t-imamichi Oct 15, 2020
01a22c3
fix cryoris comments
Zoufalc Oct 15, 2020
6a54cb5
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Zoufalc Oct 15, 2020
cf8f5d8
Merge pull request #7 from t-imamichi/spell
Zoufalc Oct 15, 2020
5f90e12
Merge branch 'master' into gradients
Cryoris Oct 15, 2020
77c83fb
Update qiskit/aqua/operators/gradients/circuit_qfis/lin_comb_full.py
Zoufalc Oct 15, 2020
50cd6f5
Update qiskit/aqua/operators/gradients/circuit_qfis/lin_comb_full.py
Zoufalc Oct 15, 2020
7b42753
Update qiskit/aqua/operators/gradients/circuit_qfis/lin_comb_full.py
Zoufalc Oct 15, 2020
f43021f
cryoris comments
Zoufalc Oct 15, 2020
4b5664b
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Zoufalc Oct 15, 2020
d5a9e46
delete unneccessary
Zoufalc Oct 15, 2020
64f5c93
Update qiskit/aqua/operators/gradients/hessian.py
Zoufalc Oct 15, 2020
345a72f
raise warning hessians
Zoufalc Oct 15, 2020
b67b145
include docstring TypeError
Zoufalc Oct 15, 2020
5cd475b
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Zoufalc Oct 15, 2020
0c41a39
Update qiskit/aqua/operators/gradients/circuit_qfis/overlap_diag.py
Zoufalc Oct 15, 2020
80b0765
Update qiskit/aqua/operators/gradients/gradient.py
Zoufalc Oct 15, 2020
ee261d9
remove unnecessary os comment
Zoufalc Oct 15, 2020
b0a9c7d
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Zoufalc Oct 15, 2020
a117ba2
Update qiskit/aqua/operators/gradients/circuit_gradients/lin_comb.py
Zoufalc Oct 15, 2020
748967b
Insert proper Error
Zoufalc Oct 15, 2020
e6b47e5
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Zoufalc Oct 15, 2020
4974ea6
apply changes from code review
Cryoris Oct 15, 2020
2633cc1
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Cryoris Oct 15, 2020
67a5459
Merge branch 'master' into gradients
Cryoris Oct 15, 2020
99529d6
Merge branch 'master' into gradients
Cryoris Oct 15, 2020
95454d4
Merge branch 'master' of https://github.com/Qiskit/qiskit-aqua into g…
Zoufalc Oct 16, 2020
841a2c5
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Zoufalc Oct 16, 2020
2919e73
Fix probability hessians parameter shift
Zoufalc Oct 18, 2020
6b22890
Merge branch 'master' of https://github.com/Qiskit/qiskit-aqua into g…
Zoufalc Oct 18, 2020
a0dae7d
Merge branch 'master' of https://github.com/Qiskit/qiskit-aqua into g…
Zoufalc Oct 20, 2020
df6b3e1
Merge branch 'master' into gradients
woodsp-ibm Oct 22, 2020
e93517e
change type hint
Zoufalc Oct 25, 2020
a884bd8
update docstrings
Zoufalc Oct 25, 2020
f60609d
Merge branch 'gradients' of github.com:Zoufalc/qiskit-aqua into gradi…
Zoufalc Oct 25, 2020
13e77f2
fix typos
Zoufalc Oct 25, 2020
b25831b
Merge branch 'master' into gradients
woodsp-ibm Oct 26, 2020
20b4a3c
Merge branch 'master' into gradients
woodsp-ibm Oct 26, 2020
ad5c7a4
Merge branch 'master' into gradients
woodsp-ibm Nov 5, 2020
8a1920b
merge fix conflicts
manoelmarques Nov 27, 2020
d29c321
Merge branch 'master' into gradients
manoelmarques Nov 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 27 additions & 6 deletions qiskit/aqua/operators/gradients/circuit_gradients/param_shift.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,19 +197,24 @@ def _parameter_shift(self,

p_param = pshift_gate.params[param_index]
m_param = mshift_gate.params[param_index]

# For analytic gradients the circuit parameters are shifted once by +pi/2 and
# once by -pi/2.
if self.analytic:
shift_constant = 0.5
pshift_gate.params[param_index] = (p_param + (np.pi / (4 * shift_constant)))
mshift_gate.params[param_index] = (m_param - (np.pi / (4 * shift_constant)))
# For finite difference gradients the circuit parameters are shifted once by
# +epsilon and once by -epsilon.
else:
shift_constant = 1. / (2 * self._epsilon)
pshift_gate.params[param_index] = (p_param + self._epsilon)
mshift_gate.params[param_index] = (m_param - self._epsilon)

# The results of the shifted operators are now evaluated according the parameter
# shift / finite difference formula.
if isinstance(operator, ComposedOp):
shifted_op = shift_constant * (pshift_op - mshift_op)

# If the operator represents a quantum state then we apply a special combo
# function to evaluate probability gradients.
elif isinstance(operator, StateFn):
shifted_op = ListOp(
[pshift_op, mshift_op],
Expand Down Expand Up @@ -261,9 +266,16 @@ def get_primitives(item):
item = item.primitive.data
return item

if isinstance(x, Iterable):
is_statefn = False
if isinstance(x, list):
# Check if all items in x are a StateFn items
if all(isinstance(item, StateFn) for item in x):
is_statefn = True
items = [get_primitives(item) for item in x]
else:
# Check if x is a StateFn item
if isinstance(x, StateFn):
is_statefn = True
items = [get_primitives(x)]
if isinstance(items[0], dict):
prob_dict: Dict[str, float] = {}
Expand All @@ -273,8 +285,17 @@ def get_primitives(item):
shift_constant * ((-1) ** i) * prob_counts
return prob_dict
elif isinstance(items[0], Iterable):
return shift_constant * np.subtract(np.multiply(items[0], np.conj(items[0])),
np.multiply(items[1], np.conj(items[1])))
# If x was given as StateFn the state amplitudes need to be multiplied in order to
# evaluate the sampling probabilities which are then subtracted according to the
# parameter shift rule.
if is_statefn:
return shift_constant * np.subtract(np.multiply(items[0], np.conj(items[0])),
np.multiply(items[1], np.conj(items[1])))
# If x was not given as a StateFn the state amplitudes were already converted into
# sampling probabilities which are then only subtracted according to the
# parameter shift rule.
else:
return shift_constant * np.subtract(items[0], items[1])
raise TypeError(
'Probability gradients can only be evaluated from VectorStateFs or DictStateFns.')

Expand Down
49 changes: 35 additions & 14 deletions qiskit/aqua/operators/gradients/circuit_qfis/lin_comb_full.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,34 +63,42 @@ def convert(self,
phase_fix_observable = ~StateFn((X + 1j * Y) ^ (I ^ operator.num_qubits))
# see https://arxiv.org/pdf/quant-ph/0108146.pdf

# Check if the given operator corresponds to a quantum state given as a circuit.
if not isinstance(operator, CircuitStateFn):
raise TypeError(
'LinCombFull is only compatible with states that are given as CircuitStateFn')

# If a single parameter is given wrap it into a list.
if not isinstance(params, (list, np.ndarray)):
params = [params]
state_qc = operator.primitive

# First, the operators are computed which can compensate for a potential phase-mismatch
# between target and trained state, i.e.〈ψ|∂lψ〉
phase_fix_states = None
# Add working qubit
qr_work = QuantumRegister(1, 'work_qubit')
work_q = qr_work[0]
additional_qubits: Tuple[List[Qubit], List[Qubit]] = ([work_q], [])
# create a copy of the original state with an additional work_q register
for param in params:
# Get the gates of the given quantum state which are parameterized by param
param_gates = state_qc._parameter_table[param]
# Loop through the occurrences of param in the quantum state
for m, param_occurence in enumerate(param_gates):
# Get the coefficients and gates for the linear combination gradient for each
# occurrence, see e.g. https://arxiv.org/abs/2006.06004
coeffs_i, gates_i = LinComb._gate_gradient_dict(param_occurence[0])[
param_occurence[1]]
# Construct the quantum states which are then evaluated for the respective QFI
# element.
for k, gate_to_insert_i in enumerate(gates_i):
grad_state = state_qc.copy()
grad_state.add_register(qr_work)

# apply Hadamard on work_q
LinComb.insert_gate(grad_state, param_occurence[0], HGate(),
qubits=[work_q])
# Fix work_q phase
# Fix work_q phase such that the gradient is correct.
coeff_i = coeffs_i[k]
sign = np.sign(coeff_i)
is_complex = np.iscomplex(coeff_i)
Expand Down Expand Up @@ -141,17 +149,21 @@ def convert(self,
gate_to_insert_i,
additional_qubits=additional_qubits)

# Remove unnecessary gates.
grad_state = self.trim_circuit(grad_state, param_occurence[0])

# Apply the final Hadamard on the working qubit.
grad_state.h(work_q)

# Add the coefficient needed for the gradient as well as the original
# coefficient of the given quantum state.
state = np.sqrt(np.abs(coeff_i)) * operator.coeff * CircuitStateFn(grad_state)

# Chain Rule parameter expressions
# Check if the gate parameter corresponding to param is a parameter expression
gate_param = param_occurence[0].params[param_occurence[1]]
if gate_param == param:
state = phase_fix_observable @ state
else:
# If the gate parameter is a parameter expressions the chain rule needs
# to be taken into account.
if isinstance(gate_param, ParameterExpression):
expr_grad = DerivativeBase.parameter_expression_grad(gate_param, param)
state = (expr_grad * phase_fix_observable) @ state
Expand All @@ -161,38 +173,41 @@ def convert(self,
if m == 0 and k == 0:
phase_fix_state = state
else:
# Take the product rule into account
phase_fix_state += state
# Create a list for the phase fix states
if not phase_fix_states:
phase_fix_states = [phase_fix_state]
else:
phase_fix_states += [phase_fix_state]

# Get 4 * Re[〈∂kψ|∂lψ]
qfi_operators = []
# Add a working qubit
qr_work_qubit = QuantumRegister(1, 'work_qubit')
work_qubit = qr_work_qubit[0]
additional_qubits = ([work_qubit], [])
# create a copy of the original circuit with an additional work_qubit register
circuit = state_qc.copy()
circuit.add_register(qr_work_qubit)
# Apply a Hadamard on the working qubit
LinComb.insert_gate(circuit, state_qc._parameter_table[params[0]][0][0], HGate(),
qubits=[work_qubit])

# Get the circuits needed to compute〈∂iψ|∂jψ〉
for i, param_i in enumerate(params): # loop over parameters
qfi_ops = None
for j, param_j in enumerate(params):
# Construct the circuits
# Get the gates of the quantum state which are parameterized by param_i
param_gates_i = state_qc._parameter_table[param_i]
for m_i, param_occurence_i in enumerate(param_gates_i):
coeffs_i, gates_i = LinComb._gate_gradient_dict(param_occurence_i[0])[
param_occurence_i[1]]
# apply Hadamard on work_qubit

for k_i, gate_to_insert_i in enumerate(gates_i):
coeff_i = coeffs_i[k_i]
# Get the gates of the quantum state which are parameterized by param_j
param_gates_j = state_qc._parameter_table[param_j]

for m_j, param_occurence_j in enumerate(param_gates_j):
coeffs_j, gates_j = \
LinComb._gate_gradient_dict(param_occurence_j[0])[
Expand All @@ -204,7 +219,8 @@ def convert(self,
qfi_circuit = QuantumCircuit(*circuit.qregs)
qfi_circuit.data = circuit.data

# Fix work_qubit phase
# Correct the phase of the working qubit according to coefficient i
# and coefficient j
sign = np.sign(np.conj(coeff_i) * coeff_j)
is_complex = np.iscomplex(np.conj(coeff_i) * coeff_j)
if sign == -1:
Expand All @@ -230,7 +246,7 @@ def convert(self,
XGate(),
qubits=[work_qubit])

# Insert controlled, intercepting gate - controlled by |1>
# Insert controlled, intercepting gate i - controlled by |1>
if isinstance(param_occurence_i[0], UGate):
if param_occurence_i[1] == 0:
LinComb.insert_gate(
Expand Down Expand Up @@ -267,7 +283,7 @@ def convert(self,
qfi_circuit, gate_to_insert_i,
XGate(), qubits=[work_qubit], after=True)

# Insert controlled, intercepting gate - controlled by |0>
# Insert controlled, intercepting gate j - controlled by |0>
if isinstance(param_occurence_j[0], UGate):
if param_occurence_j[1] == 0:
LinComb.insert_gate(
Expand Down Expand Up @@ -310,21 +326,26 @@ def convert(self,
qfi_circuit = self.trim_circuit(
qfi_circuit, param_occurence_j[0]
)

# Apply final Hadamard gate
qfi_circuit.h(work_qubit)
# Convert the quantum circuit into a CircuitStateFn
# Convert the quantum circuit into a CircuitStateFn and add the
# coefficients i, j and the original operator coefficient
term = np.sqrt(np.abs(coeff_i) * np.abs(coeff_j)) * operator.coeff
term = term * CircuitStateFn(qfi_circuit)

# Chain Rule Parameter Expression
# Check if the gate parameters i and j are parameter expressions
gate_param_i = param_occurence_i[0].params[param_occurence_i[1]]
gate_param_j = param_occurence_j[0].params[param_occurence_j[1]]

meas = deepcopy(qfi_observable)
# If the gate parameter i is a parameter expression use the chain
# rule.
if isinstance(gate_param_i, ParameterExpression):
expr_grad = DerivativeBase.parameter_expression_grad(
gate_param_i, param_i)
meas *= expr_grad
# If the gate parameter j is a parameter expression use the chain
# rule.
if isinstance(gate_param_j, ParameterExpression):
expr_grad = DerivativeBase.parameter_expression_grad(
gate_param_j, param_j)
Expand Down
7 changes: 1 addition & 6 deletions qiskit/aqua/operators/gradients/hessian.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,7 @@ def is_coeff_c(coeff, c):

elif isinstance(operator, StateFn):
if not operator.is_measurement:
from .circuit_gradients import LinComb
if isinstance(self.hess_method, LinComb):
return self.hess_method.convert(operator, params)
else:
raise TypeError('Please set the attribute hess_method to ´lin_comb´ to compute '
'probability Hessians.')
return self.hess_method.convert(operator, params)

else:
raise TypeError('The computation of Hessians is only supported for Operators which '
Expand Down
9 changes: 8 additions & 1 deletion qiskit/aqua/operators/gradients/natural_gradient.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,22 +91,29 @@ def convert(self,
'CircuitStateFn.')
if not isinstance(params, Iterable):
params = [params]
# Instantiate the gradient
grad = Gradient(self._grad_method, epsilon=self._epsilon).convert(operator, params)
# Instantiate the QFI metric which is used to re-scale the gradient
metric = self._qfi_method.convert(operator[-1], params) * 0.25

# Define the function which compute the natural gradient from the gradient and the QFI.
def combo_fn(x):
c = np.real(x[0])
a = np.real(x[1])
if self.regularization:
# If a regularization method is chosen then use a regularized solver to
# construct the natural gradient.
nat_grad = NaturalGradient._regularized_sle_solver(
a, c, regularization=self.regularization)
else:
try:
# Try to solve the system of linear equations Ax = C.
nat_grad = np.linalg.solve(a, c)
except np.linalg.LinAlgError: # singular matrix
nat_grad = np.linalg.lstsq(a, c)[0]
return np.real(nat_grad)

# Define the ListOp which combines the gradient and the QFI according to the combination
# function defined above.
return ListOp([grad, metric], combo_fn=combo_fn)

@property
Expand Down
5 changes: 3 additions & 2 deletions test/aqua/operators/test_gradients.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,8 @@ def test_prob_grad(self, method):
np.testing.assert_array_almost_equal(prob_grad_result,
correct_values[i][j], decimal=1)

def test_prob_hess_lin_comb(self):
@data('lin_comb', 'param_shift', 'fin_diff')
def test_prob_hess(self, method):
"""Test the probability Hessian using linear combination of unitaries method

d^2p0/da^2 = - sin(a)sin(b) / 2
Expand All @@ -488,7 +489,7 @@ def test_prob_hess_lin_comb(self):

op = CircuitStateFn(primitive=qc, coeff=1.)

prob_hess = Hessian(hess_method='lin_comb').convert(operator=op, params=params)
prob_hess = Hessian(hess_method=method).convert(operator=op, params=params)
values_dict = [{a: np.pi / 4, b: 0}, {a: np.pi / 4, b: np.pi / 4},
{a: np.pi / 2, b: np.pi}]
correct_values = [[[0, 0], [1 / (2 * np.sqrt(2)), - 1 / (2 * np.sqrt(2))]],
Expand Down