qat.plugins.CostFunctionPlugin

In the Qaptiva framework, variational optimization plugins are designed to minimize the energy of an observable. This formalism requires to encode the quantity to be minimized using an observable (which is not always easy to do)

This plugin has been designed to encode this quantity using a Python function. The quantity computed by the cost function given to the will be minimized by the optimizer plugin present in the stack.

Example of CostFunctionPlugin

In this example, one will try to maximize the Hamming weigth of a sample (i.e. maximizing the number of 1 in the state - or minimizing the number of 0 in this state). This cost function can be easily encoding using an observable but implementing this cost function in Python is easier. The CostFunctionPlugin has two mode:

  • Function acting on samples: the function given to this plugin takes a Sample and returns a float

  • Function acting on results: the function given to this plugin takes a Result and returns a float

This example will focus on minimizing the Hamming weight. A basic circuit composed of two qubits, with one RX gate per qubit, will be chosen to illustrate this example

from qat.lang.AQASM import Program, RX

prog = Program()
qbits = prog.qalloc(2)

for idx, qb in enumerate(qbits):
    angle = prog.new_var(float, f"V{idx}")
    prog.apply(RX(angle), qb)

circ = prog.to_circ()
job = circ.to_job()

The cost function must be defined, in this mode, the code function takes a Sample and returns a float. For instance, one can write:

def cost_function(sample):
    """
    This function should be minimize. Then, the number of 0 present in the state
    will be computed
    """
    return sample.state.bitstring.count("0")

Then, the plugin can be used to optimize the angles of our job

from qat.plugins import ScipyMinimizePlugin, CostFunctionPlugin
from qat.qpus import get_default_qpu

stack = ScipyMinimizePlugin() | CostFunctionPlugin(cost_function) | get_default_qpu()
result = stack.submit(job)

The final state can be be retrieved, state \(|11\rangle\) is the state having the higher probability

job_fixed_angles = job(**result.parameter_map)
result_fixed_angles = stack.submit(job_fixed_angles)

for sample in result_fixed_angles:
    print(f"{sample.state} has a probability of {sample.probability:.2}")
|01> has a probability of 1.9e-12
|10> has a probability of 2.5e-15
|11> has a probability of 1.0

This example will focus on minimizing the Hamming weight. A basic circuit composed of two qubits, with one RX gate per qubit, will be chosen to illustrate this example

from qat.lang.AQASM import Program, RX

prog = Program()
qbits = prog.qalloc(2)

for idx, qb in enumerate(qbits):
    angle = prog.new_var(float, f"V{idx}")
    prog.apply(RX(angle), qb)

circ = prog.to_circ()
job = circ.to_job()

The cost function must be defined, in this mode, the code function takes a Result and returns a float. For instance, one can write:

def cost_function(result):
    """
    This function should be minimize. Then, the number of 0 present in the state
    will be computed
    """
    return sum(sample.probability * sample.state.bitstring.count("0") for sample in result)

Then, the plugin can be used to optimize the angles of our job

Warning

CostFunctionPlugin assume a function taking a Sample as argument is provided. To change this behavior, an argument is_result_argument=True must be specified

from qat.plugins import ScipyMinimizePlugin, CostFunctionPlugin
from qat.qpus import get_default_qpu

stack = ScipyMinimizePlugin() | CostFunctionPlugin(cost_function, is_result_argument=True) | get_default_qpu()
result = stack.submit(job)

The final state can be be retrieved, state \(|11\rangle\) is the state having the higher probability

job_fixed_angles = job(**result.parameter_map)
result_fixed_angles = stack.submit(job_fixed_angles)

for sample in result_fixed_angles:
    print(f"{sample.state} has a probability of {sample.probability:.2}")
|01> has a probability of 8.9e-13
|10> has a probability of 4e-13
|11> has a probability of 1.0
class qat.plugins.CostFunctionPlugin(cost_function, is_result_argument: bool = False)

Encoding a cost function using a Observable can be hard. This plugin can be used to encode a cost function directly in Python. This plugin is designed to be used between the optimizer and the QPU

stack = ScipyMinimizePlugin() | CostFunctionPlugin(my_function) | LinAlg()

A cost function takes a Sample (or a Result) an return a number that should be minimized

Parameters
  • cost_function (callable) – cost function taking a Sample and return a number

  • is_result_argument (bool, optional) –

    argument type passed to the cost function:

    • if use_result=True, “cost_function” parameter is expected to be a function taking a Result and returning a float

    • if use_result=False, “cost_function” parameter is expected to be a function taking Sample and returning a float

    Default: False

compile(batch, specs)

Compiles a job. In practise, this method does nothing to the batch

Parameters
Returns

compiled batch

Return type

Batch