Example #1
0
def test_eval():
    x = Parameter('x')
    assert substitute(x, {x: 5}) == 5

    y = Parameter('y')
    assert substitute(x + y, {x: 5, y: 6}) == 11
    assert substitute(x + y, {x: 5}) == 5 + y
    assert substitute(quil_exp(x), {y: 5}) != np.exp(5)
    assert substitute(quil_exp(x), {x: 5}) == np.exp(5)

    assert np.isclose(substitute(quil_sin(x * x**2 / y), {
        x: 5.0,
        y: 10.0
    }), np.sin(12.5))
    assert np.isclose(substitute(quil_sqrt(x), {
        x: 5.0,
        y: 10.0
    }), np.sqrt(5.0))
    assert np.isclose(substitute(quil_cis(x), {
        x: 5.0,
        y: 10.0
    }), np.exp(1j * 5.0))
    assert np.isclose(substitute(x - y, {x: 5.0, y: 10.0}), -5.)

    assert substitute(quil_cis(x), {y: 5}) == quil_cis(x)
    assert np.allclose(substitute_array([quil_sin(x), quil_cos(x)], {x: 5}),
                       [np.sin(5), np.cos(5)])
Example #2
0
def _wf_from_dict(name: str, params: Dict[str, Union[Expression, Real, Complex]]) -> TemplateWaveform:
    """Construct a TemplateWaveform from a name and a dictionary of properties.

    :param name: The Quil-T name of the template.
    :param params: A mapping from parameter names to their corresponding values.
    :returns: A template waveform.
    """
    params = copy(params)
    if name not in _waveform_classes:
        raise ValueError(f"Unknown template waveform {name}.")
    cls = _waveform_classes[name]
    fields = getattr(cls, "__dataclass_fields__", {})

    for param, value in params.items():
        if param not in fields:
            raise ValueError(f"Unexpected parameter '{param}' in {name}.")

        if isinstance(value, Expression):
            value = substitute(value, {})

        if isinstance(value, Real):
            # normalize to float
            params[param] = float(value)
        elif isinstance(value, Complex):
            # no normalization needed
            pass
        else:
            raise ValueError(f"Unable to resolve parameter '{param}' in template {name} to a constant value.")

    for field, spec in fields.items():
        if field not in params and spec.default is not None:
            raise ValueError(f"Missing parameter '{field}' in {name}.")

    return cls(**params)
Example #3
0
def test_substitute_memory_reference():
    x_0 = MemoryReference("x", 0, declared_size=2)
    x_1 = MemoryReference("x", 1, declared_size=2)

    # complete substitutions

    assert substitute(x_0, {x_0: 5}) == 5

    assert substitute(x_0 + x_1, {x_0: +5, x_1: -5}) == 0
    assert substitute(x_0 - x_1, {x_0: +5, x_1: -5}) == 10
    assert substitute(x_0 * x_1, {x_0: +5, x_1: -5}) == -25
    assert substitute(x_0 / x_1, {x_0: +5, x_1: -5}) == -1

    assert substitute(x_0 * x_0**2 / x_1, {x_0: 5, x_1: 10}) == 12.5

    assert np.isclose(substitute(quil_exp(x_0), {x_0: 5, x_1: 10}), np.exp(5))
    assert np.isclose(substitute(quil_sin(x_0), {x_0: 5, x_1: 10}), np.sin(5))
    assert np.isclose(substitute(quil_cos(x_0), {x_0: 5, x_1: 10}), np.cos(5))
    assert np.isclose(substitute(quil_sqrt(x_0), {
        x_0: 5,
        x_1: 10
    }), np.sqrt(5))
    assert np.isclose(substitute(quil_cis(x_0), {
        x_0: 5,
        x_1: 10
    }), np.exp(1j * 5.0))

    # incomplete substitutions

    y = MemoryReference("y", 0, declared_size=1)
    z = MemoryReference("z", 0, declared_size=1)

    assert substitute(y + z, {y: 5}) == 5 + z

    assert substitute(quil_cis(z), {y: 5}) == quil_cis(z)

    # array substitution pass-through

    a = MemoryReference("a", 0, declared_size=1)

    assert np.allclose(substitute_array([quil_sin(a), quil_cos(a)], {a: 5}),
                       [np.sin(5), np.cos(5)])
Example #4
0
def fill_placeholders(obj, placeholder_values: Dict[Union[FormalArgument,
                                                          Parameter], Any]):
    """Update Parameter and FormalArgument references in objects with
    their corresponding definitions.

    It is an error if the object has a Parameter or FormalArgument reference without
    a corresponding definition in placeholder_values.

    :param obj: A Quil AST object.
    :param placeholder_values: A dictionary mapping placeholders to their values.
    :returns: The updated AST object.
    """
    try:
        if obj is None or isinstance(
                obj, (int, float, complex, Qubit, MemoryReference)):
            return obj
        elif isinstance(obj, Expression):
            # defer to the usual PyQuil substitution
            return substitute(
                obj, {
                    k: v
                    for k, v in placeholder_values.items()
                    if isinstance(k, Parameter)
                })
        elif isinstance(obj, FormalArgument):
            return placeholder_values[obj]
        elif isinstance(obj, Frame):
            return Frame(fill_placeholders(obj.qubits, placeholder_values),
                         obj.name)
        elif isinstance(obj, WaveformReference):
            return obj
        elif isinstance(obj, TemplateWaveform):
            return obj.__class__(
                **fill_placeholders(obj.__dict__, placeholder_values))
        elif isinstance(obj, list):
            return [fill_placeholders(elt, placeholder_values) for elt in obj]
        elif isinstance(obj, dict):
            return {
                k: fill_placeholders(v, placeholder_values)
                for (k, v) in obj.items()
            }
        elif isinstance(obj, tuple):
            return tuple(
                [fill_placeholders(item, placeholder_values) for item in obj])
        elif isinstance(obj, Pragma) and obj.command == "LOAD-MEMORY":
            (source, ) = obj.args
            arg = FormalArgument(obj.freeform_string)
            if arg in placeholder_values:
                return Pragma("LOAD-MEMORY", [source],
                              str(placeholder_values[arg]))
            else:
                return obj
        else:
            specs = {
                Gate: ["params", "qubits"],
                Measurement: ["qubit", "classical_reg"],
                ResetQubit: ["qubit"],
                Pulse: ["frame", "waveform"],
                SetFrequency: ["frame", "freq"],
                ShiftFrequency: ["frame", "freq"],
                SetPhase: ["frame", "phase"],
                ShiftPhase: ["frame", "phase"],
                SwapPhase: ["frameA", "frameB"],
                SetScale: ["frame", "scale"],
                Capture: ["frame", "kernel", "memory_region"],
                RawCapture: ["frame", "duration", "memory_region"],
                DelayQubits: ["qubits", "duration"],
                DelayFrames: ["frames", "duration"],
                Fence: ["qubits"],
                FenceAll: [],
                Declare: [],
                Pragma: [],
            }
            if type(obj) in specs:
                attrs = specs[type(obj)]
                updated = copy(obj)
                for attr in attrs:
                    setattr(
                        updated, attr,
                        fill_placeholders(getattr(updated, attr),
                                          placeholder_values))
                return updated
            else:
                raise CalibrationError(
                    f"Unable to fill placeholders in object {obj}.")
    except Exception as e:
        raise e