waveforms 1.8.6__tar.gz → 1.8.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {waveforms-1.8.6/waveforms.egg-info → waveforms-1.8.7}/PKG-INFO +1 -1
- waveforms-1.8.7/tests/test_SUN.py +15 -0
- waveforms-1.8.7/tests/test_clifford.py +135 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_group.py +0 -103
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/group/_SU_n_.py +5 -4
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/group/clifford/funtions.py +113 -25
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/group/clifford/group.py +29 -52
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/group/permutation_group.py +4 -2
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/matricies.py +15 -1
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/clifford/mat.py +2 -15
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/clifford/seq2mat.py +3 -2
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/version.py +1 -1
- {waveforms-1.8.6 → waveforms-1.8.7/waveforms.egg-info}/PKG-INFO +1 -1
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms.egg-info/SOURCES.txt +1 -0
- waveforms-1.8.6/tests/test_clifford.py +0 -57
- {waveforms-1.8.6 → waveforms-1.8.7}/LICENSE +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/MANIFEST.in +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/README.md +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/pyproject.toml +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/setup.cfg +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/setup.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/src/ikcp.c +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/src/ikcp.h +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/src/kcp.c +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/src/prime.c +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/src/waveform.c +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/src/waveform.h +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_bayes.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_compile.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_config.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_cycles.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_dicttree.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_distortion.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_interval.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_kad.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_lisp.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_msgpack.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_multi_drag.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_namespace.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_registry.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_scan_iter.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_tomo.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_vm.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_waveform.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/tests/test_wavevstack.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/__main__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/autoreload.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/baseconfig.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/cache.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/dicttree.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/loader.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/bayes.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/fibheap.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/fit/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/fit/_fit.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/fit/delay.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/fit/geo.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/fit/peak.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/fit/qubit_dynamics.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/fit/readout.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/fit/resonator.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/fit/simple.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/fit/spectrum.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/fit/symmetry.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/func.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/graph.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/group/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/group/clifford/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/group/clifford/chp.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/group/clifford/chp_numpy.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/interval.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/paulis.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/prime.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/signal/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/signal/demodulate.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/signal/distortion.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/signal/func.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/math/transmon.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/multy_drag.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/namespace.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/arch/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/assembly.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/base.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/commands.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/compiler.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/config.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/interpreter.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/library.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/libs/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/macro.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/parse.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/prog.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/eval.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/exceptions.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/libs/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/libs/qelib1.inc +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/barrier.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/binaryop.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/binaryoperator.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/creg.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/customunitary.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/expressionlist.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/external.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/format.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/gate.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/gatebody.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/id.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/idlist.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/if_.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/indexedid.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/intnode.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/measure.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/node.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/nodeexception.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/opaque.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/prefix.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/primarylist.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/program.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/qreg.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/real.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/reset.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/node/unaryoperator.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/qasm.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/qasmlexer.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/qasm/qasmparser.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/simulator/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/simulator/simple.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/tokenize.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/qlisp/utils.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/analyze/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/analyze/coupling.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/analyze/decoherence.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/analyze/gate_error.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/clifford/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/clifford/clifford.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/clifford/db.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/fourier_grid.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/math.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/rb.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/tomo.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/transmon.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/quantum/xeb.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/registry.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/scan/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/scan/base.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/scan/dataset.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/scan/expression.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/scan/scanner.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/scan/transforms.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/scan_iter.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/security/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/security/verify.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/server/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/server/__main__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/server/echo.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/backend/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/backend/redis.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/base_dataset.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/chunk.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/dataset.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/file.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/models/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/models/base.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/models/config.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/models/file.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/models/ipy.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/models/record.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/models/report.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/models/tag.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/storage/storage.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/chat.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/device/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/device/basedevice.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/device/loader.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/device/utils.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/drivers/FakeInstrument.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/drivers/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/ipy_events.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/net/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/net/bencoder.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/net/cli.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/net/dhcp.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/net/dhcpd.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/net/kad.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/net/kcp.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/progress.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/rpc/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/rpc/msgpack.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/storage/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/storage/crud.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/sys/storage/models.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/units/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/utils.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/visualization/__init__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/visualization/__main__.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/visualization/_autoplot.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/visualization/plot_layout.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/visualization/plot_seq.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/visualization/qdat.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/visualization/widgets.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/waveform.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms/waveform_parser.py +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms.egg-info/dependency_links.txt +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms.egg-info/entry_points.txt +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms.egg-info/requires.txt +0 -0
- {waveforms-1.8.6 → waveforms-1.8.7}/waveforms.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from waveforms.math.group import SU
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_SU():
|
|
7
|
+
for N in range(2, 6):
|
|
8
|
+
for i in range(N**2):
|
|
9
|
+
mat = SU(N)[i]
|
|
10
|
+
assert mat.shape == (N, N)
|
|
11
|
+
if i == 0:
|
|
12
|
+
assert np.allclose(mat, np.eye(N))
|
|
13
|
+
else:
|
|
14
|
+
assert abs(np.trace(mat)) < 1e-9
|
|
15
|
+
assert np.allclose(mat, mat.T.conj())
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import itertools
|
|
3
|
+
import operator
|
|
4
|
+
import random
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from waveforms.math.group import CliffordGroup, PermutationGroup
|
|
9
|
+
from waveforms.math.group.clifford import (cliffordOrder,
|
|
10
|
+
find_permutation_for_Unitary)
|
|
11
|
+
from waveforms.math.group.clifford.funtions import (
|
|
12
|
+
one_qubit_clifford_matricies, one_qubit_clifford_mul_table,
|
|
13
|
+
one_qubit_clifford_seq, one_qubit_clifford_seq2)
|
|
14
|
+
from waveforms.math.group.clifford.group import make_clifford_generators
|
|
15
|
+
from waveforms.math.matricies import synchronize_global_phase
|
|
16
|
+
from waveforms.qlisp.simulator.simple import applySeq, seq2mat
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def make_circuit(gate, N):
|
|
20
|
+
rest_qubits = set(range(N)) - set(gate[1:])
|
|
21
|
+
circ = [gate]
|
|
22
|
+
for qubit in rest_qubits:
|
|
23
|
+
circ.append(('I', qubit))
|
|
24
|
+
return circ
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def random_circuit(N, depth, single_qubit_gate_set, two_qubit_gate_set):
|
|
28
|
+
circ = []
|
|
29
|
+
qubits = list(range(N))
|
|
30
|
+
for i in range(depth):
|
|
31
|
+
for q in range(N):
|
|
32
|
+
circ.append((random.choice(single_qubit_gate_set), q))
|
|
33
|
+
random.shuffle(qubits)
|
|
34
|
+
for i in range(0, N - 1, 2):
|
|
35
|
+
circ.append(
|
|
36
|
+
(random.choice(two_qubit_gate_set), qubits[i], qubits[i + 1]))
|
|
37
|
+
return circ
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_cliffordOrder():
|
|
41
|
+
assert cliffordOrder(0) == 1
|
|
42
|
+
assert cliffordOrder(1) == 24
|
|
43
|
+
assert cliffordOrder(2) == 11520
|
|
44
|
+
assert cliffordOrder(3) == 92897280
|
|
45
|
+
|
|
46
|
+
for N in [1, 2, 3]:
|
|
47
|
+
clifford = PermutationGroup(list(make_clifford_generators(N).values()))
|
|
48
|
+
assert clifford.order() == cliffordOrder(N)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_mul_table():
|
|
52
|
+
group = CliffordGroup(1)
|
|
53
|
+
lst = [
|
|
54
|
+
group.circuit_to_permutation([(g, 0)]) for g in one_qubit_clifford_seq
|
|
55
|
+
]
|
|
56
|
+
for i, j in itertools.product(range(24), repeat=2):
|
|
57
|
+
assert lst[i] * lst[j] == lst[one_qubit_clifford_mul_table[i, j]]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_mul_table2():
|
|
61
|
+
for i, j in itertools.product(range(24), repeat=2):
|
|
62
|
+
assert np.allclose(
|
|
63
|
+
synchronize_global_phase(one_qubit_clifford_matricies[j]
|
|
64
|
+
@ one_qubit_clifford_matricies[i]),
|
|
65
|
+
synchronize_global_phase(
|
|
66
|
+
one_qubit_clifford_matricies[one_qubit_clifford_mul_table[i,
|
|
67
|
+
j]]))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_seq2():
|
|
71
|
+
for mat, seq in zip(one_qubit_clifford_matricies, one_qubit_clifford_seq2):
|
|
72
|
+
assert np.allclose(
|
|
73
|
+
synchronize_global_phase(mat),
|
|
74
|
+
synchronize_global_phase(seq2mat([(g, 0) for g in seq])))
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_elements():
|
|
78
|
+
group = CliffordGroup(1)
|
|
79
|
+
lst = [
|
|
80
|
+
group.circuit_to_permutation([(g, 0)]) for g in one_qubit_clifford_seq
|
|
81
|
+
]
|
|
82
|
+
assert len(group.elements) == 24
|
|
83
|
+
assert set(group.elements) == set(lst)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_rb():
|
|
87
|
+
group = CliffordGroup(2)
|
|
88
|
+
|
|
89
|
+
circ = []
|
|
90
|
+
for i in range(500):
|
|
91
|
+
circ.extend(group.permutation_to_circuit(group.random()))
|
|
92
|
+
|
|
93
|
+
circ2 = group.circuit_simplify(circ)
|
|
94
|
+
circ3 = group.circuit_fullsimplify(circ)
|
|
95
|
+
assert len(circ3) < len(circ)
|
|
96
|
+
|
|
97
|
+
circ.extend(group.circuit_inv(circ3))
|
|
98
|
+
circ2.extend(group.circuit_inv(circ3))
|
|
99
|
+
circ3.extend(group.circuit_inv(circ3))
|
|
100
|
+
|
|
101
|
+
psi = applySeq(circ)
|
|
102
|
+
assert abs((psi * psi.conj()).real[0] - 1) < 1e-6
|
|
103
|
+
|
|
104
|
+
psi = applySeq(circ2)
|
|
105
|
+
assert abs((psi * psi.conj()).real[0] - 1) < 1e-6
|
|
106
|
+
|
|
107
|
+
psi = applySeq(circ3)
|
|
108
|
+
assert abs((psi * psi.conj()).real[0] - 1) < 1e-6
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def test_express():
|
|
112
|
+
N = 2
|
|
113
|
+
DEPTH = 1000
|
|
114
|
+
|
|
115
|
+
generators = make_clifford_generators(N)
|
|
116
|
+
|
|
117
|
+
clifford = PermutationGroup(list(generators.values()))
|
|
118
|
+
|
|
119
|
+
circuit = random_circuit(
|
|
120
|
+
N, DEPTH, ['X/2', 'Y/2', 'X', 'Y', '-X/2', '-Y/2', 'Z', 'S', '-S'],
|
|
121
|
+
['CZ', 'iSWAP', 'Cnot'])
|
|
122
|
+
U = seq2mat(circuit)
|
|
123
|
+
|
|
124
|
+
circ_perm = find_permutation_for_Unitary(U, N)
|
|
125
|
+
inv_circ = clifford.express(circ_perm.inv())
|
|
126
|
+
|
|
127
|
+
assert (circ_perm *
|
|
128
|
+
functools.reduce(operator.mul, inv_circ.expand())).is_identity()
|
|
129
|
+
|
|
130
|
+
reversed_map = {v: k for k, v in generators.items()}
|
|
131
|
+
inv_circuit = [reversed_map[c] for c in inv_circ.expand()]
|
|
132
|
+
|
|
133
|
+
U = seq2mat(circuit + inv_circuit)
|
|
134
|
+
|
|
135
|
+
assert np.allclose(synchronize_global_phase(U), np.eye(U.shape[0]))
|
|
@@ -1,77 +1,7 @@
|
|
|
1
1
|
import functools
|
|
2
|
-
import itertools
|
|
3
2
|
import operator
|
|
4
|
-
import random
|
|
5
|
-
from functools import reduce
|
|
6
|
-
from itertools import chain, product
|
|
7
|
-
|
|
8
|
-
import numpy as np
|
|
9
3
|
|
|
10
4
|
from waveforms.math.group import *
|
|
11
|
-
from waveforms.math.group.clifford.funtions import cliffordOrder
|
|
12
|
-
from waveforms.qlisp.simulator.simple import seq2mat
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def make_circuit(gate, N):
|
|
16
|
-
rest_qubits = set(range(N)) - set(gate[1:])
|
|
17
|
-
circ = [gate]
|
|
18
|
-
for qubit in rest_qubits:
|
|
19
|
-
circ.append(('I', qubit))
|
|
20
|
-
return circ
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def find_permutation_for_Unitary(U, N):
|
|
24
|
-
init = []
|
|
25
|
-
final = []
|
|
26
|
-
for base in product([
|
|
27
|
-
SU(2)[0],
|
|
28
|
-
SU(2)[1],
|
|
29
|
-
SU(2)[2],
|
|
30
|
-
SU(2)[3], -SU(2)[0], -SU(2)[1], -SU(2)[2], -SU(2)[3]
|
|
31
|
-
],
|
|
32
|
-
repeat=N):
|
|
33
|
-
op = reduce(np.kron, base)
|
|
34
|
-
init.append(op)
|
|
35
|
-
final.append(U @ op @ U.T.conj())
|
|
36
|
-
return find_permutation(init, final)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def random_circuit(N, depth, single_qubit_gate_set, two_qubit_gate_set):
|
|
40
|
-
circ = []
|
|
41
|
-
qubits = list(range(N))
|
|
42
|
-
for i in range(depth):
|
|
43
|
-
for q in range(N):
|
|
44
|
-
circ.append((random.choice(single_qubit_gate_set), q))
|
|
45
|
-
random.shuffle(qubits)
|
|
46
|
-
for i in range(0, N - 1, 2):
|
|
47
|
-
circ.append(
|
|
48
|
-
(random.choice(two_qubit_gate_set), qubits[i], qubits[i + 1]))
|
|
49
|
-
return circ
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def expand_expr(perm):
|
|
53
|
-
perm.simplify()
|
|
54
|
-
expr = perm._expr
|
|
55
|
-
return itertools.chain.from_iterable([[c] * n for c, n in expr])
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def make_clifford_generators(N):
|
|
59
|
-
gate_list = []
|
|
60
|
-
|
|
61
|
-
for q in range(N):
|
|
62
|
-
gate_list.append(('H', q))
|
|
63
|
-
gate_list.append(('S', q))
|
|
64
|
-
|
|
65
|
-
for q in range(N - 1):
|
|
66
|
-
gate_list.append(('CZ', q, q + 1))
|
|
67
|
-
|
|
68
|
-
generators = {}
|
|
69
|
-
|
|
70
|
-
for gate in gate_list:
|
|
71
|
-
U = seq2mat(make_circuit(gate, N))
|
|
72
|
-
generators[gate] = find_permutation_for_Unitary(U, N)
|
|
73
|
-
|
|
74
|
-
return generators
|
|
75
5
|
|
|
76
6
|
|
|
77
7
|
def test_init():
|
|
@@ -93,10 +23,6 @@ def test_order():
|
|
|
93
23
|
])
|
|
94
24
|
assert G.order() == 88179840
|
|
95
25
|
|
|
96
|
-
for N in [1, 2, 3]:
|
|
97
|
-
clifford = PermutationGroup(list(make_clifford_generators(N).values()))
|
|
98
|
-
assert clifford.order() == cliffordOrder(N)
|
|
99
|
-
|
|
100
26
|
|
|
101
27
|
def test_orbit():
|
|
102
28
|
G = SymmetricGroup(5)
|
|
@@ -168,35 +94,6 @@ def test_subgroup():
|
|
|
168
94
|
assert not G < SymmetricGroup(5)
|
|
169
95
|
|
|
170
96
|
|
|
171
|
-
def test_express():
|
|
172
|
-
N = 2
|
|
173
|
-
DEPTH = 1000
|
|
174
|
-
|
|
175
|
-
generators = make_clifford_generators(N)
|
|
176
|
-
|
|
177
|
-
clifford = PermutationGroup(list(generators.values()))
|
|
178
|
-
|
|
179
|
-
circuit = random_circuit(
|
|
180
|
-
N, DEPTH, ['X/2', 'Y/2', 'X', 'Y', '-X/2', '-Y/2', 'Z', 'S', '-S'],
|
|
181
|
-
['CZ', 'iSWAP', 'Cnot'])
|
|
182
|
-
U = seq2mat(circuit)
|
|
183
|
-
|
|
184
|
-
circ_perm = find_permutation_for_Unitary(U, N)
|
|
185
|
-
inv_circ = clifford.express(circ_perm.inv())
|
|
186
|
-
|
|
187
|
-
assert (
|
|
188
|
-
circ_perm *
|
|
189
|
-
functools.reduce(operator.mul, expand_expr(inv_circ))).is_identity()
|
|
190
|
-
|
|
191
|
-
reversed_map = {v: k for k, v in generators.items()}
|
|
192
|
-
inv_circuit = [reversed_map[c] for c in expand_expr(inv_circ)]
|
|
193
|
-
|
|
194
|
-
U = seq2mat(circuit + inv_circuit)
|
|
195
|
-
U = U * np.exp(-1j * np.angle(U[0, 0]))
|
|
196
|
-
|
|
197
|
-
assert np.allclose(U, np.eye(U.shape[0]))
|
|
198
|
-
|
|
199
|
-
|
|
200
97
|
def test_simplify():
|
|
201
98
|
group = SymmetricGroup(5)
|
|
202
99
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import math
|
|
2
|
+
|
|
2
3
|
import numpy as np
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
def _SUn_generator(n, i):
|
|
6
|
-
assert n > 1 and 0 <= i < 2
|
|
7
|
+
assert n > 1 and 0 <= i < n**2
|
|
7
8
|
|
|
8
9
|
if i == 0:
|
|
9
10
|
return np.eye(n, dtype=np.int8), 1
|
|
@@ -36,8 +37,8 @@ class _SUGroup():
|
|
|
36
37
|
self.n = n
|
|
37
38
|
|
|
38
39
|
def __getitem__(self, i: int):
|
|
39
|
-
if not 0 <= i <
|
|
40
|
-
raise IndexError(f"i must be in [0, {
|
|
40
|
+
if not 0 <= i < self.n**2:
|
|
41
|
+
raise IndexError(f"i must be in [0, {self.n**2-1}]")
|
|
41
42
|
mat, A = _SUn_generator(self.n, i)
|
|
42
43
|
return A * mat
|
|
43
44
|
|
|
@@ -46,4 +47,4 @@ class _SUGroup():
|
|
|
46
47
|
|
|
47
48
|
|
|
48
49
|
def SU(n: int):
|
|
49
|
-
return _SUGroup(n)
|
|
50
|
+
return _SUGroup(n)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import operator
|
|
2
|
-
from functools import reduce
|
|
2
|
+
from functools import lru_cache, reduce
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
from numpy import pi
|
|
@@ -23,36 +23,70 @@ def cliffordOrder(n: int) -> int:
|
|
|
23
23
|
|
|
24
24
|
one_qubit_clifford_seq = [
|
|
25
25
|
# Paulis
|
|
26
|
-
("u3", 0
|
|
27
|
-
("u3",
|
|
28
|
-
("u3",
|
|
29
|
-
("u3", 0
|
|
26
|
+
("u3", 0 , 0 , 0 ), # I
|
|
27
|
+
("u3", pi , -pi , 0 ), # X
|
|
28
|
+
("u3", pi , 0 , 0 ), # Y
|
|
29
|
+
("u3", 0 , pi/2, pi/2), # Z
|
|
30
30
|
|
|
31
31
|
# 2 pi / 3 rotations
|
|
32
|
-
("u3",
|
|
33
|
-
("u3",
|
|
34
|
-
("u3",
|
|
35
|
-
("u3",
|
|
36
|
-
("u3",
|
|
37
|
-
("u3",
|
|
38
|
-
("u3",
|
|
39
|
-
("u3",
|
|
32
|
+
("u3", pi/2, -pi/2, 0 ),
|
|
33
|
+
("u3", pi/2, -pi/2, pi ),
|
|
34
|
+
("u3", pi/2, pi/2, 0 ),
|
|
35
|
+
("u3", pi/2, pi/2, -pi ),
|
|
36
|
+
("u3", pi/2, 0 , pi/2),
|
|
37
|
+
("u3", pi/2, 0 , -pi/2),
|
|
38
|
+
("u3", pi/2, -pi , pi/2),
|
|
39
|
+
("u3", pi/2, pi , -pi/2),
|
|
40
40
|
|
|
41
41
|
# pi / 2 rotations
|
|
42
|
-
("u3",
|
|
43
|
-
("u3",
|
|
44
|
-
("u3",
|
|
45
|
-
("u3",
|
|
46
|
-
("u3", 0
|
|
47
|
-
("u3", 0
|
|
42
|
+
("u3", pi/2, -pi/2, pi/2), # X/2
|
|
43
|
+
("u3", pi/2, pi/2, -pi/2), # -X/2
|
|
44
|
+
("u3", pi/2, 0 , 0 ), # Y/2
|
|
45
|
+
("u3", pi/2, pi , -pi ), # -Y/2
|
|
46
|
+
("u3", 0 , 0 , pi/2), # Z/2
|
|
47
|
+
("u3", 0 , 0 , -pi/2), # -Z/2
|
|
48
48
|
|
|
49
49
|
# Hadamard-like
|
|
50
|
-
("u3",
|
|
51
|
-
("u3",
|
|
52
|
-
("u3",
|
|
53
|
-
("u3",
|
|
54
|
-
("u3",
|
|
55
|
-
("u3",
|
|
50
|
+
("u3", pi/2, -pi , 0 ),
|
|
51
|
+
("u3", pi/2, 0 , pi ), # Hadamard
|
|
52
|
+
("u3", pi/2, pi/2, pi/2),
|
|
53
|
+
("u3", pi/2, -pi/2, -pi/2),
|
|
54
|
+
("u3", pi , -pi/2, 0 ),
|
|
55
|
+
("u3", pi , pi/2, 0 )
|
|
56
|
+
] #yapf: disable
|
|
57
|
+
|
|
58
|
+
one_qubit_clifford_seq2 = [
|
|
59
|
+
# Paulis
|
|
60
|
+
[], # I
|
|
61
|
+
['H', 'S', 'S', 'H'], # X
|
|
62
|
+
['H', 'S', 'S', 'H', 'S', 'S'], # Y
|
|
63
|
+
['S', 'S'], # Z
|
|
64
|
+
|
|
65
|
+
# 2 pi / 3 rotations
|
|
66
|
+
['S', 'S', 'H', 'S', 'S', 'S'],
|
|
67
|
+
['H', 'S', 'S', 'S'],
|
|
68
|
+
['S', 'S', 'H', 'S'],
|
|
69
|
+
['H', 'S'],
|
|
70
|
+
['S', 'S', 'S', 'H'],
|
|
71
|
+
['S', 'H'],
|
|
72
|
+
['S', 'S', 'S', 'H', 'S', 'S'],
|
|
73
|
+
['S', 'H', 'S', 'S'],
|
|
74
|
+
|
|
75
|
+
# pi / 2 rotations
|
|
76
|
+
['S', 'S', 'S', 'H', 'S', 'S', 'S'], # X/2
|
|
77
|
+
['S', 'H', 'S'], # -X/2
|
|
78
|
+
['S', 'S', 'H'], # Y/2
|
|
79
|
+
['H', 'S', 'S'], # -Y/2
|
|
80
|
+
['S'], # Z/2
|
|
81
|
+
['S', 'S', 'S'], # -Z/2
|
|
82
|
+
|
|
83
|
+
# Hadamard-like
|
|
84
|
+
['S', 'S', 'H', 'S', 'S'],
|
|
85
|
+
['H'],
|
|
86
|
+
['S', 'S', 'S', 'H', 'S'],
|
|
87
|
+
['S', 'H', 'S', 'S', 'S'],
|
|
88
|
+
['H', 'S', 'S', 'H', 'S'],
|
|
89
|
+
['H', 'S', 'S', 'H', 'S', 'S', 'S']
|
|
56
90
|
] #yapf: disable
|
|
57
91
|
|
|
58
92
|
one_qubit_clifford_seq_inv = {
|
|
@@ -62,6 +96,15 @@ one_qubit_clifford_seq_inv = {
|
|
|
62
96
|
one_qubit_clifford_seq_inv['H'] = 19
|
|
63
97
|
one_qubit_clifford_seq_inv['S'] = 16
|
|
64
98
|
one_qubit_clifford_seq_inv['I'] = 0
|
|
99
|
+
one_qubit_clifford_seq_inv['X'] = 1
|
|
100
|
+
one_qubit_clifford_seq_inv['Y'] = 2
|
|
101
|
+
one_qubit_clifford_seq_inv['Z'] = 3
|
|
102
|
+
one_qubit_clifford_seq_inv['X/2'] = 12
|
|
103
|
+
one_qubit_clifford_seq_inv['-X/2'] = 13
|
|
104
|
+
one_qubit_clifford_seq_inv['Y/2'] = 14
|
|
105
|
+
one_qubit_clifford_seq_inv['-Y/2'] = 15
|
|
106
|
+
one_qubit_clifford_seq_inv['-S'] = 17
|
|
107
|
+
one_qubit_clifford_seq_inv.update({f'C1_{i}': i for i in range(24)})
|
|
65
108
|
|
|
66
109
|
one_qubit_clifford_mul_table = np.array([
|
|
67
110
|
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23],
|
|
@@ -91,6 +134,51 @@ one_qubit_clifford_mul_table = np.array([
|
|
|
91
134
|
], dtype=np.int8) #yapf: disable
|
|
92
135
|
|
|
93
136
|
|
|
137
|
+
@lru_cache()
|
|
138
|
+
def _one_qubit_clifford_index(gate):
|
|
139
|
+
pass
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def one_qubit_clifford_index(gate):
|
|
143
|
+
if gate in one_qubit_clifford_seq_inv:
|
|
144
|
+
return one_qubit_clifford_seq_inv[gate]
|
|
145
|
+
else:
|
|
146
|
+
match gate:
|
|
147
|
+
case ('R', phi):
|
|
148
|
+
return one_qubit_clifford_index(
|
|
149
|
+
('U', pi / 2, phi - pi / 2, pi / 2 - phi))
|
|
150
|
+
case ('rfUnitary', theta, phi):
|
|
151
|
+
return one_qubit_clifford_index(
|
|
152
|
+
('U', theta, phi - pi / 2, pi / 2 - phi))
|
|
153
|
+
case ('u3', theta, phi, lam) | ('U', theta, phi, lam):
|
|
154
|
+
theta = np.mod(theta / (2 * pi))
|
|
155
|
+
if theta == np.pi / 2:
|
|
156
|
+
pass
|
|
157
|
+
elif theta == 0:
|
|
158
|
+
phi, lam = phi + lam, 0
|
|
159
|
+
elif theta == np.pi:
|
|
160
|
+
phi, lam = phi - lam, 0
|
|
161
|
+
elif theta == 3 * np.pi / 2:
|
|
162
|
+
theta = np.pi / 2
|
|
163
|
+
phi, lam = phi + pi, lam + pi
|
|
164
|
+
else:
|
|
165
|
+
return -1
|
|
166
|
+
phi = np.mod(phi, 2 * pi)
|
|
167
|
+
lam = np.mod(lam, 2 * pi)
|
|
168
|
+
case ('u2', phi, lam):
|
|
169
|
+
return one_qubit_clifford_index(('U', pi / 2, phi, lam))
|
|
170
|
+
case ('u1', lam) | ('Rz', lam) | ('P', lam):
|
|
171
|
+
return one_qubit_clifford_index(('U', 0, 0, lam))
|
|
172
|
+
case 'P':
|
|
173
|
+
return 16
|
|
174
|
+
case ('Rx', theta):
|
|
175
|
+
return one_qubit_clifford_index(('U', theta, -pi / 2, pi / 2))
|
|
176
|
+
case ('Ry', theta):
|
|
177
|
+
return one_qubit_clifford_index(('U', theta, 0, 0))
|
|
178
|
+
case _:
|
|
179
|
+
return -1
|
|
180
|
+
|
|
181
|
+
|
|
94
182
|
def twoQubitCliffordSequence(n):
|
|
95
183
|
"""
|
|
96
184
|
生成第 n 个群元对应的操作序列
|
|
@@ -1,90 +1,67 @@
|
|
|
1
1
|
import itertools
|
|
2
2
|
import random
|
|
3
3
|
from functools import reduce
|
|
4
|
-
from itertools import product
|
|
4
|
+
from itertools import islice, product
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
|
|
8
8
|
from waveforms.cache import cache
|
|
9
9
|
from waveforms.qlisp.simulator.simple import seq2mat
|
|
10
10
|
|
|
11
|
+
from ...paulis import encode_paulis
|
|
11
12
|
from .._SU_n_ import SU
|
|
12
13
|
from ..permutation_group import Cycles, PermutationGroup, find_permutation
|
|
14
|
+
from .chp import CZ, H, P
|
|
13
15
|
from .funtions import (cliffordOrder, one_qubit_clifford_mul_table,
|
|
14
16
|
one_qubit_clifford_seq, one_qubit_clifford_seq_inv)
|
|
15
17
|
|
|
16
|
-
_base = [SU(2)[i] for i in range(4)] + [-SU(2)[i] for i in range(4)]
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def make_circuit(gate, N):
|
|
20
|
-
rest_qubits = set(range(N)) - set(gate[1:])
|
|
21
|
-
circ = [gate]
|
|
22
|
-
for qubit in rest_qubits:
|
|
23
|
-
circ.append(('I', qubit))
|
|
24
|
-
return circ
|
|
25
|
-
|
|
26
18
|
|
|
27
19
|
def find_permutation_for_Unitary(U, N):
|
|
28
20
|
init = []
|
|
29
21
|
final = []
|
|
30
22
|
|
|
31
|
-
for
|
|
32
|
-
|
|
33
|
-
continue
|
|
34
|
-
op = reduce(np.kron, [_base[i] for i in index])
|
|
23
|
+
for s in islice(product([SU(2)[i] for i in range(4)], repeat=N), 1, None):
|
|
24
|
+
op = reduce(np.kron, s)
|
|
35
25
|
init.append(op)
|
|
36
26
|
final.append(U @ op @ U.T.conj())
|
|
27
|
+
init.append(-op)
|
|
28
|
+
final.append(U @ (-op) @ U.T.conj())
|
|
37
29
|
return find_permutation(init, final)
|
|
38
30
|
|
|
39
31
|
|
|
40
|
-
def
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
circ.append((random.choice(single_qubit_gate_set), q))
|
|
46
|
-
random.shuffle(qubits)
|
|
47
|
-
for i in range(0, N - 1, 2):
|
|
48
|
-
circ.append(
|
|
49
|
-
(random.choice(two_qubit_gate_set), qubits[i], qubits[i + 1]))
|
|
50
|
-
return circ
|
|
51
|
-
|
|
32
|
+
def make_clifford_generators(N, graph=None):
|
|
33
|
+
if graph is None:
|
|
34
|
+
graph = []
|
|
35
|
+
for i in range(N - 1):
|
|
36
|
+
graph.append((i, i + 1))
|
|
52
37
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if gate_list is None:
|
|
59
|
-
gate_list = []
|
|
60
|
-
|
|
61
|
-
for q in range(N):
|
|
62
|
-
for gate in one_qubit_gates:
|
|
63
|
-
gate_list.append((gate, q))
|
|
64
|
-
|
|
65
|
-
for q in range(N - 1):
|
|
66
|
-
for gate in two_qubit_gates:
|
|
67
|
-
gate_list.append((gate, q, q + 1))
|
|
38
|
+
stablizers = []
|
|
39
|
+
for s in islice(product('IXYZ', repeat=N), 1, None):
|
|
40
|
+
n = encode_paulis(''.join(s))
|
|
41
|
+
stablizers.append(n)
|
|
42
|
+
stablizers.append(n | 2)
|
|
68
43
|
|
|
69
44
|
generators = {}
|
|
70
45
|
|
|
71
|
-
for
|
|
72
|
-
|
|
73
|
-
|
|
46
|
+
for i in range(N):
|
|
47
|
+
generators[('H', i)] = find_permutation(stablizers,
|
|
48
|
+
[H(s, i) for s in stablizers])
|
|
49
|
+
generators[('S', i)] = find_permutation(stablizers,
|
|
50
|
+
[P(s, i) for s in stablizers])
|
|
51
|
+
|
|
52
|
+
for i, j in graph:
|
|
53
|
+
generators[('CZ', i,
|
|
54
|
+
j)] = find_permutation(stablizers,
|
|
55
|
+
[CZ(s, i, j) for s in stablizers])
|
|
74
56
|
|
|
75
57
|
return generators
|
|
76
58
|
|
|
77
59
|
|
|
78
60
|
class CliffordGroup(PermutationGroup):
|
|
79
61
|
|
|
80
|
-
def __init__(self,
|
|
81
|
-
N,
|
|
82
|
-
one_qubit_gates=('H', 'S'),
|
|
83
|
-
two_qubit_gates=('CZ', ),
|
|
84
|
-
gate_list=None):
|
|
62
|
+
def __init__(self, N, graph=None):
|
|
85
63
|
self.N = N
|
|
86
|
-
generators = make_clifford_generators(N,
|
|
87
|
-
two_qubit_gates, gate_list)
|
|
64
|
+
generators = make_clifford_generators(N, graph)
|
|
88
65
|
super().__init__(list(generators.values()))
|
|
89
66
|
self.reversed_map = {v: k for k, v in generators.items()}
|
|
90
67
|
self.gate_map = generators
|
|
@@ -206,7 +206,7 @@ class Cycles():
|
|
|
206
206
|
if isinstance(self._expr, list):
|
|
207
207
|
if self.is_identity():
|
|
208
208
|
pass
|
|
209
|
-
|
|
209
|
+
elif not self._expr:
|
|
210
210
|
self._expr = [[self, 1]]
|
|
211
211
|
return self
|
|
212
212
|
|
|
@@ -264,7 +264,9 @@ def permute(expr: list | tuple | str | bytes | np.ndarray, perm: Cycles):
|
|
|
264
264
|
|
|
265
265
|
def _ne(a, b):
|
|
266
266
|
if isinstance(a, np.ndarray):
|
|
267
|
-
|
|
267
|
+
if isinstance(b, np.ndarray):
|
|
268
|
+
return not np.allclose(a, b)
|
|
269
|
+
return True
|
|
268
270
|
else:
|
|
269
271
|
return a != b
|
|
270
272
|
|
|
@@ -67,7 +67,7 @@ CZ = make_immutable(
|
|
|
67
67
|
np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]],
|
|
68
68
|
dtype=complex))
|
|
69
69
|
iSWAP = make_immutable(
|
|
70
|
-
np.array([[1, 0, 0, 0], [0,
|
|
70
|
+
np.array([[1, 0, 0, 0], [0, 0, 1j, 0], [0, 1j, 0, 0], [0, 0, 0, 1]],
|
|
71
71
|
dtype=complex))
|
|
72
72
|
SWAP = make_immutable(
|
|
73
73
|
np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]],
|
|
@@ -173,3 +173,17 @@ def fSim(theta, phi):
|
|
|
173
173
|
[0, -1j*s, c, 0],
|
|
174
174
|
[0, 0, 0, p]
|
|
175
175
|
]) #yapf: disable
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def synchronize_global_phase(U):
|
|
179
|
+
"""
|
|
180
|
+
将第一个非零的矩阵元相位转成 0,以保证仅相差一个全局相位的矩阵具有相同的表示。
|
|
181
|
+
优先处理对角元,再依次处理下三角阵。
|
|
182
|
+
"""
|
|
183
|
+
assert U.shape[0] == U.shape[1]
|
|
184
|
+
for i in range(U.shape[0]):
|
|
185
|
+
for j in range(U.shape[0] - i):
|
|
186
|
+
if np.abs(U[j + i, j]) > 1e-9:
|
|
187
|
+
U = U * np.abs(U[j + i, j]) / U[j + i, j]
|
|
188
|
+
return U
|
|
189
|
+
return 0 * U
|
|
@@ -2,20 +2,7 @@ from itertools import count, product
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
def normalize(mat):
|
|
7
|
-
"""
|
|
8
|
-
将第一个非零的矩阵元相位转成 0,以保证仅相差一个全局相位的矩阵具有相同的表示。
|
|
9
|
-
优先处理对角元,再依次处理下三角阵。
|
|
10
|
-
"""
|
|
11
|
-
assert mat.shape[0] == mat.shape[1]
|
|
12
|
-
for i in range(mat.shape[0]):
|
|
13
|
-
for j in range(mat.shape[0] - i):
|
|
14
|
-
if np.abs(mat[j + i, j]) > 1e-3:
|
|
15
|
-
mat = mat * np.abs(mat[j + i, j]) / mat[j + i, j]
|
|
16
|
-
return mat
|
|
17
|
-
return 0 * mat
|
|
18
|
-
|
|
5
|
+
from waveforms.math.matricies import synchronize_global_phase
|
|
19
6
|
|
|
20
7
|
# 相位规范化后,2 比特 Clifford 群元的矩阵元仅可能取以下值
|
|
21
8
|
elms = [
|
|
@@ -39,7 +26,7 @@ def mat2num(mat, norm=True):
|
|
|
39
26
|
|
|
40
27
|
# 仅相隔一个全局相位的操作等价,故令第一个非零的矩阵元相位为 0,保证操作与矩阵一一对应
|
|
41
28
|
if norm:
|
|
42
|
-
mat =
|
|
29
|
+
mat = synchronize_global_phase(mat)
|
|
43
30
|
|
|
44
31
|
absData, phaseData = 0, 0
|
|
45
32
|
for index, (i, j) in zip(count(start=0, step=2), product(range(4),
|