diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index d12dbc4d7..50938f161 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -1,8 +1,24 @@
-# Release 0.18.0 (current release)
+# Release 0.18.0-post1 (current release)
+
+
Documentation
+
+* References to the ``simulon`` simulator target have been rewritten to
+ ``simulon_gaussian`` to reflect changes made on the Xanadu Quantum Cloud. The
+ language has been modified to imply that multiple simulators could be
+ available on XQC.
+ [(#576)](https://github.com/XanaduAI/strawberryfields/pull/576)
+
+Contributors
+
+This release contains contributions from (in alphabetical order):
+
+Jeremy Swinarton.
+
+# Release 0.18.0
New features since last release
-* Adds the Bosonic backend, which can simulate states represented as linear
+* Adds the Bosonic backend, which can simulate states represented as linear
combinations of Gaussian functions in phase space.
[(#533)](https://github.com/XanaduAI/strawberryfields/pull/533)
[(#538)](https://github.com/XanaduAI/strawberryfields/pull/538)
@@ -10,14 +26,14 @@
[(#541)](https://github.com/XanaduAI/strawberryfields/pull/541)
[(#546)](https://github.com/XanaduAI/strawberryfields/pull/546)
[(#549)](https://github.com/XanaduAI/strawberryfields/pull/549)
-
- It can be regarded as a generalization of the Gaussian backend, since
- transformations on states correspond to modifications of the means and
- covariances of each Gaussian in the linear combination, along with changes to
- the coefficients of the linear combination. Example states that can be
- expressed using the new backend include all Gaussian, Gottesman-Kitaev-Preskill,
+
+ It can be regarded as a generalization of the Gaussian backend, since
+ transformations on states correspond to modifications of the means and
+ covariances of each Gaussian in the linear combination, along with changes to
+ the coefficients of the linear combination. Example states that can be
+ expressed using the new backend include all Gaussian, Gottesman-Kitaev-Preskill,
cat and Fock states.
-
+
```python
prog = sf.Program(1)
eng = sf.Engine('bosonic')
@@ -41,27 +57,27 @@
GKP states are qubits, with the qubit state defined by:
.. math:: \ket{\psi}\_{gkp} = \cos\frac{\theta}{2}\ket{0}\_{gkp} + e^{-i\phi}\sin\frac{\theta}{2}\ket{1}\_{gkp},
-
+
where the computational basis states are :math:`\ket{\mu}_{gkp} = \sum_{n} \ket{(2n+\mu)\sqrt{\pi\hbar}}_{q}`.
-
-* Adds the measurement-based squeezing gate `MSgate`; a new front-end operation
+
+* Adds the measurement-based squeezing gate `MSgate`; a new front-end operation
for the Bosonic backend.
[(#538)](https://github.com/XanaduAI/strawberryfields/pull/538)
[(#539)](https://github.com/XanaduAI/strawberryfields/pull/539)
[(#541)](https://github.com/XanaduAI/strawberryfields/pull/541)
-
- `MSgate` is an implementation of inline squeezing that can be performed by
- interacting the target state with an ancillary squeezed vacuum state at a
- beamsplitter, measuring the ancillary mode with homodyne, and then applying
- a feed-forward displacement. The channel is implemented either on average
- (as a Gaussian CPTP map) or in the single-shot implementation. If the
+
+ `MSgate` is an implementation of inline squeezing that can be performed by
+ interacting the target state with an ancillary squeezed vacuum state at a
+ beamsplitter, measuring the ancillary mode with homodyne, and then applying
+ a feed-forward displacement. The channel is implemented either on average
+ (as a Gaussian CPTP map) or in the single-shot implementation. If the
single-shot implementation is used, the measurement outcome of the ancillary
mode is stored in the results object.
-
+
```python
prog = sf.Program(1)
eng = sf.Engine('bosonic')
-
+
with prog.context as q:
sf.ops.Catstate(alpha=2) | q
r = 0.3
@@ -69,14 +85,14 @@
sf.ops.MSgate(r, phi=0, r_anc=1.2, eta_anc=1, avg=True) | q
# Single-shot map
sf.ops.MSgate(r, phi=0, r_anc=1.2, eta_anc=1, avg=False) | q
-
+
results = eng.run(prog)
ancilla_samples = results.ancilla_samples
-
+
xvec = np.arange(-5, 5, 0.01)
pvec = np.arange(-5, 5, 0.01)
wigner = results.state.wigner(0, xvec, pvec)
-
+
plt.contourf(xvec, pvec, wigner)
plt.show()
```
@@ -138,7 +154,7 @@
instead of the incorrect version number `1.0.0`.
[(#540)](https://github.com/XanaduAI/strawberryfields/pull/540)
-* TDM programs now expect a flat (not nested) dictionary of `modes` in device
+* TDM programs now expect a flat (not nested) dictionary of `modes` in device
specifications obtained from the XQC platform API.
[(#566)](https://github.com/XanaduAI/strawberryfields/pull/566)
@@ -165,7 +181,7 @@
This release contains contributions from (in alphabetical order):
J. Eli Bourassa, Guillaume Dauphinais, Ish Dhand, Theodor Isacsson, Josh Izaac,
-Leonhard Neuhaus, Nicolás Quesada, Aaron Robertson, Krishna Kumar Sabapathy,
+Leonhard Neuhaus, Nicolás Quesada, Aaron Robertson, Krishna Kumar Sabapathy,
Jeremy Swinarton, Antal Száva, Ilan Tzitrin.
# Release 0.17.0
diff --git a/doc/introduction/photonic_hardware.rst b/doc/introduction/photonic_hardware.rst
index 744a0fe79..a16b42e32 100644
--- a/doc/introduction/photonic_hardware.rst
+++ b/doc/introduction/photonic_hardware.rst
@@ -133,26 +133,31 @@ You can also omit the ``--output`` parameter to print the result to the screen.
Cloud simulator
---------------
-In addition to submitting jobs to be run on quantum hardware, it is also possible to run jobs on
-the Xanadu Quantum Cloud simulator Simulon. The process is very similar to running jobs on hardware. You
-will need to configure your account, as described above, and submit a job via the ``RemoteEngine``,
-using ``"simulon"`` as the target instead of a specific chip:
-
->>> eng = sf.RemoteEngine("simulon")
+In addition to submitting jobs to be run on quantum hardware, it is also
+possible to run jobs on cloud simulators (which we refer to as "simulons") via
+the Xanadu Quantum Cloud. The process is very similar to running jobs on
+hardware. You will need to configure your account, as described above, and
+submit a job via the ``RemoteEngine``, using a simulator as the target instead
+of a specific chip:
+
+>>> eng = sf.RemoteEngine("simulon_gaussian")
>>> result = eng.run(prog)
-Simulon jobs can also be submitted asynchronously using ``eng.run_async``, or by submitting a
-Blackbird script with the ``target`` set to ``simulon`` in the Blackbird header.
+Simulator jobs can also be submitted asynchronously using ``eng.run_async``, or
+by submitting a Blackbird script with the ``target`` set to a simulator target
+in the Blackbird header.
See the `Submitting jobs on hardware`_ section above for more details.
.. note::
- Simulon runs on the ``gaussian`` backend (see :ref:`simulating_your_program`) and thus only supports
- Gaussian operations, including homodyne and heterodyne measurements, as well terminal
- Fock measurements. Note that there are limits to how many measurements a circuit can have depending
- on the type of measurement. These can be retrieved by calling ``engine.device_spec.modes`` with
- ``engine = sf.RemoteEngine("simulon")``.
+ The ``simulon_gaussian`` simulator runs on the ``gaussian`` backend (see
+ :ref:`simulating_your_program`) and thus only supports Gaussian operations,
+ including homodyne and heterodyne measurements, as well terminal Fock
+ measurements. Note that there are limits to how many measurements a circuit
+ can have depending on the type of measurement. These can be retrieved by
+ calling ``engine.device_spec.modes`` with ``engine =
+ sf.RemoteEngine("simulon_gaussian")``.
Tutorials
---------
diff --git a/strawberryfields/_version.py b/strawberryfields/_version.py
index b53bcaaab..5493e7c92 100644
--- a/strawberryfields/_version.py
+++ b/strawberryfields/_version.py
@@ -16,4 +16,4 @@
Version number (major.minor.patch[-label])
"""
-__version__ = "0.18.0"
+__version__ = "0.18.0-post1"
diff --git a/strawberryfields/backends/gaussianbackend/gaussiancircuit.py b/strawberryfields/backends/gaussianbackend/gaussiancircuit.py
index 894da35ed..11e5f642a 100644
--- a/strawberryfields/backends/gaussianbackend/gaussiancircuit.py
+++ b/strawberryfields/backends/gaussianbackend/gaussiancircuit.py
@@ -77,7 +77,7 @@ def add_mode(self, n=1):
self.nlen = newnlen
def del_mode(self, modes):
- """ delete mode from the circuit"""
+ """delete mode from the circuit"""
if isinstance(modes, int):
modes = [modes]
@@ -110,7 +110,7 @@ def get_modes(self):
return [x for x in self.active if x is not None]
def displace(self, r, phi, i):
- """ Implements a displacement operation by the complex number `beta = r * np.exp(1j * phi)` in mode i"""
+ """Implements a displacement operation by the complex number `beta = r * np.exp(1j * phi)` in mode i"""
# Update displacement of mode i by the complex amount bet
if self.active[i] is None:
raise ValueError("Cannot displace mode, mode does not exist")
@@ -118,7 +118,7 @@ def displace(self, r, phi, i):
self.mean[i] += r * np.exp(1j * phi)
def squeeze(self, r, phi, k):
- """ Implements a squeezing operation in mode k by the amount z = r*exp(1j*phi)."""
+ """Implements a squeezing operation in mode k by the amount z = r*exp(1j*phi)."""
if self.active[k] is None:
raise ValueError("Cannot squeeze mode, mode does not exist")
@@ -158,7 +158,7 @@ def squeeze(self, r, phi, k):
self.mmat[:, k] = self.mmat[k]
def phase_shift(self, phi, k):
- """ Implements a phase shift in mode k by the amount phi."""
+ """Implements a phase shift in mode k by the amount phi."""
if self.active[k] is None:
raise ValueError("Cannot phase shift mode, mode does not exist")
@@ -181,7 +181,7 @@ def phase_shift(self, phi, k):
self.mmat[:, k] = self.mmat[k]
def beamsplitter(self, theta, phi, k, l):
- """ Implements a beam splitter operation between modes k and l by the amount theta, phi"""
+ """Implements a beam splitter operation between modes k and l by the amount theta, phi"""
if self.active[k] is None or self.active[l] is None:
raise ValueError("Cannot perform beamsplitter, mode(s) do not exist")
@@ -358,7 +358,7 @@ def fromscovmat(self, V, modes=None):
self.mmat[rows, cols] = 0.25 * (A - C + 1j * (B + Bt))
def qmat(self, modes=None):
- """ Construct the covariance matrix for the Q function"""
+ """Construct the covariance matrix for the Q function"""
if modes is None:
modes = list(range(self.nlen))
@@ -382,7 +382,7 @@ def qmat(self, modes=None):
return sigmaq
def fidelity_coherent(self, alpha, modes=None):
- """ Returns a function that evaluates the Q function of the given state """
+ """Returns a function that evaluates the Q function of the given state"""
if modes is None:
modes = list(range(self.nlen))
@@ -404,7 +404,7 @@ def fidelity_vacuum(self, modes=None):
return self.fidelity_coherent(alpha)
def Amat(self):
- """ Constructs the A matrix from Hamilton's paper"""
+ """Constructs the A matrix from Hamilton's paper"""
######### this needs to be conjugated
sigmaq = (
np.concatenate(
@@ -446,12 +446,12 @@ def thermal_loss(self, T, nbar, k):
self.nmat += (1 - T) * nbar
def init_thermal(self, population, mode):
- """ Initializes a state of mode in a thermal state with the given population"""
+ """Initializes a state of mode in a thermal state with the given population"""
self.loss(0.0, mode)
self.nmat[mode][mode] = population
def is_vacuum(self, tol=0.0):
- """ Checks if the state is vacuum by calculating its fidelity with vacuum """
+ """Checks if the state is vacuum by calculating its fidelity with vacuum"""
fid = self.fidelity_vacuum()
return np.abs(fid - 1) <= tol
@@ -495,7 +495,7 @@ def homodyne(self, n, shots=1, eps=0.0002):
return res
def post_select_homodyne(self, n, val, eps=0.0002):
- """ Performs a homodyne measurement but postelecting on the value vals for mode n """
+ """Performs a homodyne measurement but postelecting on the value vals for mode n"""
if self.active[n] is None:
raise ValueError("Cannot apply homodyne measurement, mode does not exist")
covmat = np.diag(np.array([eps ** 2, 1.0 / eps ** 2]))
@@ -517,7 +517,7 @@ def post_select_homodyne(self, n, val, eps=0.0002):
return val
def post_select_heterodyne(self, n, alpha_val):
- """ Performs a homodyne measurement but postelecting on the value vals for mode n """
+ """Performs a homodyne measurement but postelecting on the value vals for mode n"""
if self.active[n] is None:
raise ValueError("Cannot apply heterodyne measurement, mode does not exist")
@@ -539,7 +539,7 @@ def post_select_heterodyne(self, n, alpha_val):
return alpha_val
def apply_u(self, U):
- """ Transforms the state according to the linear optical unitary that maps a[i] \to U[i, j]^*a[j]"""
+ """Transforms the state according to the linear optical unitary that maps a[i] \to U[i, j]^*a[j]"""
self.mean = np.dot(np.conj(U), self.mean)
self.nmat = np.dot(np.dot(U, self.nmat), np.conj(np.transpose(U)))
self.mmat = np.dot(np.dot(np.conj(U), self.mmat), np.conj(np.transpose(U)))
diff --git a/tests/frontend/test_program.py b/tests/frontend/test_program.py
index f1125633a..f82e7b784 100644
--- a/tests/frontend/test_program.py
+++ b/tests/frontend/test_program.py
@@ -240,7 +240,7 @@ def test_assert_max_number_of_measurements(self, measure_op, measure_name):
},
"layout": None, "gate_parameters": {}, "compiler": [None]
}
- spec = sf.api.DeviceSpec(target="simulon", connection=None, spec=device_dict)
+ spec = sf.api.DeviceSpec(target="simulon_gaussian", connection=None, spec=device_dict)
prog = sf.Program(3)
with prog.context as q:
@@ -256,7 +256,7 @@ def test_assert_max_number_of_measurements_wrong_entry(self):
"""Check that the correct error is raised when calling `prog.assert_number_of_measurements`
with the incorrect type of device spec mode entry."""
device_dict = {"modes": 2, "layout": None, "gate_parameters": None, "compiler": [None]}
- spec = sf.api.DeviceSpec(target="simulon", connection=None, spec=device_dict)
+ spec = sf.api.DeviceSpec(target="simulon_gaussian", connection=None, spec=device_dict)
prog = sf.Program(3)
with prog.context as q:
@@ -500,7 +500,7 @@ class DummyCompiler(Compiler):
},
"layout": None, "gate_parameters": {}, "compiler": [None]
}
- spec = sf.api.DeviceSpec(target="simulon", connection=None, spec=device_dict)
+ spec = sf.api.DeviceSpec(target="simulon_gaussian", connection=None, spec=device_dict)
prog = sf.Program(3)
with prog.context as q: