Ejemplo n.º 1
0
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."
        )
Ejemplo n.º 2
0
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])
Ejemplo n.º 3
0
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