def grad(objective: typing.Union[Objective, VectorObjective], variable: Variable = None, no_compile=False, *args, **kwargs): ''' wrapper function for getting the gradients of Objectives,ExpectationValues, Unitaries (including single gates), and Transforms. :param obj (QCircuit,ParametrizedGateImpl,Objective,ExpectationValue,Transform,Variable): structure to be differentiated :param variables (list of Variable): parameter with respect to which obj should be differentiated. default None: total gradient. return: dictionary of Objectives, if called on gate, circuit, exp.value, or objective; if Variable or Transform, returns number. ''' if variable is None: # None means that all components are created variables = objective.extract_variables() result = {} if len(variables) == 0: raise TequilaException( "Error in gradient: Objective has no variables") for k in variables: assert (k is not None) result[k] = grad(objective, k, no_compile=no_compile) return result else: variable = assign_variable(variable) if no_compile: compiled = objective else: compiler = Compiler(multitarget=True, trotterized=True, hadamard_power=True, power=True, controlled_phase=True, controlled_rotation=True, gradient_mode=True) compiled = compiler(objective, variables=[variable]) if variable not in compiled.extract_variables(): raise TequilaException( "Error in taking gradient. Objective does not depend on variable {} " .format(variable)) if isinstance(objective, ExpectationValueImpl): return __grad_expectationvalue(E=objective, variable=variable) elif objective.is_expectationvalue(): return __grad_expectationvalue(E=compiled.args[-1], variable=variable) elif isinstance(compiled, Objective) or isinstance(compiled, VectorObjective): return __grad_objective(objective=compiled, variable=variable) else: raise TequilaException( "Gradient not implemented for other types than ExpectationValue and Objective." )
def export_to(circuit: QCircuit, filename: str, always_use_generators: bool = True, decompose_control_generators: bool = False, group_together: bool = False, qubit_names: list = None, *args, **kwargs): """ Parameters ---------- circuit: the tequila circuit to export filename: filename.filetype, e.g. my_circuit.pdf, my_circuit.png (everything that qpic supports) always_use_generators: represent all gates with their generators decompose_control_generators: Decompose the controls to generators. Effective only in combination with always_use_generators=True. group_together: Keep PauliStrings from the same generator together. Effective only in combination with always_use_generators=True. possible values: False, True, 'TOUCH' and 'BARRIER'. True is the same as TOUCH. BARRIER will create a visible barrier in qpic args kwargs Returns ------- """ if not system_has_qpic: raise Exception("You need qpic in order to export circuits to pictures ---\n pip install qpic") if "." not in filename: raise Exception("export_to: No filetype given {}, expected something like {}.pdf".format(filename, filename)) filename_tmp = filename.split(".") ftype = filename_tmp[-1] fname = "".join(filename_tmp[:-1]) if len(filename_tmp) == 1: ftype = ".pdf" fname = filename compiled = Compiler(trotterized=True)(circuit) export_to_qpic(circuit=compiled, filename=fname, always_use_generators=always_use_generators, decompose_control_generators=decompose_control_generators, group_together=group_together, qubit_names=qubit_names, *args, **kwargs) if ftype != "qpic": subprocess.call(["qpic", "{}.qpic".format(fname), "-f", ftype])
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