Beispiel #1
0
def get_gate_data(gatename):
    """Return number of qubits and number of rows or columns of native gate."""
    if isinstance(gatename, QGate):
        shape = (gatename.size, 2**gatename.size)
    else:
        name, arg1, arg2, arg3, invert = prs.get_gate_data(gatename)
        if arg1 is None:
            arg1 = 0
        if arg2 is None:
            arg2 = 0
        if arg3 is None:
            arg3 = 0
        if "SWAP" in name or name == "XX" or name == "YY" or name == "ZZ":
            shape = (2, 4)
        else:
            qgate = ct.c_void_p(_cGetQGate(ct.c_char_p(name.encode()),
                                           ct.c_double(arg1),
                                           ct.c_double(arg2),
                                           ct.c_double(arg3),
                                           ct.c_int(int(invert))))
            # NOTNULLPTR and True = True, NOTNULLPTR or False = NOTNULLPTR
            if (qgate or False) == qgate:
                nqubits = int(_cGetQGateQubits(qgate))
                size = int(_cGetQGateSize(qgate))
                shape = (nqubits, size)
            else:
                shape = None
                print("Error while getting the specified gate!")

    return shape
Beispiel #2
0
def get_gate(gate_name):
    """Return the matrix of the specified gate."""
    name, arg1, arg2, arg3, invert = prs.get_gate_data(gate_name)
    if arg1 is None:
        arg1 = 0
    if arg2 is None:
        arg2 = 0
    if arg3 is None:
        arg3 = 0
    qgate = ct.c_void_p(_cGetQGate(ct.c_char_p(name.encode()),
                                   ct.c_double(arg1), ct.c_double(arg2),
                                   ct.c_double(arg3), ct.c_int(int(invert))))
    # NOTNULLPTR and True = True, NOTNULLPTR or False = NOTNULLPTR
    if (qgate or False) == qgate:
        size = int(_cGetQGateSize(qgate))
        plainmatrix2d = _cGet2dGate(qgate)[:size*size*2]
        rematrix2d = plainmatrix2d[:size*size]
        immatrix2d = plainmatrix2d[size*size:size*size*2]
        matrix = np.array([complex(rematrix2d[i], immatrix2d[i])
                           for i in range(size * size)])
        matrix = matrix.reshape(size, size)
    else:
        matrix = None
        print("Error while getting the specified gate!")

    return matrix
Beispiel #3
0
def _invert_str_gate(gatename):
    """Invert the given native gate."""
    selfinvert = ["X", "Y", "Z", "H", "SWAP", "I"]
    name, arg1, arg2, arg3, invert = prs.get_gate_data(gatename)
    if name not in selfinvert:
        if invert:
            gatename = gatename[:-2]
        else:
            gatename += "-1"
    return gatename
Beispiel #4
0
def _get_qubit_arg(gatename):
    """Get arguments from string with gate name."""
    args = None
    if isinstance(gatename, str):
        qubitargs = ["XX", "YY", "ZZ"]
        name, arg1, arg2, arg3, invert = prs.get_gate_data(gatename)
        if name in qubitargs or "SWAP" in name:
            if name in qubitargs:
                args = set([arg2, arg3])
            else:
                args = set([arg1, arg2])
    return args
Beispiel #5
0
def _rebuild_gate_name(gate):
    """Standarize name of native gate and return tuple with gate data.

    Positional arguments:
        gate: string with name of a native gate
                OR
              list containing
              0: string with name of a native gate
              1 (optional): control qubit or list of control qubits ids
              2 (optional): anticontrol qubit or list of anticontrol qubits ids
    Return:
        list containing
        0: string with standarized name of a native gate
        1: set of control qubits ids (can be empty)
        2: set of anticontrol qubits ids (can be empty)
    """
    cons = set()
    acons = set()
    gatename = gate
    if not isinstance(gate, str) and isinstance(gate, Iterable):
        gatename = gate[0]
        if (len(gate) > 1):
            if gate[1] is not None:
                if isinstance(gate[1], Iterable) and len(gate[1]) > 0:
                    cons = set(gate[1])
                elif not isinstance(gate[1], Iterable):
                    cons = set([gate[1]])
        if (len(gate) > 2):
            if gate[2] is not None:
                if isinstance(gate[2], Iterable) and len(gate[2]) > 0:
                    acons = set(gate[2])
                elif not isinstance(gate[2], Iterable):
                    acons = set([gate[2]])
    if not isinstance(gatename, QGate):
        if gatename is not None and gatename.lower() != "i":
            name, arg1, arg2, arg3, invert = prs.get_gate_data(gatename)
            if arg1 is not None:
                name += "(" + str(arg1)
            if arg2 is not None:
                name += "," + str(arg2)
            if arg3 is not None:
                name += "," + str(arg3) + ")"
            elif arg1 is not None:
                name += ")"
            if invert:
                name += "-1"
        else:
            name = None
    else:
        name = gatename
    return [name, cons, acons] if name is not None else None
Beispiel #6
0
def _add_qubit_offset(gatename, offset):
    """Return the gate name string adding the offset to any id argument."""
    qubitargs = ["XX", "YY", "ZZ"]
    name, arg1, arg2, arg3, invert = prs.get_gate_data(gatename)
    if name in qubitargs or "SWAP" in name:
        arg2 += offset
        if name in qubitargs:
            arg3 += offset
        else:
            arg1 += offset
        if arg1 is not None:
            name += "(" + str(arg1)
        if arg2 is not None:
            name += str(arg2)
        if arg3 is not None:
            name += str(arg3) + ")"
        if invert:
            name += "-1"
        gatename = name
    return gatename
Beispiel #7
0
    def apply_gate(self,
                   gate,
                   qubit=0,
                   control=None,
                   anticontrol=None,
                   optimize=True):
        """Apply specified gate to specified qubit with specified controls.

        Positional arguments:
            gate: string with the name of the gate to apply, or a QGate
        Keyworded arguments:
            qubit: id of the least significant qubit the gate will target
            control: id or list of ids of the qubit that will act as controls
            anticontrol: id or list of ids of the qubit that will act as
                         anticontrols
            optimize: only for QGates. Whether to use optimized lines or
                      user defined lines
        """
        if (np.issubdtype(type(qubit), np.integer)
                and qubit < self.get_num_qubits() and qubit >= 0):
            if (not isinstance(control, Iterable) and type(control) != int
                    and not (control is None)):
                raise ValueError("Control must be an int, " +
                                 "a list of ints or None!")
            elif (not isinstance(anticontrol, Iterable)
                  and type(anticontrol) != int and not (anticontrol is None)):
                raise ValueError("Anticontrol must be an int, " +
                                 "a list of ints or None!")
            elif (isinstance(control, Iterable)
                  and isinstance(anticontrol, Iterable)
                  and len(set(control) & set(anticontrol)) > 0):
                raise ValueError("A control can't be an anticontrol!")
            else:
                allOk = True

                clen = 0
                if np.issubdtype(type(control), np.integer):
                    int_array = ct.c_int * 1
                    control = int_array(control)
                    clen = 1
                elif control is None or len(control) == 0:
                    control = c_int_p()
                    clen = 0
                else:
                    control = set(control)
                    clen = len(control)
                    int_array = ct.c_int * clen
                    control = int_array(*control)
                    allOk = all(0 <= id < self.get_num_qubits()
                                for id in control)

                aclen = 0
                if np.issubdtype(type(anticontrol), np.integer):
                    int_array = ct.c_int * 1
                    anticontrol = int_array(control)
                    aclen = 1
                elif anticontrol is None or len(anticontrol) == 0:
                    anticontrol = c_int_p()
                    aclen = 0
                else:
                    anticontrol = set(anticontrol)
                    aclen = len(anticontrol)
                    int_array = ct.c_int * aclen
                    anticontrol = int_array(*anticontrol)
                    allOk = allOk and all(0 <= id < self.get_num_qubits()
                                          for id in anticontrol)

                if allOk:
                    if type(gate) == str:
                        name, arg1, arg2, arg3, invert = get_gate_data(gate)
                        if arg1 is None:
                            arg1 = 0
                        if arg2 is None:
                            arg2 = 0
                        if arg3 is None:
                            arg3 = 0
                        if (name.lower() == "swap"):
                            _swap_qubits(self.reg, arg1, arg2, False, False,
                                         invert, control, clen, anticontrol,
                                         aclen)
                        elif (name.lower() == "iswap"):
                            _swap_qubits(self.reg, arg1, arg2, True, False,
                                         invert, control, clen, anticontrol,
                                         aclen)
                        elif (name.lower() == "sqrtswap"):
                            _swap_qubits(self.reg, arg1, arg2, False, True,
                                         invert, control, clen, anticontrol,
                                         aclen)
                        elif (name.lower() == "xx"):
                            _ising_qubits(self.reg, 0, arg1, arg2, arg3,
                                          invert, control, clen, anticontrol,
                                          aclen)
                        elif (name.lower() == "yy"):
                            _ising_qubits(self.reg, 1, arg1, arg2, arg3,
                                          invert, control, clen, anticontrol,
                                          aclen)
                        elif (name.lower() == "zz"):
                            _ising_qubits(self.reg, 2, arg1, arg2, arg3,
                                          invert, control, clen, anticontrol,
                                          aclen)
                        else:
                            if int(
                                    _cApplyGate(self.reg,
                                                ct.c_char_p(name.encode()),
                                                ct.c_double(arg1),
                                                ct.c_double(arg2),
                                                ct.c_double(arg3),
                                                ct.c_int(int(invert)),
                                                ct.c_int(qubit), control,
                                                ct.c_int(clen), anticontrol,
                                                ct.c_int(aclen))) == 0:
                                print("Error applying gate to specified QuBit")
                    else:
                        gate._apply_gate(self,
                                         qubit,
                                         control[:clen],
                                         anticontrol[:aclen],
                                         optimize=optimize)
                else:
                    print("The ids must be between 0 and " +
                          str(self.get_num_qubits()))
        else:
            if not np.issubdtype(type(qubit), np.integer):
                print("Qubit must be of integer type!")
            elif qubit >= self.get_num_qubits() or qubit < 0:
                print("The specified qubit doesn't exist!")
Beispiel #8
0
    def apply_gate(self, *args, **kwargs):
        """Apply specified gate to specified qubit with specified controls.

        There are two variants for this method, depending on the number of
        gates you want to apply.
        One gate:
            Positional arguments:
                gate: string with the name of the gate to apply, or a QGate
            Keyworded arguments:
                qubit: id of the least significant qubit the gate will target
                control: id or list of ids of the qubit that will act as
                         controls
                anticontrol: id or list of ids of the qubit that will act as
                             anticontrols
                optimize: only for QGates. Whether to use optimized lines or
                          user defined lines
        Multiple gates:
            Positional arguments:
                comma separated gates, their sizes must match the number of
                    qubits in the system. Sorted by their least significant
                    target qubit id.
        """
        optimize = True
        if "optimize" in kwargs:
            optimize = kwargs["optimize"]
        if (len(args) == 1
                or (len(args) == 2 and np.issubdtype(type(args[1]), np.integer)
                    and "qubit" not in kwargs)):
            for key in kwargs:
                if (key != "qubit" and key != "control"
                        and key != "anticontrol" and key != "optimize"):
                    raise ValueError('Apart from the gates, you can only ' +
                                     'specify "qubit", "control", ' +
                                     '"anticontrol" (lowercase) and/or ' +
                                     '"optimize"')
            gate = args[0]
            if type(gate) == QGate:
                gate = (gate, gate.size)
            elif gate == "I" or gate is None:
                return
            else:
                gate = (gate, get_gate_data(gate)[0])
            qubit = kwargs.get("qubit", self.usable[0])
            if len(args) == 2:
                qubit = args[1]
            control = kwargs.get("control", [])
            if control is None:
                control = []
            if not isinstance(control, Iterable):
                control = [control]
            anticontrol = kwargs.get("anticontrol", [])
            if anticontrol is None:
                anticontrol = []
            if not isinstance(anticontrol, Iterable):
                anticontrol = [anticontrol]
            if isinstance(qubit, Iterable):
                for qid in qubit:
                    self.apply_gate(gate[0],
                                    qubit=qid,
                                    control=control,
                                    anticontrol=anticontrol,
                                    optimize=optimize)
            else:
                name = ""
                if type(gate[0]) != QGate:
                    name, arg1, arg2, arg3, invert = prs.get_gate_data(gate[0])
                    invstring = ""
                    if invert:
                        invstring = "-1"
                qubits = set(control).union(anticontrol)  # All affected qubits
                if "SWAP" in name:
                    qubit = arg1
                    qubits.add(arg2)
                elif name == "XX" or name == "YY" or name == "ZZ":
                    qubit = arg2
                    qubits.add(arg3)
                else:
                    qubits.update([qubit + i for i in range(1, gate[1])])
                rid = self.qubitMap[qubit]
                for qid in qubits:
                    self._superposition(rid, self.qubitMap[qid])
                reg, idlist = self.regs[rid]
                regmap = {idlist[i]: i for i in range(len(idlist))}
                newqubit = regmap[qubit]
                newcontrol = [regmap[qid] for qid in control]
                newanticontrol = [regmap[qid] for qid in anticontrol]
                if type(gate[0]) == QGate:
                    reg.apply_gate(gate[0],
                                   qubit=newqubit,
                                   control=newcontrol,
                                   anticontrol=newanticontrol,
                                   optimize=optimize)
                else:
                    if "SWAP" in name:
                        gate = (name + "(" + str(regmap[arg1]) + "," +
                                str(regmap[arg2]) + ")" + invstring, gate[1])
                    if name == "XX" or name == "YY" or name == "ZZ":
                        gate = (name + "(" + str(arg1) + "," +
                                str(regmap[arg2]) + "," + str(regmap[arg3]) +
                                ")" + invstring, gate[1])
                    reg.apply_gate(gate[0],
                                   qubit=newqubit,
                                   control=newcontrol,
                                   anticontrol=newanticontrol,
                                   optimize=optimize)
        elif len(kwargs) == 0 and len(args) > 0:
            nq = 0
            gates = []
            for arg in args:
                if type(arg) == QGate:
                    gatenq = (arg, arg.size)
                elif arg == "I" or arg is None:
                    gatenq = (None, 1)
                else:
                    gatenq = (arg, get_gate_data(arg)[0])
                nq += gatenq[1]
                gates.append(gatenq)
            if nq == self.get_num_qubits():
                qid = 0
                for gate in gates:
                    if gate[0] is not None:
                        self.apply_gate(gate[0], qubit=qid, optimize=optimize)
                    qid += gate[1]
            else:
                print("You have to specify a gate for each QuBit",
                      "(or None if you don't want to operate with it)")
        elif len(args) == 0:
            print("You must specify at least one gate")
        else:
            print("You can't apply more than one gate when using",
                  '"qubit", "control" or "anticontrol"')