def test_endianness_simulators(): tests = ["000111", "111000", "101010", "010101", "10010010001", "111100101000010"] for string in tests: binary = BitString.from_binary(binary=string) c = QCircuit() for i, v in enumerate(binary): if v == 1: c += gates.X(target=i) if v == 0: c += gates.Z(target=i) wfn_cirq = simulate(c, initial_state=0, backend="cirq") counts_cirq = simulate(c, samples=1, backend="cirq") counts_qiskit = simulate(c, samples=1, backend="qiskit") print("counts_cirq =", type(counts_cirq)) print("counts_qiskit=", type(counts_qiskit)) print("counts_cirq =", counts_cirq) print("counts_qiskit=", counts_qiskit) assert (counts_cirq.isclose(counts_qiskit)) assert (wfn_cirq.state == counts_cirq.state)
def __call__(self, wfn: QubitWaveFunction) -> QCircuit: """ :param coeffs: The QubitWaveFunction you want to initialize :return: """ try: assert (len(wfn) == len(self._target_space)) for key in wfn.keys(): try: assert (key in self._target_space) except AssertionError: print("key=", key.binary, " not found in target space") except AssertionError: raise TequilaException( "UnaryStatePrep was not initialized for the basis states in your wavefunction\n" "You gave:\n" + str(wfn) + "\n" "But the target_space is " + str([k.binary for k in self._target_space]) + "\n") angles = self._evaluate_angles(wfn=wfn) # construct new circuit with evaluated angles result = QCircuit() for g in self._abstract_circuit.gates: g2 = copy.deepcopy(g) if hasattr(g, "parameter"): symbol = g.parameter # the module needs repairing .... g2._parameter = assign_variable( -angles[-symbol()] ) # the minus follows mahas convention since the circuits are daggered in the end result += g2 return result
def test_endianness_simulators(): tests = [ "000111", "111000", "101010", "010101", "10010010001", "111100101000010" ] for string in tests: number = int(string, 2) binary = BitString.from_binary(binary=string) c = QCircuit() for i, v in enumerate(binary): if v == 1: c += gates.X(target=i) c += gates.Measurement(target=[x for x in range(len(string))]) wfn_cirq = simulate(c, initial_state=0, backend="cirq") counts_cirq = simulate(c, samples=1, backend="cirq") counts_qiskit = simulate(c, samples=1, backend="qiskit") print("counts_cirq =", type(counts_cirq)) print("counts_qiskit=", type(counts_qiskit)) print("counts_cirq =", counts_cirq) print("counts_qiskit=", counts_qiskit) assert (counts_cirq == counts_qiskit) assert (wfn_cirq.state == counts_cirq.state)
def get_circuit(self, s): ''' s = [] for counter in range(4): string = input("Enter your state: ") s.append(string) if not silenced: print(s) ''' if not self.silenced: print("s on start=", s) moves_list = [] moves_list = self.get_next_move(s, moves_list) if not self.silenced: print("last s=", s) circuit = QCircuit() for move in moves_list: circuit += self.create_sub_circ(move[0], move[1], move[2]) return circuit.dagger()
def apply_custom_gate(custom_circuit: QCircuit, qregisters_values: list) -> QCircuit: applied_custom_circuit = QCircuit() for gate in custom_circuit.gates: g = gate.copy() g._target = tuple([qregisters_values[i] for i in gate._target]) g._control = tuple([qregisters_values[i] for i in gate._control ]) if gate.is_controlled() else gate._control applied_custom_circuit += g return applied_custom_circuit
def parse_from_open_qasm_2(qasm_code: str, rigorous: bool = True) -> QCircuit: lines = qasm_code.splitlines() clean_code = [] # ignore comments for line in lines: if line.find("//") != -1: clean_line = line[0:line.find("//")].strip() else: clean_line = line.strip() if clean_line: clean_code.append(clean_line) if clean_code[0].startswith("OPENQASM"): clean_code.pop(0) elif rigorous: raise TequilaException("File must start with the 'OPENQASM' directive") if clean_code[0].startswith('include "qelib1.inc";'): clean_code.pop(0) elif rigorous: raise TequilaException( "File must import standard library (qelib1.inc)") code_circuit = "\n".join(clean_code) # separate the custom command definitions from the normal commands custom_gates_map: Dict[str, QCircuit] = {} while True: i = code_circuit.find("gate ") if i == -1: break j = code_circuit.find("}", i) custom_name, custom_circuit = parse_custom_gate( code_circuit[i:j + 1], custom_gates_map=custom_gates_map) custom_gates_map[custom_name] = custom_circuit code_circuit = code_circuit[:i] + code_circuit[j + 1:] # parse regular commands commands = [s.strip() for s in code_circuit.split(";") if s.strip()] qregisters: Dict[str, int] = {} circuit = QCircuit() for c in commands: partial_circuit = parse_command(command=c, custom_gates_map=custom_gates_map, qregisters=qregisters) if partial_circuit is not None: circuit += partial_circuit return circuit
def get_circuit(self): """ :return: Return the abstract circuit with tequila parameters """ result = QCircuit() for g in self._abstract_circuit.gates: g2 = copy.deepcopy(g) if hasattr(g, "parameter"): symbol = g.parameter name = str(-symbol) # kill the minus from the dagger g2._parameter = assign_variable(name) result += g2 return result
def parse_custom_gate( gate_custom: str, custom_gates_map: Dict[str, QCircuit]) -> (str, QCircuit): """ Parse custom gates code Args: gate_custom: code with custom gates """ gate_custom = gate_custom[5:] spec, body = gate_custom.split("{", 1) if "(" in spec: i = spec.find("(") j = spec.find(")") if spec[i + 1:j].strip(): raise TequilaException( "Parameters for custom gates not supported: {}".format(spec)) spec = spec[:i] + spec[j + 1:] spec = spec.strip() if " " in spec: name, qargs = spec.split(" ", 1) name = name.strip() qargs = qargs.strip() else: raise TequilaException( "Custom gate specification doesn't have any arguments: {}".format( spec)) custom_qregisters: Dict[str, int] = {} for qarg in qargs.split(','): custom_qregisters[qarg] = len(custom_qregisters) body = body[:-1].strip() commands = [s.strip() for s in body.split(";") if s.strip()] custom_circuit = QCircuit() for c in commands: partial_circuit = parse_command(command=c, custom_gates_map=custom_gates_map, qregisters=custom_qregisters) if partial_circuit is not None: custom_circuit += partial_circuit return name, custom_circuit
def prepare_product_state(state: BitString) -> QCircuit: """Small convenience function Parameters ---------- state : product state encoded into a bitstring state: BitString : Returns ------- type unitary circuit which prepares the product state """ result = QCircuit() for i, v in enumerate(state.array): if v == 1: result += gates.X(target=i) return result
def make_uccsd_ansatz( self, trotter_steps: int, initial_amplitudes: typing.Union[str, Amplitudes, ClosedShellAmplitudes] = "mp2", include_reference_ansatz=True, parametrized=True, threshold=1.e-8, trotter_parameters: gates.TrotterParameters = None) -> QCircuit: """ Parameters ---------- initial_amplitudes : initial amplitudes given as ManyBodyAmplitudes structure or as string where 'mp2', 'cc2' or 'ccsd' are possible initializations include_reference_ansatz : Also do the reference ansatz (prepare closed-shell Hartree-Fock) (Default value = True) parametrized : Initialize with variables, otherwise with static numbers (Default value = True) trotter_steps: int : initial_amplitudes: typing.Union[str : Amplitudes : ClosedShellAmplitudes] : (Default value = "mp2") trotter_parameters: gates.TrotterParameters : (Default value = None) Returns ------- type Parametrized QCircuit """ if self.n_electrons % 2 != 0: raise TequilaException( "make_uccsd_ansatz currently only for closed shell systems") nocc = self.n_electrons // 2 nvirt = self.n_orbitals // 2 - nocc Uref = QCircuit() if include_reference_ansatz: Uref = self.prepare_reference() amplitudes = initial_amplitudes if hasattr(initial_amplitudes, "lower"): if initial_amplitudes.lower() == "mp2": amplitudes = self.compute_mp2_amplitudes() elif initial_amplitudes.lower() == "ccsd": amplitudes = self.compute_ccsd_amplitudes() else: try: amplitudes = self.compute_amplitudes( method=initial_amplitudes.lower()) except Exception as exc: raise TequilaException( "{}\nDon't know how to initialize \'{}\' amplitudes". format(exc, initial_amplitudes)) if amplitudes is None: amplitudes = ClosedShellAmplitudes( tIjAb=numpy.zeros(shape=[nocc, nocc, nvirt, nvirt]), tIA=numpy.zeros(shape=[nocc, nvirt])) closed_shell = isinstance(amplitudes, ClosedShellAmplitudes) generators = [] variables = [] if not isinstance(amplitudes, dict): amplitudes = amplitudes.make_parameter_dictionary( threshold=threshold) amplitudes = dict(sorted(amplitudes.items(), key=lambda x: x[1])) for key, t in amplitudes.items(): assert (len(key) % 2 == 0) if not numpy.isclose(t, 0.0, atol=threshold): if closed_shell: spin_indices = [] if len(key) == 2: spin_indices = [[2 * key[0], 2 * key[1]], [2 * key[0] + 1, 2 * key[1] + 1]] partner = None else: spin_indices.append([ 2 * key[0] + 1, 2 * key[1] + 1, 2 * key[2], 2 * key[3] ]) spin_indices.append([ 2 * key[0], 2 * key[1], 2 * key[2] + 1, 2 * key[3] + 1 ]) if key[0] != key[1] and key[2] != key[3]: spin_indices.append([ 2 * key[0], 2 * key[1], 2 * key[2], 2 * key[3] ]) spin_indices.append([ 2 * key[0] + 1, 2 * key[1] + 1, 2 * key[2] + 1, 2 * key[3] + 1 ]) partner = tuple([key[2], key[1], key[0], key[3]]) # taibj -> tbiaj for idx in spin_indices: idx = [(idx[2 * i], idx[2 * i + 1]) for i in range(len(idx) // 2)] generators.append( self.make_excitation_generator(indices=idx)) if parametrized: variables.append(Variable(name=key)) # abab variables.append(Variable(name=key)) # baba if partner is not None and key[0] != key[1] and key[ 2] != key[3]: variables.append( Variable(name=key) - Variable(partner)) # aaaa variables.append( Variable(name=key) - Variable(partner)) # bbbb else: variables.append(t) variables.append(t) if partner is not None and key[0] != key[1] and key[ 2] != key[3]: variables.append(t - amplitudes[partner]) variables.append(t - amplitudes[partner]) else: generators.append( self.make_excitation_operator(indices=spin_indices)) if parametrized: variables.append(Variable(name=key)) else: variables.append(t) return Uref + gates.Trotterized(generators=generators, angles=variables, steps=trotter_steps, parameters=trotter_parameters)
def convert_to_open_qasm_2(circuit: QCircuit, variables=None, zx_calculus: bool = False) -> str: """ Allow export to OpenQASM version 2.0 Args: circuit: to be exported to OpenQASM variables: optional dictionary with values for variables zx_calculus: indicate if y-gates must be transformed to xz equivalents Returns: str: OpenQASM string """ if variables is None and not (len(circuit.extract_variables()) == 0): raise TequilaException( "You called export_open_qasm for a parametrized type but forgot to pass down the variables: {}" .format(circuit.extract_variables())) compiler = Compiler(multitarget=True, multicontrol=False, trotterized=True, generalized_rotation=True, exponential_pauli=True, controlled_exponential_pauli=True, hadamard_power=True, controlled_power=True, power=True, toffoli=True, controlled_phase=True, phase=True, phase_to_z=True, controlled_rotation=True, swap=True, cc_max=True, gradient_mode=False, ry_gate=zx_calculus, y_gate=zx_calculus, ch_gate=zx_calculus) compiled = compiler(circuit, variables=None) result = "OPENQASM 2.0;\ninclude \"qelib1.inc\";\n" qubits_names: Dict[int, str] = {} for q in compiled.qubits: name = "q[" + str(q) + "]" qubits_names[q] = name result += "qreg q[" + str(compiled.n_qubits) + "];\n" result += "creg c[" + str(compiled.n_qubits) + "];\n" for g in compiled.gates: control_str = '' if g.is_controlled(): if len(g.control) > 2: raise TequilaException( "Multi-controls beyond 2 not yet supported for OpenQASM 2.0. Gate was:\n{}" .format(g)) controls = list(map(lambda c: qubits_names[c], g.control)) control_str = ','.join(controls) + ',' gate_name = name_and_params(g, variables) for t in g.target: result += gate_name result += control_str result += qubits_names[t] result += ";\n" return result
def parse_command(command: str, custom_gates_map: Dict[str, QCircuit], qregisters: Dict[str, int]) -> QCircuit: """ Parse qasm code command Args: command: open qasm code to be parsed custom_gates_map: map with custom gates """ name, rest = command.split(" ", 1) if name in ("barrier", "creg", "measure", "id"): return None if name in ("opaque", "if"): raise TequilaException("Unsupported operation {}".format(command)) args = [s.strip() for s in rest.split(",") if s.strip()] if name == "qreg": regname, sizep = args[0].split("[", 1) size = int(sizep[:-1]) for i in range(size): qregisters[regname + "[" + str(i) + "]"] = len(qregisters) return None for arg in args: if not (arg in qregisters or arg in [key.split("[", 1)[0] for key in qregisters.keys()]): raise TequilaException("Invalid register {}".format(arg)) if name in custom_gates_map: custom_circuit = custom_gates_map[name] qregisters_values = [] for a in args: qregisters_values.append(get_qregister(a, qregisters)) return apply_custom_gate(custom_circuit=custom_circuit, qregisters_values=qregisters_values) if name in ("x", "y", "z", "h", "cx", "cy", "cz", "ch"): return QCircuit.wrap_gate( gates.impl.QGateImpl( name=(name[1] if name[0] == 'c' else name).upper(), control=get_qregister(args[0], qregisters) if name[0] == 'c' else None, target=get_qregister(args[1 if name[0] == 'c' else 0], qregisters))) if name in ("ccx", "ccy", "ccz"): return QCircuit.wrap_gate( gates.impl.QGateImpl(name=name.upper()[2], control=[ get_qregister(args[0], qregisters), get_qregister(args[1], qregisters) ], target=get_qregister(args[2], qregisters))) if name.startswith("rx(") or name.startswith("ry(") or name.startswith("rz(") or \ name.startswith("crx(") or name.startswith("cry(") or name.startswith("crz("): return QCircuit.wrap_gate( gates.impl.RotationGateImpl( axis=name[2 if name[0] == 'c' else 1], angle=get_angle(name)[0], control=get_qregister(args[0], qregisters) if name[0] == 'c' else None, target=get_qregister(args[1 if name[0] == 'c' else 0], qregisters))) if name.startswith("U("): angles = get_angle(name) return gates.U(theta=angles[0], phi=angles[1], lambd=angles[2], control=None, target=get_qregister(args[0], qregisters)) if name.startswith("u1("): angles = get_angle(name) return gates.u1(lambd=angles[0], control=None, target=get_qregister(args[0], qregisters)) if name.startswith("u2("): angles = get_angle(name) return gates.u2(phi=angles[0], lambd=angles[1], control=None, target=get_qregister(args[0], qregisters)) if name.startswith("u3("): angles = get_angle(name) return gates.u3(theta=angles[0], phi=angles[1], lambd=angles[2], control=None, target=get_qregister(args[0], qregisters)) if name.startswith("cu1("): angles = get_angle(name) return gates.u1(lambd=angles[0], control=get_qregister(args[0], qregisters), target=get_qregister(args[1], qregisters)) if name.startswith("cu2("): angles = get_angle(name) return gates.u2(phi=angles[0], lambd=angles[1], control=get_qregister(args[0], qregisters), target=get_qregister(args[1], qregisters)) if name.startswith("cu3("): angles = get_angle(name) return gates.u3(theta=angles[0], phi=angles[1], lambd=angles[2], control=get_qregister(args[0], qregisters), target=get_qregister(args[1], qregisters)) if name in ("s", "t", "sdg", "tdg"): g = gates.Phase(pi / (2 if name.startswith("s") else 4), control=None, target=get_qregister(args[0], qregisters)) if name.find("dg") != -1: g = g.dagger() return g