qat.vsolve.ansatz.AnsatzFactory
- class qat.vsolve.ansatz.AnsatzFactory
This class regroups the implementation all the different Ansätze available in the QLM.
- static qaoa_circuit(observable, depth, strategy='default', cnots=True, **to_circ_args)
Generates a QAOA Ansatz from an observable and an Ansatz depth
Example
from qat.core import Observable, Term from qat.vsolve.ansatz import AnsatzFactory line_obs = Observable(10) for i in range(9): line_obs.add_term(Term(1., "ZZ", [i, i+1])) ansatz_with_cnots = AnsatzFactory.qaoa_circuit(line_obs, 3) print("The Ansatz has {} gates".format(len(ansatz_with_cnots.ops))) ansatz_with_rzz = AnsatzFactory.qaoa_circuit(line_obs, 3, cnots=False) print("The Ansatz has {} gates".format(len(ansatz_with_rzz.ops)))
The Ansatz has 121 gates The Ansatz has 67 gates
The synthesis strategy may influence the depth of the circuit:
def depth(circuit): ''' Computes the depth of a circuit ''' slices = [set()] for op in circuit: qbits = op.qbits insert_in = None for index, slic in enumerate(reversed(slices)): if all(qb not in slic for qb in qbits): continue insert_in = index break if insert_in is None: for qb in qbits: slices[0].add(qb) elif insert_in == 0: slices.append(set(qbits)) else: for qb in qbits: slices[len(slices) - insert_in].add(qb) return len(slices) from qat.core import Observable, Term from qat.vsolve.ansatz import AnsatzFactory line_obs = Observable(10) for i in range(9): line_obs.add_term(Term(1., "ZZ", [i, i+1])) ansatz_default = AnsatzFactory.qaoa_circuit(line_obs, 3, strategy="default") print("The Ansatz has depth {}".format(depth(ansatz_default))) ansatz_coloring = AnsatzFactory.qaoa_circuit(line_obs, 3, strategy="coloring") print("The Ansatz has depth {}".format(depth(ansatz_coloring)))
The Ansatz has depth 43 The Ansatz has depth 22
When considering QAOA instances with large Clauses (i.e clauses with more than 2 variables), the “gray_synth” strategy can often remove lots of CNOTS:
def cnot_count(circuit): ''' count cnots in a circuit ''' return sum(1 if name == "CNOT" else 0 for name, args, qbits in circuit.iterate_simple()) from qat.core import Observable, Term from qat.vsolve.ansatz import AnsatzFactory n = 5 line_obs = Observable(n) for i in range(n - 2): line_obs.add_term(Term(1., "ZZZ", [i, i+1, i+2])) ansatz_default = AnsatzFactory.qaoa_circuit(line_obs, 3, strategy="default") ansatz_gray_synth = AnsatzFactory.qaoa_circuit(line_obs, 3, strategy="gray_synth") print("Cnot count in default:", cnot_count(ansatz_default)) print("Cnot count in gray synth:", cnot_count(ansatz_gray_synth))
Cnot count in default: 36 Cnot count in gray synth: 24
Synthesis strategies:
default: uses the default term ordering provided by the input observable
coloring: orders terms using a graph coloring technique in order to reduce circuit depth
gray_synth: uses Amy et al GraySynth algorithm to synthesize the entangling layer. This might help in reducing the overall CNOT count.
- Parameters
observable (
Observable
) – some diagonal observabledepth (int) – the depth of the Ansatz
strategy (str) – the strategy to adopt to generate the circuit.
cnots (optional, bool) – if set to True, the generator will onlt use CNOT gates as entangling gates. Default to True. This argument is ignored for some strategies.
**to_circ_args – arguments passed to the to_circ method