def execute(self, circuit, **options): """ Execute sympy-circuit with classical simulator We use numpy simulator as default @param circuit sympy object to simulate """ qasm = self.to_qasm(circuit) if (not self.parallel): self.simulator = CythonSimulator() else: self.simulator = CythonOmpSimulator() try: basis_gates_str = (",".join(self.simulator.basis_gates)).lower() except: basis_gates_str = "cx,m0,m1" #print(basis_gates_str) # the following one-line compilation ignores basis_gates, and returnes "u2" for "h". #json = openquantumcompiler.compile(qasm,basis_gates=basis_gates_str,format="json") circuit_dag = openquantumcompiler.compile(qasm, basis_gates=basis_gates_str) json = openquantumcompiler.dag2json(circuit_dag, basis_gates=basis_gates_str) self.simulate(json) return self.simulator
def _create_qobj(self, circuits, circuit_config, backend, seed, resources, shots, do_compile): # local and remote backends currently need different # compilied circuit formats formatted_circuits = [] if do_compile: for circuit in circuits: formatted_circuits.append(None) else: if backend in backends.local_backends(): for circuit in self.circuits: formatted_circuits.append( openquantumcompiler.dag2json(circuit)) else: for circuit in self.circuits: formatted_circuits.append(circuit.qasm(qeflag=True)) # create circuit component of qobj circuit_records = [] if circuit_config is None: config = { 'coupling_map': None, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': seed } circuit_config = [config] * len(self.circuits) for circuit, fcircuit, name, config in zip(self.circuits, formatted_circuits, self.names, circuit_config): record = { 'name': name, 'compiled_circuit': None if do_compile else fcircuit, 'compiled_circuit_qasm': None if do_compile else fcircuit, 'circuit': circuit, 'config': config } circuit_records.append(record) return { 'id': self._generate_job_id(length=10), 'config': { 'max_credits': resources['max_credits'], 'shots': shots, 'backend': backend }, 'circuits': circuit_records }
def run_local_simulator(qobj): """Run a program of compiled quantum circuits on the local machine. Args: qobj (dict): quantum object dictionary Returns: Dictionary of form, job_result = { "status": DATA, "result" : [ { "data": DATA, "status": DATA, }, ... ] "name": DATA, "backend": DATA } """ job_result = { 'status': '', 'result': [], 'name': qobj['id'], 'backend': qobj['config']['backend'] } for job in qobj['circuits']: if job['compiled_circuit'] is None: compiled_circuit = openquantumcompiler.compile(job['circuit']) job['compiled_circuit'] = openquantumcompiler.dag2json( compiled_circuit) sim_job = { 'compiled_circuit': job['compiled_circuit'], 'config': { **job['config'], **qobj['config'] } } local_simulator = simulators.LocalSimulator(qobj['config']['backend'], sim_job) local_simulator.run() job_result['result'].append(local_simulator.result()) job_result['status'] = 'COMPLETED' job_result['name'] = qobj['id'] job_result['backend'] = qobj['config']['backend'] return job_result
def _create_qobj(self, circuits, circuit_config, backend, seed, resources, shots, do_compile): # local and remote backends currently need different # compilied circuit formats formatted_circuits = [] if do_compile: for circuit in circuits: formatted_circuits.append(None) else: if backend in backends.local_backends(): for circuit in self.circuits: formatted_circuits.append(openquantumcompiler.dag2json(circuit)) else: for circuit in self.circuits: formatted_circuits.append(circuit.qasm(qeflag=True)) # create circuit component of qobj circuit_records = [] if circuit_config is None: config = {'coupling_map': None, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': seed} circuit_config = [config] * len(self.circuits) for circuit, fcircuit, name, config in zip(self.circuits, formatted_circuits, self.names, circuit_config): record = { 'name': name, 'compiled_circuit': None if do_compile else fcircuit, 'compiled_circuit_qasm': None if do_compile else fcircuit, 'circuit': circuit, 'config': config } circuit_records.append(record) return {'id': self._generate_job_id(length=10), 'config': { 'max_credits': resources['max_credits'], 'shots': shots, 'backend': backend }, 'circuits': circuit_records}
def __init__(self, data=None, file=None, backendName="cpu", verbose=False, APIToken=None): backends = [ QasmBackendGpu, QasmBackendCpu, QasmBackendCython, QasmBackendCythonOmp, QasmBackendIbmqx ] backendNames = dict([(sim.name, sim) for sim in backends]) backendBasisGates = dict([(sim.name, sim.basisGates) for sim in backends]) if (data is None and file is None): raise Exception("data or file is required") if (data is not None and file is not None): raise Exception("data or file is required") if (data is not None): text = data else: try: text = open(file).read() except: raise Exception("file not found") if (backendName not in backendNames): raise Exception("unknown backends : choose among " + str(backendNames.keys())) basisGates = backendBasisGates[backendName] circuit_dag = openquantumcompiler.compile(text, basis_gates=basisGates) circuit_json = openquantumcompiler.dag2json(circuit_dag, basis_gates=basisGates) self.backendName = backendName self.qasmtxt = circuit_dag.qasm(qeflag=True) self.circuit = circuit_json self.backend = backendNames[backendName] self.verbose = verbose self.APIToken = APIToken
def _compose_qobj(qobj_name, test_circuits, backend="local_qasm_simulator", config=None, basis_gates='u1,u2,u3,id,cx', shots=1, max_credits=3, seed=None): qobj_out = { "id": qobj_name + "_test_circuits", "config": config, "circuits": [] } qobj_out["config"] = { "max_credits": max_credits, "backend": backend, "seed": seed, "shots": shots } for name, circuit in test_circuits.items(): # only add the job if there was no error in generating the circuit if circuit["dag_" + qobj_name] is not None: job = {} job["name"] = name # config parameters used by the runner if config is None: config = {} # default to empty config dict job["config"] = copy.deepcopy(config) job["config"]["basis_gates"] = basis_gates job["config"]["seed"] = seed # Add circuit dag_circuit = copy.deepcopy(circuit["dag_" + qobj_name]) job["compiled_circuit"] = dag2json(dag_circuit, basis_gates=basis_gates) job["compiled_circuit_qasm"] = dag_circuit.qasm(qeflag=True) qobj_out["circuits"].append(copy.deepcopy(job)) return qobj_out
def run_local_simulator(qobj): """Run a program of compiled quantum circuits on the local machine. Args: qobj (dict): quantum object dictionary Returns: Dictionary of form, job_result = { "status": DATA, "result" : [ { "data": DATA, "status": DATA, }, ... ] "name": DATA, "backend": DATA } """ job_result = {'status': '', 'result': [], 'name': qobj['id'], 'backend': qobj['config']['backend']} for job in qobj['circuits']: if job['compiled_circuit'] is None: compiled_circuit = openquantumcompiler.compile(job['circuit']) job['compiled_circuit'] = openquantumcompiler.dag2json(compiled_circuit) sim_job = {'compiled_circuit': job['compiled_circuit'], 'config': {**job['config'], **qobj['config']}} local_simulator = simulators.LocalSimulator( qobj['config']['backend'], sim_job) local_simulator.run() job_result['result'].append(local_simulator.result()) job_result['status'] = 'COMPLETED' job_result['name'] = qobj['id'] job_result['backend'] = qobj['config']['backend'] return job_result
def __init__(self, circuits, backend='local_qasm_simulator', circuit_configs=None, timeout=60, seed=None, resources={'max_credits': 3}, shots=1024, names=None, doCompile=False, preformatted=False): """ Args: circuit (QuantumCircuit | qobj): QuantumCircuit or list of QuantumCircuit objects for job. backend (str): the backend to run the circuit on. resources (dict): resource requirements of job. timeout (float): timeout for job in seconds. coupling_map (dict): A directed graph of coupling:: { control(int): [ target1(int), target2(int), , ... ], ... } eg. {0: [2], 1: [2], 3: [2]} initial_layout (dict): A mapping of qubit to qubit:: { ("q", strart(int)): ("q", final(int)), ... } eg. { ("q", 0): ("q", 0), ("q", 1): ("q", 1), ("q", 2): ("q", 2), ("q", 3): ("q", 3) } shots (int): the number of shots max_credits (int): the max credits to use 3, or 5 seed (int): the intial seed the simulatros use circuit_type (str): "compiled_dag" or "uncompiled_dag" or "quantum_circuit" preformated (bool): the objects in circuits are already compiled and formatted (qasm for online, json for local). If true the parameters "names" and "circuit_configs" must also be defined of the same length as "circuits". """ if isinstance(circuits, list): self.circuits = circuits else: self.circuits = [circuits] if names is None: self.names = [] for circuit in range(len(self.circuits)): self.names.append( ''.join([random.choice(string.ascii_letters + string.digits) for i in range(10)])) elif isinstance(names, list): self.names = names else: self.names = [names] self._local_backends = local_backends() self.timeout = timeout # check whether circuits have already been compiled # and formatted for backend. if preformatted: self.qobj = circuits self.backend = self.qobj['config']['backend'] self.resources = {'max_credits': self.qobj['config']['max_credits']} else: self.backend = backend self.resources = resources # local and remote backends currently need different # compilied circuit formats formatted_circuits = [] if doCompile: for circuit in self.circuits: formatted_circuits.append(None) else: if backend in self._local_backends: for circuit in self.circuits: formatted_circuits.append(openquantumcompiler.dag2json(circuit)) else: for circuit in self.circuits: formatted_circuits.append(circuit.qasm(qeflag=True)) # create circuit component of qobj circuitRecords = [] if circuit_configs is None: config = {'coupling_map': None, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': seed} circuit_configs = [config] * len(self.circuits) for circuit, fcircuit, name, config in zip(self.circuits, formatted_circuits, self.names, circuit_configs): record = { 'name': name, 'compiled_circuit': None if doCompile else fcircuit, 'compiled_circuit_qasm': None if doCompile else fcircuit, 'circuit': circuit, 'config': config } circuitRecords.append(record) qobjid = ''.join([random.choice( string.ascii_letters + string.digits) for i in range(10)]) self.qobj = {'id': qobjid, 'config': { 'max_credits': resources['max_credits'], 'shots': shots, 'backend': backend }, 'circuits': circuitRecords } self.seed = seed self.result = None self.doCompile = doCompile
def __init__(self, circuits, backend='local_qasm_simulator', circuit_configs=None, timeout=60, seed=None, resources={'max_credits': 3}, shots=1024, names=None, doCompile=False, preformatted=False): """ Args: circuit (QuantumCircuit | qobj): QuantumCircuit or list of QuantumCircuit objects for job. backend (str): the backend to run the circuit on. resources (dict): resource requirements of job. timeout (float): timeout for job in seconds. coupling_map (dict): A directed graph of coupling:: { control(int): [ target1(int), target2(int), , ... ], ... } eg. {0: [2], 1: [2], 3: [2]} initial_layout (dict): A mapping of qubit to qubit:: { ("q", strart(int)): ("q", final(int)), ... } eg. { ("q", 0): ("q", 0), ("q", 1): ("q", 1), ("q", 2): ("q", 2), ("q", 3): ("q", 3) } shots (int): the number of shots max_credits (int): the max credits to use 3, or 5 seed (int): the intial seed the simulatros use circuit_type (str): "compiled_dag" or "uncompiled_dag" or "quantum_circuit" preformated (bool): the objects in circuits are already compiled and formatted (qasm for online, json for local). If true the parameters "names" and "circuit_configs" must also be defined of the same length as "circuits". """ if isinstance(circuits, list): self.circuits = circuits else: self.circuits = [circuits] if names is None: self.names = [] for circuit in range(len(self.circuits)): self.names.append(''.join([ random.choice(string.ascii_letters + string.digits) for i in range(10) ])) elif isinstance(names, list): self.names = names else: self.names = [names] self._local_backends = local_backends() self.timeout = timeout # check whether circuits have already been compiled # and formatted for backend. if preformatted: self.qobj = circuits self.backend = self.qobj['config']['backend'] self.resources = { 'max_credits': self.qobj['config']['max_credits'] } else: self.backend = backend self.resources = resources # local and remote backends currently need different # compilied circuit formats formatted_circuits = [] if doCompile: for circuit in self.circuits: formatted_circuits.append(None) else: if backend in self._local_backends: for circuit in self.circuits: formatted_circuits.append( openquantumcompiler.dag2json(circuit)) else: for circuit in self.circuits: formatted_circuits.append(circuit.qasm(qeflag=True)) # create circuit component of qobj circuitRecords = [] if circuit_configs is None: config = { 'coupling_map': None, 'basis_gates': 'u1,u2,u3,cx,id', 'layout': None, 'seed': seed } circuit_configs = [config] * len(self.circuits) for circuit, fcircuit, name, config in zip(self.circuits, formatted_circuits, self.names, circuit_configs): record = { 'name': name, 'compiled_circuit': None if doCompile else fcircuit, 'compiled_circuit_qasm': None if doCompile else fcircuit, 'circuit': circuit, 'config': config } circuitRecords.append(record) qobjid = ''.join([ random.choice(string.ascii_letters + string.digits) for i in range(10) ]) self.qobj = { 'id': qobjid, 'config': { 'max_credits': resources['max_credits'], 'shots': shots, 'backend': backend }, 'circuits': circuitRecords } self.seed = seed self.result = None self.doCompile = doCompile
def compile(self, name_of_circuits, backend="local_qasm_simulator", config=None, silent=True, basis_gates=None, coupling_map=None, initial_layout=None, shots=1024, max_credits=3, seed=None, qobj_id=None): """Compile the circuits into the exectution list. This builds the internal "to execute" list which is list of quantum circuits to run on different backends. Args: name_of_circuits (list[str]): circuit names to be compiled. backend (str): a string representing the backend to compile to config (dict): a dictionary of configurations parameters for the compiler silent (bool): is an option to print out the compiling information or not basis_gates (str): a comma seperated string and are the base gates, which by default are: u1,u2,u3,cx,id coupling_map (dict): A directed graph of coupling:: { control(int): [ target1(int), target2(int), , ... ], ... } eg. {0: [2], 1: [2], 3: [2]} initial_layout (dict): A mapping of qubit to qubit:: { ("q", strart(int)): ("q", final(int)), ... } eg. { ("q", 0): ("q", 0), ("q", 1): ("q", 1), ("q", 2): ("q", 2), ("q", 3): ("q", 3) } shots (int): the number of shots max_credits (int): the max credits to use 3, or 5 seed (int): the intial seed the simulatros use Returns: the job id and populates the qobj:: qobj = { id: --job id (string), config: -- dictionary of config settings (dict)--, { "max_credits" (online only): -- credits (int) --, "shots": -- number of shots (int) --. "backend": -- backend name (str) -- } circuits: [ { "name": --circuit name (string)--, "compiled_circuit": --compiled quantum circuit (JSON format)--, "compiled_circuit_qasm": --compiled quantum circuit (QASM format)--, "config": --dictionary of additional config settings (dict)--, { "coupling_map": --adjacency list (dict)--, "basis_gates": --comma separated gate names (string)--, "layout": --layout computed by mapper (dict)--, "seed": (simulator only)--initial seed for the simulator (int)--, } }, ... ] } """ # TODO: Jay: currently basis_gates, coupling_map, initial_layout, # shots, max_credits and seed are extra inputs but I would like # them to go into the config. qobj = {} if not qobj_id: qobj_id = "".join([random.choice(string.ascii_letters+string.digits) for n in range(30)]) qobj['id'] = qobj_id qobj["config"] = {"max_credits": max_credits, 'backend': backend, "shots": shots} qobj["circuits"] = [] if not name_of_circuits: raise ValueError('"name_of_circuits" must be specified') if isinstance(name_of_circuits, str): name_of_circuits = [name_of_circuits] for name in name_of_circuits: if name not in self.__quantum_program: raise QISKitError('circuit "{0}" not found in program'.format(name)) if not basis_gates: basis_gates = "u1,u2,u3,cx,id" # QE target basis # TODO: The circuit object going into this is to have .qasm() method (be careful) circuit = self.__quantum_program[name] dag_circuit, final_layout = openquantumcompiler.compile(circuit.qasm(), basis_gates=basis_gates, coupling_map=coupling_map, initial_layout=initial_layout, silent=silent, get_layout=True) # making the job to be added to qobj job = {} job["name"] = name # config parameters used by the runner if config is None: config = {} # default to empty config dict job["config"] = config # TODO: Jay: make config options optional for different backends job["config"]["coupling_map"] = mapper.coupling_dict2list(coupling_map) # Map the layout to a format that can be json encoded list_layout = None if final_layout: list_layout = [[k, v] for k, v in final_layout.items()] job["config"]["layout"] = list_layout job["config"]["basis_gates"] = basis_gates if seed is None: job["config"]["seed"] = None else: job["config"]["seed"] = seed # the compiled circuit to be run saved as a dag job["compiled_circuit"] = openquantumcompiler.dag2json(dag_circuit, basis_gates=basis_gates) job["compiled_circuit_qasm"] = dag_circuit.qasm(qeflag=True) # add job to the qobj qobj["circuits"].append(job) return qobj
def compile(self, name_of_circuits, backend="local_qasm_simulator", config=None, silent=True, basis_gates=None, coupling_map=None, initial_layout=None, shots=1024, max_credits=3, seed=None, qobj_id=None): """Compile the circuits into the exectution list. This builds the internal "to execute" list which is list of quantum circuits to run on different backends. Args: name_of_circuits (list[str]): circuit names to be compiled. backend (str): a string representing the backend to compile to config (dict): a dictionary of configurations parameters for the compiler silent (bool): is an option to print out the compiling information or not basis_gates (str): a comma seperated string and are the base gates, which by default are: u1,u2,u3,cx,id coupling_map (dict): A directed graph of coupling:: { control(int): [ target1(int), target2(int), , ... ], ... } eg. {0: [2], 1: [2], 3: [2]} initial_layout (dict): A mapping of qubit to qubit:: { ("q", strart(int)): ("q", final(int)), ... } eg. { ("q", 0): ("q", 0), ("q", 1): ("q", 1), ("q", 2): ("q", 2), ("q", 3): ("q", 3) } shots (int): the number of shots max_credits (int): the max credits to use 3, or 5 seed (int): the intial seed the simulatros use Returns: the job id and populates the qobj:: qobj = { id: --job id (string), config: -- dictionary of config settings (dict)--, { "max_credits" (online only): -- credits (int) --, "shots": -- number of shots (int) --. "backend": -- backend name (str) -- } circuits: [ { "name": --circuit name (string)--, "compiled_circuit": --compiled quantum circuit (JSON format)--, "compiled_circuit_qasm": --compiled quantum circuit (QASM format)--, "config": --dictionary of additional config settings (dict)--, { "coupling_map": --adjacency list (dict)--, "basis_gates": --comma separated gate names (string)--, "layout": --layout computed by mapper (dict)--, "seed": (simulator only)--initial seed for the simulator (int)--, } }, ... ] } """ # TODO: Jay: currently basis_gates, coupling_map, initial_layout, # shots, max_credits and seed are extra inputs but I would like # them to go into the config. qobj = {} if not qobj_id: qobj_id = "".join([random.choice(string.ascii_letters+string.digits) for n in range(30)]) qobj['id'] = qobj_id qobj["config"] = {"max_credits": max_credits, 'backend': backend, "shots": shots} qobj["circuits"] = [] if not name_of_circuits: raise ValueError('"name_of_circuits" must be specified') if isinstance(name_of_circuits, str): name_of_circuits = [name_of_circuits] for name in name_of_circuits: if name not in self.__quantum_program: raise QISKitError('circuit "{0}" not found in program'.format(name)) if not basis_gates: basis_gates = "u1,u2,u3,cx,id" # QE target basis # TODO: The circuit object going into this is to have .qasm() method (be careful) circuit = self.__quantum_program[name] dag_circuit, final_layout = openquantumcompiler.compile(circuit.qasm(), basis_gates=basis_gates, coupling_map=coupling_map, initial_layout=initial_layout, silent=silent, get_layout=True) # making the job to be added to qobj job = {} job["name"] = name # config parameters used by the runner if config is None: config = {} # default to empty config dict job["config"] = config # TODO: Jay: make config options optional for different backends job["config"]["coupling_map"] = mapper.coupling_dict2list(coupling_map) # Map the layout to a format that can be json encoded list_layout = None if final_layout: list_layout = [[k, v] for k, v in final_layout.items()] job["config"]["layout"] = list_layout job["config"]["basis_gates"] = basis_gates if seed is None: job["config"]["seed"] = None else: job["config"]["seed"] = seed # the compiled circuit to be run saved as a dag job["compiled_circuit"] = openquantumcompiler.dag2json(dag_circuit, basis_gates=basis_gates) job["compiled_circuit_qasm"] = dag_circuit.qasm(qeflag=True) # add job to the qobj qobj["circuits"].append(job) return qobj