def __call__(self, *args, **kwargs): super().__call__(*args, **kwargs) execParams = {'accelerator': self.qpu, 'ansatz': self.compiledKernel, 'observable': self.kwargs["observable"]} optParams = {} if not isinstance(args[0], xacc.AcceleratorBuffer): raise RuntimeError( 'First argument of an xacc kernel must be the Accelerator Buffer to operate on.') buffer = args[0] ars = args[1:] if len(ars) > 0: if isinstance(ars,list) or isinstance(ars,tuple): # print('ars is a list') optParams['initial-parameters'] = ars[0] else: optParams['initial-parameters'] = list(ars) # print(type(ars), optParams['initial-parameters']) if 'options' in self.kwargs: optParams = self.kwargs['options'] if 'optimizer' not in self.kwargs: self.kwargs['optimizer'] = 'nlopt' execParams['optimizer'] = xacc.getOptimizer(self.kwargs['optimizer'], optParams) vqe = xacc.getAlgorithm('vqe', execParams) vqe.execute(buffer) return
def runVqeGradientDescent(gradientStrategy): # Get access to the desired QPU and # allocate some qubits to run on qpu = xacc.getAccelerator('qpp') # Construct the Hamiltonian as an XACC PauliOperator ham = xacc.getObservable('pauli', '1.0 Y0') # Ansatz circuit: xacc.qasm('''.compiler xasm .circuit ansatz .qbit q .parameters t0, t1, t2, t3 // State-prep Ry(q[0], pi/4); Ry(q[1], pi/3); Ry(q[2], pi/7); // Parametrized gates (layer 1) Rz(q[0], t0); Rz(q[1], t1); CX(q[0], q[1]); CX(q[1], q[2]); // Parametrized gates (layer 2) Ry(q[1], t2); Rx(q[2], t3); CX(q[0], q[1]); CX(q[1], q[2]); ''') # We need 4 qubits buffer = xacc.qalloc(4) ansatz_circuit = xacc.getCompiled('ansatz') initParams = [0.432, -0.123, 0.543, 0.233] opt = xacc.getOptimizer( 'mlpack', { # Using gradient descent: 'mlpack-optimizer': 'gd', 'initial-parameters': initParams, 'mlpack-step-size': 0.01, 'mlpack-max-iter': 200 }) # Create the VQE algorithm with the requested gradient strategy vqe = xacc.getAlgorithm( 'vqe', { 'ansatz': ansatz_circuit, 'accelerator': qpu, 'observable': ham, 'optimizer': opt, 'gradient_strategy': gradientStrategy }) vqe.execute(buffer) energies = buffer.getInformation('params-energy') return energies
def __call__(self, *args, **kwargs): super().__call__(*args, **kwargs) execParams = { 'accelerator': self.qpu, 'ansatz': self.compiledKernel, 'target_dist': self.kwargs['target_dist'], 'loss': self.kwargs['loss'] } if 'gradient' in self.kwargs: execParams['gradient'] = self.kwargs['gradient'] optParams = {} if not isinstance(args[0], xacc.AcceleratorBuffer): raise RuntimeError( 'First argument of an xacc kernel must be the Accelerator Buffer to operate on.' ) buffer = args[0] ars = args[1:] if len(ars) > 0: optParams['initial-parameters'] = list(ars) if 'options' in self.kwargs: optParams = self.kwargs['options'] if 'optimizer' not in self.kwargs: self.kwargs['optimizer'] = 'nlopt' if self.kwargs['optimizer'] in self.vqe_optimizers: optimizer = self.vqe_optimizers[self.kwargs['optimizer']] optimizer.optimize(buffer, optParams, execParams) else: execParams['optimizer'] = xacc.getOptimizer( self.kwargs['optimizer'], optParams) ddcl = xacc.getAlgorithm('ddcl', execParams) ddcl.execute(buffer) return
import xacc xacc.set_verbose(True) qpu = xacc.getAccelerator('qpp') optimizer = xacc.getOptimizer('nlopt', {'nlopt-optimizer': 'l-bfgs'}) buffer = xacc.qalloc(4) opstr = ''' (-0.165606823582,-0) 1^ 2^ 1 2 + (0.120200490713,0) 1^ 0^ 0 1 + (-0.0454063328691,-0) 0^ 3^ 1 2 + (0.168335986252,0) 2^ 0^ 0 2 + (0.0454063328691,0) 1^ 2^ 3 0 + (0.168335986252,0) 0^ 2^ 2 0 + (0.165606823582,0) 0^ 3^ 3 0 + (-0.0454063328691,-0) 3^ 0^ 2 1 + (-0.0454063328691,-0) 1^ 3^ 0 2 + (-0.0454063328691,-0) 3^ 1^ 2 0 + (0.165606823582,0) 1^ 2^ 2 1 + (-0.165606823582,-0) 0^ 3^ 0 3 + (-0.479677813134,-0) 3^ 3 + (-0.0454063328691,-0) 1^ 2^ 0 3 + (-0.174072892497,-0) 1^ 3^ 1 3 + (-0.0454063328691,-0) 0^ 2^ 1 3 + (0.120200490713,0) 0^ 1^ 1 0 + (0.0454063328691,0) 0^ 2^ 3 1 + (0.174072892497,0) 1^ 3^ 3 1 + (0.165606823582,0) 2^ 1^ 1 2 + (-0.0454063328691,-0) 2^ 1^ 3 0 + (-0.120200490713,-0) 2^ 3^ 2 3 + (0.120200490713,0) 2^ 3^ 3 2 + (-0.168335986252,-0) 0^ 2^ 0 2 + (0.120200490713,0) 3^ 2^ 2 3 + (-0.120200490713,-0) 3^ 2^ 3 2 + (0.0454063328691,0) 1^ 3^ 2 0 + (-1.2488468038,-0) 0^ 0 + (0.0454063328691,0) 3^ 1^ 0 2 + (-0.168335986252,-0) 2^ 0^ 2 0 + (0.165606823582,0) 3^ 0^ 0 3 + (-0.0454063328691,-0) 2^ 0^ 3 1 + (0.0454063328691,0) 2^ 0^ 1 3 + (-1.2488468038,-0) 2^ 2 + (0.0454063328691,0) 2^ 1^ 0 3 + (0.174072892497,0) 3^ 1^ 1 3 + (-0.479677813134,-0) 1^ 1 + (-0.174072892497,-0) 3^ 1^ 3 1 + (0.0454063328691,0) 3^ 0^ 1 2 + (-0.165606823582,-0) 3^ 0^ 3 0 + (0.0454063328691,0) 0^ 3^ 2 1 + (-0.165606823582,-0) 2^ 1^ 2 1 + (-0.120200490713,-0) 0^ 1^ 0 1 + (-0.120200490713,-0) 1^ 0^ 1 0 + (0.7080240981,0) '''
# note, first run 'python3 -m xacc --benchmark-install chemistry' hamiltonianService = xacc.serviceRegistry.get_service('hamiltonian_generator', 'xaccKernelH2') obs = hamiltonianService.generate({}) # Create the UCC-1 ansatz ansatzService = xacc.serviceRegistry.get_service('ansatz_generator', 'ucc1') ucc1 = ansatzService.generate({'x-gates': [0, 1]}, 4) # Create the RDM Purification decorator error mitigation strategy # and give it the fermionic representation qpu_decorator = xacc.getAcceleratorDecorator('rdm-purification', qpu) qpu_decorator.initialize({'fermion-observable': obs}) # Let's use the NLOpt optimizer opt = xacc.getOptimizer('nlopt') # Create the VQE algorithm vqe = xacc.getAlgorithm( 'vqe', { 'ansatz': ucc1, 'accelerator': qpu_decorator, 'observable': obs, 'optimizer': opt }) # Execute vqe.execute(qbits) # qbits buffer has all results, print(qbits) # to see it all
import xacc # Get the QPU and allocate a single qubit qpu = xacc.getAccelerator('qpp') qbits = xacc.qalloc(2) # Get the MLPack Optimizer, default is Adam optimizer = xacc.getOptimizer( 'mlpack', {'initial-parameters': [0., 0., 0., 0., 0., 0., 0., 0.]}) xacc.qasm(''' .compiler xasm .circuit qubit2_depth1 .parameters x .qbit q U(q[0], x[0], -pi/2, pi/2 ); U(q[0], 0, 0, x[1]); U(q[1], x[2], -pi/2, pi/2); U(q[1], 0, 0, x[3]); CNOT(q[0], q[1]); U(q[0], 0, 0, x[4]); U(q[0], x[5], -pi/2, pi/2); U(q[1], 0, 0, x[6]); U(q[1], x[7], -pi/2, pi/2); ''') f = xacc.getCompiled('qubit2_depth1') # Get the DDCL Algorithm, initialize it # with necessary parameters ddcl = xacc.getAlgorithm(
import xacc def rosen(x): xx = (1. - x[0])**2 + 100 * (x[1] - x[0]**2)**2 return xx def rosen_with_grad(x): g = [ -2 * (1 - x[0]) + 400. * (x[0]**3 - x[1] * x[0]), 200 * (x[1] - x[0]**2) ] xx = (1. - x[0])**2 + 100 * (x[1] - x[0]**2)**2 return xx, g optimizer = xacc.getOptimizer('mlpack', {'mlpack-optimizer': 'l-bfgs'}) r, p = optimizer.optimize(rosen_with_grad, 2) print('Result = ', r, p) # cobyla = xacc.getOptimizer('nlopt',{ 'nlopt-optimizer':'cobyla', 'nlopt-maxeval':500}) # print('Result = ', result)
def execute(self, inputParams): xacc_opts = inputParams['XACC'] acc_name = xacc_opts['accelerator'] qpu = xacc.getAccelerator(acc_name, xacc_opts) if 'verbose' in xacc_opts and xacc_opts['verbose']: xacc.set_verbose(True) if 'Benchmark' not in inputParams: xacc.error('Invalid benchmark input - must have Benchmark description') if 'Observable' not in inputParams: xacc.error('Invalid benchmark input - must have Observable description') if 'Ansatz' not in inputParams: xacc.error('Invalid benchmark input - must have Ansatz circuit description') if 'Decorators' in inputParams: if 'readout_error' in inputParams['Decorators']: qpu = xacc.getAcceleratorDecorator('ro-error', qpu) H = None if inputParams['Observable']['name'] == 'pauli': obs_str = inputParams['Observable']['obs_str'] H = xacc.getObservable('pauli', obs_str) elif inputParams['Observable']['name'] == 'fermion': obs_str = inputParams['Observable']['obs_str'] H = xacc.getObservable('fermion', obs_str) elif inputParams['Observable']['name'] == 'psi4': opts = {'basis':inputParams['Observable']['basis'], 'geometry':inputParams['Observable']['geometry']} if 'fo' in inputParams['Observable'] and 'ao' in inputParams['Observable']: opts['frozen-spin-orbitals'] = ast.literal_eval(inputParams['Observable']['fo']) opts['active-spin-orbitals'] = ast.literal_eval(inputParams['Observable']['ao']) H = xacc.getObservable('psi4', opts) #print('Ham: ', H.toString()) buffer = xacc.qalloc(H.nBits()) optimizer = None if 'Optimizer' in inputParams: # check that values that can be ints/floats are opts = inputParams['Optimizer'] for k,v in inputParams['Optimizer'].items(): try: i = int(v) opts[k] = i continue except: pass try: f = float(v) opts[k] = f continue except: pass optimizer = xacc.getOptimizer(inputParams['Optimizer']['name'] if 'Optimizer' in inputParams else 'nlopt', opts) else: optimizer = xacc.getOptimizer('nlopt') provider = xacc.getIRProvider('quantum') if 'source' in inputParams['Ansatz']: # here assume this is xasm always src = inputParams['Ansatz']['source'] xacc.qasm(src) # get the name of the circuit circuit_name = None for l in src.split('\n'): if '.circuit' in l: circuit_name = l.split(' ')[1] ansatz = xacc.getCompiled(circuit_name) else: ansatz = provider.createInstruction(inputParams['Ansatz']['ansatz']) ansatz = xacc.asComposite(ansatz) alg = xacc.getAlgorithm(inputParams['Benchmark']['algorithm'], { 'ansatz': ansatz, 'accelerator': qpu, 'observable': H, 'optimizer': optimizer, }) alg.execute(buffer) return buffer
def execute(self, inputParams): """ This method is intended to be inherited by vqe and vqe_energy subclasses to allow algorithm-specific implementation. This superclass method adds extra information to the buffer and allows XACC settings options to be set before executing VQE. Parameters: inputParams : dictionary a dictionary of input parameters obtained from .ini file return QPU Accelerator buffer Options used (obtained from inputParams): 'qubit-map': map of logical qubits to physical qubits 'n-execs': number of sampler executions of measurements 'initial-parameters': list of initial parameters for the VQE algorithm 'restart-from-file': AcceleratorDecorator option to allow restart of VQE algorithm 'readout-error': AcceleratorDecorator option for readout-error mitigation """ m = xacc.HeterogeneousMap() if 'shots' in inputParams: m.insert('shots', int(inputParams['shots'])) if 'backend' in inputParams: m.insert('backend', inputParams['backend']) self.qpu = xacc.getAccelerator(inputParams['accelerator'], m) xaccOp = self.hamiltonian_generators[ inputParams['hamiltonian-generator']].generate(inputParams) self.ansatz = self.ansatz_generators[inputParams['name']].generate( inputParams, xaccOp.nBits()) if 'qubit-map' in inputParams: qubit_map = ast.literal_eval(inputParams['qubit-map']) xaccOp, self.ansatz, n_qubits = xaccvqe.mapToPhysicalQubits( xaccOp, self.ansatz, qubit_map) else: n_qubits = xaccOp.nBits() self.op = xaccOp self.n_qubits = n_qubits # create buffer, add some extra info (hamiltonian, ansatz-qasm, python-ansatz-qasm) self.buffer = xacc.qalloc(n_qubits) self.buffer.addExtraInfo('hamiltonian', self.op.toString()) self.buffer.addExtraInfo( 'ansatz-qasm', self.ansatz.toString().replace('\\n', '\\\\n')) pycompiler = xacc.getCompiler('pyxasm') # self.buffer.addExtraInfo('ansatz-qasm-py', '\n'.join(pycompiler.translate(self.ansatz).split('\n')[1:])) # heres where we can set up the algorithm Parameters # all versions of vqe require: Accelerator, Ansatz, Observable # pure-vqe requires Optimizer # energy calculation has optional Parameters - can be random self.vqe_options_dict = { 'accelerator': self.qpu, 'ansatz': self.ansatz, 'observable': self.op } # get optimizers for VQE # needs to check if optimizer is a python plugin # if not, use nlopt (with options) # so we pull 'optimizer-options' out if available # Optimizer-options needs to be passed to BOTH XACC Core optimizers and to python plugins # vqe_options_dict is used to initialize the algorithms self.optimizer = None self.optimizer_options = {} if 'optimizer-options' in inputParams: self.optimizer_options = ast.literal_eval( inputParams['optimizer-options']) # initial-parameters for optimizer (vqe) # parameters for vqe-energy if 'initial-parameters' in inputParams: self.optimizer_options['initial-parameters'] = ast.literal_eval( inputParams['initial-parameters']) if 'parameters' in inputParams: self.optimizer_options['parameters'] = ast.literal_eval( inputParams['parameters']) if 'nlopt-maxeval' in inputParams: self.optimizer_options['nlopt-maxeval'] = int( inputParams['nlopt-maxeval']) # check to see if optimizer is a python plugin # if it is, we do not put it in self.vqe_options_dict # if it is not, it is put there if 'optimizer' in inputParams: if inputParams['optimizer'] in self.vqe_optimizers: self.optimizer = self.vqe_optimizers[inputParams['optimizer']] else: self.optimizer = xacc.getOptimizer(inputParams['optimizer'], self.optimizer_options) else: self.optimizer = xacc.getOptimizer('nlopt', self.optimizer_options) # vqe.py then will check vqe_options_dict for optimizer; if it isn't there, run python optimizer # and of course if it is, we run with XACC self.buffer.addExtraInfo('accelerator', inputParams['accelerator']) # need to make sure the AcceleratorDecorators work correctly if 'n-execs' in inputParams: xacc.setOption('sampler-n-execs', inputParams['n-execs']) self.qpu = xacc.getAcceleratorDecorator('improved-sampling', self.qpu) if 'restart-from-file' in inputParams: xacc.setOption('vqe-restart-file', inputParams['restart-from-file']) self.qpu = xacc.getAcceleratorDecorator('vqe-restart', self.qpu) self.qpu.initialize() if 'readout-error' in inputParams and inputParams['readout-error']: self.qpu = xacc.getAcceleratorDecorator('ro-error', self.qpu) if 'rdm-purification' in inputParams and inputParams[ 'rdm-purification']: print("setting RDM Purification") self.qpu = xacc.getAcceleratorDecorator('rdm-purification', self.qpu) m = xacc.HeterogeneousMap() m.insert('fermion-observable', self.op) self.qpu.initialize(m) self.vqe_options_dict = { 'optimizer': self.optimizer, 'accelerator': self.qpu, 'ansatz': self.ansatz, 'observable': self.op } xacc.setOptions(inputParams)
# There are 7 gamma terms (non-identity) in the cost Hamiltonian # and 4 beta terms for mixer Hamiltonian nbParamsPerStep = 7 + 4 # The number of steps (often referred to as 'p' parameter): # alternating layers of mixer and cost Hamiltonian exponential. nbSteps = 4 # Total number of params nbTotalParams = nbParamsPerStep * nbSteps # Init params randomly: initParams = np.random.rand(nbTotalParams) # The optimizer: nlopt opt = xacc.getOptimizer('nlopt', {'initial-parameters': initParams}) # Create the QAOA algorithm qaoa = xacc.getAlgorithm('QAOA', { 'accelerator': qpu, 'observable': ham, 'optimizer': opt, 'steps': nbSteps }) result = qaoa.execute(buffer) # Expected result: ~ -11 # Ref: https://docs.entropicalabs.io/qaoa/notebooks/6_solvingqubowithqaoa print('Min QUBO value = ', buffer.getInformation('opt-val'))
# Use GOAT optimizer: # Assuming this is a rotating frame Hamiltonian in the most simple form: # H = Signal(t) * X, # where Signal(t) is the pulse to optimize. optimizer = xacc.getOptimizer( "quantum-control", { # Optimization method "method": "GOAT", # System dimension, i.e. number of qubits "dimension": 1, # Target unitary "target-U": sqrtX, # Control parameter (used in the control function) "control-params": ["amp", "sigma"], # Math expression of the pulse envelop (since GOAT is an analytical method) "control-funcs": ["amp*exp(-(t - 300.0)^2/(2*sigma^2))"], # The list of Hamiltonian terms that are modulated by the control functions # Note: this amplitude value is *estimated* from running experiments # on the armonk device. This can be changed due to backend calibration. "control-H": ["0.03329289102 X0"], # Initial params "initial-parameters": initParams, # Time horizon "max-time": 600.0 }) # The optimization will return the final fidelity error, # and the set of optimized parameters, # which, in this case, only contains a single 'sigma' param. finalFidelityError, paramValues = optimizer.optimize()
import xacc import numpy as np qpu = xacc.getAccelerator('qpp') ham = xacc.getObservable('pauli', '-5.0 - 0.5 Z0 + 1.0 Z0Z1') nbQubits = 2 steps = 1 buffer = xacc.qalloc(nbQubits) nbTotalParams = 4 # The optimizer: nlopt opt = xacc.getOptimizer('nlopt', { 'initial-parameters': np.random.rand(nbTotalParams)} ) # Create the QAOA algorithm qaoa = xacc.getAlgorithm('QAOA', { 'accelerator': qpu, 'observable': ham, 'optimizer': opt, 'steps': steps, 'parameter-scheme': 'Extend'}) # Run result = qaoa.execute(buffer) print('Min value = ', buffer.getInformation('opt-val')) print('Opt-params = ', buffer.getInformation('opt-params')) # Get the circuit qaoa_ansatz_std = xacc.createComposite('qaoa') qaoa_ansatz_std.expand({'nbQubits': nbQubits, 'nbSteps': steps, 'cost-ham': ham, 'parameter-scheme':'Extend'}) print('Extend parameterized QAOA circuit:') print(qaoa_ansatz_std)
sqrtX[1][1] = 0.5 + 1j * 0.5 # Use GOAT optimizer: # Assuming this is a rotating frame Hamiltonian in the most simple form: # H = Signal(t) * X, # where Signal(t) is the pulse to optimize. optimizer = xacc.getOptimizer( "quantum-control", { # Optimization method "method": "GOAT", # System dimension, i.e. number of qubits "dimension": 1, # Target unitary "target-U": sqrtX, # Control parameter (used in the control function) "control-params": ["sigma"], # Math expression of the pulse envelop (since GOAT is an analytical method) "control-funcs": ["0.062831853*exp(-t^2/(2*sigma^2))"], # The list of Hamiltonian terms that are modulated by the control functions "control-H": ["X0"], # Initial params "initial-parameters": initParams, # Time horizon "max-time": 100.0 }) # The optimization will return the final fidelity error, # and the set of optimized parameters, # which, in this case, only contains a single 'sigma' param. finalFidelityError, paramValues = optimizer.optimize() print("Optimal sigma = ", paramValues[0])
import xacc # xacc.set_verbose(True) # Get the QPU and allocate a single qubit qpu = xacc.getAccelerator('aer') qbits = xacc.qalloc(1) # Get the MLPack Optimizer, default is Adam optimizer = xacc.getOptimizer('mlpack') # Create a simple quantum program xacc.qasm(''' .compiler xasm .circuit foo .parameters x,y,z .qbit q Ry(q[0], x); Ry(q[0], y); Ry(q[0], z); ''') f = xacc.getCompiled('foo') f.defaultPlacement(qpu, {'qubit-map': [0]}) print(f.toString()) # exit(0) # Get the DDCL Algorithm, initialize it # with necessary parameters ddcl = xacc.getAlgorithm( 'ddcl', { 'ansatz': f, 'accelerator': qpu,
# and 4 beta terms for mixer Hamiltonian nbParamsPerStep = 7 + 4 # The number of steps (often referred to as 'p' parameter): # alternating layers of mixer and cost Hamiltonian exponential. nbSteps = 4 # Total number of params nbTotalParams = nbParamsPerStep * nbSteps # Init params randomly: initParams = np.random.rand(nbTotalParams) # The optimizer: nlopt opt = xacc.getOptimizer('nlopt', { 'initial-parameters': initParams, 'nlopt-optimizer': 'l-bfgs' }) # Create the QAOA algorithm qaoa = xacc.getAlgorithm( 'QAOA', { 'accelerator': qpu, 'observable': ham, 'optimizer': opt, 'steps': nbSteps, 'gradient_strategy': 'parameter-shift-gradient' }) result = qaoa.execute(buffer) # Expected result: ~ -11
import xacc import numpy as np def rosen(x, args): xx = (1. - x[0])**2 + 100 * (x[1] - x[0]**2)**2 return xx optimizer = xacc.getOptimizer( 'pycma', { 'tolx': 1e-12, 'AdaptSigma': True, 'CMA_elitist': True, 'popsize': 4 + np.floor(2 * np.log(2)) }) f = xacc.OptFunction(rosen, 2) r, p = optimizer.optimize(f) print('Result = ', r, p)