quantumlib / qsim Goto Github PK
View Code? Open in Web Editor NEWSchrödinger and Schrödinger-Feynman simulators for quantum circuits.
License: Apache License 2.0
Schrödinger and Schrödinger-Feynman simulators for quantum circuits.
License: Apache License 2.0
There are a couple of discrepancies between the Bazel- and Makefile-driven builds of qsim - most recently, we found that input files referenced by Bazel require a different relative address than when building with Make.
One possible solution to this is to fully migrate off of Make and require all users to build qsim with Bazel. The goal of this issue is to collect feedback on this proposal; we have not yet decided on this migration.
qsimcirq does not support passing a cirq circuit, and instead requires passing a QSimCircuit instead. This is poor user experience because the user needs to change their code when using qsimcirq instead of the native cirq simulators.
Program:
q0 = cirq.GridQubit(0, 0)
q1 = cirq.GridQubit(1, 0)
def basic_circuit(meas=False):
sqrt_x = cirq.X**0.5
yield sqrt_x(q0), sqrt_x(q1)
yield cirq.CZ(q0, q1)
yield sqrt_x(q0), sqrt_x(q1)
if meas:
yield cirq.measure(q0, key='q0'), cirq.measure(q1, key='q1')
circuit = cirq.Circuit()
circuit.append(basic_circuit())
print("Ciruit:")
print(circuit)
import qsimcirq
qsimulator = qsimcirq.QSimSimulator()
qsim_result = qsimulator.simulate(circuit)
Output:
ValueError Traceback (most recent call last)
in ()
40
41 #qsim_result = qsimulator.simulate(program = qsim_circuit)
---> 42 qsim_result = qsimulator.simulate(circuit)
43
44 #qsim_result = qsimulator.compute_amplitudes(program = qsim_circuit,
1 frames
/usr/local/lib/python3.6/dist-packages/qsimcirq/qsim_simulator.py in simulate_sweep(self, program, params, qubit_order, initial_state)
138 """
139 if not isinstance(program, qsimc.QSimCircuit):
--> 140 raise ValueError('{!r} is not a QSimCircuit'.format(program))
141
142 options = {}
ValueError: cirq.Circuit([
cirq.Moment(operations=[
(cirq.X0.5).on(cirq.GridQubit(0, 0)),
(cirq.X0.5).on(cirq.GridQubit(1, 0)),
]),
cirq.Moment(operations=[
cirq.CZ.on(cirq.GridQubit(0, 0), cirq.GridQubit(1, 0)),
]),
cirq.Moment(operations=[
(cirq.X0.5).on(cirq.GridQubit(0, 0)),
(cirq.X0.5).on(cirq.GridQubit(1, 0)),
]),
]) is not a QSimCircuit
While this issue is raised, we should also add a doc for how to perform the release process - including permissions required and any extra tests above and beyond the CI suite that should be run.
@iamvamsikrishnad, could you look into this? If I understand correctly, getting the versions to match will require a new release (i.e. v0.0.3).
Originally posted by @95-martin-orion in #57 (comment)
Named return-value optimization (NRVO) is a form of copy elision. In C++17 this optimization is mandatory, allowing sections like the following to return types with a deleted copy constructor:
Lines 41 to 48 in 9708283
However, prior to C++17 this was not the case. In order to compile successfully on C++11, we must update the snippet above to avoid NRVO. Given that this section is I/O-only (i.e. not in the hot path), some performance reduction is acceptable.
As highlighted in #40, the QSimSimulator only supports an all-zero initial state. To fix this, we should inject the necessary X gates at the start of the circuit when a non-zero initial state is requested.
I am trying to install qsim on a linux machine. I did
mkdir build && cd build && cmake3 ..
which successfully ran. However, running
make
in the root directory produces the above error logs. I am not an experienced C++ user, please bear with me if this is a stupid question. Thank you!
In order to represent quantum teleportation, error correction, and other algorithms, qsim must support classical control. There are three key parts to this feature:
(case, gate)
mapping, apply the gate whose case
matches the input, if one exists).qsim/qsimcirq/qsim_simulator.py
Line 25 in 24a9af4
The dostring states "This method returns a result which allows access to the entire wave function". But it doesn't really. The returned SimulationTrialResult
hides the final state in a private _final_simulator_state
variable.
The array returned in SimulationTrialResult._final_simulator_state
seems to be too large by a factor of 2, as if a qubit is being added somewhere.
The object in SimulationTrialResult._final_simulator_state
is a numpy array, which causes SimulationTrialResult.qubit_map
to fail.
The initial_state
method parameter is silently ignored. It does does seem possible to set the initial state.
The test test_cirq_qsim_simulate_fullstate
does not test any properties of the final fullstate.
One additional note - after installing via the pypi package, I had issues with the following script:
import qsimcirq
test = qsimcirq.qsim_simulator.QSimSimulator()
# fails with "qsimcirq has no attribute 'qsim_simulator'"
Oddly, importing the submodule with from qsimcirq
worked just fine:
from qsimcirq import qsim_simulator as qss
test = qss.QSimSimulator()
# no error
Originally posted by @95-martin-orion in #18 (comment)
This interface allows access to intermediate states as the circuit is simulated moment-by-moment. See https://github.com/quantumlib/Cirq/blob/720ea341b0082dc0cbbfb0142c161f01d8edca3e/cirq/sim/simulator.py#L258.
How difficult would this be?
Highlighted in #90 - currently the CI config explicitly specifies --config=avx
, meaning it will only test the AVX build process. We need to include SSE and basic builds as well.
Outline what should be in the documentation.
For users interested in analyzing circuit unitaries, we should provide the ability to convert an N-qubit circuit to its 2^N x 2^N unitary form. This is required for feature parity with the TFQ variant of qsim.
Qsimh sometimes gives empty output, seemingly on small circuits:
import numpy as np
import cirq
from cirq.experiments import (
random_rotations_between_grid_interaction_layers_circuit)
import qsimcirq
qsim_simulator = qsimcirq.QSimSimulator()
qsimh_options = {'k': [0], 'w': 0, 'p': 1, 'r': 1}
qsimh_simulator = qsimcirq.QSimhSimulator(qsimh_options)
a = cirq.LineQubit(0)
circuit = cirq.Circuit(
cirq.X(a)**0.5
)
qsim_circuit = qsimcirq.QSimCircuit(circuit)
bitstrings = ['0', '1']
qsim_amplitudes = qsim_simulator.compute_amplitudes(qsim_circuit, bitstrings)
qsimh_amplitudes = qsimh_simulator.compute_amplitudes(qsim_circuit, bitstrings)
print('Circuit:')
print(circuit)
print()
print(f'Qsim amplitudes: {qsim_amplitudes}')
print(f'Qsimh amplitudes: {qsimh_amplitudes}')
Output:
Circuit:
0: ───X^0.5───
Qsim amplitudes: [(0.5+0.5j), (0.5-0.5j)]
Qsimh amplitudes: []
When Qsimh does produce output (I seem to have to make the circuit big enough for this to happen), it is incorrect:
def optimized_for_qsim(circuit: cirq.Circuit):
optimized_circuit = cirq.Circuit()
for op in circuit.all_operations():
if isinstance(op.gate, cirq.PhasedXPowGate):
optimized_circuit.append(cirq.decompose(op))
else:
optimized_circuit.append(op)
return optimized_circuit
qubits = cirq.GridQubit.square(2)
circuit = random_rotations_between_grid_interaction_layers_circuit(
qubits=qubits, depth=3, seed=1234)
circuit = optimized_for_qsim(circuit)
qsim_circuit = qsimcirq.QSimCircuit(circuit)
bitstrings = ['0000', '0001']
qsim_amplitudes = qsim_simulator.compute_amplitudes(qsim_circuit, bitstrings)
qsimh_amplitudes = qsimh_simulator.compute_amplitudes(qsim_circuit, bitstrings)
print('Circuit:')
print(circuit)
print()
print(f'Qsim amplitudes: {qsim_amplitudes}')
print(f'Qsimh amplitudes: {qsimh_amplitudes}')
cirq.testing.assert_allclose_up_to_global_phase(np.array(qsim_amplitudes),
np.array(qsimh_amplitudes),
atol=1e-5)
Output:
Circuit:
┌────┐ ┌────────┐
(0, 0): ───T^-1────X^0.5───T────────SYC──────X^0.5───────T^-1────X^0.5───T───────Y^0.5──────────────────────
│
(0, 1): ───Y^0.5───T^-1────X^0.5────┼──T──────────SYC────X^0.5───Y^0.5──────────────────────────────────────
│ │
(1, 0): ───X^0.5────────────────────SYC──────T^-1─┼──────X^0.5───T───────X^0.5───SYC─────T^-1───X^0.5───T───
│ │
(1, 1): ───X^0.5───T^-1────X^0.5────T─────────────SYC────X^0.5───────────────────SYC─────T^-1───X^0.5───T───
└────┘ └────────┘
Qsim amplitudes: [(0.22928695380687714-0.1546979546546936j), (0.0881662517786026+0.3213808536529541j)]
Qsimh amplitudes: [(0.12853418290615082+0.01285102590918541j), (-0.031721945852041245+0.05422064661979675j)]
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-2-fc37687fd8cd> in <module>
25 cirq.testing.assert_allclose_up_to_global_phase(np.array(qsim_amplitudes),
26 np.array(qsimh_amplitudes),
---> 27 atol=1e-5)
~/Projects/Cirq/cirq/testing/lin_alg_utils.py in assert_allclose_up_to_global_phase(actual, desired, rtol, atol, equal_nan, err_msg, verbose)
193 equal_nan=equal_nan,
194 err_msg=err_msg,
--> 195 verbose=verbose)
/usr/lib/python3/dist-packages/numpy/testing/_private/utils.py in assert_allclose(actual, desired, rtol, atol, equal_nan, err_msg, verbose)
1501 header = 'Not equal to tolerance rtol=%g, atol=%g' % (rtol, atol)
1502 assert_array_compare(compare, actual, desired, err_msg=str(err_msg),
-> 1503 verbose=verbose, header=header, equal_nan=equal_nan)
1504
1505
/usr/lib/python3/dist-packages/numpy/testing/_private/utils.py in assert_array_compare(comparison, x, y, err_msg, verbose, header, precision, equal_nan, equal_inf)
827 verbose=verbose, header=header,
828 names=('x', 'y'), precision=precision)
--> 829 raise AssertionError(msg)
830 except ValueError:
831 import traceback
AssertionError:
Not equal to tolerance rtol=1e-07, atol=1e-05
Mismatch: 100%
Max absolute difference: 0.27085387
Max relative difference: 4.31169146
x: array([ 0.276594-2.775558e-17j, -0.10666 +3.157253e-01j])
y: array([ 0.129175+1.734723e-18j, -0.02617 +5.710753e-02j])
Could this be due to the options passed to the initialization of the Qsimh simulator? I just copied the options from https://github.com/quantumlib/qsim/blob/master/docs/cirq_interface.md; I don't know what they mean and I can't find their documentation.
If a Cirq circuit is passed into qsim with measurement at the end of the circuit, qsim fails to recognize the measurement gate. If the measurement gates are removed, then the everything works.
Program:
q0 = cirq.GridQubit(0, 0)
q1 = cirq.GridQubit(1, 0)
def basic_circuit(meas=True):
sqrt_x = cirq.X**0.5
yield sqrt_x(q0), sqrt_x(q1)
yield cirq.CZ(q0, q1)
yield sqrt_x(q0), sqrt_x(q1)
if meas:
yield cirq.measure(q0, key='q0'), cirq.measure(q1, key='q1')
circuit = cirq.Circuit()
circuit.append(basic_circuit())
print("Ciruit:")
print(circuit)
from cirq import Simulator
simulator = Simulator()
waveFunctionResult = simulator.simulate(circuit)
print("Results:")
print(waveFunctionResult)
print(np.around(waveFunctionResult.final_state, 3))
#probabilityAmplitudeResults = simulator.compute_amplitudes(program = circuit, bitstrings=['00', '01', '10', '11'])
#print("Probability Results:")
#print(probabilityAmplitudeResults)
import qsimcirq
qsim_circuit = qsimcirq.QSimCircuit(cirq_circuit=circuit)
qsimulator = qsimcirq.QSimSimulator()
qsim_result = qsimulator.simulate(program = qsim_circuit)
#qsim_result = qsimulator.compute_amplitudes(program = qsim_circuit,
print("Results:")
print(qsim_result)
Output :
ValueError Traceback (most recent call last)
in ()
41 qsimulator = qsimcirq.QSimSimulator()
42
---> 43 qsim_result = qsimulator.simulate(program = qsim_circuit)
44
45 #qsim_result = qsimulator.compute_amplitudes(program = qsim_circuit,
2 frames
/usr/local/lib/python3.6/dist-packages/qsimcirq/qsim_circuit.py in translate_cirq_to_qsim(self, qubit_order)
130 qsim_gate = "id2"
131 else:
--> 132 raise ValueError("{!r} No translation for ".format(op))
133
134 # The moment is missing
ValueError: cirq.MeasurementGate(1, 'q0', ()).on(cirq.GridQubit(0, 0)) No translation for
Hi,
We added qsim to quantum simulator benchmark: https://github.com/quantastica/quantum-simulator-benchmark
Goal is to compare quantum simulator algorithms and see how different simulators performs with single shot, one circuit at a time, 1...X qubits.
Currently, we are running QFT algorithm only, but plan is to add more circuits in near future.
Now, we would like to know if we are running qsim correctly, so if someone is willing to review our code, that is great.
qsim related code can be found here:
code which creates QFT algorithm in qsim native format: https://github.com/quantastica/quantum-simulator-benchmark/blob/master/benchmark_qft.py#L77-L94
and code which executes simulation: https://github.com/quantastica/quantum-simulator-benchmark/blob/master/benchmark_qft.py#L191-L219
Results performed on Google Cloud n1-standard-8
node shows following:
Thank you!
This will help users identify qsim when searching for it on Github.
(Assigned to @dabacon as only a repository owner can change the description)
There are currently a bunch of gates that core qsim supports in gates_cirq.h
that are not being translated from Cirq. We need to surface this support so that users have access to it.
Some nice features to have for qsim might be:
Prior to release, all documentation should be reviewed for consistency with the current state of the code. Any example code in documentation (e.g. scripts, sample qsim
/qsimh
invocations) must be verified to work as written, such that a new user can copy-paste them directly into their shell and run without modifying the command.
qsim and qsimh should be able to run on OSX, Linux, and Windows, at a minimum. We need to check the behavior on each platform and document any extra steps required.
If providing full support for a platform is not feasible prior to release, we should verify that Docker works as expected for that platform and provide instructions in the docs.
This would facilitating running cirq circuits with qsim. In principle, with all-to-all connectivity, you can always remove the SWAP gates from the circuit and relabel qubits. But I don't think there is an easy way of doing that in cirq.
Many links on the qsimcirq pypi page are broken. See for example the link to docs about input format.
We may also want to link to the quantum supremacy dataset, especially if the files there are compatible with qsimcirq (fileformats used there are described in the enclosed README file).
(Not sure this is the right place to file.)
Need to put together a colab showing how to use Cirq and qsim together.
Right now both external and internal qsim simulator and statespace objects make use of structs with static templated methods in order to provide parallelization support. For example: https://github.com/quantumlib/qsim/blob/master/lib/parfor.h . In order for TensorFlow Quantum to finish transitioning over to this version of qsim from the one we had originally adapted we need to write our own struct that defines the static methods Run
and RunReduce
that make use of Tensorflow's threadpool.
Unfortunately unlike OpenMP, TF Threads are not global state that you can immediately use with some kind of #pragma
. The way TensorFlow works is that when a C++ op is called it is supplied some portion of TensorFlow's available threads at call time. It is then our job to give these threads work to do. The problem is that because these threads are supplied to a local function at call time we can't make use of a global state and can't have our Run
and RunReduce
be truly static. I have tried some alternative like this:
struct ParallelForTFQ {
static tensorflow::OpKernelContext* context = <pointer containing thread info resolved at call time>
template <typename Function, typename... Args>
static void Run(
unsigned num_threads, uint64_t size, Function&& func, Args&&... args) {
context->run(func (etc etc))
}
Which had not let to much success because TFQ might have many instances of a qsim powered op running at once competing for and overwriting the context
resource (digging into writing a resource lock compatible with TF threadpool isn't something I think we want to do either).
With all of this in mind I'm proposing that we move from templating the type of the XXXFOR struct we want a simulator and statespace to use, to instead supplying instances of the XXXFOR struct to the methods that require it. This would mean instead of doing something like:
For::Run(stuff)
We would do
<Template typename for_runner>
... my_function(const for_runner& for_obj, ...., ... ) {
.
.
.
for_obj.Run(stuff)
This seems like a simple way to allow one to incorporate the amount of local/object state needed for parallelization with TensorFlow. What do you @sergeisakov and @95-martin-orion think ? (This is a blocking issue for TFQ to transition over to this version of qsim)
As discussed offline, installing pybind11 as part of the pip install qsimcirq
process may be driving the installation time way up. This is especially true for the Docker install test, where the Docker image must install git
in order to install qsimcirq.
To remedy this, we should instead require that users install pybind11 on their system and add documentation explaining this requirement.
Currently, operations on intermediate states are supported by the times_to_measure_at
parameter in qsim.Run
. This is flexible, but may lack some functionality required for general-purpose intermediate state operations. This issue tracks the investigation of possible improvements to this use case.
I'm working on a generator for qsim circuits, and for certain gates that qsim does not support it decomposes the gate into a sequence that qsim does support. If there are other gates running at the same time, this can create out-of-order gates in the file, e.g.:
# one input gate
0 rxy 0 0.5 0.25
1 rz 0 0.5
# another input gate
0 cp 1 2 0.75
Is this allowed in qsim or not? Either way, can we update input_format.md
to clarify this for users?
(I have no preference for whether we should support this or not - if it's currently not allowed, I can refactor my generator code.)
The docs refer to a file called qsim_test.py
, which does not appear to exist. The link goes nowhere.
Related issues: #62 (Rx vs XPow gates), #48 (SWAP gate).
In order to consistently translate Cirq gates to qsim without increasing circuit depth, we should define gates (or extend existing gates) to replicate every gate type in Cirq. As noted in #62, global phase should be taken into consideration for this.
@iamvamsikrishnad: It seems like the package on test.pypi
needs to be updated - when running qsimcirq_test.py
from a Docker image, I'm seeing the following error:
qsim-install | ______________________ ERROR collecting qsimcirq_test.py _______________________
qsim-install | ImportError while importing test module '/qsim/interfaces/tests/qsimcirq_test.py'.
qsim-install | Hint: make sure your test modules/packages have valid Python names.
qsim-install | Traceback:
qsim-install | qsimcirq_test.py:18: in <module>
qsim-install | import qsimcirq.qsim_simulator as qsimSimulator
qsim-install | /usr/local/lib/python3.7/dist-packages/qsimcirq/qsim_simulator.py:19: in <module>
qsim-install | import qsim
qsim-install | E ModuleNotFoundError: No module named 'qsim'
(note that import qsim
has been replaced with from qsimcirq import qsim
in the current version of qsim_simulator.py
)
The Dockerfile in question can be seen in PR #20. The tests in that PR pass when the package is built from HEAD.
Originally posted by @95-martin-orion in #18 (comment)
Need to put together a release process that allows cirq to upgrade independently of qsim
The "For" object in formux.h is in the global namespace, which may cause collisions with user libraries. It should be folded under the qsim namespace.
Following #135, all gates_cirq
gates are supported through qsimcirq except for matrix gates. These were excluded from the initial change because they require more complex translation logic, but going forward it would be nice to have support for them.
In a similar vein, there are some Cirq gates which are not in gates_cirq
. This is basically unavoidable, as Cirq continues to add new gates. However, Cirq has a built-in decompose
method to distill gates down to a target "gateset"; using this (with gates_cirq
as the gateset) we can support any circuit sent from Cirq.
(Of note: decompose
usually incurs a simulation cost compared to running the original gate. Having a fairly large target gateset like gates_cirq
helps to minimize this cost.)
Pulled from current head and found issues with building under Centos with Gcc 8 and openmp using the makefile (as opposed to make.sh). Simple fix to the makefile made things buildable to pass all tests, but wanted to suppress the bogus warnings about uninitialized variables as well. Patch file attached.
0001-Minor-cleanup-for-clean-make-on-Centos-with-gcc-8.patch.zip
To enable trajectory simulation, qsim must accept gates represented by a set of Kraus operators. During execution, these gates will randomly select a Kraus operator to apply using weights determined by the action of each operator on the current simulation state.
So that this does not impact existing qsim behavior, all code which is specific to trajectory simulation should be kept separate from qsim.h
and hybrid.h
. Initial discussion supported the addition of a new header file for this purpose.
Currently, users have to modify the source code to run qsim with a non-AVX simulator. In order to better support users without AVX, we should automatically detect AVX availability and select the simulator type accordingly.
inside of simulator_sse
and simlator_avx
the worker functions we have are:
auto f = [](unsigned n, unsigned m, uint64_t i,
uint64_t sizek, uint64_t mask0, uint64_t mask1,
const fp_type* matrix, fp_type* rstate)
Which then gets called in a parallel manner. Do we have any idea how many CPU cycles or nanoseconds this function needs in order to finish executing once ?
start = time()
f(...)
end = time()
What is end-start
roughly equal to ?
It isn't clear from the documentation on how QSimulator.compute_amplitudes work.
When I run a short program, this is what I get:
Output:
Circuit:
(0, 0): ───X^0.5───@───X^0.5───
│
(1, 0): ───X^0.5───@───X^0.5───
Results:
measurements: (no measurements)
output vector: 0.5|00⟩ + 0.5j|01⟩ + 0.5j|10⟩ + 0.5|11⟩
[0.5+0.j 0. +0.5j 0. +0.5j 0.5+0.j ]
Results:
measurements: (no measurements)
output vector: 0.5|00⟩ + 0.5j|01⟩ + 0.5j|10⟩ + 0.5|11⟩
Probability Amplitudes:
[(0.5+0j), 0.5j, 0.5j, (0.5+0j)]
We currently support AVX, SSE, and unoptimized simulations, each of which can either use or exclude OpenMP. Our CI tests (and possibly our test definitions) need to be updated to cover all possible combinations of these tests.
The function "compute_amplitudes" does not exist in the Cirq simulator interface, so it doesn't really make sense for the qsimcirq API to support this function. We should either add "compute_amplitudes" to the cirq simulator interface or remove this function for now.
The version string in setup.py is currently '0.0.1',
Line 79 in cb02f33
but pypi thinks the latest version is '0.0.2'
https://pypi.org/project/qsimcirq/0.0.2/
Also, it would be useful for qsimcirq to have a version attribute __version__
for programatic access. This does not currently work...
> python -c 'import qsimcirq; print(qsimcirq.__version__)'
Need to do a benchmark fo qsim with cirq, and publish documentation.
That would depend on the most recent PR prior to pushing the qsim PyPI package - I suspect that #43 was not included in that release.
@iamvamsikrishnad, do you know what PR v0.0.2 aligns with? Also, we should consider pushing a release to pick up this and other minor fixes that went in since v0.0.2.
Originally posted by @95-martin-orion in #62 (comment)
We currently have simmux
to automatically select simulator optimizations based on what the system has available / what config flags the user has specified. In a similar vein, we should add a mux for parallelism libraries (OpenMP, serial execution, etc.) to allow these to be selected in the config flags.
PR #5 provides support for running tests through Docker - we should extend this to cover simulations as well.
Travis should be used to run tests for each PR. We can't enable this until the repo goes public, but in the meantime we can set up the travis.yml file(s).
Hi,
I've been looking to replace the cirq simulator in some of my programs with the fast qsimcirq backend. I've noticed some unexpected behaviour with the system wavefunction, and wanted to check whether this was something that I'm doing wrong, or if there might be a potential bug.
I've found that for a single qubit circuit, the X and H gates behave as I expect, but the Rx and Ry gates do not seem to give the correct wavefunction:
import cirq
import qsimcirq
import numpy as np
# Working example
c0 = cirq.Circuit()
q0 = cirq.NamedQubit('Test0')
c0.append(cirq.H(q0))
print(c0)
result_0 = cirq.Simulator(dtype = np.complex64).simulate(c0)
cirq_wf_0 = result_0.final_state
print('Cirq wavefunction: ', cirq_wf_0)
print()
qsim_circuit_0 = qsimcirq.QSimCircuit(cirq_circuit=c0)
print(qsim_circuit_0)
my_sim = qsimcirq.QSimSimulator()
myres_0 = my_sim.simulate(program=qsim_circuit_0)
qsim_wf_0 = myres_0._final_simulator_state
print('Qsim wavefunction: ', qsim_wf_0)
This prints:
Test0: ───H───
Cirq wavefunction:
[0.70710677+0.j
0.70710677+0.j]
Test0: ───H───
Qsim wavefunction:
[0.70710677
0.
0.70710677
0. ]
as I would expect.
# Non-working example
c1 = cirq.Circuit()
q1 = cirq.NamedQubit('Test1')
c1.append(cirq.Rx(np.pi/2)(q1))
print(c1)
result_1 = cirq.Simulator(dtype = np.complex64).simulate(c1)
cirq_wf_1 = result_1.final_state
print('Cirq wavefunction: ', cirq_wf_1)
print()
qsim_circuit_1 = qsimcirq.QSimCircuit(cirq_circuit=c1)
print(qsim_circuit_1)
my_sim = qsimcirq.QSimSimulator()
myres_1 = my_sim.simulate(program=qsim_circuit_1)
qsim_wf_1 = myres_1._final_simulator_state
print('Qsim wavefunction: ', qsim_wf_1)
This prints:
Test1: ───Rx(0.5π)───
Cirq wavefunction:
[0.70710677+0.j
0.-0.70710677j]
Test1: ───Rx(0.5π)───
Qsim wavefunction:
[ 0.5
0.5
0.5
-0.5]
While these appear inconsistent, I think this can be explained by removing the global phase from the qsim wavefunction, which yields: e^{i*pi/4} (1/sqrt(2) , -i/sqrt(2)).
However, I obtain a similar inconsistency between the cirq and qsim wavefunctions for different rotation angles, and for the Ry gate too, which don't seem to be explainable with the global phase:
# Non-working example
c1 = cirq.Circuit()
q1 = cirq.NamedQubit('Test1')
c1.append(cirq.Ry(np.pi/3)(q1))
print(c1)
result_1 = cirq.Simulator(dtype = np.complex64).simulate(c1)
cirq_wf_1 = result_1.final_state
print('Cirq wavefunction: ', cirq_wf_1)
print()
qsim_circuit_1 = qsimcirq.QSimCircuit(cirq_circuit=c1)
print(qsim_circuit_1)
my_sim = qsimcirq.QSimSimulator()
myres_1 = my_sim.simulate(program=qsim_circuit_1)
qsim_wf_1 = myres_1._final_simulator_state
print('Qsim wavefunction: ', qsim_wf_1)
This prints:
Test1: ───Ry(0.333π)───
Cirq wavefunction:
[0.8660254+0.j
0.5 +0.j]
Test1: ───Ry(0.333π)───
Qsim wavefunction:
[0.98614323
0.
0.16589613
0. ]
I'm not sure how to reconcile these two wavefunctions, so would really appreciate any insights that you might have on this.
Thank you in advance for your help with these questions.
Best regards,
Sam
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.