├── AUTHOR ├── CONTRIBUTION ├── LICENSE ├── Makefile ├── README.md ├── core ├── Makefile ├── include │ ├── dump.h │ ├── experimental.h │ ├── gate.h │ ├── misc.h │ ├── precision.h │ ├── qplayer.h │ ├── register.h │ ├── state.h │ └── timer.h ├── module.mk └── src │ ├── dump.cpp │ ├── experimental.cpp │ ├── gate.cpp │ ├── misc.cpp │ ├── register.cpp │ ├── state.cpp │ └── timer.cpp ├── docs ├── Qplayer User's Manual-v2.3-Cougar (en).pdf ├── Qplayer User's Manual-v2.3-Cougar (kor).pdf ├── changes └── versions.md ├── qasm ├── cli │ ├── Makefile │ ├── examples │ │ ├── adder.qasm │ │ ├── gates.qasm │ │ ├── openqasm_r2.qasm │ │ ├── qec.qasm │ │ ├── qft.qasm │ │ ├── sample.qasm │ │ ├── sc17.qasm │ │ └── test.qasm │ ├── include │ │ ├── Cal.h │ │ ├── Parser.h │ │ ├── Scanner.h │ │ ├── Token.h │ │ └── ds.h │ ├── main.cpp │ ├── module.mk │ ├── qasm │ │ ├── sample.qasm │ │ └── test.qasm │ └── src │ │ ├── Parser.cpp │ │ ├── Scanner.cpp │ │ └── Token.cpp └── qiskit │ ├── CMakeLists.txt │ ├── install.sh │ ├── qplayer │ ├── QResult.py │ ├── __init__.py │ ├── core.cpp │ ├── qelib1.inc │ └── run_qplayer.py │ ├── setup.py │ └── test │ ├── .ipynb_checkpoints │ └── test-checkpoint.ipynb │ ├── test.ipynb │ └── test.py └── test ├── MLQ ├── Makefile ├── ds.h ├── lattice.h ├── logicalCNOT.h ├── logicalQubit.h ├── logicalQubits.h ├── logicalST.h ├── main.cpp └── module.mk ├── Makefile ├── benchmark ├── Makefile ├── gate_perf.cpp ├── longrun_test.cpp └── rcs.cpp ├── general ├── Makefile ├── basic.cpp ├── grover.cpp └── qft.cpp ├── surfacecode ├── Makefile ├── sc17_1LQ.cpp ├── sc17_cnot.cpp └── sc17_hadamard.cpp └── verification ├── Makefile └── install_test.cpp /AUTHOR: -------------------------------------------------------------------------------- 1 | 2 | Developers and Project Steering Committee: 3 | Active: 4 | KiSung Jin (ksjin@etri.re.kr) - Maintainer, Developer 5 | Gyuil Cha (gyuilcha@gmail.com) - Architect, Developer 6 | 7 | Co-Active: 8 | Eun-Young Cho (eycho@etri.re.kr) - Developer 9 | Sang-Min Lee (sanglee@etri.re.kr) - Developer 10 | Young-Cheol Kim (kimyc@etri.re.kr) - Developer 11 | Chei-Yol Kim (gauri@etri.re.kr) - Developer 12 | Soo-Cheol Oh (ponylife@etri.re.kr) - Developer 13 | Jin-Ho On (onjinho@etri.re.kr) - Developer 14 | -------------------------------------------------------------------------------- /CONTRIBUTION: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow, but don't worry about that. 5 | Create a pull request and we'll nudge you in the right direction. 6 | 7 | ## Contributor License Agreement 8 | 9 | Contributions to this project must be accompanied by a Contributor License 10 | Agreement. You (or your employer) retain the copyright to your contribution; 11 | this simply gives us permission to use and redistribute your contributions as 12 | part of the project. 13 | 14 | ## Code reviews 15 | 16 | All submissions, including submissions by project members, require review. 17 | We use GitHub pull requests for this purpose. Consult [GitHub Help] 18 | (https://help.github.com/articles/about-pull-requests/) for more information 19 | on using pull requests. 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Licensing Information User Manual 2 | QPlayer v2.3-Cugar 3 | 4 | This source code is licensed (Dual License: GPL v3 & Commercial) under the license 5 | found in the LICENSE file in the root directory of this source tree. 6 | 7 | ### GPL v3 License 8 | 9 | When you copy and distribute the library in object code or executable form, 10 | you should accompany it with the complete corresponding machine-readable 11 | source code under the GPL v3 license at 12 | 13 | https://www.gnu.org/licenses/gpl-3.0.html 14 | 15 | Unless required by applicable law or agreed to in writing, software distributed 16 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES 17 | OR CONDITIONS OF ANY KIND, either express or implied. See the License for 18 | the specific language governing permissions and limitations under the License. 19 | 20 | ### Commercial License 21 | 22 | If you don't want to open your source code in the course of copying and/or distribution, 23 | please consult to get a permission with applicable conditions. 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # 3 | # Electronics and Telecommunications Research Institute 4 | # 5 | # Copyright(c) 2021 Electronics and Telecommunications Research Institute, 6 | # 218 Gajeong-ro, Yuseong-gu, Daejeon, 34129, Korea. 7 | # All rights are reserved. No part of this work covered by the copyright 8 | # hereon may be reproduced, stored in retrieval systems, in any form or by 9 | # any means, electronic, mechanical, photocopying, recording or otherwise, 10 | # without the prior permission of ETRI. 11 | # 12 | # FILE NAME : Makefile 13 | # 14 | # AUTHOR : 15 | # DESCRIPTION : Makefile for QPlayer 16 | # 17 | #******************************************************************************* 18 | 19 | all: CORE QASM 20 | 21 | CORE: 22 | @ $(MAKE) -C core 23 | 24 | QASM: 25 | @ $(MAKE) -C qasm/cli 26 | 27 | TEST: 28 | @ $(MAKE) -C test 29 | 30 | clean: 31 | @ $(MAKE) -C core clean 32 | @ $(MAKE) -C qasm/cli clean 33 | @ $(MAKE) -C test clean 34 | @ $(RM) -rf release 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QPlayer v2.4-Cougar 2 | ### Light-weight, Scalable and Fast Quantum Simulator 3 | 4 | With the rapid evolution of quantum computing, classical quantum simulations 5 | are considered essential for quantum algorithm verification, quantum error 6 | analysis, and development of new quantum applications. However, the exponential 7 | increase in memory overhead and operation time are challenging issues that 8 | have not been solved for many years. We provide the QPlayer that provides 9 | more qubits and faster quantum operations with smaller memory than before. 10 | 11 | # Depencencies 12 | - gcc and g++ capable of C++11 standard 13 | - make 3.x or higher 14 | 15 | # Publication 16 | - QPlayer: Lightweight, scalable, and fast quantum simulator, 2022, [ETRI Journal (SCIE, IF1.4)](https://doi.org/10.4218/etrij.2021-0442) 17 | - Multilayered logical qubits and synthesized quantum bits, 2023, [Quantum Science and Technology (SCIE, IF6.7)](https://doi.org/10.1088/2058-9565/accec5) 18 | 19 | # OS environment 20 | - CentOS 7.x or higher 21 | - Ubuntu 20.x or higher 22 | 23 | # Installation 24 |
25 |  - build qplayer
26 |    >> cd QPlayer
27 |    >> make
28 | 
29 | 30 | # Supporting Quantum Operations 31 |
32 |  - initZ              : initialize qubit to |0>
33 |  - initX              : initialize qubit to |+>
34 |  - I                  : pauli identity gate
35 |  - X                  : pauli X gate
36 |  - Z                  : pauli Z gate
37 |  - Y                  : pauli Y gate
38 |  - Hadamard           : hadamard gate
39 |  - RX                 : rotate X-axis gate
40 |  - RY                 : rotate Y-axis gate
41 |  - RZ                 : rotate Z-axis gate
42 |  - S                  : S gate
43 |  - T                  : T gate
44 |  - S+                 : S dagger
45 |  - T+                 : S dagger
46 |  - P                  : phase gate
47 |  - SX                 : square-root x gate
48 |  - U1                 : single-qubit rotation gate about the Z axis
49 |  - U2                 : single-qubit rotation gate about the X+Z axis
50 |  - U3                 : single-qubit rotation gate with 3 euler angles
51 |  - SWAP               : SWAP gate
52 |  - CX                 : controlled x gate
53 |  - CY                 : controlled y gate
54 |  - CZ                 : controlled z gate
55 |  - CH                 : controlled h gate
56 |  - CCZ                : controlled rz gate
57 |  - CCX                : controlled-controlled x gate
58 |  - CU1                : controlled u1 gate
59 |  - CU2                : controlled u2 gate
60 |  - CU3                : controlled u3 gate
61 |  - CSWAP              : controlled swap gate
62 |  - measure(z basis)   : mesure qubit
63 | 
64 | 65 | # QPlayer Source Tree 66 |
67 |   + core                : qplayer core library
68 |   + docs                : manual and documentations
69 |   + qasm                : OpenQASM 2.0 parser & executor
70 |   + test - general      : test examples for general quantum algorithms
71 |          - surfacecode  : test examples for surface code
72 |          - MLQ          : experimental code to support 20 logical qubits with d-3 surface code
73 |          - verification : verification code to validate QPlayer installation
74 |          - benchmark    : several benchmark codes
75 | 
76 | -------------------------------------------------------------------------------- /core/Makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | CXXLD = g++ 3 | 4 | CXXFLAGS = -g -Wall -O2 -std=c++11 -MMD -MP -fopenmp 5 | CXXFLAGS += -I. -I./include 6 | CXXFLAGS += -Wno-reorder -Wno-sign-compare -Wno-parentheses -Wno-pessimizing-move 7 | CXXFLAGS += -Wno-unused-function -Wno-unused-variable -Wno-write-strings 8 | CXXFLAGS += -Wno-class-conversion -Wno-unused-result -Wno-class-memaccess 9 | 10 | LIBS = -lm -lpthread -lgomp 11 | 12 | Q=@echo 13 | E=@ 14 | 15 | BUILD_DIR = ../release 16 | 17 | QPLAYER_SRC := 18 | QPLAYER_HDR := 19 | CIRCUIT_HDR := 20 | include ./module.mk 21 | 22 | # OBJECT FILES 23 | QPLAYER_OBJS=$(patsubst %.cpp,%.o,$(QPLAYER_SRC)) 24 | QPLAYER_HDRS=$(patsubst %.h,%.h,$(QPLAYER_HDR)) 25 | 26 | QPLAYER_LIB=libqplayer.a 27 | 28 | .PHONY: all clean 29 | 30 | .DEFAULT_GOAL := all 31 | 32 | all: qplayer install 33 | 34 | qplayer: $(QPLAYER_OBJS) 35 | ar ruv $(QPLAYER_LIB) $(QPLAYER_OBJS) 36 | 37 | %.o : %.cpp $(QPLAYER_HDRS) $(CIRCUIT_HDRS) 38 | $(Q) "CC $(@)" 39 | $(E) $(CXX) $(CXXFLAGS) -Wno-deprecated-declarations $(LIB_CXX_FLAGS) -c $< -o $@ 40 | 41 | install: 42 | $(Q) "$(@)" 43 | @mkdir -p $(BUILD_DIR)/include 44 | @mkdir -p $(BUILD_DIR)/lib 45 | @mkdir -p $(BUILD_DIR)/bin 46 | @cp -f include/* $(BUILD_DIR)/include 47 | @mv -f $(QPLAYER_LIB) $(BUILD_DIR)/lib 48 | 49 | clean: 50 | @echo "Clean Objects, Deps, Executions" 51 | @rm -fv src/*.d 52 | @rm -fv $(QPLAYER_OBJS) 53 | @rm -fv $(QPLAYER_EXEC) 54 | @rm -fv $(QPLAYER_DEPS) 55 | @rm -fv $(QPLAYER_LIB) 56 | -------------------------------------------------------------------------------- /core/include/dump.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file dump.h 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @brief 18 | */ 19 | 20 | #ifndef _DUMP_H_ 21 | #define _DUMP_H_ 22 | 23 | #include "precision.h" 24 | #include "register.h" 25 | #include "state.h" 26 | #include "misc.h" 27 | #include "timer.h" 28 | 29 | extern void dump(QRegister *QReg, char *msg, int begin, int end, struct qubit_delimiter *qd); 30 | extern void dump(QRegister *QReg, char *msg, int begin, int end, struct qubit_delimiter qd); 31 | extern void dump(QRegister *QReg, char *msg, struct qubit_delimiter *qd); 32 | extern void dump(QRegister *QReg, char *msg, struct qubit_delimiter qd); 33 | extern void dump(QRegister *QReg, struct qubit_delimiter *qd); 34 | extern void dump(QRegister *QReg, struct qubit_delimiter qd); 35 | extern void dump(QRegister *QReg, int begin, int end); 36 | extern void dump(QRegister *QReg, char *msg); 37 | extern void dump(QRegister *QReg); 38 | extern void dumpln(QRegister *QReg); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /core/include/experimental.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file gate.h 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @brief 18 | */ 19 | 20 | #ifndef _EXPERIMENTAL_H 21 | #define _EXPERIMENTAL_H 22 | 23 | #include "register.h" 24 | 25 | /* These are experimental functions */ 26 | extern double getQubitProb(QRegister *QReg, int qubit, int state); 27 | extern int QType(QRegister *QReg, int qubit); 28 | extern char *QTypeStr(QRegister *QReg, int qubit); 29 | extern void getEntanglements(QRegister *QReg); 30 | extern void getEntanglements(QRegister *QReg, std::vector>& eGroups); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /core/include/gate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file gate.h 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @brief 18 | */ 19 | 20 | #ifndef _QGATE_H 21 | #define _QGATE_H 22 | 23 | #include "register.h" 24 | 25 | extern void initZ(QRegister *QReg, int qubit); 26 | extern void initX(QRegister *QReg, int qubit); 27 | extern void I(QRegister *QReg, int qubit); 28 | extern void X(QRegister *QReg, int qubit); 29 | extern void Z(QRegister *QReg, int qubit); 30 | extern void Y(QRegister *QReg, int qubit); 31 | extern void H(QRegister *QReg, int qubit); 32 | extern void U1(QRegister *QReg, int qubit, double angle); 33 | extern void U2(QRegister *QReg, int qubit, double phi, double lambda); 34 | extern void U3(QRegister *QReg, int qubit, double theta, double pie, double lambda); 35 | extern void S(QRegister *QReg, int qubit); 36 | extern void T(QRegister *QReg, int qubit); 37 | extern void SDG(QRegister *QReg, int qubit); 38 | extern void TDG(QRegister *QReg, int qubit); 39 | extern void RX(QRegister *QReg, int qubit, double angle); 40 | extern void RY(QRegister *QReg, int qubit, double angle); 41 | extern void RZ(QRegister *QReg, int qubit, double angle); 42 | extern void P(QRegister *QReg, int qubit, double angle); 43 | extern void CU1(QRegister *QReg, int control, int target, double lambda); 44 | extern void CU2(QRegister *QReg, int control, int target, double phi, double lambda); 45 | extern void CU3(QRegister *QReg, int control, int target, double theta, double pie, double lambda); 46 | extern void CH(QRegister *QReg, int control, int target); 47 | extern void CX(QRegister *QReg, int control, int target); 48 | extern void CY(QRegister *QReg, int control, int target); 49 | extern void CZ(QRegister *QReg, int control, int target); 50 | extern void CRZ(QRegister *QReg, int control, int target, double angle); 51 | extern void CCX(QRegister *QReg, int control1, int control2, int target); 52 | extern void SWAP(QRegister *QReg, int qubit1, int qubit2); 53 | extern void CSWAP(QRegister *QReg, int control, int qubit1, int qubit2); 54 | extern void SX(QRegister *QReg, int qubit); 55 | extern void SXDG(QRegister *QReg, int qubit); 56 | extern void iSWAP(QRegister *QReg, int qubit1, int qubit2); 57 | extern int M(QRegister *QReg, int qubit); 58 | extern int MV(QRegister *QReg, int qubit); 59 | extern int MF(QRegister *QReg, int qubit, int collapse); 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /core/include/misc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file misc.h 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @brief 18 | */ 19 | 20 | #ifndef _MISC_H 21 | #define _MISC_H 22 | 23 | #include 24 | #include 25 | 26 | #include "precision.h" 27 | 28 | #define __bit_test(x,pos) ((x) & (1ULL<<(pos))) 29 | #define __bit_set(x,pos) ((x) | (1ULL<<(pos))) 30 | #define __bit_flip(x,pos) ((x) ^ (1ULL<<(pos))) 31 | #define __bit_reset(x,pos) ((x) & ~(1ULL<<(pos))) 32 | 33 | #define _F_ __FUNCTION__ 34 | #define _L_ __LINE__ 35 | 36 | struct qubit_delimiter { 37 | int size; 38 | int qubits[128]; 39 | }; 40 | 41 | typedef enum { 42 | KET_ZERO=0, 43 | KET_ONE, 44 | KET_PLUS, 45 | KET_MINUS, 46 | KET_LZERO, 47 | KET_LONE, 48 | KET_LPLUS, 49 | KET_LMINUS, 50 | KET_SUPERPOSED, 51 | KET_UNKNOWN 52 | } QUBIT_TYPE_T; 53 | 54 | typedef enum { 55 | TENSOR=0, 56 | ENTANGLE 57 | } QUBIT_RELATION; 58 | 59 | typedef enum { 60 | QGATE_ID = 0, 61 | QGATE_U1, 62 | QGATE_U2, 63 | QGATE_U3, 64 | QGATE_X, 65 | QGATE_Y, 66 | QGATE_Z, 67 | QGATE_H, 68 | QGATE_P, 69 | QGATE_S, 70 | QGATE_T, 71 | QGATE_SDG, 72 | QGATE_TDG, 73 | QGATE_RX, 74 | QGATE_RY, 75 | QGATE_RZ, 76 | QGATE_CX, 77 | QGATE_CZ, 78 | QGATE_CY, 79 | QGATE_CH, 80 | QGATE_CCX, 81 | QGATE_CRZ, 82 | QGATE_CU1, 83 | QGATE_CU2, 84 | QGATE_CU3, 85 | QGATE_SWAP, 86 | QGATE_CSWAP, 87 | QGATE_SX, 88 | QGATE_SXDG, 89 | QGATE_ISWAP, 90 | QGATE_MEASURE 91 | } QUANTUM_GATE; 92 | 93 | #define MAX_GATES 31 94 | 95 | struct qregister_stat { 96 | /* Quantum Circuit */ 97 | int qubits; 98 | int usedGates; 99 | int totalGateCalls; 100 | int gateCalls[MAX_GATES]; 101 | 102 | /* Execution Time */ 103 | double tm_total; /* micro seconds */ 104 | double tm_gate_max; /* micro seconds */ 105 | double tm_gate_min; /* micro seconds */ 106 | double tm_gate_avg; /* micro seconds */ 107 | 108 | double tm_gates_total[MAX_GATES]; /* micro seconds */ 109 | double tm_gates_max[MAX_GATES]; /* micro seconds */ 110 | double tm_gates_min[MAX_GATES]; /* micro seconds */ 111 | double tm_gates_avg[MAX_GATES]; /* micro seconds */ 112 | 113 | /* Quantum Circuit */ 114 | qsize_t maxQStates; 115 | qsize_t finalQStates; 116 | 117 | /* System Resources */ 118 | char os_name[64]; 119 | char os_version[64]; 120 | 121 | char cpu_model[64]; 122 | char cpu_herz[64]; 123 | int cpu_cores; 124 | 125 | uint64_t memTotal; /* bytes */ 126 | uint64_t memUsed; /* bytes */ 127 | uint64_t memAvail; /* bytes */ 128 | }; 129 | 130 | #define NUM_SIZES 8 131 | static inline char big_size_map(int idx) 132 | { 133 | char big_size_map[NUM_SIZES] = { 'B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z' }; 134 | 135 | return big_size_map[idx]; 136 | } 137 | 138 | static inline char small_size_map(int idx) 139 | { 140 | char small_size_map[NUM_SIZES] = { 'b', 'k', 'm', 'g', 't', 'p', 'e', 'z' }; 141 | 142 | return small_size_map[idx]; 143 | } 144 | 145 | static inline char *human_readable_size(uint64_t size, char *buf) 146 | { 147 | int i; 148 | float remain_ratio = size; 149 | 150 | for (i = 0; i < NUM_SIZES; i++) { 151 | if ((remain_ratio / 1024) < 1) { 152 | break; 153 | } 154 | remain_ratio = remain_ratio / 1024; 155 | } 156 | 157 | if (i >= NUM_SIZES) { 158 | sprintf(buf, "-"); 159 | } else { 160 | if(big_size_map(i) == 'B') { 161 | sprintf(buf, "%.1f %c", remain_ratio, big_size_map(i)); 162 | } else { 163 | sprintf(buf, "%.1f %cB", remain_ratio, big_size_map(i)); 164 | } 165 | } 166 | 167 | return buf; 168 | } 169 | 170 | extern void init_strides(void); 171 | extern qsize_t get_stride(int qubit); 172 | extern qsize_t quantum_shiftL(qsize_t left, qsize_t right); 173 | extern qsize_t quantum_shiftR(qsize_t left, qsize_t right); 174 | extern bool stripe_lower(qsize_t index, int qubit); 175 | extern bool stripe_upper(qsize_t index, int qubit); 176 | extern void print_binary(int size, qsize_t value); 177 | extern void print_binary(int size, qsize_t value, struct qubit_delimiter *qd); 178 | extern void to_binary(qsize_t state, qsize_t nq, char *qstring); 179 | extern char *modeString(int mode); 180 | extern char *relationString(int mode); 181 | extern int getSchmidtNumber(complex_t M[4]); 182 | extern char *gateString(int gate); 183 | extern void getMemory(uint64_t *memTotal, uint64_t *memAvail, uint64_t *memUsed); 184 | extern void getTotalMem(uint64_t *memTotal, uint64_t *memAvail); 185 | extern uint64_t getUsedMem(void); 186 | extern void getCPU(char *cpu, int *cores, char *herz); 187 | extern void getOS(char *name, char *version); 188 | extern char *getUsedMemHuman(char *buf); 189 | extern void showMemoryInfo(void); 190 | extern void sec2str(double tm, char *str); 191 | extern void msec2str(double tm, char *str); 192 | extern void usec2str(double tm, char *str); 193 | extern void nsec2str(double tm, char *str); 194 | extern void set_affinity(int coreid); 195 | extern bool isRealizedState(complex_t amp); 196 | 197 | #endif 198 | -------------------------------------------------------------------------------- /core/include/precision.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file precision.h 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @brief 18 | */ 19 | 20 | #ifndef _PRECISION_H 21 | #define _PRECISION_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | using namespace std; 29 | 30 | #define SQRT_2 (1.4142135623730950488016887242096980785696718753769480731766797379f) 31 | #define R_SQRT_2 (0.7071067811865475244008443621048490392848359376884740365883398690f) 32 | 33 | #define Q_PI 3.141592653589793238462643383279502884L 34 | 35 | #define AMPLITUDE_EPS 1e-13 36 | 37 | typedef __uint128_t qsize_t; 38 | 39 | #define MAX_QUBITS 128 40 | #define QSTORE_PARTITION 1171 41 | #define MAX_CORES 256 42 | 43 | typedef complex complex_t; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /core/include/qplayer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file qplayer.h 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @brief 18 | */ 19 | 20 | #ifndef _QPLAYER_H_ 21 | #define _QPLAYER_H_ 22 | 23 | #include "precision.h" 24 | #include "register.h" 25 | #include "gate.h" 26 | #include "timer.h" 27 | #include "misc.h" 28 | #include "dump.h" 29 | #include "experimental.h" 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /core/include/register.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file qregister.h 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @brief 18 | */ 19 | 20 | #ifndef _QREGISTER_H 21 | #define _QREGISTER_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include "precision.h" 39 | #include "state.h" 40 | #include "misc.h" 41 | 42 | using namespace std; 43 | 44 | #define QMAP std::map 45 | #define QMAPITER std::map::iterator 46 | 47 | class QRegister { 48 | private: 49 | int numQubit; 50 | int cpuCores; 51 | qsize_t maxStates; 52 | struct qregister_stat qstat; 53 | 54 | public: 55 | QMAP qstore[QSTORE_PARTITION]; 56 | QMAPITER qiter[QSTORE_PARTITION]; 57 | int qubitTypes[MAX_QUBITS]; 58 | 59 | public: 60 | QRegister(int n); 61 | QRegister(QRegister *src); 62 | ~QRegister(void); 63 | 64 | /* clear all quantum states */ 65 | void clear(void) { 66 | #pragma omp parallel for 67 | for(int i=0; i */ 76 | void init(void) { 77 | QState *q = getQState(0, complex_t(1, 0)); 78 | qstore[0][0] = q; 79 | init_strides(); 80 | for(int i=0; i */ 86 | void reset(void) { 87 | clear(); 88 | init(); 89 | } 90 | 91 | /* replace quantum state by using input QRegister */ 92 | void replace(QRegister *qreg) { 93 | QState *Q; 94 | 95 | clear(); 96 | 97 | qreg->setOrderedQState(); 98 | while((Q = qreg->getOrderedQState()) != NULL) { 99 | QState *newQ = getQState(Q->getIndex(), Q->getAmplitude()); 100 | addQState(newQ->getIndex(), newQ); 101 | } 102 | } 103 | 104 | /* return the number of qubits for this Q-register */ 105 | int getNumQubits(void) { return numQubit; } 106 | void setNumQubits(int n) { 107 | numQubit = n; 108 | maxStates = quantum_shiftL(1, numQubit); 109 | } 110 | 111 | /* return the number of CPU cores */ 112 | int getCPUCores(void) { return cpuCores; } 113 | 114 | /* return the total number of non-zero amplitude states */ 115 | qsize_t getNumStates() { 116 | qsize_t states = 0; 117 | 118 | for(int i=0; ifind(index); 147 | if(it != part->end()) { 148 | putQState(it->second); 149 | part->erase(it); 150 | } 151 | } 152 | 153 | /* search the quantum state corresponding to state index */ 154 | QState *findQState(qsize_t index) { 155 | QMAP *part = &qstore[getPartId(index)]; 156 | QMAPITER it; 157 | QState *Q = NULL; 158 | 159 | it = part->find(index); 160 | if(it != part->end()) { 161 | Q = it->second; 162 | } 163 | 164 | return Q; 165 | } 166 | 167 | /* Normalize amplitudes */ 168 | void normalize(void) { 169 | double lengthm[QSTORE_PARTITION]; 170 | double length = 0; 171 | 172 | for(int i=0; isecond; 181 | lengthm[i] += norm(Q->getAmplitude()); 182 | } 183 | } 184 | 185 | for(int i=0; isecond; 195 | Q->resizeAmplitude(length); 196 | } 197 | } 198 | } 199 | 200 | /* set all qstore iterators to the starting position */ 201 | void setOrderedQState() { 202 | for(int i =0; isecond->getIndex() < minState) { 219 | Q = qiter[i]->second; 220 | iterPos = i; 221 | minState = qiter[i]->second->getIndex(); 222 | } 223 | } 224 | 225 | if(iterPos != -1) { 226 | qiter[iterPos]++; 227 | } 228 | 229 | return Q; 230 | } 231 | 232 | /* cleanup all zero amplitude states */ 233 | void clearZeroStates() { 234 | #pragma omp parallel for 235 | for(int i=0; isecond; 239 | if(abs(Q->getAmplitude()) == 0) { 240 | putQState(Q); 241 | qstore[i].erase(it++); 242 | } else { 243 | ++it; 244 | } 245 | } 246 | } 247 | } 248 | 249 | public: 250 | void updateQRegStat(int gate, QTimer timer); 251 | struct qregister_stat getQRegStat(void); 252 | void showQRegStat(void); 253 | void checkMemory(void); 254 | }; 255 | 256 | #endif 257 | -------------------------------------------------------------------------------- /core/include/state.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file state.h 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @brief 18 | */ 19 | 20 | #ifndef _QSTATE_H 21 | #define _QSTATE_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include "precision.h" 39 | #include "timer.h" 40 | 41 | using namespace std; 42 | 43 | class QState { 44 | private: 45 | qsize_t index; 46 | complex_t amplitude; 47 | 48 | public: 49 | QState(void); 50 | QState(qsize_t i, complex_t a); 51 | QState(QState *Q); 52 | ~QState(void); 53 | 54 | complex_t getAmplitude() { return amplitude; } 55 | qsize_t getIndex() { return index; } 56 | 57 | void setIndex(qsize_t i) { index = i; } 58 | void setAmplitude(complex_t a) { amplitude = a; } 59 | void resizeAmplitude(complex_t a) { amplitude /= a; } 60 | }; 61 | 62 | extern QState *getQState(void); 63 | extern QState *getQState(qsize_t qidx, complex_t amp); 64 | extern void putQState(QState *Q); 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /core/include/timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file qtimer.h 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @brief 18 | */ 19 | 20 | #ifndef _QTIMER_H_ 21 | #define _QTIMER_H_ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | class QTimer { 30 | 31 | public: 32 | struct timespec startT; 33 | struct timespec endT; 34 | double elapsedSec; 35 | double elapsedMSec; 36 | double elapsedUSec; 37 | double elapsedNSec; 38 | char timeStr[32]; 39 | 40 | public: 41 | QTimer(void); 42 | ~QTimer(void); 43 | 44 | void start() { 45 | clock_gettime(CLOCK_MONOTONIC, &startT); 46 | } 47 | 48 | void end() { 49 | clock_gettime(CLOCK_MONOTONIC, &endT); 50 | elapsedNSec = ((endT.tv_sec - startT.tv_sec) * 1000000000LL) + (endT.tv_nsec - startT.tv_nsec); 51 | 52 | calculateTime(); 53 | } 54 | 55 | void lapStart() { 56 | clock_gettime(CLOCK_MONOTONIC, &startT); 57 | } 58 | 59 | void lapStop() { 60 | clock_gettime(CLOCK_MONOTONIC, &endT); 61 | elapsedNSec += ((endT.tv_sec - startT.tv_sec) * 1000000000LL) + (endT.tv_nsec - startT.tv_nsec); 62 | } 63 | 64 | void lapFinish() { 65 | lapStop(); 66 | calculateTime(); 67 | } 68 | 69 | void calculateTime() { 70 | elapsedUSec = elapsedNSec / 1000LL; 71 | elapsedMSec = elapsedNSec / 1000000LL; 72 | elapsedSec = elapsedNSec / 1000000000LL; 73 | 74 | int h = (int)elapsedSec / 3600; 75 | int m = (int)(((long)elapsedSec / 60) % 60); 76 | int s = (int)((long)elapsedSec % 60); 77 | 78 | if(s > 0) { 79 | double remainingMSec = elapsedMSec - ((uint64_t)elapsedSec * 1000LL); 80 | sprintf(timeStr, "%02d:%02d:%02d + %dms", h, m, s, (uint32_t)remainingMSec); 81 | } else if(elapsedMSec >= 1) { 82 | sprintf(timeStr, "%f ms", elapsedMSec); 83 | } else if(elapsedUSec >= 1 ) { 84 | sprintf(timeStr, "%f us", elapsedUSec); 85 | } else if(elapsedNSec > 0) { 86 | sprintf(timeStr, "%f ns", elapsedNSec); 87 | } 88 | } 89 | 90 | const char *getTime() { return timeStr; } 91 | double getElapsedSec() { return elapsedSec; } 92 | double getElapsedMSec() { return elapsedMSec; } 93 | double getElapsedUSec() { return elapsedUSec; } 94 | double getElapsedNSec() { return elapsedNSec; } 95 | }; 96 | 97 | #endif /* _QIMER_H_ */ 98 | -------------------------------------------------------------------------------- /core/module.mk: -------------------------------------------------------------------------------- 1 | QPLAYER_SRC = ./src/register.cpp 2 | QPLAYER_SRC += ./src/state.cpp 3 | QPLAYER_SRC += ./src/gate.cpp 4 | QPLAYER_SRC += ./src/timer.cpp 5 | QPLAYER_SRC += ./src/misc.cpp 6 | QPLAYER_SRC += ./src/dump.cpp 7 | QPLAYER_SRC += ./src/experimental.cpp 8 | 9 | QPLAYER_HDR = ./include/qplayer.h 10 | QPLAYER_HDR += ./include/precision.h 11 | QPLAYER_HDR += ./include/state.h 12 | QPLAYER_HDR += ./include/gate.h 13 | QPLAYER_HDR += ./include/register.h 14 | QPLAYER_HDR += ./include/timer.h 15 | QPLAYER_HDR += ./include/misc.h 16 | QPLAYER_HDR += ./include/dump.h 17 | QPLAYER_HDR += ./include/experimental.h 18 | -------------------------------------------------------------------------------- /core/src/dump.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file dump.cpp 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @date 10-09-21 18 | * @brief 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "precision.h" 37 | #include "register.h" 38 | #include "state.h" 39 | #include "misc.h" 40 | 41 | // #define FLAG_QINDEX 42 | #define FLAG_QPROB 43 | 44 | void dump(QRegister *QReg, char *msg, int begin, int end, struct qubit_delimiter *qd) 45 | { 46 | QState *Q; 47 | qsize_t totalStates = QReg->getNumStates(); 48 | int numQubits = QReg->getNumQubits(); 49 | 50 | QReg->setOrderedQState(); 51 | while ((Q = QReg->getOrderedQState()) != NULL) { 52 | double real = Q->getAmplitude().real(); 53 | double imag = Q->getAmplitude().imag(); 54 | double p = norm(Q->getAmplitude()); 55 | char qstring[1024] = ""; 56 | 57 | #ifdef FLAG_QINDEX 58 | printf("[%15ld] ", (uint64_t) Q->getIndex()); 59 | #endif 60 | 61 | #ifdef FLAG_QPROB 62 | printf("[P=%f] ", p); 63 | if (real >= 0 && imag >= 0) { 64 | printf("[+%.6f, +%.6f] ", abs(real), abs(imag)); 65 | } else if (real >= 0 && imag < 0) { 66 | printf("[+%.6f, %.6f] ", abs(real), imag); 67 | } else if (real < 0 && imag >= 0) { 68 | printf("[%.6f, +%.6f] ", real, abs(imag)); 69 | } else { 70 | printf("[%.6f, %.6f] ", real, imag); 71 | } 72 | #else 73 | if (real >= 0 && imag >= 0) { 74 | printf("+"); 75 | } else if (real >= 0 && imag < 0) { 76 | printf("+"); 77 | } else if (real < 0 && imag >= 0) { 78 | printf("-"); 79 | } else { 80 | printf("-"); 81 | } 82 | #endif 83 | 84 | printf("|"); 85 | to_binary(Q->getIndex(), numQubits, qstring); 86 | for (int i = end; i >= begin; i--) { 87 | if (qd != NULL) { 88 | for (int j = 0; j < qd->size; j++) { 89 | if (i == qd->qubits[j]) { 90 | printf(" "); 91 | break; 92 | } 93 | } 94 | } 95 | printf("%c", qstring[numQubits - i - 1]); 96 | } 97 | printf(">\n"); 98 | } 99 | 100 | if (msg != NULL) { 101 | printf("======== [%s] dump quantum states(%lu) ========\n", msg, (uint64_t) totalStates); 102 | } else { 103 | printf("======== dump quantum states(%lu) ========\n", (uint64_t) totalStates); 104 | } 105 | } 106 | 107 | void dump(QRegister *QReg, char *msg, int begin, int end, struct qubit_delimiter qd) 108 | { 109 | dump(QReg, msg, begin, end, &qd); 110 | } 111 | 112 | void dump(QRegister *QReg, char *msg, struct qubit_delimiter *qd) 113 | { 114 | dump(QReg, msg, 0, QReg->getNumQubits() - 1, qd); 115 | } 116 | 117 | void dump(QRegister *QReg, char *msg, struct qubit_delimiter qd) 118 | { 119 | dump(QReg, msg, 0, QReg->getNumQubits() - 1, &qd); 120 | } 121 | 122 | void dump(QRegister *QReg, struct qubit_delimiter *qd) 123 | { 124 | dump(QReg, NULL, 0, QReg->getNumQubits() - 1, qd); 125 | } 126 | 127 | void dump(QRegister *QReg, struct qubit_delimiter qd) 128 | { 129 | dump(QReg, NULL, 0, QReg->getNumQubits() - 1, &qd); 130 | } 131 | 132 | void dump(QRegister *QReg, int begin, int end) 133 | { 134 | dump(QReg, NULL, 0, QReg->getNumQubits() - 1, NULL); 135 | } 136 | 137 | void dump(QRegister *QReg, char *msg) 138 | { 139 | dump(QReg, msg, 0, QReg->getNumQubits() - 1, NULL); 140 | } 141 | 142 | void dump(QRegister *QReg) 143 | { 144 | dump(QReg, NULL, 0, QReg->getNumQubits() - 1, NULL); 145 | } 146 | 147 | void dumpln(QRegister *QReg) 148 | { 149 | dump(QReg, NULL, 0, QReg->getNumQubits() - 1, NULL); 150 | printf("\n"); 151 | } 152 | -------------------------------------------------------------------------------- /core/src/experimental.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file gate.cpp 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @date 10-09-21 18 | * @brief 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "register.h" 26 | #include "experimental.h" 27 | #include "gate.h" 28 | #include "dump.h" 29 | 30 | using namespace std; 31 | 32 | std::mutex lock_is_entangle; 33 | std::mutex lock_add_entangle; 34 | 35 | 36 | void showEntangle(std::vector> eGroups) 37 | { 38 | printf("entanglement qubits.... \n"); 39 | for(auto group : eGroups) { 40 | printf("\t"); 41 | for(auto qubit : group) { 42 | printf("%d ", qubit); 43 | } 44 | printf("\n"); 45 | } 46 | } 47 | 48 | bool __is_entangle(std::vector>& eGroups, int q1, int q2) 49 | { 50 | lock_is_entangle.lock(); 51 | 52 | for(auto group : eGroups) { 53 | bool find_q1 = false; 54 | bool find_q2 = false; 55 | for(auto qubit : group) { 56 | if(qubit == q1) { 57 | find_q1 = true; 58 | } else if(qubit == q2) { 59 | find_q2 = true; 60 | } 61 | 62 | if(find_q1 == true && find_q2 == true) { 63 | lock_is_entangle.unlock(); 64 | return true; 65 | } 66 | } 67 | } 68 | 69 | lock_is_entangle.unlock(); 70 | 71 | return false; 72 | } 73 | 74 | bool __is_samestates(QRegister *QReg1, QRegister *QReg2) 75 | { 76 | QState *Q1 = NULL; 77 | QState *Q2 = NULL; 78 | bool positive_same = true; 79 | bool negative_same = true; 80 | double real1 = 0; 81 | double real2 = 0; 82 | double imag1 = 0; 83 | double imag2 = 0; 84 | double delta = 0.0000000000001; 85 | 86 | /* check normal phase */ 87 | QReg1->setOrderedQState(); 88 | QReg2->setOrderedQState(); 89 | do { 90 | Q1 = QReg1->getOrderedQState(); 91 | Q2 = QReg2->getOrderedQState(); 92 | 93 | if(Q1 == NULL || Q2 == NULL) { 94 | break; 95 | } 96 | 97 | real1 = Q1->getAmplitude().real(); 98 | imag1 = Q1->getAmplitude().imag(); 99 | real2 = Q2->getAmplitude().real(); 100 | imag2 = Q2->getAmplitude().imag(); 101 | 102 | if(((real1 != real2) && (real1-real2) > delta) || 103 | ((imag1 != imag2) && (imag1-imag2) > delta)) { 104 | positive_same = false; 105 | break; 106 | } 107 | } while(1); 108 | 109 | if(positive_same == true) { 110 | return true; 111 | } 112 | 113 | /* check normal phase */ 114 | QReg1->setOrderedQState(); 115 | QReg2->setOrderedQState(); 116 | do { 117 | Q1 = QReg1->getOrderedQState(); 118 | Q2 = QReg2->getOrderedQState(); 119 | 120 | if(Q1 == NULL || Q2 == NULL) { 121 | break; 122 | } 123 | 124 | real1 = Q1->getAmplitude().real(); 125 | imag1 = Q1->getAmplitude().imag(); 126 | real2 = Q2->getAmplitude().real() * -1.0; 127 | imag2 = Q2->getAmplitude().imag() * -1.0; 128 | 129 | if(((real1 != real2) && (real1-real2) > delta) || 130 | ((imag1 != imag2) && (imag1-imag2) > delta)) { 131 | negative_same = false; 132 | break; 133 | } 134 | } while(1); 135 | 136 | if(positive_same == true || negative_same == true) { 137 | return true; 138 | } 139 | 140 | return false; 141 | } 142 | 143 | void __add_entangle(std::vector>& eGroups, int q1, int q2) 144 | { 145 | bool found = false; 146 | int gsize = eGroups.size(); 147 | int group1 = -1; 148 | int group2 = -1; 149 | 150 | lock_add_entangle.lock(); 151 | 152 | /* find previous entangle group of q1, q2 */ 153 | for(int i=0; i group; 166 | group.push_back(q1); 167 | group.push_back(q2); 168 | eGroups.push_back(group); 169 | } else if(group1 != -1 && group2 == -1) { 170 | /* add q2 into q1 group */ 171 | eGroups[group1].push_back(q2); 172 | } else if(group1 == -1 && group2 != -1) { 173 | /* add q1 into q0 group */ 174 | eGroups[group2].push_back(q1); 175 | } else { 176 | /* merge q1 and q2 group */ 177 | for(auto qubit : eGroups[group2]) { 178 | eGroups[group1].push_back(qubit); 179 | } 180 | eGroups.erase(eGroups.begin() + group2); 181 | } 182 | 183 | lock_add_entangle.unlock(); 184 | } 185 | 186 | void __updateCandidates(std::vector& candidates, std::vector>& eGroups) 187 | { 188 | for(auto group : eGroups) { 189 | int Q1 = group.front(); 190 | for(auto Q2 : group) { 191 | if(Q1 == Q2) { 192 | continue; 193 | } 194 | 195 | /* remove Q2 from candidates */ 196 | std::remove(candidates.begin(), candidates.end(), Q2); 197 | candidates.resize(candidates.size()-1); 198 | } 199 | } 200 | } 201 | 202 | void __estimation_step1(QRegister *QReg, std::vector candidates, std::vector>& eGroups) 203 | { 204 | int qubits = QReg->getNumQubits(); 205 | int candidateQubits = candidates.size(); 206 | int Q1 = 0; 207 | int Q2 = 0; 208 | 209 | for(int i=0; i candidates, std::vector>& eGroups) 234 | { 235 | int qubits = QReg->getNumQubits(); 236 | int candidateQubits = candidates.size(); 237 | int Q1 = 0; 238 | int Q2 = 0; 239 | 240 | for(int i=0; i candidates, std::vector>& eGroups) 266 | { 267 | int qubits = QReg->getNumQubits(); 268 | int candidateQubits = candidates.size(); 269 | QState *Q = NULL; 270 | QState *newQ = NULL; 271 | int Q1 = 0; 272 | int Q2 = 0; 273 | 274 | for(int i=0; iclear(); 294 | QRegClone->setOrderedQState(); 295 | while((Q = QRegClone->getOrderedQState()) != NULL) { 296 | qsize_t newIdx = Q->getIndex() & mask; 297 | newQ = QRegMask->findQState(newIdx); 298 | if(newQ == NULL) { 299 | newQ = getQState(newIdx, Q->getAmplitude()); 300 | QRegMask->addQState(newIdx, newQ); 301 | } 302 | } 303 | 304 | 305 | /* build matrix for schmit number */ 306 | QRegMask->normalize(); 307 | QRegMask->setOrderedQState(); 308 | while((Q = QRegMask->getOrderedQState()) != NULL) { 309 | qsize_t newIdx = Q->getIndex() & mask; 310 | int oneQ1 = 0; 311 | int oneQ2 = 0; 312 | 313 | if(newIdx & maskQ1) { oneQ1 = 1; } 314 | if(newIdx & maskQ2) { oneQ2 = 1; } 315 | 316 | 317 | if(oneQ1 == 0 && oneQ2 == 0) { Matrix[0] = Q->getAmplitude(); } 318 | else if(oneQ1 == 0 && oneQ2 == 1) { Matrix[1] = Q->getAmplitude(); } 319 | else if(oneQ1 == 1 && oneQ2 == 0) { Matrix[2] = Q->getAmplitude(); } 320 | else if(oneQ1 == 1 && oneQ2 == 1) { Matrix[3] = Q->getAmplitude(); } 321 | } 322 | 323 | if(getSchmidtNumber(Matrix) != 1) { 324 | // dumpln(QRegMask); 325 | __add_entangle(eGroups, Q1, Q2); 326 | } 327 | 328 | delete QRegMask; 329 | } 330 | 331 | delete QRegClone; 332 | } 333 | 334 | __updateCandidates(candidates, eGroups); 335 | } 336 | 337 | void __estimation_step3(QRegister *QReg, std::vector candidates, std::vector>& eGroups) 338 | { 339 | /* inspect as original quantum states */ 340 | __estimation_step3_internal(QReg, candidates, eGroups); 341 | 342 | for(auto qubit : candidates) { 343 | QRegister *QRegClone = new QRegister(QReg); 344 | 345 | MF(QRegClone, qubit, 0); 346 | __estimation_step3_internal(QRegClone, candidates, eGroups); 347 | 348 | delete QRegClone; 349 | } 350 | } 351 | 352 | void entangle_estimation(QRegister *QReg, std::vector>& eGroups) 353 | { 354 | QRegister *QRegClone = new QRegister(QReg); 355 | QRegister *QRegs[128]; 356 | int qubits = QReg->getNumQubits(); 357 | std::vector candidates; 358 | 359 | for (int i = 0; i < qubits; i++) { 360 | if (QType(QReg, i) == KET_ZERO || QType(QReg, i) == KET_ONE) { 361 | continue; 362 | } 363 | candidates.push_back(i); 364 | } 365 | std::sort(candidates.begin(), candidates.end()); 366 | 367 | __estimation_step1(QRegClone, candidates, eGroups); 368 | __estimation_step2(QRegClone, candidates, eGroups); 369 | __estimation_step3(QRegClone, candidates, eGroups); 370 | 371 | for(int i=0; i>& eGroups) { 382 | entangle_estimation(QReg, eGroups); 383 | } 384 | 385 | void getEntanglements(QRegister *QReg) { 386 | std::vector> eGroups; 387 | getEntanglements(QReg, eGroups); 388 | 389 | printf("========== Entanglement Groups ==========\n"); 390 | for(auto group : eGroups) { 391 | for(auto qubit : group) { 392 | printf("%d ", qubit); 393 | } 394 | printf("\n"); 395 | } 396 | } 397 | 398 | /* 399 | * Estimate the quantum state int four types below. 400 | * 401 | * - KET_ZERO : |0> 402 | * - KET_ONE : |1> 403 | * - KET_SUPERPOSED : a|0> + b|1> or a|0> - b|1> 404 | */ 405 | int QType(QRegister *QReg, int qubit) 406 | { 407 | QState *Q = NULL; 408 | qsize_t qidx = 0; 409 | bool isLower = false; 410 | bool isUpper = false; 411 | int type = KET_UNKNOWN; 412 | 413 | #pragma omp parallel for 414 | for(int i=0; iqstore[i].begin(); it != QReg->qstore[i].end(); it++) { 420 | Q = it->second; 421 | qidx = Q->getIndex(); 422 | 423 | if(stripe_lower(qidx, qubit) == true) { 424 | isLowerLocal = true; 425 | } else { 426 | isUpperLocal = true; 427 | } 428 | 429 | if(isLowerLocal == true && isUpperLocal == true) { 430 | break; 431 | } 432 | } 433 | 434 | if(isLowerLocal == true) isLower = true; 435 | if(isUpperLocal == true) isUpper = true; 436 | } 437 | 438 | if(isLower == true && isUpper == true) { 439 | type = KET_SUPERPOSED; 440 | } else if(isLower == true) { 441 | type = KET_ZERO; 442 | } else if(isUpper == true) { 443 | type = KET_ONE; 444 | } 445 | 446 | return type; 447 | } 448 | 449 | char *QTypeStr(QRegister *QReg, int qubit) 450 | { 451 | int type = QType(QReg, qubit); 452 | 453 | if(type == KET_ZERO) return "|0>"; 454 | else if(type == KET_ONE) return "|1>"; 455 | else if(type == KET_SUPERPOSED) return "|S>"; 456 | 457 | return "UNKNOWN"; 458 | } 459 | 460 | /* 461 | * show probability of the qubit 462 | */ 463 | double getQubitProb(QRegister *QReg, int qubit, int state) 464 | { 465 | if(qubit >= QReg->getNumQubits()) { 466 | printf("[%s] qubit(%d) out of range!\n", __func__, qubit); 467 | exit(0); 468 | } 469 | 470 | double real = 0; 471 | double imag = 0; 472 | double length = 0; 473 | complex_t lo = 0; 474 | complex_t up = 0; 475 | 476 | QMAPITER it[QSTORE_PARTITION]; 477 | for(int i=0; iqstore[i].begin(); it[i] != QReg->qstore[i].end(); it[i]++) { 479 | QState *Q = it[i]->second; 480 | real = Q->getAmplitude().real(); 481 | imag = Q->getAmplitude().imag(); 482 | if(stripe_lower(Q->getIndex(), qubit) == true) { 483 | lo += complex_t(abs(real), abs(imag)); 484 | } else { 485 | up += complex_t(abs(real), abs(imag)); 486 | } 487 | } 488 | } 489 | 490 | /* normalize */ 491 | length = (norm(lo) + norm(up)); 492 | length = std::sqrt(length); 493 | 494 | lo = lo / length; 495 | up = up / length; 496 | 497 | if(state == KET_ZERO) { 498 | return norm(lo); 499 | } else if(state == KET_ONE) { 500 | return norm(up); 501 | } 502 | 503 | return 0; 504 | } 505 | -------------------------------------------------------------------------------- /core/src/misc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file misc.cpp 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @brief 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "precision.h" 25 | #include "misc.h" 26 | 27 | using namespace std; 28 | 29 | static qsize_t strides[MAX_QUBITS]; 30 | 31 | std::ostream& 32 | operator<<( std::ostream& dest, qsize_t value) 33 | { 34 | std::ostream::sentry s( dest ); 35 | if ( s ) { 36 | __uint128_t tmp = value < 0 ? -value : value; 37 | char buffer[ 128 ]; 38 | char* d = std::end( buffer ); 39 | do 40 | { 41 | -- d; 42 | *d = "0123456789"[ tmp % 10 ]; 43 | tmp /= 10; 44 | } while ( tmp != 0 ); 45 | if ( value < 0 ) { 46 | -- d; 47 | *d = '-'; 48 | } 49 | int len = std::end( buffer ) - d; 50 | if ( dest.rdbuf()->sputn( d, len ) != len ) { 51 | dest.setstate( std::ios_base::badbit ); 52 | } 53 | } 54 | return dest; 55 | } 56 | 57 | void init_strides(void) 58 | { 59 | for(int i=0; i> right; 77 | } 78 | 79 | /* 80 | * Check if the qubit in the lower bound of stripe. The meaning of 81 | * lower/upper bound is illustrated in the example below. 82 | * 83 | * Q1 Q0 84 | * |00> lower lower 85 | * |01> lower upper 86 | * |10> upper lower 87 | * |11> upper upper 88 | */ 89 | bool stripe_lower(qsize_t index, int qubit) 90 | { 91 | qsize_t stride = strides[qubit]; 92 | 93 | if((index & stride) != stride) { 94 | return true; 95 | } 96 | 97 | return false; 98 | } 99 | 100 | /* 101 | * Check if the qubit in the upper bound of stripe 102 | */ 103 | bool stripe_upper(qsize_t index, int qubit) 104 | { 105 | qsize_t stride = strides[qubit]; 106 | 107 | if((index & stride) == stride) { 108 | return true; 109 | } 110 | 111 | return false; 112 | } 113 | 114 | /* 115 | * Displays quantum state. Each qubit is printed in reverse order. 116 | * 117 | * param state : index of quantum states 118 | * param nq : total number of qubits 119 | * 120 | * Let's suppose a mixed state of two qubits as follows. 121 | * - number of qubit : 2 122 | * - quantum states : 4 2^2 123 | * - outputs are... 124 | * if(state == 0) --> |00> 125 | * else if(state == 1) --> |01> --> q0=1, q1=0 126 | * else if(state == 2) --> |10> --> q0=0, q1=1 127 | * else if(state == 3) --> |11> 128 | */ 129 | void to_binary(qsize_t state, qsize_t nq, char *qstring) 130 | { 131 | int pos = 0; 132 | while (nq--) { 133 | qstring[pos++] = ((quantum_shiftR(state, nq)) & 1) ? '1' : '0'; 134 | } 135 | } 136 | 137 | void print_binary(int size, qsize_t value) 138 | { 139 | for(int i=size-1; i>=0; i--) { 140 | cout << ((value >> i) & 1L); 141 | } 142 | printf("\n"); 143 | } 144 | 145 | void print_binary(int size, qsize_t value, struct qubit_delimiter *qd) 146 | { 147 | for(int i=size-1; i>=0; i--) { 148 | if(qd != NULL) { 149 | for(int j=0; jsize; j++) { 150 | if(i == qd->qubits[j]) { 151 | printf(" "); 152 | break; 153 | } 154 | } 155 | } 156 | cout << ((value >> i) & 1L); 157 | } 158 | printf("\n"); 159 | } 160 | 161 | char *modeString(int mode) { 162 | if(mode == KET_ZERO) { 163 | return "|0>"; 164 | } else if(mode == KET_ONE) { 165 | return "|1>"; 166 | } else if(mode == KET_PLUS) { 167 | return "|+>"; 168 | } else if(mode == KET_MINUS) { 169 | return "|->"; 170 | } else if(mode == KET_LZERO) { 171 | return "|L0>"; 172 | } else if(mode == KET_LONE) { 173 | return "|L1>"; 174 | } else if(mode == KET_LPLUS) { 175 | return "|L+>"; 176 | } else if(mode == KET_LMINUS) { 177 | return "|L->"; 178 | } 179 | 180 | return "UNKNOWN"; 181 | } 182 | 183 | char *relationString(int type) { 184 | if(type == TENSOR) { 185 | return "TENSOR PRODUCT"; 186 | } else if(type == ENTANGLE) { 187 | return "ENTANGLE STATE"; 188 | } 189 | 190 | return "UNKNOWN"; 191 | } 192 | 193 | 194 | static void OuterProduct(complex_t S[4], complex_t **PT) 195 | { 196 | complex_t OM[16]; 197 | 198 | for(int i=0; i<4; i++) 199 | for(int j=0; j<4; j++) 200 | OM[i*4+j] = S[i] * S[j]; 201 | 202 | #if 0 203 | printf("--> density matrix\n"); 204 | for(int i=0; i<16; i++) { 205 | cout << OM[i] << " "; 206 | } 207 | cout << endl << endl; 208 | #endif 209 | 210 | (*PT)[0] = OM[0] + OM[9]; 211 | (*PT)[1] = OM[2] + OM[11]; 212 | (*PT)[2] = OM[4] + OM[13]; 213 | (*PT)[3] = OM[6] + OM[15]; 214 | } 215 | 216 | static int QRDecompositionMethod(complex_t M[2][2]) 217 | { 218 | int SchmidtNum = 0; 219 | int maxIteration = 1000; 220 | int iteration = 0; 221 | double eps = 1E-13; 222 | 223 | while (iteration < maxIteration) { 224 | complex_t MR[2][2]; 225 | complex_t MQ[2][2]; 226 | 227 | for(int i=0; i<2; i++) 228 | for(int j=0; j<2; j++) 229 | MR[i][j] = MQ[i][j] = 0; 230 | 231 | for (int j = 0; j < 2; j++) { 232 | for (int i = 0; i < j; i++) 233 | for (int k = 0; k < 2; k++) 234 | MR[i][j] += M[k][j] * MQ[k][i]; 235 | 236 | for (int i = 0; i < 2; i++) { 237 | MQ[i][j] = M[i][j]; 238 | 239 | for (int k = 0; k < j; k++) 240 | MQ[i][j] -= MR[k][j] * MQ[i][k]; 241 | 242 | MR[j][j] += MQ[i][j] * MQ[i][j]; 243 | } 244 | 245 | MR[j][j] = sqrt(MR[j][j]); 246 | 247 | for (int i = 0; i < 2; i++) { 248 | MQ[i][j] /= MR[j][j]; 249 | } 250 | } 251 | 252 | double max = 0; 253 | 254 | for (int i = 0; i < 2; i++) 255 | for (int j = i + 1; j < 2; j++) 256 | if (norm(MQ[i][j]) > max) 257 | max = norm(MQ[i][j]); 258 | 259 | if (max < eps) 260 | break; 261 | 262 | M[0][0] = (MR[0][0] * MQ[0][0]) + (MR[0][1] * MQ[1][0]); 263 | M[0][1] = (MR[0][0] * MQ[0][1]) + (MR[0][1] * MQ[1][1]); 264 | M[1][0] = (MR[1][0] * MQ[0][0]) + (MR[1][1] * MQ[1][0]); 265 | M[1][1] = (MR[1][0] * MQ[0][1]) + (MR[1][1] * MQ[1][1]); 266 | iteration++; 267 | } 268 | 269 | if (iteration != maxIteration) { 270 | complex_t eigenvalues[2]; 271 | for (int i = 0; i < 2; i++) { 272 | bool found = false; 273 | 274 | if (norm(M[i][i]) < eps) { 275 | continue; 276 | } 277 | 278 | eigenvalues[SchmidtNum++] = M[i][i]; 279 | } 280 | } 281 | 282 | #if 0 283 | cout << "SchmidtNum = " << SchmidtNum << endl; 284 | #endif 285 | 286 | return SchmidtNum; 287 | } 288 | 289 | int getSchmidtNumber(complex_t M[4]) 290 | { 291 | complex_t *PT = (complex_t *)malloc(sizeof(complex_t) * 4); 292 | complex_t MT[2][2]; 293 | 294 | OuterProduct(M, &PT); 295 | 296 | #if 0 297 | printf("--> partial traces\n"); 298 | for(int i=0; i<4; i++) { 299 | cout << PT[i] << " "; 300 | } 301 | cout << endl << endl; 302 | #endif 303 | 304 | MT[0][0] = PT[0]; 305 | MT[0][1] = PT[1]; 306 | MT[1][0] = PT[2]; 307 | MT[1][1] = PT[3]; 308 | 309 | free(PT); 310 | 311 | return QRDecompositionMethod(MT); 312 | } 313 | 314 | char *gateString(int gate) 315 | { 316 | switch(gate) { 317 | case QGATE_ID: return "ID"; 318 | case QGATE_U1: return "U1"; 319 | case QGATE_U2: return "U2"; 320 | case QGATE_U3: return "U3"; 321 | case QGATE_X: return "Pauli-X"; 322 | case QGATE_Y: return "Pauli-Y"; 323 | case QGATE_Z: return "Pauli-Z"; 324 | case QGATE_H: return "H"; 325 | case QGATE_P: return "P"; 326 | case QGATE_S: return "S"; 327 | case QGATE_T: return "T"; 328 | case QGATE_SDG: return "SDG"; 329 | case QGATE_TDG: return "TDG"; 330 | case QGATE_RX: return "RX"; 331 | case QGATE_RY: return "RY"; 332 | case QGATE_RZ: return "RZ"; 333 | case QGATE_CX: return "CX"; 334 | case QGATE_CZ: return "CZ"; 335 | case QGATE_CY: return "CY"; 336 | case QGATE_CH: return "CH"; 337 | case QGATE_CCX: return "CCX"; 338 | case QGATE_CRZ: return "CRZ"; 339 | case QGATE_CU1: return "CU1"; 340 | case QGATE_CU2: return "CU2"; 341 | case QGATE_CU3: return "CU3"; 342 | case QGATE_SWAP: return "SWAP"; 343 | case QGATE_CSWAP: return "CSWAP"; 344 | case QGATE_SX: return "SX"; 345 | case QGATE_SXDG: return "SXDG"; 346 | case QGATE_ISWAP: return "ISWAP"; 347 | case QGATE_MEASURE: return "MEASURE"; 348 | } 349 | 350 | return "UNKNOWN GATE"; 351 | } 352 | 353 | /* 354 | * get pysical memory size(bytes) for this system 355 | */ 356 | void getTotalMem(uint64_t *memTotal, uint64_t *memAvail) { 357 | FILE *fp = NULL; 358 | 359 | *memTotal = 0; 360 | *memAvail = 0; 361 | fp = fopen("/proc/meminfo", "rt"); 362 | if(fp == NULL) { 363 | return; 364 | } 365 | 366 | while(!feof(fp)) { 367 | char cmd[256] = ""; 368 | char kb[256] = ""; 369 | char unit[256] = ""; 370 | 371 | fscanf(fp, "%s %s %s\n", cmd, kb, unit); 372 | if(strcmp(cmd, "MemTotal:") == 0) { 373 | *memTotal = (uint64_t)atoi(kb) * 1024ULL; 374 | } else if(strcmp(cmd, "MemAvailable:") == 0) { 375 | *memAvail = (uint64_t)atoi(kb) * 1024ULL; 376 | } 377 | } 378 | 379 | fclose(fp); 380 | } 381 | 382 | /* 383 | * get free memory size(bytes) for this system 384 | */ 385 | uint64_t getUsedMem(void) { 386 | FILE *fp = NULL; 387 | char fname[256] = ""; 388 | char cmd[256] = ""; 389 | char size[32] = ""; 390 | uint64_t memFree = 0; 391 | 392 | sprintf(fname, "/proc/%d/status", getpid()); 393 | 394 | fp = fopen(fname, "r"); 395 | if(fp == NULL) { 396 | return 0; 397 | } 398 | 399 | while(fgets(cmd, 256, fp) != NULL) { 400 | if(strstr(cmd, "VmHWM")) { 401 | char t[32] = ""; 402 | sscanf(cmd, "%s%s", t, size); 403 | memFree = (uint64_t)atoi(size) * 1024ULL; 404 | break; 405 | } 406 | } 407 | 408 | fclose(fp); 409 | 410 | return memFree; 411 | } 412 | 413 | /* 414 | * get pysical memory size(bytes) for this system 415 | */ 416 | void getMemory(uint64_t *memTotal, uint64_t *memAvail, uint64_t *memUsed) 417 | { 418 | getTotalMem(memTotal, memAvail); 419 | *memUsed = getUsedMem(); 420 | } 421 | 422 | 423 | void getCPU(char *cpu, int *cores, char *herz) 424 | { 425 | FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); 426 | char line[256]; 427 | 428 | if(cpuinfo == NULL) { 429 | return; 430 | } 431 | 432 | *cores = *herz = 0; 433 | 434 | while(fgets(line, sizeof(line), cpuinfo)) { 435 | if(strncmp(line, "model name", 10) == 0) { 436 | char *str = strchr(line, ':'); 437 | if(str != NULL) { 438 | str++; 439 | while(*str == ' ') { 440 | ++str; 441 | } 442 | strcpy(cpu, str); 443 | cpu[strlen(cpu)-1] = '\0'; 444 | } 445 | } else if(strncmp(line, "cpu MHz", 7) == 0) { 446 | char *str = strchr(line, ':'); 447 | if(str != NULL) { 448 | str++; 449 | while(*str == ' ') { 450 | ++str; 451 | } 452 | strcpy(herz, str); 453 | herz[strlen(herz)-1] = '\0'; 454 | } 455 | } else if(strncmp(line, "processor", 9) == 0) { 456 | (*cores)++; 457 | } 458 | } 459 | 460 | fclose(cpuinfo); 461 | } 462 | 463 | void getOS(char *name, char *version) 464 | { 465 | FILE* osinfo = fopen("/etc/os-release", "r"); 466 | char line[256]; 467 | 468 | if(osinfo == NULL) { 469 | return; 470 | } 471 | 472 | while(fgets(line, sizeof(line), osinfo)) { 473 | if(strncmp(line, "NAME=", 5) == 0) { 474 | char *str = strchr(line, '"'); 475 | if(str != NULL) { 476 | str++; 477 | strcpy(name, str); 478 | name[strlen(name)-2] = '\0'; 479 | } 480 | } else if(strncmp(line, "VERSION=", 8) == 0) { 481 | char *str = strchr(line, '"'); 482 | if(str != NULL) { 483 | str++; 484 | strcpy(version, str); 485 | version[strlen(version)-2] = '\0'; 486 | } 487 | } 488 | } 489 | 490 | fclose(osinfo); 491 | } 492 | 493 | char *getUsedMemHuman(char *buf) 494 | { 495 | uint64_t mem = getUsedMem(); 496 | 497 | human_readable_size(mem, buf); 498 | 499 | return buf; 500 | } 501 | 502 | void showMemoryInfo(void) 503 | { 504 | uint64_t memTotal = 0; 505 | uint64_t memAvail = 0; 506 | uint64_t memUsed = 0; 507 | 508 | char memTotalStr[32] = ""; 509 | char memAvailStr[32] = ""; 510 | char memUsedStr[32] = ""; 511 | 512 | getTotalMem(&memTotal, &memAvail); 513 | memUsed = getUsedMem(); 514 | 515 | human_readable_size(memTotal, memTotalStr); 516 | human_readable_size(memAvail, memAvailStr); 517 | human_readable_size(memUsed, memUsedStr); 518 | 519 | printf("Total:%s, Avail=%s --> Used:%s\n", memTotalStr, memAvailStr, memUsedStr); 520 | } 521 | 522 | void sec2str(double tm, char *str) 523 | { 524 | return nsec2str(tm * 1000000000LL, str); 525 | } 526 | 527 | void msec2str(double tm, char *str) 528 | { 529 | return nsec2str(tm * 1000000LL, str); 530 | } 531 | 532 | void usec2str(double tm, char *str) 533 | { 534 | return nsec2str(tm * 1000LL, str); 535 | } 536 | 537 | void nsec2str(double tm, char *str) 538 | { 539 | double elapsedNSec = tm; 540 | double elapsedUSec = elapsedNSec / 1000LL; 541 | double elapsedMSec = elapsedNSec / 1000000LL; 542 | double elapsedSec = elapsedNSec / 1000000000LL; 543 | 544 | int h = (int)elapsedSec / 3600; 545 | int m = (int)(((long)elapsedSec / 60) % 60); 546 | int s = (int)((long)elapsedSec % 60); 547 | 548 | if(s > 0) { 549 | double remainingMSec = elapsedMSec - ((uint64_t)elapsedSec * 1000LL); 550 | sprintf(str, "%02d:%02d:%02d + %dms", h, m, s, (uint32_t)remainingMSec); 551 | } else if(elapsedMSec >= 1) { 552 | sprintf(str, "%f ms", elapsedMSec); 553 | } else if(elapsedUSec >= 1 ) { 554 | sprintf(str, "%f us", elapsedUSec); 555 | } else if(elapsedNSec > 0) { 556 | sprintf(str, "%f ns", elapsedNSec); 557 | } 558 | } 559 | 560 | void set_affinity(int coreid) 561 | { 562 | cpu_set_t cpuset; 563 | CPU_ZERO(&cpuset); 564 | CPU_SET(coreid, &cpuset); 565 | pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); 566 | } 567 | 568 | bool isRealizedState(complex_t amp) 569 | { 570 | #if 1 571 | if(norm(amp) > AMPLITUDE_EPS) { 572 | return true; 573 | } else { 574 | return false; 575 | } 576 | #else 577 | if(abs(amp.real()) > AMPLITUDE_EPS || abs(amp.imag()) > AMPLITUDE_EPS) { 578 | return true; 579 | } else { 580 | return false; 581 | } 582 | #endif 583 | } 584 | -------------------------------------------------------------------------------- /core/src/register.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file qregister.cpp 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @date 10-09-21 18 | * @brief 19 | */ 20 | 21 | #include "register.h" 22 | 23 | using namespace std; 24 | 25 | /* 26 | * QRegister constructor 27 | */ 28 | QRegister::QRegister(int n) { 29 | char cpu[64] = ""; 30 | char herz[64] = ""; 31 | 32 | if(n > MAX_QUBITS) { 33 | printf("the number of allowed qubit is %d\n", MAX_QUBITS); 34 | exit(0); 35 | } 36 | 37 | memset(&qstat, 0, sizeof(struct qregister_stat)); 38 | 39 | numQubit = n; 40 | maxStates = quantum_shiftL(1, numQubit); 41 | qstat.qubits = numQubit; 42 | getCPU(cpu, &cpuCores, herz); 43 | 44 | init(); 45 | 46 | /* set random seed */ 47 | srand(time(NULL)); 48 | } 49 | 50 | QRegister::QRegister(QRegister *src) { 51 | memset(&qstat, 0, sizeof(struct qregister_stat)); 52 | 53 | for(int i=0; iqubitTypes[i]; 55 | } 56 | 57 | numQubit = src->getNumQubits(); 58 | maxStates = quantum_shiftL(1, numQubit); 59 | qstat.qubits = numQubit; 60 | cpuCores = src->getCPUCores(); 61 | replace(src); 62 | } 63 | 64 | /* 65 | * QRegister constructor 66 | */ 67 | QRegister::~QRegister(void) { 68 | #pragma omp parallel for 69 | for(int i=0; i memAvail) { 90 | char memTotalStr[32] = ""; 91 | char memAvailStr[32] = ""; 92 | char memUsedStr[32] = ""; 93 | 94 | human_readable_size(memTotal, memTotalStr); 95 | human_readable_size(memAvail, memAvailStr); 96 | human_readable_size(memUsed, memAvailStr); 97 | 98 | printf("Memory space is insufficient!!\n"); 99 | printf("Your quantum circuit may generate too many quantum states.\n"); 100 | printf(" - Memory: Total=%s, Avail=%s --> Used=%s\n", memTotalStr, memAvailStr, memUsedStr); 101 | printf(" - Quantum states: %lu\n", (uint64_t)getNumStates()); 102 | exit(0); 103 | } 104 | } 105 | 106 | void QRegister::updateQRegStat(int gate, QTimer timer) { 107 | double tm = timer.getElapsedUSec(); 108 | 109 | /* update max number of quantum states */ 110 | qsize_t numStates = getNumStates(); 111 | if(qstat.maxQStates < numStates) { 112 | qstat.maxQStates = numStates; 113 | } 114 | 115 | /* increase total gate calls */ 116 | qstat.totalGateCalls++; 117 | 118 | /* increase each gate calls */ 119 | qstat.gateCalls[gate]++; 120 | 121 | /* update execution time stats */ 122 | if(qstat.tm_total == 0) { 123 | qstat.tm_total = tm; 124 | } else { 125 | qstat.tm_total += tm; 126 | } 127 | 128 | /* update execution time stats for each gate */ 129 | if(qstat.tm_gates_total[gate] == 0) { 130 | qstat.tm_gates_total[gate] = tm; 131 | qstat.tm_gates_max[gate] = tm; 132 | qstat.tm_gates_min[gate] = tm; 133 | qstat.tm_gates_avg[gate] = tm; 134 | } else { 135 | qstat.tm_gates_total[gate] += tm; 136 | 137 | if(qstat.tm_gates_max[gate] < tm) { 138 | qstat.tm_gates_max[gate] = tm; 139 | } 140 | 141 | if(qstat.tm_gates_min[gate] > tm) { 142 | qstat.tm_gates_min[gate] = tm; 143 | } 144 | 145 | qstat.tm_gates_avg[gate] = qstat.tm_gates_total[gate] / (double)qstat.gateCalls[gate]; 146 | } 147 | } 148 | 149 | struct qregister_stat QRegister::getQRegStat(void) { 150 | qstat.finalQStates = getNumStates(); 151 | 152 | getTotalMem(&qstat.memTotal, &qstat.memAvail); 153 | qstat.memUsed = getUsedMem(); 154 | 155 | getOS(qstat.os_name, qstat.os_version); 156 | getCPU(qstat.cpu_model, &qstat.cpu_cores, qstat.cpu_herz); 157 | 158 | qstat.usedGates = 0; 159 | for(int i=0; igetIndex(); 40 | amplitude = Q->getAmplitude(); 41 | } 42 | 43 | QState::~QState(void) 44 | { 45 | } 46 | 47 | /****************************************************/ 48 | /* external APIs for alloc/dealloc QState */ 49 | /****************************************************/ 50 | QState *getQState(void) 51 | { 52 | QState *Q = NULL; 53 | 54 | Q = new QState(); 55 | 56 | return Q; 57 | } 58 | 59 | QState *getQState(qsize_t qidx, complex_t amp) 60 | { 61 | QState *Q = NULL; 62 | 63 | Q = new QState(qidx, amp); 64 | 65 | return Q; 66 | } 67 | 68 | void putQState(QState *Q) 69 | { 70 | delete Q; 71 | } 72 | -------------------------------------------------------------------------------- /core/src/timer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file qtimer.cpp 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @date 10-09-21 18 | * @brief 19 | */ 20 | 21 | #include "timer.h" 22 | 23 | QTimer::QTimer(void) 24 | { 25 | elapsedNSec = 0; 26 | } 27 | 28 | QTimer::~QTimer(void) 29 | { 30 | } 31 | -------------------------------------------------------------------------------- /docs/Qplayer User's Manual-v2.3-Cougar (en).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eQuantumOS/QPlayer/33cf77f7d586c0642d3899d1b25a0dd85b8b382e/docs/Qplayer User's Manual-v2.3-Cougar (en).pdf -------------------------------------------------------------------------------- /docs/Qplayer User's Manual-v2.3-Cougar (kor).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eQuantumOS/QPlayer/33cf77f7d586c0642d3899d1b25a0dd85b8b382e/docs/Qplayer User's Manual-v2.3-Cougar (kor).pdf -------------------------------------------------------------------------------- /docs/changes: -------------------------------------------------------------------------------- 1 | 2024-02-13 add sxdg gate (inverse sx gate) 2 | 3 | 2024-02-13 support qiskit compatible python interface 4 | - remove ~/qasm directory 5 | - add ~/qasm/cli directory (for qplayer cli) 6 | - add ~/qasm/qiskit directory (for qiskit compatible python interface) 7 | 8 | 2024-02-12 fix CCX code 9 | 10 | 2024-01-03 fix abnormal execution of multi qregister in OpenQASM 11 | 12 | 2024-01-02 fix abnormal execution of multi-shot processing in OpenQASM 13 | 14 | 2023-11-13 use __uint128_t instead of boost multiprecision class 15 | - remove boost library dependency 16 | - support the number of qubits up to 128 17 | 18 | 2023-10-19 update version --> QPlayer v2.1-Cheetah 19 | 20 | 2023-10-18 remove all lock-contentions from matrix operations 21 | - remove state pooling mechanism 22 | - update gate operational functions 23 | - update benchmark programs 24 | 25 | 2023-10-04 bug fix. malfunction swap gate in OpenQASM 2.0 26 | 27 | 2023-08-31 release QPlayer v2.0-Puma 28 | 29 | 2023-08-30 add get_stride(int qubit) function 30 | 31 | 2023-08-30 update stripe_lower()/stripe_upper() 32 | - check state by using bit operation 33 | 34 | 2023-08-30 move checkMemory(): register.h --> register.cpp 35 | 36 | 2023-08-30 update register.h 37 | - remove all locking logic 38 | - rename QState functions 39 | * setQState() -> addQState() 40 | * eraseQSTate() -> delQSTate() 41 | 42 | 2023-08-30 move temporal vector variables: register.h --> gate.cpp 43 | - vector addQList[QSTORE_PARTITION][MAX_CORES]; 44 | - vector delQList[QSTORE_PARTITION][MAX_CORES]; 45 | 46 | 2023-08-30 alias data structures 47 | - std::map --> QMAP 48 | - std::map::iterator --> QMAPITER 49 | 50 | 2023-08-29 move some functions register.h --> register.cpp 51 | - void updateQRegStat(int gate, QTimer timer) 52 | - struct qregister_stat getQRegStat(void) 53 | - void showQRegStat(void) 54 | 55 | 2023-08-29 remove old matrix calculation logic 56 | - we only support new matrix calculation algorithm. 57 | 58 | 2023-08-29 support gate-aware matrix calculation 59 | - add core/src/gate_nmc.cpp 60 | - update core/src/gate.cpp 61 | - add benchmard codes : ~/test/benchmark/gate_perf.cpp 62 | 63 | 2023-08-29 update testing directory 64 | - move general/install_test.cpp --> verification/install_test.cpp 65 | - add benchmark/longrun_test.cpp 66 | - add benchmark/rcs.cpp 67 | 68 | 2023-07-10 add memory utility function 69 | - add getMemory(uint64_t *memTotal, uint64_t *memAvail, uint64_t *memUsed) 70 | 71 | 2023-07-07 minor revision of qplayer CLI options 72 | - change -f to -i 73 | - change -j option to have argument 74 | 75 | 2023-07-06 add test file for verifying installtion 76 | - add ~/test/general/install_test.cpp 77 | 78 | 2023-06-23 generate monitoring statistics to json file 79 | - update qregister->stat data structure 80 | - add -j option for qplayer CLI 81 | 82 | 2023-06-22 add monitoring function for simulation jobs 83 | - there are 4 categories (Circuit, Runtime, Simulation Jobs, System Information) 84 | - add --verbose option for qplayer CLI 85 | 86 | 2023-06-21 disable state pool quota control 87 | - if the number of states in queue is greater than MAX_POOL_SIZE, 88 | delete QState memory directly instead of storing it into queue 89 | 90 | 2023-06-21 update README.md 91 | - update version 92 | - update some style 93 | 94 | 2023-06-21 add QState memory pool 95 | - add spool.h, spool.cpp 96 | - alloc/dealloc QState memory from state pool 97 | 98 | 2023-06-20 Integrated test directory compilation 99 | - add ~/test/Makefile 100 | - link ~/Makefile and ~/test/Makefile 101 | 102 | 2023-06-20 speficied the ownership of the OpenQASM compilier 103 | - add AUTHOR into ~/qasm directory 104 | - add LICENSE into ~/qasm directory 105 | 106 | 2023-06-20 source code indentation 107 | - fix the consistency of the indentations of all source codes 108 | 109 | 2023-06-20 support OpenQASM 2.0 110 | - add qasm directory 111 | - change -o option from mandatory to optional 112 | - release 'qplayer' CLI to ~release/bin 113 | 114 | 2023-06-19 refactoring code directories 115 | - rename qplayer(D) --> core(D) 116 | - rename circuit(D) --> test(D) 117 | - breakdown test directories by role 118 | - add docs(D) 119 | - update Makefiles 120 | -------------------------------------------------------------------------------- /docs/versions.md: -------------------------------------------------------------------------------- 1 | ![image](https://github.com/eQuantumOS/QPlayer/assets/17871602/3e9517cf-bed6-45b9-8cea-255bf1b84935) 2 | 3 | # v2.4-Cougar 4 | + release date : March 4, 2024 5 | + features 6 | - optimize toffoli gate 7 | - support qiskit-compatible python interface 8 | - reorganize ~/qasm directory 9 | * ~/qasm/cli : CLI utility for OpenQASM code 10 | * ~/qasm/qiskit : python interface 11 | 12 | # v2.0-Puma 13 | + release date : August 31, 2023 14 | + features 15 | - approximately 2 to 10 times improved calculation performance thana 16 | v1.0-Leopard by utilizing gate-aware low computational matrix calculation 17 | * DiagonalGates() : Z, S, T, SDG, TDG, RZ, U1 18 | * NoneDiagonalGates() : X, Y, H, U2, U3, RX, RY, SX 19 | * DiagonalControlGates() : CZ, CU1, CRZ 20 | * NoneDiagonalControlGates() : CX, CY, CU2, CU3, CH, CSWAP 21 | - remove locking on access to multiple state containers 22 | - refine the testing directory as follows 23 | * ~/test/general 24 | * ~/test/surfacecode 25 | * ~/test/verification 26 | * ~/test/benchmark 27 | 28 | # v1.0-Leopard 29 | + release date : June 23, 2023 30 | + features 31 | - re-organize whole directory trees & sources 32 | - OpenQASM v2.0 /w a complete grammar check 33 | - add state memory pool for handling dynamical state memory 34 | - provide simulation statistics through the json file 35 | 36 | # v0.5-Jaguar 37 | + release date : March 30, 2023 38 | + features 39 | - optimize matrix calculation logic 40 | - fix memory overflow in log-run testing 41 | - enhance gate operation performance 42 | - OpenQASM v2.0 /w a simple grammar check 43 | - Support for 32 quantum gate operations 44 | 45 | # v0.2-Cat 46 | + release date : June 24, 2021 47 | + features 48 | - Schrödinger style state vector simulator 49 | - Fast operation in the reduced Hilbert space 50 | - User-friendly interfaces: native-C 51 | - Support for 21 quantum gate operations 52 | -------------------------------------------------------------------------------- /qasm/cli/Makefile: -------------------------------------------------------------------------------- 1 | QPLAYER_RELEASE=../../release 2 | 3 | CXX = g++ 4 | CXXLD = g++ 5 | 6 | CXXFLAGS = -g -Wall -O2 -std=c++11 -MMD -MP -fopenmp 7 | CXXFLAGS += -I. -I./include -I$(QPLAYER_RELEASE)/include 8 | CXXFLAGS += -Wno-reorder -Wno-sign-compare -Wno-parentheses -Wno-pessimizing-move 9 | CXXFLAGS += -Wno-unused-function -Wno-unused-variable -Wno-write-strings 10 | CXXFLAGS += -Wno-class-conversion -Wno-unused-result 11 | 12 | LIBS = -L$(QPLAYER_RELEASE)/lib 13 | LIBS += -lm -lpthread -lqplayer -lgomp 14 | 15 | Q=@echo 16 | E=@ 17 | 18 | QASM_SRC := 19 | QASM_HDR := 20 | include ./module.mk 21 | 22 | # OBJECT FILES 23 | QASM_OBJS=$(patsubst %.cpp,%.o,$(QASM_SRC)) 24 | QASM_HDRS=$(patsubst %.h,%.h,$(QASM_HDR)) 25 | 26 | QASM_EXEC=qplayer 27 | QASM_DEPS=src/*.d ./*.d 28 | 29 | .PHONY: all clean 30 | 31 | .DEFAULT_GOAL := all 32 | 33 | all: QPlayerQASM install 34 | 35 | QPlayerQASM: $(QASM_OBJS) 36 | $(CXXLD) $(LDFLAGS) $(QASM_OBJS) -o $(QASM_EXEC) $(LIBS) 37 | 38 | %.o : %.cpp $(QASM_HDRS) 39 | $(Q) "CC $(@)" 40 | $(E) $(CXX) $(CXXFLAGS) -Wno-deprecated-declarations $(LIB_CXX_FLAGS) -c $< -o $@ 41 | 42 | install: 43 | @mkdir -p $(QPLAYER_RELEASE)/bin 44 | @cp -f $(QASM_EXEC) $(QPLAYER_RELEASE)/bin 45 | @cp -rf ./examples $(QPLAYER_RELEASE)/bin 46 | 47 | clean: 48 | @echo "Clean Objects, Deps, Executions" 49 | @rm -rf logs 50 | @rm -fv core.* 51 | @rm -fv $(QASM_OBJS) 52 | @rm -fv $(QASM_EXEC) 53 | @rm -fv $(QASM_DEPS) 54 | -------------------------------------------------------------------------------- /qasm/cli/examples/adder.qasm: -------------------------------------------------------------------------------- 1 | // quantum ripple-carry adder from Cuccaro et al, quant-ph/0410184 2 | OPENQASM 2.0; 3 | include "qelib1.inc"; 4 | gate majority a,b,c 5 | { 6 | cx c,b; 7 | cx c,a; 8 | ccx a,b,c; 9 | } 10 | gate unmaj a,b,c 11 | { 12 | ccx a,b,c; 13 | cx c,a; 14 | cx a,b; 15 | } 16 | qreg cin[1]; 17 | qreg a[4]; 18 | qreg b[4]; 19 | qreg cout[1]; 20 | creg ans[5]; 21 | // set input states 22 | x a[0]; // a = 0001 23 | x b; // b = 1111 24 | // add a to b, storing result in b 25 | majority cin[0],b[0],a[0]; 26 | majority a[0],b[1],a[1]; 27 | majority a[1],b[2],a[2]; 28 | majority a[2],b[3],a[3]; 29 | cx a[3],cout[0]; 30 | unmaj a[2],b[3],a[3]; 31 | unmaj a[1],b[2],a[2]; 32 | unmaj a[0],b[1],a[1]; 33 | unmaj cin[0],b[0],a[0]; 34 | //measure b[0] -> ans[0]; 35 | //measure b[1] -> ans[1]; 36 | //measure b[2] -> ans[2]; 37 | //measure b[3] -> ans[3]; 38 | //measure cout[0] -> ans[4]; 39 | -------------------------------------------------------------------------------- /qasm/cli/examples/gates.qasm: -------------------------------------------------------------------------------- 1 | // QuvieC initial code 2 | OPENQASM 2.0; 3 | include "qelib1.inc"; 4 | 5 | qreg q[3]; 6 | creg c[3]; 7 | 8 | id q[0]; 9 | u1 (pi/2) q[1]; 10 | u2 (pi/2, pi/3) q[1]; 11 | u3 (pi/2, pi/3, pi/4) q[1]; 12 | x q[0]; 13 | y q[0]; 14 | z q[0]; 15 | h q[0]; 16 | p q[0]; 17 | s q[0]; 18 | t q[0]; 19 | sdg q[0]; 20 | tdg q[0]; 21 | rx (pi/2) q[0]; 22 | ry (pi/2) q[0]; 23 | rz (pi/2) q[0]; 24 | cx q[0],q[1]; 25 | cz q[0],q[1]; 26 | cy q[0],q[1]; 27 | ch q[0],q[1]; 28 | ccx q[0],q[1],q[2]; 29 | crz (pi/2) q[0],q[1]; 30 | cu1 (pi/2) q[0],q[1]; 31 | cu2 (pi/2, pi/3) q[0],q[1]; 32 | cu3 (pi/2, pi/3, pi/4) q[0],q[1]; 33 | swap q[0],q[1]; 34 | cswap q[0],q[1],q[2]; 35 | sx q[0]; 36 | sxdg q[0]; 37 | iswap q[0],q[1]; 38 | -------------------------------------------------------------------------------- /qasm/cli/examples/qec.qasm: -------------------------------------------------------------------------------- 1 | // Repetition code syndrome measurement 2 | OPENQASM 2.0; 3 | include "qelib1.inc"; 4 | qreg q[3]; 5 | qreg a[2]; 6 | creg c[3]; 7 | creg syn[2]; 8 | gate syndrome d1,d2,d3,a1,a2 9 | { 10 | cx d1,a1; cx d2,a1; 11 | cx d2,a2; cx d3,a2; 12 | } 13 | x q[0]; // error 14 | barrier q; 15 | syndrome q[0],q[1],q[2],a[0],a[1]; 16 | measure a -> syn; 17 | if(syn==1) x q[0]; 18 | if(syn==2) x q[2]; 19 | if(syn==3) x q[1]; 20 | //measure q -> c; 21 | -------------------------------------------------------------------------------- /qasm/cli/examples/qft.qasm: -------------------------------------------------------------------------------- 1 | // quantum Fourier transform 2 | OPENQASM 2.0; 3 | include "qelib1.inc"; 4 | qreg q[4]; 5 | creg c[4]; 6 | x q[0]; 7 | x q[2]; 8 | barrier q; 9 | h q[0]; 10 | cu1(pi/2) q[1],q[0]; 11 | h q[1]; 12 | cu1(pi/4) q[2],q[0]; 13 | cu1(pi/2) q[2],q[1]; 14 | h q[2]; 15 | cu1(pi/8) q[3],q[0]; 16 | cu1(pi/4) q[3],q[1]; 17 | cu1(pi/2) q[3],q[2]; 18 | h q[3]; 19 | //measure q -> c; 20 | -------------------------------------------------------------------------------- /qasm/cli/examples/sample.qasm: -------------------------------------------------------------------------------- 1 | // QuvieC initial code 2 | OPENQASM 2.0; 3 | include "qelib1.inc"; 4 | 5 | qreg q[4]; 6 | qreg qq[3]; 7 | creg c[4]; 8 | creg cc[3]; 9 | 10 | gate ugate1(r1, r2, r3) a, b, c { 11 | cx a, b; 12 | h c; 13 | u3(r1, r2, r3) c; 14 | } 15 | 16 | gate ugate2 a, b { 17 | cx a, b; 18 | x a; 19 | } 20 | 21 | h q; 22 | u1(cos(pi/3)/0.3*sin(10.2)) q[2]; 23 | u2(pi/10, cos(pi/3)/0.3*sin(10.2)) q[2]; 24 | 25 | u3(pi/4, -pi/10, pi/15) q[2]; 26 | u2(pi/10, cos(pi/3)/0.3*sin(10.2)) q[2]; 27 | rz(cos(pi/3)/0.3*sin(10.2)) q[2]; 28 | u2(pi/10, cos(pi/3)/0.3*sin(10.2)) q[2]; 29 | 30 | ugate1 (pi/2, pi/3, pi/4) q[0], q[1], q[2]; 31 | ugate2 q[0], q[1]; 32 | 33 | if (c == 1) u2(pi/10, cos(pi/3)/0.3*sin(10.2)) q[2]; 34 | if (c <= 2) h q; 35 | if (c < 3) cx q[0],q[2]; 36 | if (cc >= 4) ccx q[0],q[1], q[2]; 37 | if (c == 0) rx(pi) q; 38 | 39 | measure q -> c; 40 | -------------------------------------------------------------------------------- /qasm/cli/examples/sc17.qasm: -------------------------------------------------------------------------------- 1 | OPENQASM 2.0; 2 | include "qelib1.inc"; 3 | 4 | qreg q[17]; 5 | creg c[17]; 6 | 7 | reset q[0]; 8 | reset q[1]; 9 | reset q[2]; 10 | reset q[3]; 11 | reset q[4]; 12 | reset q[5]; 13 | reset q[6]; 14 | reset q[7]; 15 | reset q[8]; 16 | reset q[9]; 17 | reset q[10]; 18 | reset q[11]; 19 | reset q[12]; 20 | reset q[13]; 21 | reset q[14]; 22 | reset q[15]; 23 | reset q[16]; 24 | h q[9]; 25 | h q[10]; 26 | h q[11]; 27 | h q[12]; 28 | cx q[9],q[1]; 29 | cx q[9],q[2]; 30 | h q[9]; 31 | measure q[9] -> c[9]; 32 | cx q[10],q[0]; 33 | cx q[10],q[1]; 34 | cx q[10],q[3]; 35 | cx q[10],q[4]; 36 | h q[10]; 37 | measure q[10] -> c[10]; 38 | cx q[11],q[4]; 39 | cx q[11],q[5]; 40 | cx q[11],q[7]; 41 | cx q[11],q[8]; 42 | h q[11]; 43 | measure q[11] -> c[11]; 44 | cx q[12],q[6]; 45 | cx q[12],q[7]; 46 | h q[12]; 47 | measure q[12] -> c[12]; 48 | cx q[0],q[13]; 49 | cx q[3],q[13]; 50 | measure q[13] -> c[13]; 51 | cx q[3],q[14]; 52 | cx q[4],q[14]; 53 | cx q[6],q[14]; 54 | cx q[7],q[14]; 55 | measure q[14] -> c[14]; 56 | cx q[1],q[15]; 57 | cx q[2],q[15]; 58 | cx q[4],q[15]; 59 | cx q[5],q[15]; 60 | measure q[15] -> c[15]; 61 | cx q[5],q[16]; 62 | cx q[8],q[16]; 63 | measure q[16] -> c[16]; 64 | -------------------------------------------------------------------------------- /qasm/cli/examples/test.qasm: -------------------------------------------------------------------------------- 1 | // QuvieC initial code 2 | OPENQASM 2.0; 3 | include "qelib1.inc"; 4 | 5 | qreg q[4]; 6 | creg c[4]; 7 | 8 | gate mygate (r1) a b { 9 | h a; 10 | u1 (r1) b; 11 | } 12 | 13 | x q[0]; 14 | cx q[0], q[1]; 15 | mygate (pi) q[0], q[2]; 16 | 17 | measure q -> c; 18 | 19 | if (c == 0) x q[1]; 20 | -------------------------------------------------------------------------------- /qasm/cli/include/Cal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define MAX_LENG 512 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /* operation parameter for calculator */ 12 | struct opparam { 13 | int p; // priority 14 | std::string o; // op 15 | }; 16 | 17 | inline static void calc(stack &opval, stack &op) { 18 | double p1 = 0; 19 | double p2 = 0; 20 | double result = 0; 21 | 22 | p2 = opval.top(); 23 | opval.pop(); 24 | p1 = opval.top(); 25 | opval.pop(); 26 | std::string opparam = op.top().o; 27 | op.pop(); 28 | 29 | if (opparam == "*") 30 | result = p1 * p2; 31 | else if (opparam == "/") 32 | result = p1 / p2; 33 | else if (opparam == "+") 34 | result = p1 + p2; 35 | else if (opparam == "-") 36 | result = p1 - p2; 37 | 38 | opval.push(result); 39 | } 40 | 41 | inline static void calTokenizer(std::string &str) { 42 | std::string netStr; 43 | std::string valString; 44 | int leftPos = 0; 45 | int rightPos = 0; 46 | int pos = 0; 47 | int type; 48 | 49 | /**********************************************/ 50 | /* STEP1: replace 'pi' string to double value */ 51 | /**********************************************/ 52 | netStr.clear(); 53 | do { 54 | if((pos = str.find("pi")) == string::npos) { 55 | break; 56 | } 57 | 58 | leftPos = str.find("p", pos); 59 | rightPos = str.find("i", leftPos); 60 | 61 | valString = str.substr(leftPos+1, rightPos-leftPos-1); 62 | netStr = str.substr(0, pos); 63 | netStr += "3.141592653589793238462643383279502884"; 64 | if(rightPos < str.size() - 1) { 65 | netStr += str.substr(rightPos+1, str.size()-1); 66 | } 67 | str = netStr; 68 | } while(1); 69 | 70 | /**************************************************/ 71 | /* STEP2: replace cos(val) string to double value */ 72 | /**************************************************/ 73 | netStr.clear(); 74 | do { 75 | if((pos = str.find("cos")) != string::npos) { 76 | type = COS; 77 | } else if((pos = str.find("sin")) != string::npos) { 78 | type = SIN; 79 | } else if((pos = str.find("tan")) != string::npos) { 80 | type = TAN; 81 | } else if((pos = str.find("exp")) != string::npos) { 82 | type = EXP; 83 | } else if((pos = str.find("ln")) != string::npos) { 84 | type = LOG; 85 | } else if((pos = str.find("sqrt")) != string::npos) { 86 | type = SQRT; 87 | } else { 88 | break; 89 | } 90 | 91 | leftPos = str.find("(", pos); 92 | rightPos = str.find(")", leftPos); 93 | 94 | valString = str.substr(leftPos+1, rightPos-leftPos-1); 95 | netStr = str.substr(0, pos); 96 | 97 | switch(type) { 98 | case COS: netStr += to_string(cos(stod(valString))); break; 99 | case SIN: netStr += to_string(sin(stod(valString))); break; 100 | case TAN: netStr += to_string(tan(stod(valString))); break; 101 | case EXP: netStr += to_string(exp(stod(valString))); break; 102 | case LOG: netStr += to_string(log(stod(valString))); break; 103 | case SQRT: netStr += to_string(sqrt(stod(valString))); break; 104 | } 105 | 106 | if(rightPos < str.size() - 1) { 107 | netStr += str.substr(rightPos+1, str.size()-1); 108 | } 109 | str = netStr; 110 | } while(1); 111 | 112 | /*******************************************/ 113 | /* STEP3: split tokens for stack operation */ 114 | /*******************************************/ 115 | netStr.clear(); 116 | for(int i=0; i opval; 147 | stack op; 148 | double rval = 0; 149 | 150 | std::string tok; 151 | while (ss >> tok) { 152 | if (tok == "(") { 153 | op.push({0, tok}); 154 | } else if (tok == ")") { 155 | while (op.top().o != "(") 156 | calc(opval, op); 157 | op.pop(); 158 | } else if (tok == "*" || tok == "/" || tok == "+" || tok == "-") { 159 | int prior = 0; 160 | if(tok == "*") 161 | prior = 2; 162 | else if(tok == "/") 163 | prior = 2; 164 | else if(tok == "+") 165 | prior = 1; 166 | else if(tok == "-") 167 | prior = 1; 168 | 169 | while (!op.empty() && prior <= op.top().p) 170 | calc(opval, op); 171 | 172 | op.push({prior, tok}); 173 | } else { 174 | opval.push(stod(tok)); 175 | } 176 | } 177 | 178 | while (!op.empty()) 179 | calc(opval, op); 180 | 181 | return opval.top(); 182 | } 183 | -------------------------------------------------------------------------------- /qasm/cli/include/Parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "Token.h" 11 | #include "Scanner.h" 12 | 13 | class Parser { 14 | public: 15 | std::istream *in; 16 | std::map qregs; 17 | std::map cregs; 18 | std::map gates; 19 | std::map ugates; 20 | std::vector stmts; 21 | std::vector creg_measure; 22 | QRegister *QReg; 23 | int numQubits; 24 | int numCubits; 25 | 26 | public: 27 | Scanner *scanner; 28 | 29 | public: 30 | Parser(std::string fname) { 31 | in = new std::ifstream (fname, std::ifstream::in); 32 | if(!in->good()) { 33 | std::cerr << "ERROR opening file " << fname << std::endl; 34 | std::exit(1); 35 | } 36 | scanner = new Scanner(in); 37 | 38 | init_gates(); 39 | } 40 | 41 | ~Parser() { 42 | delete in; 43 | delete scanner; 44 | } 45 | 46 | private: 47 | void init_gates(void); 48 | void check_brack(std::vector tokens, bool &is_brack); 49 | void get_qubit(Token tk, std::string qname, int val, std::vector &qubits); 50 | void get_cubit(Token tk, std::string cname, int val, std::vector &cubits); 51 | void get_qubits(Token tk, std::string qname, std::vector &qubits); 52 | void get_cubits(Token tk, std::string cname, std::vector &cubits); 53 | void get_cregvalue(Token tk, std::string cname, int &cuval); 54 | void check_gate_stmt(STMT stmt); 55 | 56 | void build_gate_stmt(std::vector tokens); 57 | void build_ugate_stmt(std::vector tokens); 58 | void build_if_stmt(std::vector tokens); 59 | void build_measure_stmt(std::vector tokens); 60 | 61 | void exec_gate(STMT stmt); 62 | 63 | public: 64 | void parse(void); 65 | void run(void); 66 | void get_measure(std::string &str); 67 | void show_tokens(void); 68 | void show_stmt(void); 69 | void reset(void); 70 | struct qregister_stat getQRegStat(void); 71 | 72 | public: 73 | /* for debugging */ 74 | void dumpQReg(void); 75 | }; 76 | -------------------------------------------------------------------------------- /qasm/cli/include/Scanner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Token.h" 8 | 9 | class Scanner { 10 | public: 11 | std::istream *in; 12 | std::vector tokens; 13 | int line; 14 | char ch; 15 | 16 | public: 17 | Scanner(std::istream *in_stream) : in(in_stream) { 18 | line = 1; 19 | } 20 | 21 | ~Scanner() {} 22 | 23 | public: 24 | void readName(Token &t); 25 | void readNumber(Token &t); 26 | void skipComment(); 27 | void nextCh(void); 28 | void scan(void); 29 | void check_args(void); 30 | void build_ugates(std::map &ugates); 31 | void build_qregs(std::map &qregs); 32 | void build_cregs(std::map &cregs); 33 | void get_tokens(std::vector &tokens, int &pos); 34 | void get_utokens(std::vector source, std::vector &tokens, int &pos); 35 | void show(void); 36 | }; 37 | -------------------------------------------------------------------------------- /qasm/cli/include/Token.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "qplayer.h" 10 | #include "ds.h" 11 | 12 | class Token { 13 | public: 14 | Kind kind; 15 | int line; 16 | int val; 17 | double rval; 18 | std::string str; 19 | 20 | public: 21 | Token(Kind k, int l) { 22 | kind = k; 23 | line = l; 24 | val = INT_MAX; 25 | rval = LONG_MAX; 26 | str = ""; 27 | } 28 | ~Token() {} 29 | 30 | char *token2str(Kind kind); 31 | void show(void); 32 | }; 33 | 34 | /*************************************************** 35 | STMT class contains indivisual instructions to be 36 | executed in the simulator. 37 | - type : command type { GATE, IF, MEASURE } 38 | - line : line in the QASM code 39 | - gate : gate 40 | - args : angle arguments (if angle exists) 41 | - qubits : qubit arguments 42 | - cubits : creg arguments (in case of MEASURE) 43 | - compare : compare condition (in case of IF) 44 | ***************************************************/ 45 | class STMT { 46 | public: 47 | int type; 48 | int line; 49 | std::string gate; 50 | std::vector args; 51 | std::vector qubits; 52 | std::vector cubits; 53 | std::vector compare; 54 | }; 55 | 56 | /*************************************************** 57 | Ugate class is used to manage user-defined gates 58 | - name : user gate name 59 | - args : user gate angle arguments 60 | - params : user gate qubit arguments 61 | - tokens : internal gate statements in this ugate 62 | 63 | < code example > 64 | gate mygate (r1, r2) a b { 65 | x a; 66 | u2 (r1, r2) b; 67 | } 68 | 69 | < data structures > 70 | name : mygate 71 | args : { r1, r2 } 72 | params : { a, b } 73 | tokens : { x a } - { u2 r1 r2 b } 74 | 75 | ***************************************************/ 76 | class Ugate { 77 | public: 78 | std::string name; 79 | std::vector args; 80 | std::vector params; 81 | std::vector tokens; 82 | }; 83 | 84 | /*************************************************** 85 | It is used to handle qreg, creg lists. 'pos', 'size' 86 | means the start number and size, respectively. 87 | Assuming that we declared qreg, creg as in the below 88 | example, the values are as follows... 89 | 90 | < code example > 91 | qreg q1[3]; pos=0, size=3 92 | qreg q2[2]; pos=3, size=2 93 | creg c1[3]; pos=0, size=3 94 | creg c2[2]; pos=3, size=2 95 | ***************************************************/ 96 | class Reg_args { 97 | public: 98 | int pos; 99 | int size; 100 | }; 101 | -------------------------------------------------------------------------------- /qasm/cli/include/ds.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define LOG_SIZE 256 12 | 13 | enum StmtType { 14 | GATE, 15 | IF, 16 | MEASURE 17 | }; 18 | 19 | enum GateType { 20 | G1, // no angle, 1 qubit 21 | G2, // no angle, 2 qubit 22 | G3, // no angle, 3 qubit 23 | G4, // 1 angle, 1 qubit 24 | G5, // 2 angle, 1 qubit 25 | G6, // 3 angle, 1 qubit 26 | G7, // 1 angle, 2 qubit 27 | G8, // 2 angle, 2 qubit 28 | G9 // 3 angle, 2 qubit 29 | }; 30 | 31 | enum Kind { 32 | none, 33 | openqasm, 34 | include, 35 | qreg, 36 | creg, 37 | gate, 38 | number, 39 | rnumber, 40 | str, 41 | semicolon, 42 | eol, 43 | comma, 44 | plus, 45 | minus, 46 | multiply, 47 | divide, 48 | lpar, 49 | rpar, 50 | lbrack, 51 | rbrack, 52 | lbrace, 53 | rbrace, 54 | PI, 55 | SIN, 56 | COS, 57 | TAN, 58 | EXP, 59 | LOG, 60 | SQRT, 61 | POWER, 62 | lt, 63 | lte, 64 | eq, 65 | gt, 66 | gte, 67 | arrow, 68 | barrier, 69 | ifstmt 70 | }; 71 | 72 | inline static void logExit(const char *fmt, ...) 73 | { 74 | char log[LOG_SIZE]; 75 | va_list ap; 76 | 77 | va_start(ap, fmt); 78 | vsnprintf(log, LOG_SIZE, fmt, ap); 79 | va_end(ap); 80 | 81 | printf("%s\n", log); 82 | exit(0); 83 | } 84 | 85 | -------------------------------------------------------------------------------- /qasm/cli/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "include/Parser.h" 18 | 19 | #define MAX_LENG 512 20 | 21 | static char *prog; 22 | static char *f_qasm = "/tmp/xyz"; 23 | static char f_in[MAX_LENG]; 24 | static char f_out[MAX_LENG]; 25 | static char j_out[MAX_LENG]; 26 | static int shots; 27 | static int is_verbose; 28 | static int is_json; 29 | static char *version = "QPlayer v2.3-Cougar"; 30 | static char *dirc = NULL; 31 | static char *dname = NULL; 32 | 33 | static void usage(void) 34 | { 35 | printf("%s \n", prog); 36 | printf("options:\n" ); 37 | printf(" -i : input QASM file (mandatory)\n"); 38 | printf(" -o : output result file (mandatory)\n"); 39 | printf(" -j : output simulation statistics to json file\n"); 40 | printf(" -s : number of shots\n"); 41 | printf(" -h : help\n"); 42 | printf(" --version : version\n"); 43 | printf(" --verbose : show simulation statistics\n"); 44 | 45 | exit(0); 46 | } 47 | 48 | static void sig_handler(int sig) 49 | { 50 | printf ("signal(%d) catched..\n", sig); 51 | exit(0); 52 | } 53 | 54 | void showStat(struct qregister_stat *stat) 55 | { 56 | char memTotalStr[32] = ""; 57 | char memAvailStr[32] = ""; 58 | char memUsedStr[32] = ""; 59 | char totalTimeStr[32] = ""; 60 | 61 | human_readable_size(stat->memTotal, memTotalStr); 62 | human_readable_size(stat->memAvail, memAvailStr); 63 | human_readable_size(stat->memUsed, memUsedStr); 64 | usec2str(stat->tm_total, totalTimeStr); 65 | 66 | printf("\n"); 67 | printf("\033[1;34m1. Circuit Information\033[0;39m\n"); 68 | printf("+--------------------------+-----------------+\n"); 69 | printf("| 1. used qubits | %7d |\n", stat->qubits); 70 | printf("+--------------------------+-----------------+\n"); 71 | printf("| 2. used gates | %7d |\n", stat->usedGates); 72 | printf("+--------------------------+-----------------+\n"); 73 | printf("| 3. total gate calls | %7d |\n", stat->totalGateCalls); 74 | printf("+--------------------------+-----------------+\n"); 75 | printf("| 4. individual gate calls | |\n"); 76 | printf("+--------------------------+ |\n"); 77 | for(int i=0; igateCalls[i] != 0) { 79 | printf("| %10s | %7d (%2d %%) |\n", 80 | gateString(i), stat->gateCalls[i], 81 | (stat->gateCalls[i] * 100) / stat->totalGateCalls); 82 | } 83 | } 84 | printf("+--------------------------+-----------------+\n"); 85 | 86 | printf("\n"); 87 | printf("\033[1;34m2. Runtime (micro seconds)\033[0;39m\n"); 88 | printf("+-----------------------------+---------------------------------------------+\n"); 89 | printf("| 1. total simulation time | %11.f %29s |\n", stat->tm_total, totalTimeStr); 90 | printf("+-----------------------------+---------------+-----------+-------+---------+\n"); 91 | printf("| 2. each gate execution time | total | max | min | avg |\n"); 92 | printf("+-----------------------------+---------------+-----------+-------+---------+\n"); 93 | for(int i=0; igateCalls[i] != 0) { 95 | printf("| %27s | %13.0f | %9.0f | %5.0f | %7.0f |\n", gateString(i), 96 | stat->tm_gates_total[i], 97 | stat->tm_gates_max[i], 98 | stat->tm_gates_min[i], 99 | stat->tm_gates_avg[i]); 100 | } 101 | } 102 | printf("+-----------------------------+---------------+-----------+-------+---------+\n"); 103 | 104 | printf("\n"); 105 | printf("\033[1;34m3. Simulation Jobs\033[0;39m\n"); 106 | printf("+-----------------------------------+---------------+\n"); 107 | printf("| 1. max number of quantum states | %13ld |\n", (uint64_t)stat->maxQStates); 108 | printf("+-----------------------------------+---------------+\n"); 109 | printf("| 2. final number of quantum states | %13ld |\n", (uint64_t)stat->finalQStates); 110 | printf("+-----------------------------------+---------------+\n"); 111 | printf("| 3. used memory | %13s |\n", memUsedStr); 112 | printf("+-----------------------------------+---------------+\n"); 113 | 114 | printf("\n"); 115 | printf("\033[1;34m4. System Information\033[0;39m\n"); 116 | printf("+-----------+---------+-------------------------------------------------+\n"); 117 | printf("| | name | %47s | \n", stat->os_name); 118 | printf("| OS |---------+-------------------------------------------------+\n"); 119 | printf("| | version | %47s | \n", stat->os_version); 120 | printf("+-----------+---------+-------------------------------------------------+\n"); 121 | printf("| | model | %47s | \n", stat->cpu_model); 122 | printf("| |---------+-------------------------------------------------+\n"); 123 | printf("| CPU | cores | %47d | \n", stat->cpu_cores); 124 | printf("| |---------+-------------------------------------------------+\n"); 125 | printf("| | herz | %47s | \n", stat->cpu_herz); 126 | printf("+-----------+---------+-------------------------------------------------+\n"); 127 | printf("| | total | %47s | \n", memTotalStr); 128 | printf("| MEM |---------+-------------------------------------------------+\n"); 129 | printf("| | avail | %47s | \n", memAvailStr); 130 | printf("+-----------+---------+-------------------------------------------------+\n"); 131 | } 132 | 133 | void genStatJson(struct qregister_stat *stat) 134 | { 135 | char cmd[256] = ""; 136 | 137 | dirc = strdup(j_out); 138 | dname = dirname(dirc); 139 | sprintf(cmd, "mkdir -p %s", dname); 140 | system(cmd); 141 | 142 | FILE *fp = fopen(j_out, "wt"); 143 | 144 | char memTotalStr[32] = ""; 145 | char memAvailStr[32] = ""; 146 | char memUsedStr[32] = ""; 147 | int pos = 0; 148 | 149 | human_readable_size(stat->memTotal, memTotalStr); 150 | human_readable_size(stat->memAvail, memAvailStr); 151 | human_readable_size(stat->memUsed, memUsedStr); 152 | 153 | fprintf(fp, "{\n"); 154 | fprintf(fp, " \"circuit\" : {\n"); 155 | fprintf(fp, " \"used qubits\" : %d,\n", stat->qubits); 156 | fprintf(fp, " \"used gates\" : %d,\n", stat->usedGates); 157 | fprintf(fp, " \"gate calls\" : {\n"); 158 | pos = 0; 159 | for(int i=0; igateCalls[i] != 0) { 161 | if(++pos < stat->usedGates) { 162 | fprintf(fp, " \"%s\" : %d,\n", gateString(i), stat->gateCalls[i]); 163 | } else { 164 | fprintf(fp, " \"%s\" : %d\n", gateString(i), stat->gateCalls[i]); 165 | } 166 | } 167 | } 168 | fprintf(fp, " }\n"); 169 | fprintf(fp, " },\n"); 170 | 171 | fprintf(fp, " \"runtime\" : {\n"); 172 | fprintf(fp, " \"total simulation time\" : %.f,\n", stat->tm_total); 173 | fprintf(fp, " \"individual gate time\" : {\n"); 174 | pos = 0; 175 | for(int i=0; igateCalls[i] != 0) { 177 | if(++pos < stat->usedGates) { 178 | fprintf(fp, " \"%s\" : [%.f, %.f, %.f, %.f],\n", gateString(i), 179 | stat->tm_gates_total[i], 180 | stat->tm_gates_max[i], 181 | stat->tm_gates_min[i], 182 | stat->tm_gates_avg[i]); 183 | } else { 184 | fprintf(fp, " \"%s\" : [%.f, %.f, %.f, %.f]\n", gateString(i), 185 | stat->tm_gates_total[i], 186 | stat->tm_gates_max[i], 187 | stat->tm_gates_min[i], 188 | stat->tm_gates_avg[i]); 189 | } 190 | } 191 | } 192 | fprintf(fp, " }\n"); 193 | fprintf(fp, " },\n"); 194 | 195 | fprintf(fp, " \"simulation jobs\" : {\n"); 196 | fprintf(fp, " \"max states\" : %ld,\n", (uint64_t)stat->maxQStates); 197 | fprintf(fp, " \"final states\" : %ld,\n", (uint64_t)stat->finalQStates); 198 | fprintf(fp, " \"used memory\" : \"%s\"\n", memUsedStr); 199 | fprintf(fp, " },\n"); 200 | 201 | fprintf(fp, " \"system\" : {\n"); 202 | fprintf(fp, " \"OS\" : {\n"); 203 | fprintf(fp, " \"name\" : \"%s\",\n", stat->os_name); 204 | fprintf(fp, " \"version\" : \"%s\"\n", stat->os_version); 205 | fprintf(fp, " },\n"); 206 | fprintf(fp, " \"CPU\" : {\n"); 207 | fprintf(fp, " \"model\" : \"%s\",\n", stat->cpu_model); 208 | fprintf(fp, " \"cores\" : %d,\n", stat->cpu_cores); 209 | fprintf(fp, " \"herz\" : \"%s\"\n", stat->cpu_herz); 210 | fprintf(fp, " },\n"); 211 | fprintf(fp, " \"Memory\" : {\n"); 212 | fprintf(fp, " \"total\" : \"%s\",\n", memTotalStr); 213 | fprintf(fp, " \"avail\" : \"%s\"\n", memAvailStr); 214 | fprintf(fp, " }\n"); 215 | fprintf(fp, " }\n"); 216 | 217 | fprintf(fp, "}\n"); 218 | 219 | fclose(fp); 220 | } 221 | 222 | void convertQASM(void) 223 | { 224 | FILE *in = NULL; 225 | FILE *out = NULL; 226 | 227 | in = fopen(f_in, "rt"); 228 | out = fopen(f_qasm, "wt"); 229 | 230 | while(!feof(in)) { 231 | char line[1024] = ""; 232 | 233 | fgets(line, sizeof(line), in); 234 | fprintf(out, "%s", line); 235 | } 236 | fprintf(out, "\n\n"); 237 | 238 | fclose(in); 239 | fclose(out); 240 | } 241 | 242 | void runQASM(void) 243 | { 244 | map cregMap; 245 | 246 | /*********************************************/ 247 | /* STEP1: parsing qasm codes */ 248 | /*********************************************/ 249 | Parser *parser = new Parser(f_qasm); 250 | parser->parse(); 251 | 252 | /*********************************************/ 253 | /* STEP2: run qasm codes for nshots */ 254 | /*********************************************/ 255 | for(int i=0; irun(); 259 | parser->get_measure(str); 260 | 261 | auto it = cregMap.find(str); 262 | if(it == cregMap.end()) { 263 | cregMap[str] = 1; 264 | } else { 265 | it->second++; 266 | } 267 | 268 | parser->reset(); 269 | }; 270 | 271 | /*********************************************/ 272 | /* STEP3: generate measured output */ 273 | /*********************************************/ 274 | char cmd[256]= ""; 275 | dirc = strdup(f_out); 276 | dname = dirname(dirc); 277 | sprintf(cmd, "mkdir -p %s", dname); 278 | system(cmd); 279 | 280 | FILE *fp = fopen(f_out, "wt"); 281 | if(fp == NULL) { 282 | printf("error: cannot open '%s'\n", f_out); 283 | } 284 | 285 | fprintf(fp, "Total Shots: %d\n", shots); 286 | fprintf(fp, "Measured States: %ld\n", cregMap.size()); 287 | 288 | if(cregMap.size() > 0) { 289 | fprintf(fp, "\n"); 290 | for(auto entry : cregMap) { 291 | fprintf(fp, "%d%%, %d/%d, |%s>\n", 292 | (int)(entry.second*100/shots), 293 | entry.second, shots, entry.first.c_str()); 294 | } 295 | } 296 | 297 | fclose(fp); 298 | 299 | /*********************************************/ 300 | /* STEP4: generate simulation stat to json */ 301 | /*********************************************/ 302 | struct qregister_stat stat = parser->getQRegStat(); 303 | 304 | if(is_verbose) { 305 | showStat(&stat); 306 | } 307 | 308 | if(is_json) { 309 | genStatJson(&stat); 310 | } 311 | 312 | delete parser; 313 | } 314 | 315 | int main(int argc, char **argv) 316 | { 317 | struct sigaction sa; 318 | int c; 319 | 320 | prog = argv[0]; 321 | 322 | memset(&sa, 0, sizeof(struct sigaction)); 323 | sa.sa_handler = sig_handler; 324 | sigemptyset(&sa.sa_mask); 325 | sa.sa_flags = 0; 326 | 327 | sigaction(SIGABRT, &sa, NULL); 328 | 329 | strcpy(f_in, ""); 330 | strcpy(f_out, ""); 331 | strcpy(j_out, ""); 332 | shots = 1; /* default number of shot */ 333 | is_verbose = 0; 334 | is_json = 0; 335 | 336 | static const struct option options[] = { 337 | {"verbose", 0, 0, '1'}, 338 | {"version", 0, 0, '2'} 339 | }; 340 | 341 | while ((c = getopt_long(argc, argv, "i:o:s:j:h", options, NULL)) != -1) { 342 | switch(c) { 343 | case 'i': 344 | if(!optarg) 345 | usage(); 346 | strcpy(f_in, optarg); 347 | break; 348 | case 'o': 349 | if(!optarg) 350 | usage(); 351 | strcpy(f_out, optarg); 352 | break; 353 | case 's': 354 | if(!optarg) 355 | usage(); 356 | shots = atoi(optarg); 357 | break; 358 | case 'j': 359 | if(!optarg) 360 | usage(); 361 | strcpy(j_out, optarg); 362 | is_json = 1; 363 | break; 364 | case '1': 365 | is_verbose = 1; 366 | break; 367 | case '2': 368 | printf("%s\n", version); 369 | exit(0); 370 | break; 371 | default: 372 | case 'h': 373 | usage(); 374 | break; 375 | } 376 | } 377 | 378 | if(strlen(f_in) == 0 || strlen(f_out) == 0) { 379 | usage(); 380 | } 381 | 382 | convertQASM(); 383 | runQASM(); 384 | } 385 | -------------------------------------------------------------------------------- /qasm/cli/module.mk: -------------------------------------------------------------------------------- 1 | QASM_SRC = ./main.cpp 2 | QASM_SRC += ./src/Parser.cpp 3 | QASM_SRC += ./src/Token.cpp 4 | QASM_SRC += ./src/Scanner.cpp 5 | 6 | QASM_HDR = ./include/Parser.h 7 | QASM_HDR += ./include/Token.h 8 | QASM_HDR += ./include/Scanner.h 9 | QASM_HDR += ./include/Cal.h 10 | QASM_HDR += ./include/ds.h 11 | -------------------------------------------------------------------------------- /qasm/cli/qasm/sample.qasm: -------------------------------------------------------------------------------- 1 | // QuvieC initial code 2 | OPENQASM 2.0; 3 | include "qelib1.inc"; 4 | 5 | qreg q[4]; 6 | creg c[4]; 7 | 8 | gate ugate1 a, b, c { 9 | cx a, b; 10 | h c; 11 | u3(pi/4, pi/10, pi/15) c; 12 | } 13 | 14 | gate ugate2 a, b { 15 | cx a, b; 16 | x a; 17 | } 18 | 19 | h q; 20 | u1(cos(pi/3)/0.3*sin(10.2)) q[2]; 21 | u2(pi/10, cos(pi/3)/0.3*sin(10.2)) q[2]; 22 | 23 | u3(pi/4, -pi/10, pi/15) q[2]; 24 | u2(pi/10, cos(pi/3)/0.3*sin(10.2)) q[2]; 25 | rz(cos(pi/3)/0.3*sin(10.2)) q[2]; 26 | u2(pi/10, cos(pi/3)/0.3*sin(10.2)) q[2]; 27 | 28 | ugate1 q[0], q[1], q[2]; 29 | 30 | if (c == 3) u2(pi/10, cos(pi/3)/0.3*sin(10.2)) q[2]; 31 | if (c <= 3) h q; 32 | if (c < 3) cx q[0],q[2]; 33 | if (c >= 3) ccx q[0],q[1], q[2]; 34 | 35 | measure q -> c; 36 | measure q[0] -> c [1]; 37 | -------------------------------------------------------------------------------- /qasm/cli/qasm/test.qasm: -------------------------------------------------------------------------------- 1 | // QuvieC initial code 2 | OPENQASM 2.0; 3 | include "qelib1.inc"; 4 | 5 | qreg q[4]; 6 | creg c[4]; 7 | creg c2[3]; 8 | 9 | gate ugate1(r1, r2, r3) a, b, c { 10 | cx a, b; 11 | h c; 12 | u3(r1, r2, r3) c; 13 | } 14 | 15 | gate ugate2 a, b { 16 | cx a, b; 17 | x a; 18 | } 19 | 20 | h q; 21 | u1(cos(pi/3)/0.3*sin(10.2)) q[2]; 22 | u2(pi/10, cos(pi/3)/0.3*sin(10.2)) q[2]; 23 | 24 | u3(pi/4, -pi/10, pi/15) q[2]; 25 | u2(pi/10, cos(pi/3)/0.3*sin(10.2)) q[2]; 26 | rz(cos(pi/3)/0.3*sin(10.2)) q[2]; 27 | u2(pi/10, cos(pi/3)/0.3*sin(10.2)) q[2]; 28 | 29 | ugate1 (pi/2, pi/3, pi/4) q[0], q[1], q[2]; 30 | ugate2 q[0], q[1]; 31 | 32 | measure q -> c; 33 | measure q[0] -> c [1]; 34 | 35 | if (c == 1) u2(pi/10, cos(pi/3)/0.3*sin(10.2)) q[2]; 36 | if (c <= 2) h q; 37 | if (c < 3) cx q[0],q[2]; 38 | if (c2 >= 4) ccx q[0],q[1], q[2]; 39 | if (c == 0) rx(pi) q; 40 | -------------------------------------------------------------------------------- /qasm/cli/src/Scanner.cpp: -------------------------------------------------------------------------------- 1 | #include "Scanner.h" 2 | 3 | void Scanner::readName(Token &t) 4 | { 5 | std::stringstream ss; 6 | while(isdigit(ch) || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_' || ch == '.') { 7 | ss << ch; 8 | nextCh(); 9 | } 10 | 11 | t.kind = Kind::str; 12 | t.str = ss.str(); 13 | } 14 | 15 | void Scanner::readNumber(Token &t) 16 | { 17 | std::stringstream ss; 18 | while(isdigit(ch)) { 19 | ss << ch; 20 | nextCh(); 21 | } 22 | if(ch != '.') { 23 | t.kind = Kind::number; 24 | t.val = std::stoi(ss.str()); 25 | return; 26 | } 27 | ss << ch; 28 | nextCh(); 29 | while(isdigit(ch)) { 30 | ss << ch; 31 | nextCh(); 32 | } 33 | 34 | t.kind = Kind::rnumber; 35 | t.rval = std::stod(ss.str()); 36 | 37 | return; 38 | } 39 | 40 | void Scanner::skipComment() 41 | { 42 | while(ch != '\n' && ch != (char) -1) { 43 | nextCh(); 44 | } 45 | } 46 | 47 | void Scanner::nextCh(void) 48 | { 49 | in->get(ch); 50 | } 51 | 52 | void Scanner::scan(void) 53 | { 54 | bool need_next = true; 55 | 56 | while(!in->eof()) { 57 | Token t(Kind::none, line); 58 | 59 | if(need_next == true) { 60 | nextCh(); 61 | } else { 62 | need_next = true; 63 | } 64 | 65 | if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { 66 | readName(t); 67 | need_next = false; 68 | } else if(isdigit(ch)) { 69 | readNumber(t); 70 | need_next = false; 71 | } else if(ch == ';') { 72 | t.kind = Kind::semicolon; 73 | t.str = ";"; 74 | } else if(ch == '\n') { 75 | line++; 76 | } else if(ch == '(') { 77 | t.kind = Kind::lpar; 78 | t.str = "("; 79 | } else if(ch == ')') { 80 | t.kind = Kind::rpar; 81 | t.str = ")"; 82 | } else if(ch == '[') { 83 | t.kind = Kind::lbrack; 84 | t.str = "["; 85 | } else if(ch == ']') { 86 | t.kind = Kind::rbrack; 87 | t.str = "]"; 88 | } else if(ch == '{') { 89 | t.kind = Kind::lbrace; 90 | t.str = "{"; 91 | } else if(ch == '}') { 92 | t.kind = Kind::rbrace; 93 | t.str = "}"; 94 | } else if(ch == ',') { 95 | t.kind = Kind::comma; 96 | t.str = ","; 97 | } else if(ch == '+') { 98 | t.kind = Kind::plus; 99 | t.str = ";"; 100 | } else if(ch == '-') { 101 | nextCh(); 102 | if(ch == '>') { 103 | t.kind = Kind::arrow; 104 | t.str = "->"; 105 | } else { 106 | t.kind = Kind::minus; 107 | t.str = "-"; 108 | need_next = false; 109 | } 110 | } else if(ch == '*') { 111 | t.kind = Kind::multiply; 112 | t.str = "*"; 113 | } else if(ch == '/') { 114 | nextCh(); 115 | if(ch == '/') { 116 | skipComment(); 117 | } else { 118 | t.kind = Kind::divide; 119 | t.str = "/"; 120 | } 121 | need_next = false; 122 | } else if(ch == '>') { 123 | nextCh(); 124 | if(ch == '=') { 125 | t.kind = Kind::gte; 126 | t.str = ">="; 127 | } else { 128 | t.kind = Kind::gt; 129 | t.str = ">"; 130 | need_next = false; 131 | } 132 | } else if(ch == '<') { 133 | nextCh(); 134 | if(ch == '=') { 135 | t.kind = Kind::lte; 136 | t.str = "<="; 137 | } else { 138 | t.kind = Kind::lt; 139 | t.str = "<"; 140 | need_next = false; 141 | } 142 | } else if(ch == '=') { 143 | nextCh(); 144 | if(ch == '=') { 145 | t.kind = Kind::eq; 146 | t.str = "=="; 147 | } else { 148 | need_next = false; 149 | t.str = "="; 150 | } 151 | } 152 | 153 | if(t.kind != Kind::none) { 154 | tokens.push_back(t); 155 | } 156 | } 157 | 158 | check_args(); 159 | } 160 | 161 | void Scanner::check_args(void) 162 | { 163 | Kind curKind = Kind::none; 164 | int brack_cnt = 0; 165 | int par_cnt = 0; 166 | int brace_cnt = 0; 167 | for(auto k : tokens) { 168 | if(k.kind == Kind::lbrack) { 169 | if(brack_cnt != 0) { 170 | logExit("[%s:%d] '[]' pair is invalid in line %d", _F_, _L_, k.line); 171 | } 172 | brack_cnt++; 173 | } else if(k.kind == Kind::rbrack) { 174 | if(brack_cnt == 0) { 175 | logExit("[%s:%d] '[]' pair is invalid in line %d", _F_, _L_, k.line); 176 | } 177 | brack_cnt--; 178 | } else if(k.kind == Kind::lpar) { 179 | par_cnt++; 180 | } else if(k.kind == Kind::rpar) { 181 | if(par_cnt == 0) { 182 | logExit("[%s:%d] '()' pair is invalid in line %d", _F_, _L_, k.line); 183 | } 184 | par_cnt--; 185 | } else if(k.kind == Kind::lbrace) { 186 | brace_cnt++; 187 | } else if(k.kind == Kind::rbrace) { 188 | if(brace_cnt == 0) { 189 | logExit("[%s:%d] '{}' pair is invalid in line %d", _F_, _L_, k.line); 190 | } 191 | brace_cnt--; 192 | } 193 | } 194 | 195 | if(par_cnt != 0 || brack_cnt != 0 || brace_cnt != 0) { 196 | logExit("[%s:%d] symbolic pair('[]', '()', '{}') is invalid.", _F_, _L_); 197 | } 198 | } 199 | 200 | void Scanner::build_ugates(std::map &ugates) 201 | { 202 | for(int i=0; i &qregs) 240 | { 241 | Reg_args regs; 242 | int qsize = 0; 243 | int qpos = 0; 244 | 245 | for(int i=0; i &cregs) 270 | { 271 | Reg_args regs; 272 | int csize = 0; 273 | int cpos = 0; 274 | 275 | for(int i=0; i &stmt, int &pos) 300 | { 301 | stmt.clear(); 302 | 303 | for(; pos source, std::vector &stmt, int &pos) 325 | { 326 | stmt.clear(); 327 | 328 | for(; pos 17 | #include 18 | #include 19 | 20 | #include "Parser.h" 21 | 22 | #define MAX_LENG 512 23 | 24 | 25 | /** START UPDATE[01.16] */ 26 | #include 27 | #include 28 | #include 29 | 30 | /** 31 | * @brief Returns the library location of the currently executing code. 32 | * 33 | * @return The path to the library directory. 34 | */ 35 | std::string getLibraryLocation() { 36 | Dl_info info; 37 | if (dladdr((void*)getLibraryLocation, &info)) { 38 | std::string fullPath(info.dli_fname); 39 | return std::string(dirname(&fullPath[0])); 40 | } 41 | return ""; 42 | } 43 | // std::string libraryLocation(getLibraryLocation()); 44 | /** END of UPDATE[01.16] */ 45 | 46 | /** 47 | * @brief Converts a gate value to a string representation. 48 | * 49 | * @param gate The gate value to convert. 50 | * @return The string representation of the gate value. 51 | */ 52 | std::string convertGate2String(int gate) 53 | { 54 | switch(gate) { 55 | case QGATE_ID: return "ID"; 56 | case QGATE_U1: return "U1"; 57 | case QGATE_U2: return "U2"; 58 | case QGATE_U3: return "U3"; 59 | case QGATE_X: return "Pauli-X"; 60 | case QGATE_Y: return "Pauli-Y"; 61 | case QGATE_Z: return "Pauli-Z"; 62 | case QGATE_H: return "H"; 63 | case QGATE_P: return "P"; 64 | case QGATE_S: return "S"; 65 | case QGATE_T: return "T"; 66 | case QGATE_SDG: return "SDG"; 67 | case QGATE_TDG: return "TDG"; 68 | case QGATE_RX: return "RX"; 69 | case QGATE_RY: return "RY"; 70 | case QGATE_RZ: return "RZ"; 71 | case QGATE_CX: return "CX"; 72 | case QGATE_CZ: return "CZ"; 73 | case QGATE_CY: return "CY"; 74 | case QGATE_CH: return "CH"; 75 | case QGATE_CCX: return "CCX"; 76 | case QGATE_CRZ: return "CRZ"; 77 | case QGATE_CU1: return "CU1"; 78 | case QGATE_CU2: return "CU2"; 79 | case QGATE_CU3: return "CU3"; 80 | case QGATE_SWAP: return "SWAP"; 81 | case QGATE_CSWAP: return "CSWAP"; 82 | case QGATE_SX: return "SX"; 83 | case QGATE_SXDG: return "SXDG"; 84 | case QGATE_ISWAP: return "ISWAP"; 85 | case QGATE_MEASURE: return "MEASURE"; 86 | } 87 | 88 | return "UNKNOWN GATE"; 89 | } 90 | 91 | /** 92 | * @brief Saves a string to a temporary file. 93 | * 94 | * @param data The string to be saved. 95 | * @return The path of the temporary file. 96 | */ 97 | std::string saveStringToTempFile(const std::string& data) { 98 | char tempFileName[] = "/tmp/tempfileXXXXXX"; // Adjust the path as needed 99 | 100 | // Create a temporary file using C-style functions 101 | int tempFileDescriptor = mkstemp(tempFileName); 102 | if (tempFileDescriptor == -1) { 103 | std::cerr << "Error creating temporary file." << std::endl; 104 | return ""; 105 | } 106 | 107 | // Open the temporary file using C-style functions 108 | FILE* tempFilePointer = fdopen(tempFileDescriptor, "w"); 109 | if (!tempFilePointer) { 110 | close(tempFileDescriptor); 111 | std::cerr << "Error opening temporary file." << std::endl; 112 | return ""; 113 | } 114 | 115 | // Write the string to the temporary file using C-style functions 116 | fwrite(data.c_str(), sizeof(char), data.size(), tempFilePointer); 117 | fprintf(tempFilePointer, "\n"); 118 | 119 | fclose(tempFilePointer); 120 | 121 | return tempFileName; 122 | } 123 | 124 | /** 125 | * @brief Removes a file from the file system. 126 | * 127 | * This function removes the file specified by the given file path. 128 | * If the file cannot be removed, an error message is printed to the standard error stream. 129 | * 130 | * @param filePath The path of the file to be removed. 131 | */ 132 | void removeFile(const std::string& filePath) { 133 | if (std::remove(filePath.c_str()) != 0) { 134 | std::cerr << "Error removing file: " << filePath << std::endl; 135 | } 136 | } 137 | 138 | /** 139 | * @brief Replaces all occurrences of a substring in a given string with a replacement string. 140 | * 141 | * @param originalString The original string to be modified. 142 | * @param substringToReplace The substring to be replaced. 143 | * @param replacementString The string to replace the substring with. 144 | */ 145 | void replaceSubstring(std::string& originalString, const std::string& substringToReplace, const std::string& replacementString) { 146 | // Find the position of the substring in the original string 147 | size_t pos = originalString.find(substringToReplace); 148 | 149 | // Check if the substring was found 150 | if (pos != std::string::npos) { 151 | // Replace the substring with the new string 152 | originalString.replace(pos, substringToReplace.length(), replacementString); 153 | } else { 154 | std::cout << "Substring not found." << std::endl; 155 | } 156 | } 157 | 158 | /** 159 | * @brief Converts the given qregister_stat struct, cregMap, and shots into a JSON string. 160 | * 161 | * @param stat The qregister_stat struct containing the quantum register statistics. 162 | * @param cregMap The map containing the classical register values. 163 | * @param shots The number of shots taken in the quantum computation. 164 | * @return The JSON string representation of the given data. 165 | */ 166 | std::string getStringJson(struct qregister_stat *stat, map &cregMap, int shots){ 167 | 168 | char memTotalStr[32] = ""; 169 | char memAvailStr[32] = ""; 170 | char memUsedStr[32] = ""; 171 | 172 | // convert char memUsedStr[32] to string type 173 | int pos = 0; 174 | 175 | human_readable_size(stat->memTotal, memTotalStr); 176 | human_readable_size(stat->memAvail, memAvailStr); 177 | human_readable_size(stat->memUsed, memUsedStr); 178 | 179 | std::string memUsedString(memUsedStr); 180 | std::string memAvailString(memAvailStr); 181 | std::string memTotalString(memTotalStr); 182 | 183 | std::string json = "{\n"; 184 | 185 | json += " \"simulation_results\" : {\n"; 186 | json += " \"total_shots\" : " + to_string(shots) + ",\n"; 187 | json += " \"measured_states\" : " + to_string(cregMap.size()) + ",\n"; 188 | 189 | if (cregMap.size() > 0) { 190 | json += " \"measurement_details\" : [\n"; 191 | for (auto entry : cregMap) { 192 | std::string percentage = to_string(entry.second * 100 / shots); 193 | json += " {\n"; 194 | json += " \"percentage\" : " + percentage + ",\n"; 195 | json += " \"count\" : " + to_string(entry.second) + ",\n"; 196 | json += " \"state\" : \"" + entry.first + "\"\n"; 197 | json += " },\n"; 198 | } 199 | // Remove the trailing comma and newline character 200 | json = json.substr(0, json.size() - 2) + "\n"; 201 | json += " ]\n"; 202 | } 203 | 204 | json += " },\n"; 205 | 206 | 207 | json += " \"circuit\" : {\n"; 208 | json += " \"used_qubits\" : " + to_string(stat->qubits) + ",\n"; 209 | json += " \"used_gates\" : " + to_string(stat->usedGates) + ",\n"; 210 | json += " \"gate_calls\" : {\n"; 211 | 212 | pos = 0; 213 | for(int i=0; igateCalls[i] != 0) { 215 | if(++pos < stat->usedGates) { 216 | json += " \"" + convertGate2String(i) + "\" : " + to_string(stat->gateCalls[i]) + ",\n"; 217 | } else { 218 | json += " \"" + convertGate2String(i) + "\" : " + to_string(stat->gateCalls[i]) + "\n"; 219 | } 220 | } 221 | } 222 | json += " }\n"; 223 | json += " },\n"; 224 | 225 | json += " \"runtime\" : {\n"; 226 | json += " \"total_simulation_time\" : " + to_string(stat->tm_total) + ",\n"; 227 | json += " \"individual_gate_time\" : {\n"; 228 | pos = 0; 229 | for(int i=0; igateCalls[i] != 0) { 231 | if(++pos < stat->usedGates) { 232 | json += " \"" + convertGate2String(i) + "\" : [" + to_string(stat->tm_gates_total[i]) + ", " + to_string(stat->tm_gates_max[i]) + ", " + to_string(stat->tm_gates_min[i]) + ", " + to_string(stat->tm_gates_avg[i]) + "],\n"; 233 | } else { 234 | json += " \"" + convertGate2String(i) + "\" : [" + to_string(stat->tm_gates_total[i]) + ", " + to_string(stat->tm_gates_max[i]) + ", " + to_string(stat->tm_gates_min[i]) + ", " + to_string(stat->tm_gates_avg[i]) + "]\n"; 235 | } 236 | } 237 | } 238 | json += " }\n"; 239 | json += " },\n"; 240 | 241 | json += " \"simulation_jobs\" : {\n"; 242 | json += " \"max_states\" : " + to_string((uint64_t)stat->maxQStates) + ",\n"; 243 | json += " \"final_states\" : " + to_string((uint64_t)stat->finalQStates) + ",\n"; 244 | json += " \"used_memory\" : \"" + memUsedString + "\"\n"; 245 | json += " },\n"; 246 | 247 | json += " \"system\" : {\n"; 248 | json += " \"os\" : {\n"; 249 | json += " \"name\" : \"" + string(stat->os_name) + "\",\n"; 250 | json += " \"version\" : \"" + string(stat->os_version) + "\"\n"; 251 | json += " },\n"; 252 | 253 | json += " \"cpu\" : {\n"; 254 | json += " \"model\" : \"" + string(stat->cpu_model) + "\",\n"; 255 | json += " \"cores\" : " + to_string(stat->cpu_cores) + ",\n"; 256 | json += " \"herz\" : \"" + string(stat->cpu_herz) + "\"\n"; 257 | json += " },\n"; 258 | 259 | json += " \"memory\" : {\n"; 260 | json += " \"total\" : \"" + memTotalString + "\",\n"; 261 | json += " \"avail\" : \"" + memAvailString + "\"\n"; 262 | json += " }\n"; 263 | json += " }\n"; 264 | 265 | json += "}\n"; 266 | 267 | return json; 268 | } 269 | 270 | /** 271 | * @brief Executes the given QASM code and returns the result. 272 | * 273 | * @param qasm The QASM code to execute. 274 | * @param shots The number of shots to perform (default: 1080). 275 | * @return The result of the execution. 276 | */ 277 | std::string executeQASM(std::string qasm, int shots=1080){ 278 | map cregMap; 279 | std::string json_str; 280 | 281 | // STEP 1 : preprocessing QASM file 282 | 283 | /** STAERT UPDATE[01.16] */ 284 | /* 285 | //* Replace qelib1.inc path [1] 286 | //* : If you include qelib1.inc directly in the file. 287 | // get current this file path 288 | string currentPath = std::filesystem::path(__FILE__).parent_path().string(); 289 | // Replace qelib1.inc path 290 | string qelib_path = currentPath + "/qelib1.inc"; 291 | */ 292 | 293 | /* 294 | //* Replace qelib1.inc path [2] 295 | //* : If you specify the file path of qelib1.inc directly. 296 | // Replace qelib1.inc path 297 | string qelib_path = "/usr/local/lib/python3.10/dist-packages/qplayer/qelib1.inc"; 298 | */ 299 | 300 | //* Replace qelib1.inc path [3] 301 | //* : Function to get the current library location. 302 | // Replace qelib1.inc path 303 | std::string qelib_path = getLibraryLocation() + "/qplayer/qelib1.inc"; 304 | /** END of UPDATE[01.16] */ 305 | 306 | replaceSubstring(qasm, "qelib1.inc", qelib_path); 307 | 308 | std::string path = saveStringToTempFile(qasm); 309 | 310 | // STEP 2 : execute QASM file for shot-round 311 | Parser* parser = new Parser(path); 312 | parser->parse(); 313 | 314 | for(int i=0; irun(); 318 | parser->get_measure(str); 319 | 320 | auto it = cregMap.find(str); 321 | if(it == cregMap.end()) { 322 | cregMap[str] = 1; 323 | } else { 324 | it->second++; 325 | } 326 | 327 | parser->reset(); 328 | } 329 | 330 | // STEP 4 : show simulation stat or generate json and result of measurement 331 | struct qregister_stat stat = parser->getQRegStat(); 332 | 333 | if(cregMap.size() != 0) 334 | json_str = getStringJson(&stat, cregMap, shots); 335 | 336 | // STEP 5 : delete path file and parser 337 | removeFile(path); 338 | 339 | delete parser; 340 | 341 | return json_str; 342 | } 343 | 344 | namespace py = pybind11; 345 | 346 | /** 347 | * @brief Binds the module to Python using Pybind11. 348 | * 349 | * @param m The Pybind11 module object. 350 | */ 351 | PYBIND11_MODULE(qplayer_wra, m) { 352 | m.def("executeQASM", &executeQASM, "Description of executeQASM function", 353 | py::arg("_qasm"), py::arg("_shots")=1080); 354 | } 355 | -------------------------------------------------------------------------------- /qasm/qiskit/qplayer/qelib1.inc: -------------------------------------------------------------------------------- 1 | // File taken from https://github.com/Qiskit/openqasm/blob/master/examples/generic/qelib1.inc 2 | // License: Apache License Version 2.0, January 2004 3 | // Quantum Experience (QE) Standard Header 4 | // file: qelib1.inc 5 | 6 | // --- QE Hardware primitives --- 7 | 8 | // 3-parameter 2-pulse single qubit gate 9 | gate u3(theta,phi,lambda) q { U(theta,phi,lambda) q; } 10 | // 2-parameter 1-pulse single qubit gate 11 | gate u2(phi,lambda) q { U(pi/2,phi,lambda) q; } 12 | // 1-parameter 0-pulse single qubit gate 13 | gate u1(lambda) q { U(0,0,lambda) q; } 14 | // controlled-NOT 15 | gate cx c,t { CX c,t; } 16 | // idle gate (identity) 17 | gate id a { U(0,0,0) a; } 18 | 19 | // --- QE Standard Gates --- 20 | 21 | // Pauli gate: bit-flip 22 | gate x a { u3(pi,0,pi) a; } 23 | // Pauli gate: bit and phase flip 24 | gate y a { u3(pi,pi/2,pi/2) a; } 25 | // Pauli gate: phase flip 26 | gate z a { u1(pi) a; } 27 | // Clifford gate: Hadamard 28 | gate h a { u2(0,pi) a; } 29 | // Clifford gate: sqrt(Z) phase gate 30 | gate s a { u1(pi/2) a; } 31 | // Clifford gate: conjugate of sqrt(Z) 32 | gate sdg a { u1(-pi/2) a; } 33 | // C3 gate: sqrt(S) phase gate 34 | gate t a { u1(pi/4) a; } 35 | // C3 gate: conjugate of sqrt(S) 36 | gate tdg a { u1(-pi/4) a; } 37 | // sx gate : fake implementation 38 | gate sx a { id a; } 39 | 40 | // --- Standard rotations --- 41 | // Rotation around X-axis 42 | gate rx(theta) a { u3(theta,-pi/2,pi/2) a; } 43 | // rotation around Y-axis 44 | gate ry(theta) a { u3(theta,0,0) a; } 45 | // rotation around Z axis 46 | gate rz(phi) a { u1(phi) a; } 47 | 48 | // --- QE Standard User-Defined Gates --- 49 | 50 | // controlled-Phase 51 | gate cz a,b { h b; cx a,b; h b; } 52 | // controlled-Y 53 | gate cy a,b { sdg b; cx a,b; s b; } 54 | // controlled-H 55 | gate ch a,b { 56 | h b; sdg b; 57 | cx a,b; 58 | h b; t b; 59 | cx a,b; 60 | t b; h b; s b; x b; s a; 61 | } 62 | // C3 gate: Toffoli 63 | gate ccx a,b,c 64 | { 65 | h c; 66 | cx b,c; tdg c; 67 | cx a,c; t c; 68 | cx b,c; tdg c; 69 | cx a,c; t b; t c; h c; 70 | cx a,b; t a; tdg b; 71 | cx a,b; 72 | } 73 | // controlled rz rotation 74 | gate crz(lambda) a,b 75 | { 76 | u1(lambda/2) b; 77 | cx a,b; 78 | u1(-lambda/2) b; 79 | cx a,b; 80 | } 81 | // controlled phase rotation 82 | gate cu1(lambda) a,b 83 | { 84 | u1(lambda/2) a; 85 | cx a,b; 86 | u1(-lambda/2) b; 87 | cx a,b; 88 | u1(lambda/2) b; 89 | } 90 | // controlled-U 91 | gate cu3(theta,phi,lambda) c, t 92 | { 93 | // implements controlled-U(theta,phi,lambda) with target t and control c 94 | u1((lambda-phi)/2) t; 95 | cx c,t; 96 | u3(-theta/2,0,-(phi+lambda)/2) t; 97 | cx c,t; 98 | u3(theta/2,phi,0) t; 99 | } 100 | //swap 101 | gate swap a, b 102 | { 103 | cx a,b; 104 | cx b,a; 105 | cx a,b; 106 | } 107 | //cswap 108 | gate cswap a, b, c 109 | { 110 | cx c,b; 111 | ccx a, b, c; 112 | cx c,b; 113 | } 114 | gate sxdg a 115 | { 116 | u3(-1.2309594173407747, -pi/2, pi/2) a; 117 | } 118 | -------------------------------------------------------------------------------- /qasm/qiskit/qplayer/run_qplayer.py: -------------------------------------------------------------------------------- 1 | ####################################################################### 2 | # run_qplayer.py 3 | # 4 | # Created: 2023. 12. 13 5 | # Last Modified: 2023. 12. 14 6 | # 7 | # Authors: 8 | # Sengthai Heng (sengthai@pukyong.ac.kr) 9 | # Nagyeong Choi (choi2019@pukyong.ac.kr) 10 | # 11 | # Quantum Computing Laboratory, PKNU (quantum.pknu.ac.kr) 12 | ####################################################################### 13 | 14 | import qiskit 15 | from qiskit import qasm2 16 | from qiskit import QuantumCircuit 17 | from packaging import version 18 | import qplayer_wra 19 | import json 20 | from .QResult import QResult 21 | 22 | def executeQASM(qc : QuantumCircuit, shots:int = 1080): 23 | """ 24 | Executes the given QASM code using the qplayer_wra module. 25 | 26 | Args: 27 | qasm_code (str): The QASM code to be executed. 28 | shots (int): The run number. 29 | 30 | Returns: 31 | QResult: The result of the QASM execution. 32 | """ 33 | 34 | qiskit_version = qiskit.__version__ 35 | if version.parse(qiskit_version) >= version.parse("1.0.1"): 36 | qasm_code = qasm2.dumps(qc) 37 | elif version.parse(qiskit_version) < version.parse("1.0.1"): 38 | qasm_code = qc.qasm() 39 | result = qplayer_wra.executeQASM(qasm_code, shots) 40 | result = json.loads(result) 41 | 42 | try: 43 | result = QResult(**result) 44 | except Exception as e: 45 | print(f"Error creating QResult: {e}") 46 | return None 47 | 48 | return result 49 | -------------------------------------------------------------------------------- /qasm/qiskit/setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Learn more: https://github.com/kennethreitz/setup.py 4 | 5 | ## for pybind11 6 | #start 7 | import os 8 | import re 9 | import subprocess 10 | import sys 11 | from pathlib import Path 12 | 13 | from setuptools import Extension, setup 14 | from setuptools.command.build_ext import build_ext 15 | 16 | from setuptools import setup, find_packages 17 | #end 18 | 19 | readme = ""; 20 | license = ""; 21 | 22 | dependencies = "setuptools"; 23 | dependencies += "\nscikit-build"; 24 | dependencies += "\nqiskit"; 25 | dependencies += "\nmatplotlib"; 26 | dependencies += "\npybind11"; 27 | dependencies += "\ncmake"; 28 | dependencies += "\nvirtualenv"; 29 | 30 | ## for pybind11 31 | #start 32 | 33 | # Convert distutils Windows platform specifiers to CMake -A arguments 34 | PLAT_TO_CMAKE = { 35 | "win32": "Win32", 36 | "win-amd64": "x64", 37 | "win-arm32": "ARM", 38 | "win-arm64": "ARM64", 39 | } 40 | 41 | 42 | # A CMakeExtension needs a sourcedir instead of a file list. 43 | # The name must be the _single_ output extension from the CMake build. 44 | # If you need multiple extensions, see scikit-build. 45 | class CMakeExtension(Extension): 46 | def __init__(self, name: str, sourcedir: str = "") -> None: 47 | super().__init__(name, sources=[]) 48 | self.sourcedir = os.fspath(Path(sourcedir).resolve()) 49 | 50 | 51 | class CMakeBuild(build_ext): 52 | def build_extension(self, ext: CMakeExtension) -> None: 53 | # Must be in this form due to bug in .resolve() only fixed in Python 3.10+ 54 | ext_fullpath = Path.cwd() / self.get_ext_fullpath(ext.name) 55 | extdir = ext_fullpath.parent.resolve() 56 | 57 | # Using this requires trailing slash for auto-detection & inclusion of 58 | # auxiliary "native" libs 59 | 60 | debug = int(os.environ.get("DEBUG", 0)) if self.debug is None else self.debug 61 | cfg = "Debug" if debug else "Release" 62 | 63 | # CMake lets you override the generator - we need to check this. 64 | # Can be set with Conda-Build, for example. 65 | cmake_generator = os.environ.get("CMAKE_GENERATOR", "") 66 | 67 | # Set Python_EXECUTABLE instead if you use PYBIND11_FINDPYTHON 68 | # EXAMPLE_VERSION_INFO shows you how to pass a value into the C++ code 69 | # from Python. 70 | cmake_args = [ 71 | f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={extdir}{os.sep}", 72 | f"-DPYTHON_EXECUTABLE={sys.executable}", 73 | f"-DCMAKE_BUILD_TYPE={cfg}", # not used on MSVC, but no harm 74 | ] 75 | build_args = [] 76 | # Adding CMake arguments set as environment variable 77 | # (needed e.g. to build for ARM OSx on conda-forge) 78 | if "CMAKE_ARGS" in os.environ: 79 | cmake_args += [item for item in os.environ["CMAKE_ARGS"].split(" ") if item] 80 | 81 | # In this example, we pass in the version to C++. You might not need to. 82 | cmake_args += [f"-DEXAMPLE_VERSION_INFO={self.distribution.get_version()}"] 83 | 84 | if self.compiler.compiler_type != "msvc": 85 | # Using Ninja-build since it a) is available as a wheel and b) 86 | # multithreads automatically. MSVC would require all variables be 87 | # exported for Ninja to pick it up, which is a little tricky to do. 88 | # Users can override the generator with CMAKE_GENERATOR in CMake 89 | # 3.15+. 90 | if not cmake_generator or cmake_generator == "Ninja": 91 | try: 92 | import ninja 93 | 94 | ninja_executable_path = Path(ninja.BIN_DIR) / "ninja" 95 | cmake_args += [ 96 | "-GNinja", 97 | f"-DCMAKE_MAKE_PROGRAM:FILEPATH={ninja_executable_path}", 98 | ] 99 | except ImportError: 100 | pass 101 | 102 | else: 103 | # Single config generators are handled "normally" 104 | single_config = any(x in cmake_generator for x in {"NMake", "Ninja"}) 105 | 106 | # CMake allows an arch-in-generator style for backward compatibility 107 | contains_arch = any(x in cmake_generator for x in {"ARM", "Win64"}) 108 | 109 | # Specify the arch if using MSVC generator, but only if it doesn't 110 | # contain a backward-compatibility arch spec already in the 111 | # generator name. 112 | if not single_config and not contains_arch: 113 | cmake_args += ["-A", PLAT_TO_CMAKE[self.plat_name]] 114 | 115 | # Multi-config generators have a different way to specify configs 116 | if not single_config: 117 | cmake_args += [ 118 | f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{cfg.upper()}={extdir}" 119 | ] 120 | build_args += ["--config", cfg] 121 | 122 | if sys.platform.startswith("darwin"): 123 | # Cross-compile support for macOS - respect ARCHFLAGS if set 124 | archs = re.findall(r"-arch (\S+)", os.environ.get("ARCHFLAGS", "")) 125 | if archs: 126 | cmake_args += ["-DCMAKE_OSX_ARCHITECTURES={}".format(";".join(archs))] 127 | 128 | # Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level 129 | # across all generators. 130 | if "CMAKE_BUILD_PARALLEL_LEVEL" not in os.environ: 131 | # self.parallel is a Python 3 only way to set parallel jobs by hand 132 | # using -j in the build_ext call, not supported by pip or PyPA-build. 133 | if hasattr(self, "parallel") and self.parallel: 134 | # CMake 3.12+ only. 135 | build_args += [f"-j{self.parallel}"] 136 | 137 | build_temp = Path(self.build_temp) / ext.name 138 | if not build_temp.exists(): 139 | build_temp.mkdir(parents=True) 140 | 141 | subprocess.run( 142 | ["cmake", ext.sourcedir, *cmake_args], cwd=build_temp, check=True 143 | ) 144 | subprocess.run( 145 | ["cmake", "--build", ".", *build_args], cwd=build_temp, check=True 146 | ) 147 | #end 148 | 149 | 150 | setup( 151 | name='QPlayer', 152 | version='2.4', 153 | author='QPlayer development members', 154 | author_email='ksjin@etri.re.kr', 155 | description='Qiskit-compatible python interface for QPlayer', 156 | url='https://github.com/eQuantumOS/QPlayer', 157 | ext_modules=[CMakeExtension("qplayer_wra")], 158 | cmdclass={"build_ext": CMakeBuild}, 159 | zip_safe=False, 160 | extras_require={"test": ["pytest>=6.0"]}, 161 | python_requires=">=3.7", 162 | license='GPL v3', 163 | packages=find_packages(exclude=('tests', 'docs')), 164 | install_requires=dependencies, 165 | include_package_data=True 166 | ) 167 | -------------------------------------------------------------------------------- /qasm/qiskit/test/test.py: -------------------------------------------------------------------------------- 1 | from qiskit import QuantumCircuit 2 | from qiskit.visualization import plot_histogram 3 | from qplayer import executeQASM 4 | import matplotlib.pyplot as plt 5 | 6 | qc = QuantumCircuit(2) 7 | qc.h(0) 8 | qc.h(1) 9 | qc.y(0) 10 | qc.cx(0, 1) 11 | qc.measure_all() 12 | 13 | result = executeQASM(qc, 16) 14 | figure = plot_histogram(result.get_counts(), figsize=(10, 6)) 15 | 16 | #case1: store result image to file 17 | #figure.savefig('result.png') 18 | 19 | #case2: display result image in terminlal 20 | plt.show(); 21 | -------------------------------------------------------------------------------- /test/MLQ/Makefile: -------------------------------------------------------------------------------- 1 | QPLAYER_RELEASE=../../release 2 | 3 | CXX = g++ 4 | CXXLD = g++ 5 | 6 | CXXFLAGS = -g -Wall -O2 -std=c++11 -MMD -MP -fopenmp 7 | CXXFLAGS += -I. -I$(QPLAYER_RELEASE)/include 8 | CXXFLAGS += -Wno-reorder -Wno-sign-compare -Wno-parentheses -Wno-pessimizing-move 9 | CXXFLAGS += -Wno-unused-function -Wno-unused-variable -Wno-write-strings 10 | CXXFLAGS += -Wno-class-conversion -Wno-unused-result 11 | 12 | LIBS = -L$(QPLAYER_RELEASE)/lib 13 | LIBS += -lm -lpthread -lgomp -lqplayer -fopenmp 14 | 15 | Q=@echo 16 | E=@ 17 | 18 | MLQ_SRC := 19 | MLQ_HDR := 20 | include ./module.mk 21 | 22 | # OBJECT FILES 23 | MLQ_OBJS=$(patsubst %.cpp,%.o,$(MLQ_SRC)) 24 | MLQ_HDRS=$(patsubst %.h,%.h,$(MLQ_HDR)) 25 | 26 | MLQ_EXEC=mlq 27 | MLQ_DEPS=./*.d 28 | 29 | .PHONY: all clean 30 | 31 | .DEFAULT_GOAL := all 32 | 33 | all: mlq 34 | 35 | mlq: $(MLQ_OBJS) 36 | $(CXXLD) $(LDFLAGS) $(MLQ_OBJS) -o $(MLQ_EXEC) $(LIBS) 37 | 38 | %.o : %.cpp $(MLQ_HDRS) 39 | $(Q) "CC $(@)" 40 | $(E) $(CXX) $(CXXFLAGS) -Wno-deprecated-declarations $(LIB_CXX_FLAGS) -c $< -o $@ 41 | 42 | clean: 43 | @echo "Clean Objects, Deps, Executions" 44 | @rm -rf logs 45 | @rm -fv core.* 46 | @rm -fv $(MLQ_OBJS) 47 | @rm -fv $(MLQ_EXEC) 48 | @rm -fv $(MLQ_DEPS) 49 | -------------------------------------------------------------------------------- /test/MLQ/ds.h: -------------------------------------------------------------------------------- 1 | #ifndef __DS_H__ 2 | #define __DS_H__ 3 | 4 | #include 5 | 6 | /* 7 | * We map the number of the qubits by assuming surface code 17. 8 | * The numbers of individual physical qubits of logical qubit are 9 | * converted into a single shape as follows. 10 | */ 11 | typedef enum { 12 | Q0, Q1, Q2, Q3, Q4, 13 | Q5, Q6, Q7, Q8, Q9, 14 | Q10, Q11, Q12, Q13, Q14, 15 | Q15, Q16, Q17, Q18, Q19, 16 | Q20, Q21, Q22, Q23, Q24 17 | } QUBIT_INDEX; 18 | 19 | typedef enum { Z_BASIS=0, X_BASIS } MEASURE_TYPE; 20 | typedef enum { X_LEFT=0, X_RIGHT, Z_LEFT, Z_RIGHT } FLAVOUR; 21 | typedef enum { LEFT_UP=0, RIGHT_UP, LEFT_DOWN, RIGHT_DOWN } MERGE_TYPE; 22 | 23 | #define MAX_LQUBITS 25 24 | 25 | struct lqubit_info { 26 | int id; 27 | int flavor; 28 | int row; 29 | int col; 30 | int pq_num; 31 | int qubits[128]; 32 | }; 33 | 34 | struct lqubits_info { 35 | int lq_num; 36 | int pq_num; 37 | struct lqubit_info lqubits[MAX_LQUBITS]; 38 | }; 39 | 40 | struct stabilizer_circuit { 41 | int sq_index; 42 | int sq_mval; 43 | int dq_size; 44 | int dq_index[4]; 45 | }; 46 | 47 | struct merge_circuit { 48 | int sq; 49 | int sq_mval; 50 | int dq_size; 51 | int dq_list[4]; 52 | }; 53 | 54 | static int x_decoder[2][16] = { 55 | { 56 | /* flavor x-left */ 57 | -1, /* 0000 */ 58 | Q20, /* 0001 */ 59 | Q18, /* 0010 */ 60 | Q19, /* 0011 */ 61 | Q6, /* 0100 */ 62 | Q6, /* 0101 */ 63 | Q12, /* 0110 */ 64 | Q12, /* 0111 */ 65 | Q4, /* 1000 */ 66 | Q4, /* 1001 */ 67 | Q4, /* 1010 */ 68 | Q19, /* 1011 */ 69 | Q5, /* 1100 */ 70 | Q5, /* 1101 */ 71 | Q5, /* 1110 */ 72 | Q5 /* 1111 */ 73 | }, 74 | { 75 | /* flavor x-right */ 76 | -1, /* 0000 */ 77 | Q18, /* 0001 */ 78 | Q20, /* 0010 */ 79 | Q19, /* 0011 */ 80 | Q4, /* 0100 */ 81 | Q4, /* 0101 */ 82 | Q12, /* 0110 */ 83 | Q12, /* 0111 */ 84 | Q6, /* 1000 */ 85 | Q6, /* 1001 */ 86 | Q6, /* 1010 */ 87 | Q19, /* 1011 */ 88 | Q5, /* 1100 */ 89 | Q5, /* 1101 */ 90 | Q5, /* 1110 */ 91 | Q5 /* 1111 */ 92 | } 93 | }; 94 | 95 | static int z_decoder[2][16] = { 96 | { 97 | /* flavor x-left */ 98 | -1, /* 0000 */ 99 | Q6, /* 0001 */ 100 | Q20, /* 0010 */ 101 | Q13, /* 0011 */ 102 | Q4, /* 0100 */ 103 | Q4, /* 0101 */ 104 | Q12, /* 0110 */ 105 | Q12, /* 0111 */ 106 | Q18, /* 1000 */ 107 | Q18, /* 1001 */ 108 | Q18, /* 1010 */ 109 | Q13, /* 1011 */ 110 | Q11, /* 1100 */ 111 | Q11, /* 1101 */ 112 | Q11, /* 1110 */ 113 | Q11 /* 1111 */ 114 | }, 115 | { 116 | /* flavor x-right */ 117 | -1, /* 0000 */ 118 | Q20, /* 0001 */ 119 | Q6, /* 0010 */ 120 | Q13, /* 0011 */ 121 | Q18, /* 0100 */ 122 | Q18, /* 0101 */ 123 | Q12, /* 0110 */ 124 | Q12, /* 0111 */ 125 | Q4, /* 1000 */ 126 | Q4, /* 1001 */ 127 | Q4, /* 1010 */ 128 | Q13, /* 1011 */ 129 | Q11, /* 1100 */ 130 | Q11, /* 1101 */ 131 | Q11, /* 1110 */ 132 | Q11 /* 1111 */ 133 | } 134 | }; 135 | 136 | extern struct qubit_delimiter qd; 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /test/MLQ/logicalQubits.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOGICAL_QUBITS_H__ 2 | #define __LOGICAL_QUBITS_H__ 3 | 4 | #include 5 | 6 | #include "qplayer.h" 7 | 8 | #include "ds.h" 9 | #include "logicalQubit.h" 10 | #include "logicalCNOT.h" 11 | #include "logicalST.h" 12 | 13 | struct qubit_delimiter qd; 14 | 15 | class logicalQubits { 16 | public: 17 | logicalQubit *LQ[MAX_LQUBITS]; 18 | int lq_num; 19 | int pq_num; 20 | 21 | public: 22 | logicalQubits(struct lqubits_info *lqinfo) { 23 | /********************************/ 24 | /* STEP1: set global parameters */ 25 | /********************************/ 26 | lq_num = lqinfo->lq_num; 27 | pq_num = lqinfo->pq_num; 28 | 29 | /**********************************/ 30 | /* STEP2: allocate Logical Qubits */ 31 | /**********************************/ 32 | for(int i=0; ilqubits[i].id, lqinfo); 34 | } 35 | 36 | /**********************************/ 37 | /* [DEBUG] set dump delimeter */ 38 | /**********************************/ 39 | qd.size = lq_num; 40 | for(int i=0; igetPQ(LQ[i]->dq_list[8]); 42 | } 43 | } 44 | 45 | ~logicalQubits(void) { 46 | for(int i=0; iQReg->normalize(); 54 | } 55 | } 56 | 57 | void showQState(void) { 58 | printf("**********************************"); 59 | printf(" Dump %2d Logical Qubits ", lq_num); 60 | printf("**********************************\n"); 61 | for(int i=0; ishowQState(0, LQ[lq_num-1]->getPQ(LQ[lq_num-1]->dq_list[8])); 63 | } 64 | } 65 | 66 | void showNumStates(void) { 67 | for(int i=0; iQReg->getNumStates()); 69 | } 70 | fflush(stdout); 71 | } 72 | 73 | public: 74 | void initLQ(int lqid, int mode) { 75 | /* initialize this logical qubit */ 76 | LQ[lqid]->init(mode); 77 | 78 | /* initialize neighbor magic qubits */ 79 | for(int i=0; imagic_initZ(lqid); 86 | } else if(mode == KET_LONE) { 87 | LQ[i]->magic_initZ(lqid); 88 | LQ[i]->magic_X(lqid); 89 | } else if(mode == KET_LPLUS) { 90 | LQ[i]->magic_initZ(lqid); 91 | LQ[i]->magic_H(lqid); 92 | } else if(mode == KET_LMINUS) { 93 | LQ[i]->magic_initZ(lqid); 94 | LQ[i]->magic_X(lqid); 95 | LQ[i]->magic_H(lqid); 96 | } 97 | } 98 | 99 | normalize(); 100 | } 101 | 102 | void inject(int lqid, double rx, double ry, double rz) { 103 | /* logical X operation for this logical qubit */ 104 | LQ[lqid]->inject(rx, ry, rz); 105 | 106 | /* physical X operation for neighbor magic qubits */ 107 | for(int i=0; imagic_inject(lqid, rx, ry, rz); 110 | } 111 | } 112 | } 113 | 114 | public: 115 | void LX(int lqid) { 116 | /* logical X operation for this logical qubit */ 117 | LQ[lqid]->LX(); 118 | 119 | /* physical X operation for neighbor magic qubits */ 120 | for(int i=0; imagic_X(lqid); 123 | } 124 | } 125 | } 126 | 127 | void LZ(int lqid) { 128 | /* logical Z operation for this logical qubit */ 129 | LQ[lqid]->LZ(); 130 | 131 | /* physical Z operation for neighbor magic qubits */ 132 | for(int i=0; imagic_Z(lqid); 135 | } 136 | } 137 | } 138 | 139 | void LH(int lqid) { 140 | /* logical H operation for this logical qubit */ 141 | LQ[lqid]->LH(); 142 | 143 | /* physical H operation for neighbor magic qubits */ 144 | for(int i=0; imagic_H(lqid); 147 | } 148 | } 149 | } 150 | 151 | int LMZ(int lqid) { 152 | int mv = 0; 153 | 154 | /* Z-basis measurement of this logical logical qubit */ 155 | mv = LQ[lqid]->LMZ(); 156 | 157 | /* forced collpase of neighbor magic qubits */ 158 | for(int i=0; imagic_collapse(lqid, mv); 161 | } 162 | } 163 | 164 | normalize(); 165 | 166 | return mv; 167 | } 168 | 169 | int LMX(int lqid) { 170 | int mv = 0; 171 | 172 | /* X-basis measurement of this logical logical qubit */ 173 | mv = LQ[lqid]->LMX(); 174 | 175 | /* forced collpase of neighbor magic qubits */ 176 | for(int i=0; imagic_collapse(lqid, mv); 179 | } 180 | } 181 | 182 | return mv; 183 | } 184 | 185 | void LCNOT(int id_A, int id_C, int id_T) { 186 | /* logical CNOT operation for this logical qubit */ 187 | logicalCNOT *mergeLQ = NULL; 188 | logicalQubit *AQ = LQ[id_A]; 189 | logicalQubit *CQ = LQ[id_C]; 190 | logicalQubit *TQ = LQ[id_T]; 191 | int mxx1, mxx2; 192 | int mzz1, mzz2; 193 | int mx; 194 | 195 | QTimer timer; 196 | 197 | timer.start(); 198 | mergeLQ = new logicalCNOT(CQ, TQ); 199 | timer.end(); 200 | printf("[composite ] Elapsed Time : %s\n", timer.getTime()); 201 | 202 | timer.start(); 203 | mergeLQ->latticeSurgery(AQ); 204 | timer.end(); 205 | printf("[logicalCNOT] Elapsed Time : %s\n", timer.getTime()); 206 | 207 | timer.start(); 208 | mergeLQ->decompose(); 209 | timer.end(); 210 | printf("[decomposite] Elapsed Time : %s\n", timer.getTime()); 211 | delete mergeLQ; 212 | 213 | /* physical CNOT operation for neighbor magic qubits */ 214 | timer.start(); 215 | for(int i=0; imagic_CNOT(id_C, id_T); 218 | } 219 | } 220 | timer.end(); 221 | printf("[magicCX] Elapsed Time : %s\n", timer.getTime()); 222 | } 223 | 224 | void LS(int lqid, int lqid_A) { 225 | /* logical S operation for this logical qubit */ 226 | logicalST *ST = new logicalST(LQ[lqid], LQ[lqid_A]); 227 | ST->logicalS(); 228 | delete ST; 229 | 230 | /* physical S operation for neighbor magic qubits */ 231 | for(int i=0; imagic_S(lqid); 234 | } 235 | } 236 | } 237 | 238 | void LT(int lqid, int lqid_A) { 239 | /* logical T operation for this logical qubit */ 240 | logicalST *ST = new logicalST(LQ[lqid], LQ[lqid_A]); 241 | ST->logicalT(); 242 | delete ST; 243 | 244 | /* physical T operation for neighbor magic qubits */ 245 | for(int i=0; imagic_T(lqid); 248 | } 249 | } 250 | } 251 | }; 252 | 253 | #endif 254 | -------------------------------------------------------------------------------- /test/MLQ/logicalST.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOGICAL_ST_H__ 2 | #define __LOGICAL_ST_H__ 3 | 4 | #include 5 | 6 | #include "qplayer.h" 7 | #include "logicalQubit.h" 8 | 9 | class logicalST { 10 | public: 11 | logicalQubit *LQ; 12 | logicalQubit *AQ; 13 | 14 | logicalQubit *LQHigh; 15 | logicalQubit *LQLow; 16 | 17 | int mzz; 18 | int mx; 19 | 20 | public: 21 | logicalST(logicalQubit *_lq, logicalQubit *_aq) { 22 | /***************************************/ 23 | /* STEP1: allocate merged Q-Register */ 24 | /***************************************/ 25 | LQ = _lq; 26 | AQ = _aq; 27 | 28 | /***************************************/ 29 | /* STEP2: set LQs in qubit order */ 30 | /***************************************/ 31 | if(LQ->getPQ(LQ->dq_list[0]) < AQ->getPQ(AQ->dq_list[0])) { 32 | LQLow = LQ; 33 | LQHigh = AQ; 34 | } else { 35 | LQLow = AQ; 36 | LQHigh = LQ; 37 | } 38 | } 39 | 40 | ~logicalST(void) { } 41 | 42 | private: 43 | void inject_Y(void) { 44 | for(int i=0; igetPQSize(); i++) { 45 | initZ(LQ->QReg, AQ->getPQ(i)); 46 | } 47 | 48 | /* set seed to center PQ */ 49 | H(LQ->QReg, AQ->getPQ(Q12)); 50 | S(LQ->QReg, AQ->getPQ(Q12)); 51 | 52 | /* CNOT along with X operator */ 53 | CX(LQ->QReg, AQ->getPQ(Q12), AQ->getPQ(Q5)); 54 | CX(LQ->QReg, AQ->getPQ(Q12), AQ->getPQ(Q19)); 55 | 56 | AQ->runStabilizer(LQ->QReg); 57 | } 58 | 59 | void inject_A(void) { 60 | for(int i=0; igetPQSize(); i++) { 61 | initZ(LQ->QReg, AQ->getPQ(i)); 62 | } 63 | 64 | /* set seed to center PQ */ 65 | H(LQ->QReg, AQ->getPQ(Q12)); 66 | T(LQ->QReg, AQ->getPQ(Q12)); 67 | 68 | /* CNOT along with X operator */ 69 | CX(LQ->QReg, AQ->getPQ(Q12), AQ->getPQ(Q5)); 70 | CX(LQ->QReg, AQ->getPQ(Q12), AQ->getPQ(Q19)); 71 | 72 | AQ->runStabilizer(LQ->QReg); 73 | } 74 | 75 | /* As the goal is to verify logical S or T operations, test qubit numbering 76 | is mapped statically. In other words, dynamic logical S or T operations 77 | based on the flavor of logical qubits are not supported. Of course, 78 | this is not impossible, but the code will not be further improved for 79 | the time being. 80 | */ 81 | void merge_ZZ(void) { 82 | int mz1 = 0; 83 | int mz2 = 0; 84 | int mx1 = 0; 85 | 86 | /* Z-merge #1 */ 87 | initZ(LQ->QReg, LQ->getPQ(Q21)); 88 | CX(LQ->QReg, LQ->getPQ(Q18), LQ->getPQ(Q21)); 89 | CX(LQ->QReg, AQ->getPQ(Q4), AQ->getPQ(Q0)); 90 | 91 | /* Z-merge #2 */ 92 | initZ(LQ->QReg, LQ->getPQ(Q23)); 93 | CX(LQ->QReg, LQ->getPQ(Q19), LQ->getPQ(Q23)); 94 | CX(LQ->QReg, LQ->getPQ(Q20), LQ->getPQ(Q23)); 95 | CX(LQ->QReg, AQ->getPQ(Q5), AQ->getPQ(Q0)); 96 | CX(LQ->QReg, AQ->getPQ(Q6), AQ->getPQ(Q2)); 97 | 98 | /* split */ 99 | mz1 = M(LQ->QReg, LQ->getPQ(Q21)) == 0 ? 1 : -1; 100 | mz2 = M(LQ->QReg, LQ->getPQ(Q23)) == 0 ? 1 : -1; 101 | 102 | /* X-measure ancilla */ 103 | AQ->runStabilizer(LQ->QReg); 104 | LQ->runStabilizer(); 105 | mx1 = AQ->LMX(LQ->QReg) == 0 ? 1 : -1; 106 | 107 | /* set measured value for post operation */ 108 | mzz = mz1 * mz2; 109 | mx = mx1; 110 | } 111 | 112 | void do_post_S(void) { 113 | printf("[%s] mzz(%d), mx(%d)\n", __FUNCTION__, mzz, mx); 114 | if(mzz == -1) LQ->LZ(); 115 | if(mx == -1) LQ->LZ(); 116 | } 117 | 118 | void do_post_T(void) { 119 | printf("[%s] mzz(%d), mx(%d)\n", __FUNCTION__, mzz, mx); 120 | if(mzz == 1) { 121 | if(mx == -1) { 122 | LQ->LZ(); 123 | } 124 | } else { 125 | if(mx == 1) { 126 | logicalS(); 127 | } else { 128 | LQ->LZ(); 129 | logicalS(); 130 | } 131 | } 132 | } 133 | 134 | public: 135 | void logicalS(void) { 136 | /* inject ancilla states to |Y> */ 137 | inject_Y(); 138 | 139 | /* do Mzz operation */ 140 | merge_ZZ(); 141 | 142 | /* do post operation */ 143 | do_post_S(); 144 | } 145 | 146 | void logicalT(void) { 147 | /* inject ancilla states to |A> */ 148 | inject_A(); 149 | 150 | /* do Mzz operation */ 151 | merge_ZZ(); 152 | 153 | /* do post operation */ 154 | do_post_T(); 155 | 156 | LQ->runStabilizer(); 157 | } 158 | }; 159 | 160 | #endif 161 | -------------------------------------------------------------------------------- /test/MLQ/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "qplayer.h" 4 | #include "lattice.h" 5 | #include "logicalQubits.h" 6 | 7 | /**************************************************/ 8 | /* Scenarios #1 : initialize logical qubits */ 9 | /**************************************************/ 10 | void init_LQ4(void) { 11 | logicalQubits *MLQ = new logicalQubits(&lqs4); 12 | QTimer timer; 13 | int state = KET_LMINUS; 14 | 15 | timer.start(); 16 | for(int i=0; ilq_num; i++) { 17 | MLQ->initLQ(i, state); 18 | } 19 | timer.end(); 20 | 21 | MLQ->showQState(); 22 | printf("[%s] Elapsed Time : %s\n", __FUNCTION__, timer.getTime()); 23 | showMemoryInfo(); 24 | } 25 | 26 | void init_LQ9(void) { 27 | logicalQubits *MLQ = new logicalQubits(&lqs9); 28 | QTimer timer; 29 | int state = KET_LMINUS; 30 | 31 | timer.start(); 32 | for(int i=0; ilq_num; i++) { 33 | MLQ->initLQ(i, state); 34 | } 35 | timer.end(); 36 | 37 | MLQ->showQState(); 38 | printf("[%s] Elapsed Time : %s\n", __FUNCTION__, timer.getTime()); 39 | showMemoryInfo(); 40 | } 41 | 42 | void init_LQ16(void) { 43 | logicalQubits *MLQ = new logicalQubits(&lqs16); 44 | QTimer timer; 45 | int state = KET_LMINUS; 46 | 47 | timer.start(); 48 | for(int i=0; ilq_num; i++) { 49 | MLQ->initLQ(i, state); 50 | } 51 | timer.end(); 52 | 53 | MLQ->showQState(); 54 | printf("[%s] Elapsed Time : %s\n", __FUNCTION__, timer.getTime()); 55 | showMemoryInfo(); 56 | } 57 | 58 | void init_LQ20(void) { 59 | logicalQubits *MLQ = new logicalQubits(&lqs20); 60 | QTimer timer; 61 | int state = KET_LMINUS; 62 | 63 | timer.start(); 64 | for(int i=0; ilq_num; i++) { 65 | MLQ->initLQ(i, state); 66 | } 67 | timer.end(); 68 | 69 | MLQ->showQState(); 70 | printf("[%s] Elapsed Time : %s\n", __FUNCTION__, timer.getTime()); 71 | showMemoryInfo(); 72 | } 73 | 74 | /**************************************************/ 75 | /* Scenarios #2 : logical CNOT with LS */ 76 | /**************************************************/ 77 | void cnot_LQ4(void) { 78 | logicalQubits *MLQ = new logicalQubits(&lqs4); 79 | QTimer timer; 80 | 81 | timer.start(); 82 | 83 | MLQ->initLQ(0, KET_LPLUS); 84 | MLQ->initLQ(3, KET_LZERO); 85 | 86 | MLQ->LCNOT(2, 0, 3); /* A, C, T */ 87 | 88 | timer.end(); 89 | 90 | MLQ->showQState(); 91 | printf("[%s] Elapsed Time : %s\n", __FUNCTION__, timer.getTime()); 92 | showMemoryInfo(); 93 | } 94 | 95 | void cnot_LQ9(void) { 96 | logicalQubits *MLQ = new logicalQubits(&lqs9); 97 | QTimer timer; 98 | 99 | timer.start(); 100 | 101 | MLQ->initLQ(4, KET_LPLUS); 102 | MLQ->initLQ(0, KET_LZERO); 103 | MLQ->initLQ(2, KET_LZERO); 104 | MLQ->initLQ(6, KET_LZERO); 105 | MLQ->initLQ(8, KET_LZERO); 106 | 107 | MLQ->LCNOT(1, 4, 0); /* A, C, T */ 108 | MLQ->LCNOT(1, 4, 2); /* A, C, T */ 109 | MLQ->LCNOT(7, 4, 6); /* A, C, T */ 110 | MLQ->LCNOT(7, 4, 8); /* A, C, T */ 111 | 112 | timer.end(); 113 | 114 | MLQ->showQState(); 115 | printf("[%s] Elapsed Time : %s\n", __FUNCTION__, timer.getTime()); 116 | showMemoryInfo(); 117 | } 118 | 119 | void cnot_LQ16(void) { 120 | logicalQubits *MLQ = new logicalQubits(&lqs16); 121 | QTimer timer; 122 | 123 | timer.start(); 124 | 125 | MLQ->initLQ(0, KET_LPLUS); 126 | MLQ->initLQ(2, KET_LZERO); 127 | MLQ->initLQ(5, KET_LZERO); 128 | MLQ->initLQ(7, KET_LZERO); 129 | MLQ->initLQ(8, KET_LZERO); 130 | MLQ->initLQ(10, KET_LZERO); 131 | MLQ->initLQ(13, KET_LZERO); 132 | MLQ->initLQ(15, KET_LZERO); 133 | 134 | MLQ->LCNOT(1, 0, 5); /* A, C, T */ 135 | MLQ->LCNOT(1, 5, 2); /* A, C, T */ 136 | MLQ->LCNOT(6, 2, 7); /* A, C, T */ 137 | MLQ->LCNOT(11, 7, 10); /* A, C, T */ 138 | MLQ->LCNOT(14, 10, 13); /* A, C, T */ 139 | MLQ->LCNOT(14, 10, 15); /* A, C, T */ 140 | 141 | timer.end(); 142 | 143 | MLQ->showQState(); 144 | printf("[%s] Elapsed Time : %s\n", __FUNCTION__, timer.getTime()); 145 | showMemoryInfo(); 146 | } 147 | 148 | void cnot_LQ20(void) { 149 | logicalQubits *MLQ = new logicalQubits(&lqs20); 150 | QTimer timer; 151 | 152 | timer.start(); 153 | 154 | MLQ->initLQ(0, KET_LPLUS); 155 | MLQ->initLQ(2, KET_LZERO); 156 | MLQ->initLQ(4, KET_LZERO); 157 | MLQ->initLQ(6, KET_LZERO); 158 | MLQ->initLQ(8, KET_LZERO); 159 | MLQ->initLQ(10, KET_LZERO); 160 | MLQ->initLQ(12, KET_LZERO); 161 | MLQ->initLQ(14, KET_LZERO); 162 | MLQ->initLQ(16, KET_LZERO); 163 | MLQ->initLQ(18, KET_LZERO); 164 | 165 | MLQ->LCNOT(5, 0, 6); /* A, C, T */ 166 | MLQ->LCNOT(1, 6, 2); /* A, C, T */ 167 | MLQ->LCNOT(7, 2, 8); /* A, C, T */ 168 | MLQ->LCNOT(3, 8, 4); /* A, C, T */ 169 | MLQ->LCNOT(13, 8, 14); /* A, C, T */ 170 | MLQ->LCNOT(19, 14, 18); /* A, C, T */ 171 | MLQ->LCNOT(11, 6, 10); /* A, C, T */ 172 | MLQ->LCNOT(11, 6, 12); /* A, C, T */ 173 | MLQ->LCNOT(15, 10, 16); /* A, C, T */ 174 | 175 | timer.end(); 176 | 177 | MLQ->showQState(); 178 | printf("[%s] Elapsed Time : %s\n", __FUNCTION__, timer.getTime()); 179 | showMemoryInfo(); 180 | } 181 | 182 | /***************************************************************/ 183 | /* Scenarios #3 : logical S and T gate */ 184 | /* */ 185 | /* NOTICE: It should be noted that the global phase varies */ 186 | /* depending on the joint-measurement values. */ 187 | /* */ 188 | /* For example, after performing a logical S operation, 3 */ 189 | /* different logical states can be obtained. However, if the */ 190 | /* global phase is removed, all of these states are equivalent.*/ 191 | /* */ 192 | /* [Post operation after joint-measurement for logical-S] */ 193 | /* if Mzz = +1 */ 194 | /* if Mx = +1, (1) |psi> = a|0> + bi|1> */ 195 | /* else if Mx = -1, (1) |psi> = a|0> + bi|1> */ 196 | /* else if Mzz = -1, */ 197 | /* if Mx = +1 (2) |psi> = ai|0> - b|1> */ 198 | /* = e^(i*pi/2)(ai|0> + b|1>) */ 199 | /* else if Mx = -1, (3) |psi> = -ai|0> + b|1> */ 200 | /* = -e^(i*pi/2)(ai|0> + b|1>) */ 201 | /***************************************************************/ 202 | void S_LQ1(void) { 203 | logicalQubits *MLQ = new logicalQubits(&lqs4); 204 | 205 | MLQ->initLQ(0, KET_LPLUS); 206 | MLQ->LS(0, 2); /* LQ, Ancilla(|Y>) */ 207 | 208 | MLQ->showQState(); 209 | } 210 | 211 | void T_LQ1(void) { 212 | logicalQubits *MLQ = new logicalQubits(&lqs4); 213 | 214 | MLQ->initLQ(0, KET_LPLUS); 215 | MLQ->LT(0, 2); /* LQ, Ancilla(|A>) */ 216 | 217 | MLQ->showQState(); 218 | } 219 | 220 | /**************************************************/ 221 | /* control function */ 222 | /**************************************************/ 223 | int main(int argc, char **argv) 224 | { 225 | int mode = 1; 226 | 227 | if(mode == 0) { 228 | init_LQ4(); 229 | // init_LQ9(); 230 | // init_LQ16(); 231 | // init_LQ20(); 232 | } else if(mode == 1) { 233 | cnot_LQ4(); 234 | // cnot_LQ9(); 235 | // cnot_LQ16(); 236 | // cnot_LQ20(); 237 | } else if(mode == 2) { 238 | S_LQ1(); 239 | T_LQ1(); 240 | } 241 | 242 | return 0; 243 | } 244 | -------------------------------------------------------------------------------- /test/MLQ/module.mk: -------------------------------------------------------------------------------- 1 | MLQ_SRC = ./main.cpp 2 | 3 | MLQ_HDR = ds.h 4 | MLQ_HDR += lattice.h 5 | MLQ_HDR += logicalQubit.h 6 | MLQ_HDR += logicalQubits.h 7 | MLQ_HDR += logicalCNOT.h 8 | MLQ_HDR += logicalST.h 9 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # 3 | # Electronics and Telecommunications Research Institute 4 | # 5 | # Copyright(c) 2021 Electronics and Telecommunications Research Institute, 6 | # 218 Gajeong-ro, Yuseong-gu, Daejeon, 34129, Korea. 7 | # All rights are reserved. No part of this work covered by the copyright 8 | # hereon may be reproduced, stored in retrieval systems, in any form or by 9 | # any means, electronic, mechanical, photocopying, recording or otherwise, 10 | # without the prior permission of ETRI. 11 | # 12 | # FILE NAME : Makefile 13 | # 14 | # AUTHOR : 15 | # DESCRIPTION : Makefile for QPlayer 16 | # 17 | #******************************************************************************* 18 | 19 | all: GENERAL SURFACECODE VERIFICATION BENCHMARK 20 | 21 | GENERAL: 22 | @ $(MAKE) -C general 23 | 24 | SURFACECODE: 25 | @ $(MAKE) -C surfacecode 26 | 27 | MLQ: 28 | @ $(MAKE) -C MLQ 29 | 30 | VERIFICATION: 31 | @ $(MAKE) -C verification 32 | 33 | BENCHMARK: 34 | @ $(MAKE) -C benchmark 35 | 36 | clean: 37 | @ $(MAKE) -C general clean 38 | @ $(MAKE) -C surfacecode clean 39 | @ $(MAKE) -C MLQ clean 40 | @ $(MAKE) -C verification clean 41 | @ $(MAKE) -C benchmark clean 42 | -------------------------------------------------------------------------------- /test/benchmark/Makefile: -------------------------------------------------------------------------------- 1 | QPLAYER_RELEASE=../../release 2 | 3 | CXX = g++ 4 | CXXLD = g++ 5 | 6 | CXXFLAGS = -g -Wall -O2 -std=c++11 -fopenmp 7 | CXXFLAGS += -I. -I$(QPLAYER_RELEASE)/include 8 | CXXFLAGS += -Wno-reorder -Wno-sign-compare -Wno-parentheses -Wno-pessimizing-move 9 | CXXFLAGS += -Wno-unused-function -Wno-unused-variable -Wno-write-strings 10 | CXXFLAGS += -Wno-class-conversion -Wno-unused-result 11 | 12 | LOADLIBES = -L$(QPLAYER_RELEASE)/lib 13 | LOADLIBES += -lm -lpthread -lgomp -lqplayer 14 | 15 | SRCS=$(wildcard *.cpp) 16 | TARGETS=$(patsubst %.cpp,%,$(SRCS)) 17 | 18 | Q=@echo 19 | E=@ 20 | 21 | all: $(TARGETS) 22 | 23 | clean: 24 | @echo "Clean Objects, Deps, Executions" 25 | @rm -rf logs 26 | @rm -fv core.* 27 | @rm -fv *.d 28 | @rm -fv $(TARGETS) 29 | -------------------------------------------------------------------------------- /test/benchmark/gate_perf.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "qplayer.h" 21 | 22 | #define S_ZERO 0 23 | #define S_ONE 1 24 | #define S_SUPERPOSED 2 25 | 26 | static QRegister *QReg = NULL; 27 | static char *prog = NULL; 28 | static int opt_qubits = 0; 29 | static int opt_runs = 0; 30 | static int control = 0; 31 | static int target = 0; 32 | static int baseMode = 0; 33 | 34 | int get_rand(void) 35 | { 36 | static std::random_device rd; 37 | #if 0 38 | static std::mt19937 gen(rd()); 39 | #else 40 | static std::mt19937 gen(1234567); 41 | #endif 42 | static std::uniform_int_distribution dist(0, INT_MAX); 43 | 44 | return dist(gen); 45 | } 46 | 47 | void usage(void) 48 | { 49 | printf("usage: %s \n", prog); 50 | printf("\n"); 51 | printf("options:\n"); 52 | printf(" -q : number of qubits\n"); 53 | printf(" -r : number of gate runs\n"); 54 | } 55 | 56 | double get_angle(void) 57 | { 58 | return (get_rand() % 100)+1; 59 | } 60 | 61 | void init(void) 62 | { 63 | QReg = new QRegister(opt_qubits); 64 | target = opt_qubits - 1; 65 | control = opt_qubits - 2; 66 | 67 | for(int i=0; igetNumStates()); 85 | // fflush(stdout); 86 | } 87 | 88 | void run_gate(int gtype) 89 | { 90 | if(gtype == QGATE_X) { 91 | X(QReg, target); 92 | } else if(gtype == QGATE_Y) { 93 | Y(QReg, target); 94 | } else if(gtype == QGATE_Z) { 95 | Z(QReg, target); 96 | } else if(gtype == QGATE_H) { 97 | H(QReg, target); 98 | } else if(gtype == QGATE_S) { 99 | S(QReg, target); 100 | } else if(gtype == QGATE_T) { 101 | T(QReg, target); 102 | } else if(gtype == QGATE_SDG) { 103 | SDG(QReg, target); 104 | } else if(gtype == QGATE_TDG) { 105 | TDG(QReg, target); 106 | } else if(gtype == QGATE_RX) { 107 | RX(QReg, target, M_PI / get_angle()); 108 | } else if(gtype == QGATE_RY) { 109 | RY(QReg, target, M_PI / get_angle()); 110 | } else if(gtype == QGATE_RZ) { 111 | RZ(QReg, target, M_PI / get_angle()); 112 | } else if(gtype == QGATE_U1) { 113 | U1(QReg, target, M_PI / get_angle()); 114 | } else if(gtype == QGATE_U2) { 115 | U2(QReg, target, M_PI / get_angle(), get_angle()); 116 | } else if(gtype == QGATE_U3) { 117 | U3(QReg, target, M_PI / get_angle(), get_angle(), get_angle()); 118 | } else if(gtype == QGATE_CX) { 119 | CX(QReg, control, target); 120 | } else if(gtype == QGATE_CY) { 121 | CY(QReg, control, target); 122 | } else if(gtype == QGATE_CZ) { 123 | CZ(QReg, control, target); 124 | } else if(gtype == QGATE_CH) { 125 | CH(QReg, control, target); 126 | } else if(gtype == QGATE_CRZ) { 127 | CRZ(QReg, control, target, get_angle()); 128 | } else if(gtype == QGATE_CU1) { 129 | CU1(QReg, control, target, get_angle()); 130 | } else if(gtype == QGATE_CU3) { 131 | CU3(QReg, control, target, get_angle(), get_angle(), get_angle()); 132 | } 133 | } 134 | 135 | void run_gate_loop(int gtype) 136 | { 137 | QTimer timer; 138 | 139 | if(baseMode == KET_ZERO) { 140 | set_targetState(KET_ZERO); 141 | } else if(baseMode == KET_ONE) { 142 | set_targetState(KET_ONE); 143 | } else { 144 | set_targetState(KET_SUPERPOSED); 145 | } 146 | 147 | timer.start(); 148 | for(int i=0; i\n"); 194 | baseMode = KET_ZERO; 195 | run(); 196 | } 197 | 198 | void run_single_one(void) 199 | { 200 | printf("\nRun under target state is |1>\n"); 201 | baseMode = KET_ZERO; 202 | run(); 203 | } 204 | 205 | void run_superposed(void) 206 | { 207 | printf("\nRun under target state is |S>\n"); 208 | baseMode = KET_SUPERPOSED; 209 | run(); 210 | } 211 | 212 | int main(int argc, char **argv) 213 | { 214 | int c; 215 | 216 | prog = argv[0]; 217 | opt_qubits = -1; 218 | opt_runs = -1; 219 | 220 | while ((c = getopt_long(argc, argv, "q:r:", NULL, NULL)) != -1) { 221 | switch(c) { 222 | case 'q': 223 | if(!optarg) usage(); 224 | opt_qubits = atoi(optarg); 225 | break; 226 | case 'r': 227 | if(!optarg) usage(); 228 | opt_runs = atoi(optarg); 229 | break; 230 | default: 231 | usage(); 232 | exit(0); 233 | } 234 | } 235 | 236 | if(opt_qubits == -1 || opt_runs == -1) { 237 | usage(); 238 | exit(0); 239 | } 240 | 241 | if(opt_qubits > 30) { 242 | printf("We only support less than 30 qubits\n"); 243 | exit(0); 244 | } 245 | 246 | init(); 247 | // run_single_zero(); 248 | run_single_one(); 249 | run_superposed(); 250 | } 251 | -------------------------------------------------------------------------------- /test/benchmark/longrun_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "qplayer.h" 21 | 22 | static QRegister *QReg = NULL; 23 | static char *prog = NULL; 24 | static int opt_qubits = 0; 25 | static int opt_runs = 0; 26 | static bool opt_qasm = false; 27 | static bool opt_states = false; 28 | static bool opt_task = false; 29 | static FILE *fp1 = NULL; 30 | static FILE *fp2 = NULL; 31 | 32 | struct gate_params { 33 | int gate; 34 | int qubit; 35 | int control1; 36 | int control2; 37 | double angle; 38 | double theta; 39 | double phi; 40 | double rambda; 41 | }; 42 | 43 | typedef enum { 44 | GATE_U1 = 0, 45 | GATE_U2, 46 | GATE_U3, 47 | GATE_X, 48 | GATE_Y, 49 | GATE_Z, 50 | GATE_H, 51 | GATE_CX, 52 | GATE_S, 53 | GATE_SDG, 54 | GATE_T, 55 | GATE_TDG, 56 | GATE_RX, 57 | GATE_RY, 58 | GATE_RZ, 59 | GATE_CZ, 60 | GATE_CY, 61 | GATE_CH, 62 | GATE_CCX, 63 | GATE_CRZ, 64 | GATE_CU1, 65 | GATE_CU3, 66 | GATE_MEASURE 67 | } GATE_TYPE; 68 | #define MAX_GATE 23 69 | 70 | int get_rand(void) 71 | { 72 | static std::random_device rd; 73 | #if 0 74 | static std::mt19937 gen(rd()); 75 | #else 76 | static std::mt19937 gen(1234567); 77 | #endif 78 | static std::uniform_int_distribution dist(0, INT_MAX); 79 | 80 | return dist(gen); 81 | } 82 | 83 | void showGate(struct gate_params *p) 84 | { 85 | if(p->gate == GATE_U1) { 86 | fprintf(fp1, "u1(%f) q[%d];\n", p->rambda, p->qubit); 87 | fprintf(fp2, "\tU1(QReg, %d, %f);\n", p->qubit, p->rambda); 88 | } else if(p->gate == GATE_U2) { 89 | fprintf(fp1, "u2(%f, %f) q[%d];\n", p->phi, p->rambda, p->qubit); 90 | fprintf(fp2, "\tU2(QReg, %d, %f, %f);\n", p->qubit, p->phi, p->rambda); 91 | } else if(p->gate == GATE_U3) { 92 | fprintf(fp1, "u3(%f, %f, %f) q[%d];\n", p->theta, p->phi, p->rambda, p->qubit); 93 | fprintf(fp2, "\tU3(QReg, %d, %f, %f, %f);\n", p->qubit, p->theta, p->phi, p->rambda); 94 | } else if(p->gate == GATE_X) { 95 | fprintf(fp1, "x q[%d];\n", p->qubit); 96 | fprintf(fp2, "\tX(QReg, %d);\n", p->qubit); 97 | } else if(p->gate == GATE_Y) { 98 | fprintf(fp1, "y q[%d];\n", p->qubit); 99 | fprintf(fp2, "\tY(QReg, %d);\n", p->qubit); 100 | } else if(p->gate == GATE_Z) { 101 | fprintf(fp1, "z q[%d];\n", p->qubit); 102 | fprintf(fp2, "\tZ(QReg, %d);\n", p->qubit); 103 | } else if(p->gate == GATE_H) { 104 | fprintf(fp1, "h q[%d];\n", p->qubit); 105 | fprintf(fp2, "\tH(QReg, %d);\n", p->qubit); 106 | } else if(p->gate == GATE_S) { 107 | fprintf(fp1, "s q[%d];\n", p->qubit); 108 | fprintf(fp2, "\tS(QReg, %d);\n", p->qubit); 109 | } else if(p->gate == GATE_SDG) { 110 | fprintf(fp1, "sdg q[%d];\n", p->qubit); 111 | fprintf(fp2, "\tSDG(QReg, %d);\n", p->qubit); 112 | } else if(p->gate == GATE_T) { 113 | fprintf(fp1, "t q[%d];\n", p->qubit); 114 | fprintf(fp2, "\tT(QReg, %d);\n", p->qubit); 115 | } else if(p->gate == GATE_TDG) { 116 | fprintf(fp1, "tdg q[%d];\n", p->qubit); 117 | fprintf(fp2, "\tTDG(QReg, %d);\n", p->qubit); 118 | } else if(p->gate == GATE_RX) { 119 | fprintf(fp1, "rx(%f) q[%d];\n", p->angle, p->qubit); 120 | fprintf(fp2, "\tRX(QReg, %d, %f);\n", p->qubit, p->angle); 121 | } else if(p->gate == GATE_RY) { 122 | fprintf(fp1, "ry(%f) q[%d];\n", p->angle, p->qubit); 123 | fprintf(fp2, "\tRY(QReg, %d, %f);\n", p->qubit, p->angle); 124 | } else if(p->gate == GATE_RZ) { 125 | fprintf(fp1, "rz(%f) q[%d];\n", p->angle, p->qubit); 126 | fprintf(fp2, "\tRZ(QReg, %d, %f);\n", p->qubit, p->angle); 127 | } else if(p->gate == GATE_CX) { 128 | fprintf(fp1, "cx q[%d],q[%d];\n", p->control1, p->qubit); 129 | fprintf(fp2, "\tCX(QReg, %d, %d);\n", p->control1, p->qubit); 130 | } else if(p->gate == GATE_CZ) { 131 | fprintf(fp1, "cz q[%d],q[%d];\n", p->control1, p->qubit); 132 | fprintf(fp2, "\tCZ(QReg, %d, %d);\n", p->control1, p->qubit); 133 | } else if(p->gate == GATE_CY) { 134 | fprintf(fp1, "cy q[%d],q[%d];\n", p->control1, p->qubit); 135 | fprintf(fp2, "\tCY(QReg, %d, %d);\n", p->control1, p->qubit); 136 | } else if(p->gate == GATE_CH) { 137 | fprintf(fp1, "ch q[%d],q[%d];\n", p->control1, p->qubit); 138 | fprintf(fp2, "\tCH(QReg, %d, %d);\n", p->control1, p->qubit); 139 | } else if(p->gate == GATE_CCX) { 140 | fprintf(fp1, "ccx q[%d],q[%d],q[%d];\n", p->control1, p->control2, p->qubit); 141 | fprintf(fp2, "\tCCX(QReg, %d, %d, %d);\n", p->control1, p->control2, p->qubit); 142 | } else if(p->gate == GATE_CRZ) { 143 | fprintf(fp1, "crz(%f) q[%d],q[%d];\n", p->angle, p->control1, p->control2); 144 | fprintf(fp2, "\tCRZ(QReg, %d, %d, %f);\n", p->control1, p->control2, p->angle); 145 | } else if(p->gate == GATE_CU1) { 146 | fprintf(fp1, "cu1(%f) q[%d],q[%d];\n", p->rambda, p->control1, p->qubit); 147 | fprintf(fp2, "\tCU1(QReg, %d, %d, %f);\n", p->control1, p->qubit, p->rambda); 148 | } else if(p->gate == GATE_CU3) { 149 | fprintf(fp1, "cu3(%f, %f, %f) q[%d],q[%d];\n", p->theta, p->phi, p->rambda, p->control1, p->qubit); 150 | fprintf(fp2, "\tCU3(QReg, %d, %d, %f, %f, %f);\n", p->control1, p->qubit, p->theta, p->phi, p->rambda); 151 | } else if(p->gate == GATE_MEASURE) { 152 | fprintf(fp1, "measure q[%d] -> c[%d];\n", p->qubit, p->qubit); 153 | // fprintf(fp2, "\tM(QReg, %d);\n", p->qubit); 154 | } 155 | } 156 | 157 | int select_gate(void) 158 | { 159 | int ratio_U1 = 100; 160 | int ratio_U2 = 100; 161 | int ratio_U3 = 100; 162 | int ratio_X = 100; 163 | int ratio_Y = 100; 164 | int ratio_Z = 100; 165 | int ratio_H = 100; 166 | int ratio_S = 100; 167 | int ratio_SDG = 100; 168 | int ratio_T = 100; 169 | int ratio_TDG = 100; 170 | int ratio_RX = 100; 171 | int ratio_RY = 100; 172 | int ratio_RZ = 100; 173 | int ratio_CCX = 0; 174 | #if 1 175 | int ratio_CX = 100; 176 | int ratio_CY = 100; 177 | int ratio_CZ = 100; 178 | int ratio_CH = 100; 179 | int ratio_CRZ = 100; 180 | int ratio_CU1 = 100; 181 | int ratio_CU3 = 100; 182 | #else 183 | int ratio_CX = 0; 184 | int ratio_CY = 0; 185 | int ratio_CZ = 0; 186 | int ratio_CH = 0; 187 | int ratio_CRZ = 0; 188 | int ratio_CU1 = 0; 189 | int ratio_CU3 = 0; 190 | #endif 191 | #if 1 192 | int ratio_MEASURE = 100; 193 | #else 194 | int ratio_MEASURE = 0; 195 | #endif 196 | int ratio; 197 | int gate; 198 | 199 | while(1) { 200 | gate = get_rand() % MAX_GATE; 201 | ratio = get_rand() % 100; 202 | if(gate == GATE_U1) { 203 | if(ratio >= ratio_U1) { continue; } 204 | } else if(gate == GATE_U2) { 205 | if(ratio >= ratio_U2) { continue; } 206 | } else if(gate == GATE_U3) { 207 | if(ratio >= ratio_U3) { continue; } 208 | } else if(gate == GATE_X) { 209 | if(ratio >= ratio_X) { continue; } 210 | } else if(gate == GATE_Y) { 211 | if(ratio >= ratio_Y) { continue; } 212 | } else if(gate == GATE_Z) { 213 | if(ratio >= ratio_Z) { continue; } 214 | } else if(gate == GATE_H) { 215 | if(ratio >= ratio_H) { continue; } 216 | } else if(gate == GATE_S) { 217 | if(ratio >= ratio_S) { continue; } 218 | } else if(gate == GATE_SDG) { 219 | if(ratio >= ratio_SDG) { continue; } 220 | } else if(gate == GATE_T) { 221 | if(ratio >= ratio_T) { continue; } 222 | } else if(gate == GATE_TDG) { 223 | if(ratio >= ratio_TDG) { continue; } 224 | } else if(gate == GATE_RX) { 225 | if(ratio >= ratio_RX) { continue; } 226 | } else if(gate == GATE_RY) { 227 | if(ratio >= ratio_RY) { continue; } 228 | } else if(gate == GATE_RZ) { 229 | if(ratio >= ratio_RZ) { continue; } 230 | } else if(gate == GATE_CX) { 231 | if(ratio >= ratio_CX) { continue; } 232 | } else if(gate == GATE_CZ) { 233 | if(ratio >= ratio_CZ) { continue; } 234 | } else if(gate == GATE_CY) { 235 | if(ratio >= ratio_CY) { continue; } 236 | } else if(gate == GATE_CH) { 237 | if(ratio >= ratio_CH) { continue; } 238 | } else if(gate == GATE_CCX) { 239 | if(ratio >= ratio_CCX) { continue; } 240 | } else if(gate == GATE_CRZ) { 241 | if(ratio >= ratio_CRZ) { continue; } 242 | } else if(gate == GATE_CU1) { 243 | if(ratio >= ratio_CU1) { continue; } 244 | } else if(gate == GATE_CU3) { 245 | if(ratio >= ratio_CU3) { continue; } 246 | } else if(gate == GATE_MEASURE) { 247 | if(ratio >= ratio_MEASURE) { continue; } 248 | } 249 | break; 250 | } 251 | 252 | return gate; 253 | } 254 | 255 | void get_params(struct gate_params *param) 256 | { 257 | param->gate = select_gate(); 258 | param->qubit = get_rand() % opt_qubits; 259 | param->angle = M_PI / ((get_rand() % 100)+1); 260 | param->theta = M_PI / ((get_rand() % 100)+1); 261 | param->phi = M_PI / ((get_rand() % 100)+1); 262 | param->rambda = M_PI / ((get_rand() % 100)+1); 263 | 264 | do { 265 | param->control1 = get_rand() % opt_qubits; 266 | if(param->control1 != param->qubit) { 267 | break; 268 | } 269 | } while(1); 270 | 271 | do { 272 | param->control2 = get_rand() % opt_qubits; 273 | if(param->control2 != param->qubit && param->control2 != param->control1) { 274 | break; 275 | } 276 | } while(1); 277 | } 278 | 279 | void long_run_test(void) 280 | { 281 | struct gate_params param; 282 | struct gate_params *p; 283 | int count = 0; 284 | 285 | for(int i=0; igate) { 295 | case GATE_U1: 296 | U1(QReg, p->qubit, p->rambda); 297 | break; 298 | case GATE_U2: 299 | U2(QReg, p->qubit, p->phi, p->rambda); 300 | break; 301 | case GATE_U3: 302 | U3(QReg, p->qubit, p->theta, p->phi, p->rambda); 303 | break; 304 | case GATE_X: 305 | X(QReg, p->qubit); 306 | break; 307 | case GATE_Y: 308 | Y(QReg, p->qubit); 309 | break; 310 | case GATE_Z: 311 | Z(QReg, p->qubit); 312 | break; 313 | case GATE_H: 314 | H(QReg, p->qubit); 315 | break; 316 | case GATE_S: 317 | S(QReg, p->qubit); 318 | break; 319 | case GATE_SDG: 320 | SDG(QReg, p->qubit); 321 | break; 322 | case GATE_T: 323 | T(QReg, p->qubit); 324 | break; 325 | case GATE_TDG: 326 | TDG(QReg, p->qubit); 327 | break; 328 | case GATE_RX: 329 | RX(QReg, p->qubit, p->angle); 330 | break; 331 | case GATE_RY: 332 | RY(QReg, p->qubit, p->angle); 333 | break; 334 | case GATE_RZ: 335 | RZ(QReg, p->qubit, p->angle); 336 | break; 337 | case GATE_CX: 338 | CX(QReg, p->control1, p->qubit); 339 | break; 340 | case GATE_CZ: 341 | CZ(QReg, p->control1, p->qubit); 342 | break; 343 | case GATE_CY: 344 | CY(QReg, p->control1, p->qubit); 345 | break; 346 | case GATE_CH: 347 | CH(QReg, p->control1, p->qubit); 348 | break; 349 | case GATE_CCX: 350 | CCX(QReg, p->control1, p->control2, p->qubit); 351 | break; 352 | case GATE_CRZ: 353 | CRZ(QReg, p->control1, p->qubit, p->angle); 354 | break; 355 | case GATE_CU1: 356 | CU1(QReg, p->control1, p->qubit, p->rambda); 357 | break; 358 | case GATE_CU3: 359 | CU3(QReg, p->control1, p->qubit, p->theta, p->phi, p->rambda); 360 | break; 361 | case GATE_MEASURE: 362 | double probZero = getQubitProb(QReg, p->qubit, 0); 363 | if(probZero >= 0.5) { 364 | MF(QReg, p->qubit, 0); 365 | if(opt_qasm) { 366 | fprintf(fp2, "\tMF(QReg, %d, 0);\n", p->qubit); 367 | } 368 | } else { 369 | MF(QReg, p->qubit, 1); 370 | if(opt_qasm) { 371 | fprintf(fp2, "\tMF(QReg, %d, 1);\n", p->qubit); 372 | } 373 | } 374 | break; 375 | } 376 | 377 | if(QReg->getNumStates() == 0) { 378 | break; 379 | } 380 | 381 | if((++count % 100) == 0) { 382 | printf("%d/%d done... (%d %%)\n", count, opt_runs, (count * 100) / opt_runs); 383 | } 384 | } 385 | } 386 | 387 | void usage(void) 388 | { 389 | printf("usage: %s \n", prog); 390 | printf("\n"); 391 | printf("options(mandatory):\n"); 392 | printf(" -q : number of qubits\n"); 393 | printf("\n"); 394 | printf("options(optional):\n"); 395 | printf(" -r : number of gate runs (default: 100)\n"); 396 | printf(" --qasm : store QASM gate to file\n"); 397 | printf(" --states : display quantum states\n"); 398 | printf(" --task : display execution information\n"); 399 | } 400 | 401 | int main(int argc, char **argv) 402 | { 403 | int c; 404 | 405 | prog = argv[0]; 406 | opt_qubits = 0; 407 | opt_runs = 100; 408 | 409 | static const struct option options[] = { 410 | {"qasm", 0, 0, '1'}, 411 | {"states", 0, 0, '2'}, 412 | {"task", 0, 0, '3'} 413 | }; 414 | 415 | while ((c = getopt_long(argc, argv, "q:r:", options, NULL)) != -1) { 416 | switch(c) { 417 | case 'q': 418 | if(!optarg) usage(); 419 | opt_qubits = atoi(optarg); 420 | break; 421 | case 'r': 422 | if(!optarg) usage(); 423 | opt_runs = atoi(optarg); 424 | break; 425 | case '1': 426 | opt_qasm = true; 427 | break; 428 | case '2': 429 | opt_states = true; 430 | break; 431 | case '3': 432 | opt_task = true; 433 | break; 434 | default: 435 | usage(); 436 | exit(0); 437 | } 438 | } 439 | 440 | if(opt_qubits == 0) { 441 | usage(); 442 | exit(0); 443 | } 444 | 445 | if(opt_qubits > 30) { 446 | printf("We only support less than 30 qubits\n"); 447 | exit(0); 448 | } 449 | 450 | QReg = new QRegister(opt_qubits); 451 | 452 | if(opt_qasm) { 453 | fp1 = fopen("test.qasm", "wt"); 454 | fp2 = fopen("test.cpp", "wt"); 455 | 456 | fprintf(fp1, "OPENQASM 2.0;\n"); 457 | fprintf(fp1, "include \"qelib1.inc\";\n"); 458 | fprintf(fp1, "qreg q[%d]\n", opt_qubits); 459 | fprintf(fp1, "creg c[%d]\n", opt_qubits); 460 | 461 | fprintf(fp2, "#include \"qplayer.h\"\n\n"); 462 | fprintf(fp2, "int main(int argc, char **argv)\n"); 463 | fprintf(fp2, "{\n"); 464 | fprintf(fp2, "\tQRegister *QReg = new QRegister(%d);\n\n", opt_qubits); 465 | } 466 | 467 | 468 | long_run_test(); 469 | 470 | if(opt_states) { 471 | dump(QReg); 472 | } 473 | 474 | if(opt_task) { 475 | QReg->showQRegStat(); 476 | } 477 | 478 | if(opt_qasm) { 479 | #if 0 480 | fprintf(fp2, "\n\tQReg->showQRegStat();\n"); 481 | #else 482 | fprintf(fp2, "\n\tdump(QReg);\n"); 483 | #endif 484 | fprintf(fp2, "}\n"); 485 | 486 | fclose(fp1); 487 | fclose(fp2); 488 | } 489 | } 490 | -------------------------------------------------------------------------------- /test/benchmark/rcs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "qplayer.h" 21 | 22 | #define S_ZERO 0 23 | #define S_ONE 1 24 | #define S_SUPERPOSED 2 25 | 26 | static QRegister *QReg = NULL; 27 | static char *prog = NULL; 28 | static int opt_qubits = 0; 29 | static int opt_depth = 0; 30 | static int opt_dratio = 0; 31 | static int opt_task = 0; 32 | 33 | typedef enum { 34 | GATE_ID = 0, 35 | GATE_U1, 36 | GATE_U2, 37 | GATE_U3, 38 | GATE_X, 39 | GATE_Y, 40 | GATE_Z, 41 | GATE_H, 42 | GATE_CX, 43 | GATE_S, 44 | GATE_SDG, 45 | GATE_T, 46 | GATE_TDG, 47 | GATE_RX, 48 | GATE_RY, 49 | GATE_RZ, 50 | GATE_CZ, 51 | GATE_CY, 52 | GATE_CH, 53 | GATE_CCX, 54 | GATE_CRZ, 55 | GATE_CU1, 56 | GATE_CU3, 57 | GATE_MEASURE 58 | } GATE_TYPE; 59 | #define MAX_GATE 23 60 | 61 | struct gate_param { 62 | int gate; 63 | int control; 64 | int target; 65 | double angle1; 66 | double angle2; 67 | double angle3; 68 | }; 69 | 70 | int get_rand(void) 71 | { 72 | static std::random_device rd; 73 | #if 0 74 | static std::mt19937 gen(rd()); 75 | #else 76 | static std::mt19937 gen(1234567); 77 | #endif 78 | static std::uniform_int_distribution dist(0, INT_MAX); 79 | 80 | return dist(gen); 81 | } 82 | 83 | void usage(void) 84 | { 85 | printf("usage: %s \n", prog); 86 | printf("\n"); 87 | printf("options:\n"); 88 | printf(" -q : number of qubits\n"); 89 | printf(" -d : circuit depth\n"); 90 | printf(" -r : diagonal gate ratio(0-100)\n"); 91 | printf(" --task : show task info.\n"); 92 | } 93 | 94 | void init(void) 95 | { 96 | for(int i=0; itarget = qubit; 106 | do { 107 | param->control = rand() % opt_qubits; 108 | } while(param->control == qubit); 109 | param->angle1 = M_PI / ((get_rand() % 10)+1); 110 | param->angle2 = M_PI / ((get_rand() % 10)+1); 111 | param->angle3 = M_PI / ((get_rand() % 10)+1); 112 | 113 | #if 1 114 | if((rand() % 100 < opt_dratio)) { 115 | int gate = rand() % 5; 116 | if(gate == 0) { 117 | param->gate = GATE_Z; 118 | } else if(gate == 1) { 119 | param->gate = GATE_S; 120 | } else if(gate == 2) { 121 | param->gate = GATE_T; 122 | } else if(gate == 3) { 123 | param->gate = GATE_SDG; 124 | } else if(gate == 4) { 125 | param->gate = GATE_TDG; 126 | } else if(gate == 5) { 127 | param->gate = GATE_U1; 128 | } 129 | } else { 130 | int gate = rand() % 5; 131 | if(gate == 0) { 132 | param->gate = GATE_X; 133 | } else if(gate == 1) { 134 | param->gate = GATE_Y; 135 | } else if(gate == 2) { 136 | param->gate = GATE_RX; 137 | } else if(gate == 3) { 138 | param->gate = GATE_RY; 139 | } else if(gate == 4) { 140 | param->gate = GATE_U2; 141 | } else if(gate == 5) { 142 | param->gate = GATE_U3; 143 | } 144 | } 145 | #else 146 | if((rand() % 100 < opt_dratio)) { 147 | int gate = rand() % 8; 148 | if(gate == 0) { 149 | param->gate = GATE_Z; 150 | } else if(gate == 1) { 151 | param->gate = GATE_S; 152 | } else if(gate == 2) { 153 | param->gate = GATE_T; 154 | } else if(gate == 3) { 155 | param->gate = GATE_SDG; 156 | } else if(gate == 4) { 157 | param->gate = GATE_TDG; 158 | } else if(gate == 5) { 159 | param->gate = GATE_RZ; 160 | } else if(gate == 6) { 161 | param->gate = GATE_CZ; 162 | } else if(gate == 7) { 163 | param->gate = GATE_CU1; 164 | } 165 | } else { 166 | int gate = rand() % 8; 167 | if(gate == 0) { 168 | param->gate = GATE_H; 169 | } else if(gate == 1) { 170 | param->gate = GATE_X; 171 | } else if(gate == 2) { 172 | param->gate = GATE_Y; 173 | } else if(gate == 3) { 174 | param->gate = GATE_RX; 175 | } else if(gate == 4) { 176 | param->gate = GATE_RY; 177 | } else if(gate == 5) { 178 | param->gate = GATE_U2; 179 | } else if(gate == 6) { 180 | param->gate = GATE_U3; 181 | } else if(gate == 7) { 182 | param->gate = GATE_CX; 183 | } 184 | } 185 | #endif 186 | } 187 | 188 | void run_gate(struct gate_param *param) 189 | { 190 | int gate = param->gate; 191 | int control = param->control; 192 | int target = param->target; 193 | double angle1 = param->angle1; 194 | double angle2 = param->angle2; 195 | double angle3 = param->angle3; 196 | 197 | if(gate == GATE_ID) { 198 | I(QReg, target); 199 | } else if(gate == GATE_X) { 200 | X(QReg, target); 201 | } else if(gate == GATE_Y) { 202 | Y(QReg, target); 203 | } else if(gate == GATE_Z) { 204 | Z(QReg, target); 205 | } else if(gate == GATE_H) { 206 | H(QReg, target); 207 | } else if(gate == GATE_S) { 208 | S(QReg, target); 209 | } else if(gate == GATE_T) { 210 | T(QReg, target); 211 | } else if(gate == GATE_SDG) { 212 | SDG(QReg, target); 213 | } else if(gate == GATE_TDG) { 214 | TDG(QReg, target); 215 | } else if(gate == GATE_RX) { 216 | RX(QReg, target, angle1); 217 | } else if(gate == GATE_RY) { 218 | RY(QReg, target, angle1); 219 | } else if(gate == GATE_RZ) { 220 | RZ(QReg, target, angle1); 221 | } else if(gate == GATE_U1) { 222 | U1(QReg, target, angle1); 223 | } else if(gate == GATE_U2) { 224 | U2(QReg, target, angle1, angle2); 225 | } else if(gate == GATE_U3) { 226 | U3(QReg, target, angle1, angle2, angle3); 227 | } else if(gate == GATE_CX) { 228 | CX(QReg, control, target); 229 | } else if(gate == GATE_CY) { 230 | CY(QReg, control, target); 231 | } else if(gate == GATE_CZ) { 232 | CZ(QReg, control, target); 233 | } else if(gate == GATE_CH) { 234 | CH(QReg, control, target); 235 | } else if(gate == GATE_CRZ) { 236 | CRZ(QReg, control, target, angle1); 237 | } else if(gate == GATE_CU1) { 238 | CU1(QReg, control, target, angle1); 239 | } else if(gate == GATE_CU3) { 240 | CU3(QReg, control, target, angle1, angle2, angle3); 241 | } 242 | } 243 | 244 | void test(void) 245 | { 246 | struct gate_param param; 247 | 248 | for(int i=0; i 30) { 295 | printf("We only support less than 30 qubits\n"); 296 | exit(0); 297 | } 298 | 299 | QReg = new QRegister(opt_qubits); 300 | init(); 301 | 302 | for(int i=0; i<=100; i++) { 303 | opt_dratio = i; 304 | 305 | timer.start(); 306 | test(); 307 | timer.end(); 308 | 309 | printf("dratio=%02d -> %20s (%.0f sec)\n", opt_dratio, timer.getTime(), timer.getElapsedSec()); 310 | fflush(stdout); 311 | } 312 | 313 | if(opt_task) { 314 | QReg->showQRegStat(); 315 | } 316 | } 317 | -------------------------------------------------------------------------------- /test/general/Makefile: -------------------------------------------------------------------------------- 1 | QPLAYER_RELEASE=../../release 2 | 3 | CXX = g++ 4 | CXXLD = g++ 5 | 6 | CXXFLAGS = -g -Wall -O2 -std=c++11 -fopenmp 7 | CXXFLAGS += -I. -I$(QPLAYER_RELEASE)/include 8 | CXXFLAGS += -Wno-reorder -Wno-sign-compare -Wno-parentheses -Wno-pessimizing-move 9 | CXXFLAGS += -Wno-unused-function -Wno-unused-variable -Wno-write-strings 10 | CXXFLAGS += -Wno-class-conversion -Wno-unused-result 11 | 12 | LOADLIBES = -L$(QPLAYER_RELEASE)/lib 13 | LOADLIBES += -lm -lpthread -lgomp -lqplayer 14 | 15 | SRCS=$(wildcard *.cpp) 16 | TARGETS=$(patsubst %.cpp,%,$(SRCS)) 17 | 18 | Q=@echo 19 | E=@ 20 | 21 | all: $(TARGETS) 22 | 23 | clean: 24 | @echo "Clean Objects, Deps, Executions" 25 | @rm -rf logs 26 | @rm -fv core.* 27 | @rm -fv *.d 28 | @rm -fv $(TARGETS) 29 | -------------------------------------------------------------------------------- /test/general/basic.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file basic.cpp 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @date 10-09-21 18 | * @brief 19 | */ 20 | 21 | #include 22 | 23 | #include "qplayer.h" 24 | 25 | int main(int argc, char **argv) 26 | { 27 | QRegister *QReg = new QRegister(4); 28 | QTimer timer; 29 | 30 | timer.start(); 31 | for(int i=0; i<1000; i++) { 32 | X(QReg, 0); 33 | H(QReg, 1); 34 | CX(QReg, 1, 2); 35 | M(QReg, 2); 36 | }; 37 | timer.end(); 38 | 39 | // dump(QReg); 40 | 41 | QReg->showQRegStat(); 42 | printf("%s\n", timer.getTime()); 43 | } 44 | -------------------------------------------------------------------------------- /test/general/grover.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file grover.cpp 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @date 10-09-21 18 | * @brief 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | #include "qplayer.h" 25 | 26 | using namespace std; 27 | 28 | void grover(QRegister *QReg, int qubits) { 29 | QTimer timer; 30 | int target = qubits / 2; 31 | #if 1 32 | int repeat = qubits * 2; 33 | #else 34 | int repeat = (int)((M_PI/4) * sqrt(pow(2, qubits))); 35 | #endif 36 | 37 | timer.start(); 38 | 39 | /* prepare grover algorithm */ 40 | X(QReg, target); 41 | for(int i=0; i= qubits) { 57 | break; 58 | } 59 | CCX(QReg, j, target+j, target+j+1); 60 | } 61 | 62 | CX(QReg, qubits-1, target); 63 | 64 | for(int j=0; j : %s -q \n", argv[0]); 141 | exit(0); 142 | } else if(qubits < 3) { 143 | printf("we recommend that the qubia number is 7 or more.\n"); 144 | exit(0); 145 | } 146 | 147 | QRegister *QReg = new QRegister(qubits); 148 | 149 | grover(QReg, qubits); 150 | } 151 | 152 | -------------------------------------------------------------------------------- /test/general/qft.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | /** 15 | * @file qft.cpp 16 | * @author Kisung Jin - ksjin@etri.re.kr 17 | * @date 10-09-21 18 | * @brief 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | #include "qplayer.h" 25 | 26 | using namespace std; 27 | 28 | void qft(QRegister *QReg, int qubits) { 29 | QTimer timer; 30 | 31 | timer.start(); 32 | 33 | X(QReg, qubits-1); 34 | 35 | for(int i=0; i : %s -q \n", argv[0]); 70 | exit(0); 71 | } 72 | 73 | QRegister *QReg = new QRegister(qubits); 74 | 75 | qft(QReg, qubits); 76 | } 77 | -------------------------------------------------------------------------------- /test/surfacecode/Makefile: -------------------------------------------------------------------------------- 1 | QPLAYER_RELEASE=../../release 2 | 3 | CXX = g++ 4 | CXXLD = g++ 5 | 6 | CXXFLAGS = -g -Wall -O2 -std=c++11 -fopenmp 7 | CXXFLAGS += -I. -I$(QPLAYER_RELEASE)/include 8 | CXXFLAGS += -Wno-reorder -Wno-sign-compare -Wno-parentheses -Wno-pessimizing-move 9 | CXXFLAGS += -Wno-unused-function -Wno-unused-variable -Wno-write-strings 10 | CXXFLAGS += -Wno-class-conversion -Wno-unused-result 11 | 12 | LOADLIBES = -L$(QPLAYER_RELEASE)/lib 13 | LOADLIBES += -lm -lpthread -lgomp -lqplayer 14 | 15 | SRCS=$(wildcard *.cpp) 16 | TARGETS=$(patsubst %.cpp,%,$(SRCS)) 17 | 18 | Q=@echo 19 | E=@ 20 | 21 | all: $(TARGETS) 22 | 23 | clean: 24 | @echo "Clean Objects, Deps, Executions" 25 | @rm -rf logs 26 | @rm -fv core.* 27 | @rm -fv *.d 28 | @rm -fv $(TARGETS) 29 | -------------------------------------------------------------------------------- /test/verification/Makefile: -------------------------------------------------------------------------------- 1 | QPLAYER_RELEASE=../../release 2 | 3 | CXX = g++ 4 | CXXLD = g++ 5 | 6 | CXXFLAGS = -g -Wall -O2 -std=c++11 -fopenmp 7 | CXXFLAGS += -I. -I$(QPLAYER_RELEASE)/include 8 | CXXFLAGS += -Wno-reorder -Wno-sign-compare -Wno-parentheses -Wno-pessimizing-move 9 | CXXFLAGS += -Wno-unused-function -Wno-unused-variable -Wno-write-strings 10 | CXXFLAGS += -Wno-class-conversion -Wno-unused-result 11 | 12 | LOADLIBES = -L$(QPLAYER_RELEASE)/lib 13 | LOADLIBES += -lm -lpthread -lgomp -lqplayer 14 | 15 | SRCS=$(wildcard *.cpp) 16 | TARGETS=$(patsubst %.cpp,%,$(SRCS)) 17 | 18 | Q=@echo 19 | E=@ 20 | 21 | all: $(TARGETS) 22 | 23 | clean: 24 | @echo "Clean Objects, Deps, Executions" 25 | @rm -rf logs 26 | @rm -fv core.* 27 | @rm -fv *.d 28 | @rm -fv $(TARGETS) 29 | -------------------------------------------------------------------------------- /test/verification/install_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Electronics and Telecommunications Research Institute 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3 of the License. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | */ 13 | 14 | #include 15 | 16 | #include "qplayer.h" 17 | 18 | static QRegister *QReg = NULL; 19 | static int qubits = 10; 20 | 21 | void test_gates(void) 22 | { 23 | H(QReg, 0); 24 | CX(QReg, 0, 1); 25 | CX(QReg, 0, 2); 26 | CX(QReg, 0, 3); 27 | CX(QReg, 0, 4); 28 | H(QReg, 0); 29 | 30 | H(QReg, 5); 31 | CX(QReg, 5, 6); 32 | CX(QReg, 5, 7); 33 | CX(QReg, 5, 8); 34 | CX(QReg, 5, 9); 35 | H(QReg, 5); 36 | 37 | MF(QReg, 0, 0); 38 | MF(QReg, 5, 1); 39 | 40 | dump(QReg); 41 | } 42 | 43 | int main(int argc, char **argv) 44 | { 45 | QReg = new QRegister(16); 46 | 47 | test_gates(); 48 | } 49 | --------------------------------------------------------------------------------