Coder Social home page Coder Social logo

quantumlib / qsim Goto Github PK

View Code? Open in Web Editor NEW
411.0 28.0 137.0 6.01 MB

Schrödinger and Schrödinger-Feynman simulators for quantum circuits.

License: Apache License 2.0

Shell 0.97% C++ 83.19% CMake 0.67% Python 8.88% Makefile 0.64% Dockerfile 0.18% Starlark 2.24% Cuda 2.91% C 0.32%
quantum-computing quantum-simulator nisq quantum-circuit-simulator

qsim's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

qsim's Issues

Consider full migration to Bazel

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

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.X
0.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.X
0.5).on(cirq.GridQubit(1, 0)),
]),
]) is not a QSimCircuit

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.

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)

Remove reliance on NRVO

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:

qsim/lib/io.h

Lines 41 to 48 in 9708283

static std::ifstream StreamFromFile(const std::string& file) {
std::ifstream fs;
fs.open(file);
if (!fs) {
errorf("cannot open %s for reading.\n", file.c_str());
}
return fs;
}

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.

QSimSimulator: support non-zero initial states

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.

Error with make

error_logs.txt

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!

Classical control

In order to represent quantum teleportation, error correction, and other algorithms, qsim must support classical control. There are three key parts to this feature:

  1. Classical registers: qsim must be able to track classical variables alongside the quantum state. These integer variables include measurement output (added in #141), user-specified input, and calculated values.
  2. Classical operators: qsim must have a framework for applying arithmetic functions to classical registers and storing the result in a target register. This framework should accept user-specified functions - the operators need not be defined in qsim itself.
  3. Classical control: qsim must allow classical registers to control quantum gates. A "switch" operation is sufficient for this (given an input value, and a (case, gate) mapping, apply the gate whose case matches the input, if one exists).

QSimSimulator: Can't access final state or set initial state

class QSimSimulator(SimulatesAmplitudes, SimulatesFinalState):

  1. 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.

  2. 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.

  3. The object in SimulationTrialResult._final_simulator_state is a numpy array, which causes SimulationTrialResult.qubit_map to fail.

  4. The initial_state method parameter is silently ignored. It does does seem possible to set the initial state.

  5. The test test_cirq_qsim_simulate_fullstate does not test any properties of the final fullstate.

After installing via the pypi package, I had issues with the following script:

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)

Update CI to cover SSE and basic modes

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.

Support converting circuits to unitary format

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.

Update docs and error messages for qsim flags

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.

qsimcirq fails when it encounters measurement gates

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,

bitstrings=['00', '01', '10', '11'])

print("Results:")
print(qsim_result)

Output :

Ciruit:
(0, 0): ───X^0.5───@───X^0.5───M('q0')───

(1, 0): ───X^0.5───@───X^0.5───M('q1')───
Results:
measurements: q0=0 q1=0
output vector: |00⟩
[1.+0.j 0.+0.j 0.+0.j 0.+0.j]

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

qsim performance advice needed

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:

Results performed on Google Cloud n1-standard-8 node shows following:

benchmark_qft

Thank you!

Surface gates_cirq in qsimcirq interface

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.

New Features for qsim

Some nice features to have for qsim might be:

  1. The ability to compute inner products between two state objects.
  2. The ability to actually draw X number of bitstring samples from a state object.

Documentation

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.

Cross-platform support

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.

Feature request: SWAP gate

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.

Broken links

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.)

Qsim Cirq tutorial

Need to put together a colab showing how to use Cirq and qsim together.

[Proposal] Convert Templated XXXFor Structs to Objects

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)

Move pybind requirement to the user

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.

Improved intermediate state operations

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.

Can gates in the circuit file be out of order?

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.)

Provide gate parity with Cirq

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.

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:

@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)

Put For in qsim namespace

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.

Support MatrixGate and unknown gate decomposition in qsimcirq

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.)

Kraus operator sampling

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.

Automate simulator selection

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.

[Question]: Cycle count for Simulation functions

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 ?

Need some more documentation on how QSimulator.compute_amplitudes work

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)]

Cover all flag combinations in tests

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.

qsimcirq needs better documenation support for "compute_amplitudes"

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.

Inconsistent versions

The version string in setup.py is currently '0.0.1',

qsim/setup.py

Line 79 in cb02f33

version='0.0.1',

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__)'

Release v0.0.3

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)

Add parallelism mux

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.

Automated testing

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).

Possible bug: qsimcirq with single qubit rotation gates

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.