Source code for qlazy.util

# -*- coding: utf-8 -*-
""" various kind of utilities """
import os
import subprocess
import shutil
import math
import configparser
import numpy as np

import qlazy.config as cfg

[docs]def get_lib_ext(): """ get library extension (for Mac OS)""" import platform if platform.system() == 'Darwin': return 'dylib' return 'so'
[docs]def qstate_check_args(qs, kind=None, qid=None): """ check arguments for qstate """ for q in qid: if (q >= qs.qubit_num) or (q < 0): raise IndexError("index out of range.") qnum = get_qgate_qubit_num(kind) if qnum == 0: # any qubit number # check qubit number if len(qid) > qs.qubit_num: raise IndexError("Too many arguments.") if len(qid) < 1: raise IndexError("Need more arguments.") # check same qubit number if len(set(qid)) != len(qid): raise IndexError("Same qubit ID.") elif qnum == 1: # check qubit number if len(qid) > qnum: raise IndexError("Too many arguments.") if len(qid) < qnum: raise IndexError("Need more arguments.") elif qnum == 2: # check qubit number if len(qid) > qnum: raise IndexError("Too many arguments.") if len(qid) < qnum: raise IndexError("Need more arguments.") # check same qubit number if qid[0] == qid[1]: raise IndexError("Same qubit ID.") elif qnum == 3: # check qubit number if len(qid) > qnum: raise IndexError("Too many arguments.") if len(qid) < qnum: raise IndexError("Need more arguments.") # check same qubit id if qid[0] == qid[1] or qid[1] == qid[2] or qid[2] == qid[0]: raise IndexError("Same qubit ID.") return True
[docs]def densop_check_args(de, kind=None, qid=None): """ check arguments for densop """ qubit_num = int(math.log2(de.row)) for q in qid: if (q >= qubit_num) or (q < 0): raise IndexError("index out of range.") qnum = get_qgate_qubit_num(kind) if qnum == 0: # any qubit number # check qubit number if len(qid) > qubit_num: raise IndexError("Too many arguments.") if len(qid) < 1: raise IndexError("Need more arguments.") # check same qubit number if len(set(qid)) != len(qid): raise IndexError("Same qubit ID.") elif qnum == 1: # check qubit number if len(qid) > qnum: raise IndexError("Too many arguments.") if len(qid) < qnum: raise IndexError("Need more arguments.") elif qnum == 2: # check qubit number if len(qid) > qnum: raise IndexError("Too many arguments.") if len(qid) < qnum: raise IndexError("Need more arguments.") # check same qubit number if qid[0] == qid[1]: raise IndexError("Same qubit ID.") elif qnum == 3: # check qubit number if len(qid) > qnum: raise IndexError("Too many arguments.") if len(qid) < qnum: raise IndexError("Need more arguments.") # check same qubit id if qid[0] == qid[1] or qid[1] == qid[2] or qid[2] == qid[0]: raise IndexError("Same qubit ID.") return True
[docs]def get_qgate_qubit_num(kind=None): """ get qubit number for the quantum gate """ if kind in (cfg.SHOW, cfg.MEASURE, cfg.MEASURE_X, cfg.MEASURE_Y, cfg.MEASURE_Z, cfg.RESET): # 0 if any number return 0 if ((kind in (cfg.BLOCH, cfg.PAULI_X, cfg.PAULI_Y, cfg.PAULI_Z, cfg.ROOT_PAULI_X, cfg.ROOT_PAULI_X_, cfg.HADAMARD, cfg.PHASE_SHIFT_S, cfg.PHASE_SHIFT_S_, cfg.PHASE_SHIFT_T, cfg.PHASE_SHIFT_T_, cfg.PHASE_SHIFT, cfg.ROTATION_X, cfg.ROTATION_Y, cfg.ROTATION_Z, cfg.ROTATION_U1, cfg.ROTATION_U2, cfg.ROTATION_U3))): return 1 if (kind in (cfg.CONTROLLED_X, cfg.CONTROLLED_Y, cfg.CONTROLLED_Z, cfg.CONTROLLED_XR, cfg.CONTROLLED_XR_, cfg.CONTROLLED_H, cfg.CONTROLLED_S, cfg.CONTROLLED_S_, cfg.CONTROLLED_T, cfg.CONTROLLED_T_, cfg.SWAP_QUBITS, cfg.CONTROLLED_P, cfg.CONTROLLED_RX, cfg.CONTROLLED_RY, cfg.CONTROLLED_RZ, cfg.CONTROLLED_U1, cfg.CONTROLLED_U2, cfg.CONTROLLED_U3, cfg.MEASURE_BELL, cfg.ROTATION_XX, cfg.ROTATION_YY, cfg.ROTATION_ZZ)): return 2 raise ValueError("unknown quantum gate.")
[docs]def get_qgate_param_num(kind=None): """ get parameter number for the quantum gate """ if (kind in (cfg.SHOW, cfg.BLOCH, cfg.MEASURE, cfg.MEASURE_X, cfg.MEASURE_Y, cfg.MEASURE_Z, cfg.MEASURE_BELL, cfg.RESET, cfg.PAULI_X, cfg.PAULI_Y, cfg.PAULI_Z, cfg.ROOT_PAULI_X, cfg.ROOT_PAULI_X_, cfg.HADAMARD, cfg.PHASE_SHIFT_S, cfg.PHASE_SHIFT_S_, cfg.PHASE_SHIFT_T, cfg.PHASE_SHIFT_T_, cfg.CONTROLLED_X, cfg.CONTROLLED_Y, cfg.CONTROLLED_Z, cfg.CONTROLLED_XR, cfg.CONTROLLED_XR_, cfg.CONTROLLED_H, cfg.CONTROLLED_S, cfg.CONTROLLED_S_, cfg.CONTROLLED_T, cfg.CONTROLLED_T_, cfg.SWAP_QUBITS)): return 0 if (kind in (cfg.PHASE_SHIFT, cfg.ROTATION_X, cfg.ROTATION_Y, cfg.ROTATION_Z, cfg.ROTATION_U1, cfg.CONTROLLED_P, cfg.CONTROLLED_RX, cfg.CONTROLLED_RY, cfg.CONTROLLED_RZ, cfg.CONTROLLED_U1, cfg.ROTATION_XX, cfg.ROTATION_YY, cfg.ROTATION_ZZ)): return 1 if kind in (cfg.ROTATION_U2, cfg.CONTROLLED_U2): return 2 if kind in (cfg.ROTATION_U3, cfg.CONTROLLED_U3): return 3 raise ValueError("unknown quantum gate.")
[docs]def is_unitary_gate(kind=None): """ is the gate unitary? """ return (kind in (cfg.PAULI_X, cfg.PAULI_Y, cfg.PAULI_Z, cfg.ROOT_PAULI_X, cfg.ROOT_PAULI_X_, cfg.HADAMARD, cfg.PHASE_SHIFT_S, cfg.PHASE_SHIFT_S_, cfg.PHASE_SHIFT_T, cfg.PHASE_SHIFT_T_, cfg.PHASE_SHIFT, cfg.ROTATION_X, cfg.ROTATION_Y, cfg.ROTATION_Z, cfg.CONTROLLED_X, cfg.CONTROLLED_Y, cfg.CONTROLLED_Z, cfg.CONTROLLED_XR, cfg.CONTROLLED_XR_, cfg.CONTROLLED_H, cfg.CONTROLLED_S, cfg.CONTROLLED_S_, cfg.CONTROLLED_T, cfg.CONTROLLED_T_, cfg.SWAP_QUBITS, cfg.CONTROLLED_P, cfg.CONTROLLED_RX, cfg.CONTROLLED_RY, cfg.CONTROLLED_RZ, cfg.ROTATION_XX, cfg.ROTATION_YY, cfg.ROTATION_ZZ))
[docs]def is_clifford_gate(kind): """ is the gate clifford? """ return kind in (cfg.PAULI_X, cfg.PAULI_Y, cfg.PAULI_Z, cfg.HADAMARD, cfg.PHASE_SHIFT_S, cfg.PHASE_SHIFT_S_, cfg.CONTROLLED_X, cfg.CONTROLLED_Y, cfg.CONTROLLED_Z)
[docs]def is_non_clifford_gate(kind): """ is the gate non-clifford? """ return (is_clifford_gate(kind) is False and is_measurement_gate(kind) is False and is_reset_gate(kind) is False)
[docs]def is_measurement_gate(kind): """ is the gate measurement? """ return kind in (cfg.MEASURE, cfg.MEASURE_X, cfg.MEASURE_Y, cfg.MEASURE_Z, cfg.MEASURE_BELL)
[docs]def is_reset_gate(kind): """ is the gate reset? """ return kind == cfg.RESET
[docs]def reverse_bit_order(vec_in): """ reverse bit order of the state vector """ vec_out = [0] * len(vec_in) digits = len(format(len(vec_in), 'b')) - 1 for idx, val in enumerate(vec_in): idx_binstr = '{:0{digits}b}'.format(idx, digits=digits) idx_binstr_rev = ''.join(reversed(list(idx_binstr))) idx_rev = int(idx_binstr_rev, 2) vec_out[idx_rev] = val return vec_out
[docs]def read_config_ini(config_ini_path=None): """ read config.ini file """ if config_ini_path is None: config_ini_path = os.environ['HOME'] + '/.qlazy/config.ini' if os.path.exists(config_ini_path) is False: raise FileNotFoundError("config.ini is not found.") # read config.ini config_ini = configparser.ConfigParser() config_ini.read(config_ini_path, encoding='utf-8') # check sections of config_ini sections = ('DEFAULT', 'backend_braket') for cs in config_ini.keys(): if not cs in sections: raise ValueError("config.ini> [{}] is not supported.".format(cs)) # check keys of backend_braket keys = ('backet_name', 'poll_timeout_seconds') for k in config_ini['backend_braket'].keys(): # raise exception if invalid keys are defined. if not k in keys: raise ValueError("config.ini> [backend_braket]> {} is not supported.".format(k)) if ((k == 'poll_timeout_seconds' and config_ini['backend_braket'].get('poll_timeout_seconds').isdecimal() is False)): raise ValueError(("config.ini> [backend_braket]> poll_timeout_seconds({}) " "must be decimal number." .format(config_ini['backend_braket'].get('poll_timeout_seconds')))) keys_required = ('backet_name',) for k in keys_required: # raise exception if required keys are not defined. if k not in config_ini['backend_braket'].keys(): raise ValueError("config.ini> [backend_braket]> {} is not defined.".format(k)) return config_ini
[docs]def check_gpu(): """ NVIDIA GPU is available or not """ if shutil.which('nvidia-smi') is None: return False try: res = subprocess.check_output(["nvidia-smi"], shell=True) return True except: return False
[docs]def is_num(s): """ is this string numeric or not """ try: float(s) except ValueError: return False else: return True