Пример #1
0
 def test_api_auth_token(self):
     '''
     Authentication with Quantum Experience Platform
     '''
     api = IBMQuantumExperience(API_TOKEN)
     credential = api.check_credentials()
     self.assertTrue(credential)
Пример #2
0
 def test_api_devices_availables(self):
     '''
     Check the devices availables
     '''
     api = IBMQuantumExperience(API_TOKEN)
     devices = api.available_devices()
     self.assertGreaterEqual(len(devices), 2)
Пример #3
0
 def test_api_device_parameters(self):
     '''
     Check the parameters of calibration of a real chip
     '''
     api = IBMQuantumExperience(API_TOKEN)
     parameters = api.device_parameters()
     self.assertIsNotNone(parameters)
Пример #4
0
 def test_api_device_status(self):
     '''
     Check the status of a real chip
     '''
     api = IBMQuantumExperience(API_TOKEN)
     is_available = api.device_status()
     self.assertIsNotNone(is_available)
Пример #5
0
 def test_api_device_calibration(self):
     '''
     Check the calibration of a real chip
     '''
     api = IBMQuantumExperience(API_TOKEN)
     calibration = api.device_calibration()
     self.assertIsNotNone(calibration)
Пример #6
0
 def test_api_backend_simulators_available(self):
     '''
     Check the backend simulators available
     '''
     api = IBMQuantumExperience(API_TOKEN)
     backends = api.available_backend_simulators()
     self.assertGreaterEqual(len(backends), 1)
Пример #7
0
 def test_api_get_jobs(self):
     '''
     Check get jobs by user authenticated
     '''
     api = IBMQuantumExperience(API_TOKEN)
     jobs = api.get_jobs(2)
     self.assertEqual(len(jobs), 2)
Пример #8
0
 def test_api_backends_availables(self):
     '''
     Check the backends availables
     '''
     api = IBMQuantumExperience(API_TOKEN)
     backends = api.available_backends()
     self.assertGreaterEqual(len(backends), 2)
Пример #9
0
    def _setup_api(self, token, url):
        try:
            self.__api = IBMQuantumExperience(token, {"url": url})
            return True
        except BaseException:
            print('---- Error: Exception connect to servers ----')

            return False
Пример #10
0
 def test_api_run_job(self):
     '''
     Check run an job by user authenticated
     '''
     api = IBMQuantumExperience(API_TOKEN)
     device = 'simulator'
     shots = 1
     job = api.run_job(qasms, device, shots)
     self.assertIsNotNone(job['status'])
Пример #11
0
 def test_api_run_experiment(self):
     '''
     Check run an experiment by user authenticated
     '''
     api = IBMQuantumExperience(API_TOKEN)
     device = 'simulator'
     shots = 1
     experiment = api.run_experiment(qasm, device, shots)
     self.assertIsNotNone(experiment['status'])
Пример #12
0
 def test_api_run_experiment_with_seed(self):
     '''
     Check run an experiment with seed by user authenticated
     '''
     api = IBMQuantumExperience(API_TOKEN)
     device = 'simulator'
     shots = 1
     seed = 815
     experiment = api.run_experiment(qasm, device, shots, seed=seed)
     self.assertEqual(int(experiment['result']['extraInfo']['seed']), seed)
Пример #13
0
 def test_api_run_job_fail_device(self):
     '''
     Check run an job by user authenticated is not run because the device
     does not exist
     '''
     api = IBMQuantumExperience(API_TOKEN)
     device = 'real5'
     shots = 1
     job = api.run_job(qasms, device, shots)
     self.assertIsNotNone(job['error'])
Пример #14
0
 def test_api_get_my_credits(self):
     '''
     Check the credits of the user
     '''
     api = IBMQuantumExperience(API_TOKEN)
     my_credits = api.get_my_credits()
     check_credits = None
     if 'remaining' in my_credits:
         check_credits = my_credits['remaining']
     self.assertIsNotNone(check_credits)
Пример #15
0
 def test_api_run_experiment_fail_device(self):
     '''
     Check run an experiment by user authenticated is not run because the
     device does not exist
     '''
     api = IBMQuantumExperience(API_TOKEN)
     device = '5qreal'
     shots = 1
     experiment = api.run_experiment(qasm, device, shots)
     self.assertIsNotNone(experiment['error'])
Пример #16
0
 def test_api_run_experiment(self):
     '''
     Check run an experiment by user authenticated
     '''
     api = IBMQuantumExperience(API_TOKEN)
     backend = api.available_backend_simulators()[0]['name']
     shots = 1
     experiment = api.run_experiment(self.qasm, backend, shots)
     check_status = None
     if 'status' in experiment:
         check_status = experiment['status']
     self.assertIsNotNone(check_status)
Пример #17
0
 def test_api_run_job(self):
     '''
     Check run an job by user authenticated
     '''
     api = IBMQuantumExperience(API_TOKEN)
     backend = 'simulator'
     shots = 1
     job = api.run_job(self.qasms, backend, shots)
     check_status = None
     if 'status' in job:
         check_status = job['status']
     self.assertIsNotNone(check_status)
Пример #18
0
 def test_api_run_experiment_with_seed(self):
     '''
     Check run an experiment with seed by user authenticated
     '''
     api = IBMQuantumExperience(API_TOKEN)
     backend = api.available_backend_simulators()[0]['name']
     shots = 1
     seed = 815
     experiment = api.run_experiment(self.qasm, backend, shots, seed=seed)
     check_seed = -1
     if ('result' in experiment) and \
        ('extraInfo' in experiment['result']) and \
        ('seed' in experiment['result']['extraInfo']):
         check_seed = int(experiment['result']['extraInfo']['seed'])
     self.assertEqual(check_seed, seed)
Пример #19
0
 def test_run_remote_simulator_compile(self):
     quantum_job = QuantumJob(self.qc,
                              do_compile=True,
                              backend='ibmqx_qasm_simulator')
     api = IBMQuantumExperience(self.QE_TOKEN, {"url": self.QE_URL},
                                verify=True)
     jobprocessor.run_remote_backend(quantum_job.qobj, api)
Пример #20
0
    def setUpClass(cls):
        super().setUpClass()

        try:
            import Qconfig
            cls.QE_TOKEN = Qconfig.APItoken
            cls.QE_URL = Qconfig.config['url']
        except ImportError:
            if 'QE_TOKEN' in os.environ:
                cls.QE_TOKEN = os.environ['QE_TOKEN']
            if 'QE_URL' in os.environ:
                cls.QE_URL = os.environ['QE_URL']

        n_circuits = 20
        min_depth = 1
        max_depth = 40
        min_qubits = 1
        max_qubits = 5
        random_circuits = RandomCircuitGenerator(100,
                                                 min_qubits=min_qubits,
                                                 max_qubits=max_qubits,
                                                 min_depth=min_depth,
                                                 max_depth=max_depth)
        random_circuits.add_circuits(n_circuits)
        cls.rqg = random_circuits
        if hasattr(cls, 'QE_TOKEN'):
            cls._api = IBMQuantumExperience(cls.QE_TOKEN,
                                            {"url": cls.QE_URL},
                                            verify=True)
            qiskit.backends.discover_remote_backends(cls._api)
Пример #21
0
 def test_run_remote_simulator(self):
     compiled_circuit = openquantumcompiler.compile(self.qc.qasm())
     quantum_job = QuantumJob(compiled_circuit,
                              do_compile=False,
                              backend='ibmqx_qasm_simulator')
     api = IBMQuantumExperience(self.QE_TOKEN, {"url": self.QE_URL},
                                verify=True)
     jobprocessor.run_remote_backend(quantum_job.qobj, api)
Пример #22
0
 def _set_api(token, config):
     api = IBMQuantumExperience(token=token, config=config)
     qiskit.register(token=token,
                     url=config.get('url'),
                     hub=config.get('hub'),
                     group=config.get('group'),
                     project=config.get('project'))
     return api
Пример #23
0
 def test_api_run_job_fail_backend(self):
     '''
     Check run an job by user authenticated is not run because the backend
     does not exist
     '''
     api = IBMQuantumExperience(API_TOKEN)
     backend = 'real5'
     shots = 1
     self.assertRaises(BadBackendError, api.run_job, self.qasms, backend,
                       shots)
Пример #24
0
    def __init__(self,
                 q_jobs,
                 callback,
                 max_workers=1,
                 token=None,
                 url=None,
                 api=None):
        """
        Args:
            q_jobs (list(QuantumJob)): List of QuantumJob objects.
            callback (fn(results)): The function that will be called when all
                jobs finish. The signature of the function must be:
                fn(results)
                results: A list of Result objects.
            max_workers (int): The maximum number of workers to use.
            token (str): Server API token
            url (str): Server URL.
            api (IBMQuantumExperience): API instance to use. If set,
                /token/ and /url/ are ignored.
        """
        self.q_jobs = q_jobs
        self.max_workers = max_workers
        # check whether any jobs are remote
        self._local_backends = backends.local_backends()
        self.online = any(qj.backend not in self._local_backends
                          for qj in q_jobs)
        self.futures = {}
        self.lock = Lock()
        # Set a default dummy callback just in case the user doesn't want
        # to pass any callback.
        self.callback = (lambda rs: ()) if callback is None else callback
        self.num_jobs = len(self.q_jobs)
        self.jobs_results = []
        if self.online:
            self._api = api if api else IBMQuantumExperience(
                token, {"url": url}, verify=True)
            self._online_backends = remote_backends(self._api)
            # Check for the existance of the backend
            for q_job in q_jobs:
                if q_job.backend not in self._online_backends + self._local_backends:
                    raise QISKitError("Backend %s not found!" % q_job.backend)

            self._api_config = {}
            self._api_config["token"] = token
            self._api_config["url"] = {"url": url}
        else:
            self._api = None
            self._online_backends = None
            self._api_config = None
        if self.online:
            # I/O intensive -> use ThreadedPoolExecutor
            self.executor_class = futures.ThreadPoolExecutor
        else:
            # CPU intensive -> use ProcessPoolExecutor
            self.executor_class = futures.ProcessPoolExecutor
Пример #25
0
    def test_quantum_program_online(self, QE_TOKEN, QE_URL):
        self._init_api(QE_TOKEN, QE_URL)

        qp = QuantumProgram()
        qr = qp.create_quantum_register('qr', 2)
        cr = qp.create_classical_register('cr', 2)
        qc = qp.create_circuit('qc', [qr], [cr])
        qc.h(qr[0])
        qc.measure(qr[0], cr[0])
        backend = 'ibmqx_qasm_simulator'  # the backend to run on
        shots = 1024  # the number of shots in the experiment.
        api = IBMQuantumExperience(QE_TOKEN, {'url': QE_URL})
        qiskit.backends.discover_remote_backends(api)
        _ = qp.execute(['qc'], backend=backend, shots=shots, seed=78)
    def set_api(self, token, url, verify=True):
        """ Setup the API.

        Does not catch exceptions from IBMQuantumExperience.

        Args:
            Token (str): The token used to register on the online backend such
                as the quantum experience.
            URL (str): The url used for online backend such as the quantum
                experience.
        Returns:
            Nothing but fills the __ONLINE_BACKENDS, __api, and __api_config
        """
        self.__api = IBMQuantumExperience(token, {"url": url}, verify)
        self.__ONLINE_BACKENDS = self.online_backends()
        self.__api_config["token"] = token
        self.__api_config["url"] =  {"url": url}
Пример #27
0
 def _set_api(token, config):
     api = IBMQuantumExperience(token=token, config=config)
     _ = qiskit.backends.update_backends(api)
     return api
Пример #28
0
import json

from IBMQuantumExperience.IBMQuantumExperience import IBMQuantumExperience

token = "a6c65f024279c033c9368bd14e6f9079b71fdfd00625b1f3d3573475c97d84d429c8b4316aa572709dd2670e9a069e735f127342360a7ec6bd8f17f82a997ba2"

qe: IBMQuantumExperience = IBMQuantumExperience(token)
print(qe.available_backends())

print(qe.check_credentials())

print(qe.backend_parameters("ibmqx2"))
Пример #29
0
class QuantumProgram(object):
    """ Quantum Program Class

     Class internal properties """

    __online_devices = [
        "real", "ibmqx2", "ibmqx3", "simulator", "ibmqx_qasm_simulator"
    ]
    __local_devices = ["local_unitary_simulator", "local_qasm_simulator"]

    __quantum_program = {}
    __api = {}
    __api_config = {}
    """
    Elements that are not python identifiers or string constants are denoted
    by "--description (type)--". For example, a circuit's name is denoted by
    "--circuit name (string)--" and might have the value "teleport".

    __quantum_program = {
        "circuits": {
            --circuit name (string)--: {
                "circuit": --circuit object (TBD)--,
                "execution": {  #### FILLED IN AFTER RUN -- JAY WANTS THIS MOVED DOWN ONE LAYER ####
                    --device name (string)--: {
                        "coupling_map": --adjacency list (dict)--,
                        "basis_gates": --comma separated gate names (string)--,
                        "compiled_circuit": --compiled quantum circuit (currently QASM text)--,
                        "shots": --shots (int)--,
                        "max_credits": --credits (int)--,
                        "result": {
                            "data": {  #### DATA CAN BE A DIFFERENT DICTIONARY FOR EACH BACKEND ####
                                "counts": {’00000’: XXXX, ’00001’: XXXXX},
                                "time"  : xx.xxxxxxxx
                            },
                            "date"  : "2017−05−09Txx:xx:xx.xxxZ",
                            "status": --status (string)--
                        }
                    },
            }
        }
    }

    __to_execute = {
        --device name (string)--: [
            {
                "name": --circuit name (string)--,
                "coupling_map": --adjacency list (dict)--,
                "basis_gates": --comma separated gate names (string)--,
                "compiled_circuit": --compiled quantum circuit (currently QASM text)--,
                "shots": --shots (int)--,
                "max_credits": --credits (int)--
                "seed": --initial seed for the simulator (int) --
            },
            ...
        ]
    }
    """

    # -- FUTURE IMPROVEMENTS --
    # TODO: for status results choose ALL_CAPS, or This but be consistent
    # TODO: coupling_map, basis_gates will move to compiled_circuit object
    # TODO: compiled_circuit is currently QASM text. In the future we will
    #       make a method in the QuantumCircuit object that makes an object
    #       to be passed to the runner and this will live in compiled_circuit.

    def __init__(self, specs=None, name=""):
        self.__quantum_program = {"circuits": {}}
        self.__quantum_registers = {}
        self.__classical_registers = {}
        self.__init_circuit = None
        self.__last_device_backend = ""
        self.__to_execute = {}
        self.mapper = mapper

        if specs:
            self.__init_specs(specs)

    # API functions
    def get_api_config(self):
        """Return the program specs"""
        return self.__api.req.credential.config

    def _setup_api(self, token, url):
        try:
            self.__api = IBMQuantumExperience(token, {"url": url})
            return True
        except BaseException:
            print('---- Error: Exception connect to servers ----')

            return False

    def set_api(self, token=None, url=None):
        """Set the API conf"""
        if not token:
            token = self.__api_config["token"]
        else:
            self.__api_config["token"] = token
        if not url:
            url = self.__api_config["url"]
        else:
            self.__api_config["url"] = {"url": url}
        api = self._setup_api(token, url)
        return api

    def set_api_token(self, token):
        """ Set the API Token """
        self.set_api(token=token)

    def set_api_url(self, url):
        """ Set the API url """
        self.set_api(url=url)

    def get_device_status(self, device):
        """Return the online device status via QX API call
        device is the name of the real chip
        """

        if device in self.__online_devices:
            return self.__api.device_status(device)
        else:
            return {"status": "Error", "result": "This device doesn't exist"}

    def get_device_calibration(self, device):
        """Return the online device calibrations via QX API call
        device is the name of the real chip
        """

        if device in self.__online_devices:
            return self.__api.device_calibration(device)
        else:
            return {"status": "Error", "result": "This device doesn't exist"}

    # Building parts of the program
    def create_quantum_registers(self, name, size):
        """Create a new set of Quantum Registers"""
        self.__quantum_registers[name] = QuantumRegister(name, size)
        print(">> quantum_registers created:", name, size)
        return self.__quantum_registers[name]

    def create_quantum_registers_group(self, registers_array):
        """Create a new set of Quantum Registers based on a array of that"""
        new_registers = []
        for register in registers_array:
            register = self.create_quantum_registers(register["name"],
                                                     register["size"])
            new_registers.append(register)
        return new_registers

    def create_classical_registers(self, name, size):
        """Create a new set of Classical Registers"""
        self.__classical_registers[name] = ClassicalRegister(name, size)
        print(">> classical_registers created:", name, size)
        return self.__classical_registers[name]

    def create_classical_registers_group(self, registers_array):
        """Create a new set of Classical Registers based on a array of that"""
        new_registers = []
        for register in registers_array:
            new_registers.append(
                self.create_classical_registers(register["name"],
                                                register["size"]))
        return new_registers

    def create_circuit(self,
                       name,
                       qregisters=None,
                       cregisters=None,
                       circuit_object=None):
        """Create a new Quantum Circuit into the Quantum Program
        name is a string, the name of the circuit
        qregisters is an Array of Quantum Registers, can be String, by name or the object reference
        cregisters is an Array of Classical Registers, can be String, by name or the object reference
        """
        if not qregisters:
            qregisters = []
        if not cregisters:
            cregisters = []

        if not circuit_object:
            circuit_object = QuantumCircuit()
        self.__quantum_program['circuits'][name] = {
            "name": name,
            "circuit": circuit_object
        }

        for register in qregisters:
            if isinstance(register, str):
                self.__quantum_program['circuits'][name]['circuit'].add(
                    self.__quantum_registers[register])
            else:
                self.__quantum_program['circuits'][name]['circuit'].add(
                    register)
        for register in cregisters:
            if isinstance(register, str):
                self.__quantum_program['circuits'][name]['circuit'].add(
                    self.__classical_registers[register])
            else:
                self.__quantum_program['circuits'][name]['circuit'].add(
                    register)

        return self.__quantum_program['circuits'][name]['circuit']

    def get_quantum_registers(self, name):
        """Return a Quantum Register by name"""
        return self.__quantum_registers[name]

    def get_classical_registers(self, name):
        """Return a Classical Register by name"""
        return self.__classical_registers[name]

    def get_circuit(self, name):
        """Return a Circuit Object by name"""
        return self.__quantum_program['circuits'][name]['circuit']

    def get_quantum_elements(self, specs=None):
        """Return the basic elements, Circuit, Quantum Registers, Classical Registers"""
        return self.__init_circuit, \
            self.__quantum_registers[list(self.__quantum_registers)[0]], \
            self.__classical_registers[list(self.__classical_registers)[0]]

    def load_qasm(self, name="", qasm_file=None, basis_gates=None):
        """ Load qasm file
        qasm_file qasm file name
        """
        if not qasm_file:
            print('"Not filename provided')
            return {"status": "Error", "result": "Not filename provided"}
        if not basis_gates:
            basis_gates = "u1,u2,u3,cx,id"  # QE target basis

        if name == "":
            name = qasm_file

        circuit_object = qasm.Qasm(filename=qasm_file).parse()  # Node (AST)

        # TODO: add method to convert to QuantumCircuit object from Node
        self.__quantum_program['circuits'][name] = {"circuit": circuit_object}

        return {"status": "COMPLETED", "result": 'all done'}

    def __init_specs(self, specs):
        """Populate the Quantum Program Object with initial Specs"""
        quantumr = []
        classicalr = []
        if "api" in specs:
            if specs["api"]["token"]:
                self.__api_config["token"] = specs["api"]["token"]
            if specs["api"]["url"]:
                self.__api_config["url"] = specs["api"]["url"]

        if "circuits" in specs:
            for circuit in specs["circuits"]:
                quantumr = self.create_quantum_registers_group(
                    circuit["quantum_registers"])
                classicalr = self.create_classical_registers_group(
                    circuit["classical_registers"])
                self.__init_circuit = self.create_circuit(
                    name=circuit["name"],
                    qregisters=quantumr,
                    cregisters=classicalr)
        else:
            if "quantum_registers" in specs:
                print(">> quantum_registers created")
                quantumr = specs["quantum_registers"]
                self.create_quantum_registers(quantumr["name"],
                                              quantumr["size"])
            if "classical_registers" in specs:
                print(">> quantum_registers created")
                classicalr = specs["classical_registers"]
                self.create_classical_registers(classicalr["name"],
                                                classicalr["size"])
            if quantumr and classicalr:
                self.create_circuit(name=specs["name"],
                                    qregisters=quantumr["name"],
                                    cregisters=classicalr["name"])

    def add_circuit(self, name, circuit_object):
        """Add a new circuit based on an Object representation.
        name is the name or index of one circuit."""
        self.__quantum_program['circuits'][name] = {
            "name": name,
            "circuit": circuit_object
        }
        return circuit_object

    def get_qasm_image(self, circuit):
        """Get image circuit representation from API."""
        pass

    def get_qasm(self, name):
        """get the circut by name.
        name of the circuit"""
        if name in self.__quantum_program['circuits']:
            return self.__quantum_program['circuits'][name]['circuit'].qasm()
        else:
            return {"status": "Error", "result": 'Circuit not found'}

    def get_qasms(self, list_circuit_name):
        """get the circut by name.
        name of the circuit"""
        qasm_source = []
        for name in list_circuit_name:
            qasm_source.append(self.get_qasm(name))
        return qasm_source

    # Compiling methods
    def unroller_code(self, circuit, basis_gates=None):
        """ Unroll the code
        circuit is circuits to unroll
        basis_gates are the base gates, which by default are: u1,u2,u3,cx,id
        """
        if not basis_gates:
            basis_gates = "u1,u2,u3,cx,id"  # QE target basis

        unrolled_circuit = unroll.Unroller(
            qasm.Qasm(data=circuit.qasm()).parse(),
            unroll.CircuitBackend(basis_gates.split(",")))
        unrolled_circuit.execute()

        circuit_unrolled = unrolled_circuit.backend.circuit  # circuit DAG
        qasm_source = circuit_unrolled.qasm(qeflag=True)
        return qasm_source, circuit_unrolled

    def compile(self,
                name_of_circuits,
                device="local_qasm_simulator",
                shots=1024,
                max_credits=3,
                basis_gates=None,
                coupling_map=None,
                seed=None):
        """Compile the name_of_circuits by names.

        name_of_circuits is a list of circuit names to compile.
        device is the target device name.
        basis_gates are the base gates by default are: u1,u2,u3,cx,id
        coupling_map is the adjacency list for coupling graph

        This method adds elements of the following form to the self.__to_execute
        list corresponding to the device:

        --device name (string)--: [
                {
                    "name": --circuit name (string)--,
                    "coupling_map": --adjacency list (dict)--,
                    "basis_gates": --comma separated gate names (string)--,
                    "compiled_circuit": --compiled quantum circuit (currently QASM text)--,
                    "shots": --shots (int)--,
                    "max_credits": --credits (int)--
                    "seed": --initial seed for the simulator (int) --
                },
                ...
            ]
        }
        """
        if name_of_circuits == []:
            return {"status": "Error", "result": 'No circuits'}

        for name in name_of_circuits:
            if name not in self.__quantum_program["circuits"]:
                return {
                    "status": "Error",
                    "result": "%s not in QuantumProgram" % name
                }

            # TODO: The circuit object has to have .qasm() method (be careful)
            qasm_compiled, dag_unrolled = self.unroller_code(
                self.__quantum_program['circuits'][name]['circuit'],
                basis_gates)
            if coupling_map:
                print("pre-mapping properties: %s" %
                      dag_unrolled.property_summary())
                # Insert swap gates
                coupling = self.mapper.Coupling(coupling_map)
                dag_unrolled, final_layout = self.mapper.swap_mapper(
                    dag_unrolled, coupling)
                print("layout: %s" % final_layout)
                # Expand swaps
                qasm_compiled, dag_unrolled = self.unroller_code(dag_unrolled)
                # Change cx directions
                dag_unrolled = mapper.direction_mapper(dag_unrolled, coupling)
                # Simplify cx gates
                mapper.cx_cancellation(dag_unrolled)
                # Simplify single qubit gates
                dag_unrolled = mapper.optimize_1q_gates(dag_unrolled)
                qasm_compiled = dag_unrolled.qasm(qeflag=True)
                print("post-mapping properties: %s" %
                      dag_unrolled.property_summary())
            # TODO: add timestamp, compilation
            if device not in self.__to_execute:
                self.__to_execute[device] = []

            job = {}
            job["name"] = name
            job["coupling_map"] = coupling_map
            job["basis_gates"] = basis_gates
            job["shots"] = shots
            job["max_credits"] = max_credits
            # TODO: This will become a new compiled circuit object in the
            #       future. See future improvements at the top of this
            #       file.
            job["compiled_circuit"] = qasm_compiled
            job["seed"] = random.random()
            if seed is not None:
                job["seed"] = seed
            self.__to_execute[device].append(job)
        return {"status": "COMPLETED", "result": 'all done'}

    def get_compiled_qasm(self, name, device=None):
        """Get the compiled qasm for the named circuit and device.

        If device is None, it defaults to the last device.
        """
        if not device:
            device = self.__last_device_backend
        try:
            return self.__quantum_program["circuits"][name]["execution"][
                device]["compiled_circuit"]
        except KeyError:
            return "No compiled qasm for this circuit"

    def print_execution_list(self, verbose=False):
        """Print the compiled circuits that are ready to run.

        verbose controls how much is returned.
        """
        for device, jobs in self.__to_execute.items():
            print("%s:" % device)
            for job in jobs:
                print("  %s:" % job["name"])
                print("    shots = %d" % job["shots"])
                print("    max_credits = %d" % job["max_credits"])
                print("    seed (simulator only) = %d" % job["seed"])
                if verbose:
                    print("    compiled_circuit =")
                    print("// *******************************************")
                    print(job["compiled_circuit"], end="")
                    print("// *******************************************")

    #runners
    def run(self, wait=5, timeout=60):
        """Run a program (a pre-compiled quantum program).

        All input for run comes from self.__to_execute
        wait time is how long to check if the job is completed
        timeout is time until the execution stopa
        """
        for backend in self.__to_execute:
            self.__last_device_backend = backend
            if backend in self.__online_devices:
                last_shots = -1
                last_max_credits = -1
                jobs = []
                for job in self.__to_execute[backend]:
                    jobs.append({'qasm': job["compiled_circuit"]})
                    shots = job["shots"]
                    max_credits = job["max_credits"]
                    if last_shots == -1:
                        last_shots = shots
                    else:
                        if last_shots != shots:
                            # Clear the list of compiled programs to execute
                            self.__to_execute = {}
                            return {
                                "status":
                                "Error",
                                "result":
                                'Online devices only support job batches with equal numbers of shots'
                            }
                    if last_max_credits == -1:
                        last_max_credits = max_credits
                    else:
                        if last_max_credits != max_credits:
                            # Clear the list of compiled programs to execute
                            self.__to_execute = {}
                            return {
                                "status":
                                "Error",
                                "result":
                                'Online devices only support job batches with equal max credits'
                            }

                print("running on backend: %s" % (backend))
                output = self.__api.run_job(jobs, backend, last_shots,
                                            last_max_credits)
                if 'error' in output:
                    # Clear the list of compiled programs to execute
                    self.__to_execute = {}
                    return {"status": "Error", "result": output['error']}
                job_result = self.wait_for_job(output['id'],
                                               wait=wait,
                                               timeout=timeout)

                if job_result['status'] == 'Error':
                    # Clear the list of compiled programs to execute
                    self.__to_execute = {}
                    return job_result
            else:
                jobs = []
                for job in self.__to_execute[backend]:
                    jobs.append({
                        "compiled_circuit": job["compiled_circuit"],
                        "shots": job["shots"],
                        "seed": job["seed"]
                    })
                print("running on backend: %s" % (backend))
                if backend == "local_qasm_simulator":
                    job_result = self.run_local_qasm_simulator(jobs)
                elif backend == "local_unitary_simulator":
                    job_result = self.run_local_unitary_simulator(jobs)
                else:
                    # Clear the list of compiled programs to execute
                    self.__to_execute = {}
                    return {
                        "status": "Error",
                        "result": 'Not a local simulator'
                    }

            assert len(self.__to_execute[backend]) == len(
                job_result["qasms"]
            ), "Internal error in QuantumProgram.run(), job_result"

            # Fill data into self.__quantum_program for this backend
            index = 0
            for job in self.__to_execute[backend]:
                name = job["name"]
                if name not in self.__quantum_program["circuits"]:
                    # Clear the list of compiled programs to execute
                    self.__to_execute = {}
                    return {
                        "status": "Error",
                        "result": "Internal error, circuit not found"
                    }
                if not "execution" in self.__quantum_program["circuits"][name]:
                    self.__quantum_program["circuits"][name]["execution"] = {}
                # We override the results
                if backend not in self.__quantum_program["circuits"][name][
                        "execution"]:
                    self.__quantum_program["circuits"][name]["execution"][
                        backend] = {}
                # TODO: return date, executionId, ...
                for field in [
                        "coupling_map", "basis_gates", "compiled_circuit",
                        "shots", "max_credits", "seed"
                ]:
                    self.__quantum_program["circuits"][name]["execution"][
                        backend][field] = job[field]
                self.__quantum_program["circuits"][name]["execution"][backend][
                    "result"] = job_result["qasms"][index]["result"]
                self.__quantum_program["circuits"][name]["execution"][backend][
                    "status"] = job_result["qasms"][index]["status"]
                index += 1

        # Clear the list of compiled programs to execute
        self.__to_execute = {}

        return {"status": "COMPLETED", "result": 'all done'}

    def wait_for_job(self, jobid, wait=5, timeout=60):
        """Wait until all status results are 'COMPLETED'.
        jobids is a list of id strings.
        api is an IBMQuantumExperience object.
        wait is the time to wait between requests, in seconds
        timeout is how long we wait before failing, in seconds
        Returns an list of results that correspond to the jobids.
        """
        timer = 0
        timeout_over = False
        job = self.__api.get_job(jobid)
        while job['status'] == 'RUNNING':
            if timer == timeout:
                return {"status": "Error", "result": "Time Out"}
            time.sleep(wait)
            timer += wait
            print("status = %s (%d seconds)" % (job['status'], timer))
            job = self.__api.get_job(jobid)
            if job['status'] == 'ERROR_CREATING_JOB' or job[
                    'status'] == 'ERROR_RUNNING_JOB':
                return {"status": "Error", "result": job['status']}

        # Get the results
        return job

    def run_local_qasm_simulator(self, jobs):
        """run_local_qasm_simulator, run a program (precompile of quantum circuits).
        jobs is list of dicts {"compiled_circuit": simulator input data, "shots": integer num shots}

        returns
        job_results = {
            "qasms": [
                {
                    "result": DATA,
                    "status": DATA,
                },
                ...
            ]
        }
        """
        job_results = {"qasms": []}
        for job in jobs:
            one_result = {'result': None, 'status': "Error"}
            qasm_circuit = simulators.QasmSimulator(job["compiled_circuit"],
                                                    job["shots"],
                                                    job["seed"]).run()
            one_result["result"] = {}
            one_result["result"]["data"] = qasm_circuit["data"]
            one_result["status"] = qasm_circuit["status"]
            job_results['qasms'].append(one_result)
        return job_results

    def run_local_unitary_simulator(self, jobs):
        """run_local_unitary_simulator, run a program (precompile of quantum circuits).
        jobs is list of dicts {"compiled_circuit": simulator input data}

        returns
        job_results = {
            "qasms": [
                {
                    "result": DATA,
                    "status": DATA,
                },
                ...
            ]
        }
        """
        job_results = {"qasms": []}
        for job in jobs:
            one_result = {'result': None, 'status': "Error"}
            unitary_circuit = simulators.UnitarySimulator(
                job["compiled_circuit"]).run()
            one_result["result"] = {}
            one_result["result"]["data"] = unitary_circuit["data"]
            one_result["status"] = unitary_circuit["status"]
            job_results['qasms'].append(one_result)
        return job_results

    def execute(self,
                name_of_circuits,
                device="local_qasm_simulator",
                shots=1024,
                max_credits=3,
                wait=5,
                timeout=60,
                basis_gates=None,
                coupling_map=None,
                seed=None):
        """Execute, compile, and run a program (array of quantum circuits).
        program is a list of quantum_circuits
        api is the api for the device
        device is a string for real or simulator
        shots is the number of shots
        max_credits is the maximum credits for the experiments
        basis_gates are the base gates, which by default are: u1,u2,u3,cx,id
        """
        self.compile(name_of_circuits, device, shots, max_credits, basis_gates,
                     coupling_map, seed)
        output = self.run(wait, timeout)
        return output

    # method to process the data
    def get_result(self, name, device=None):
        """get the get_result from one circut and backend
        name of the circuit
        device that is use to compile, run, or execute
        """
        if not device:
            device = self.__last_device_backend

        if name in self.__quantum_program["circuits"]:
            return self.__quantum_program["circuits"][name]['execution'][
                device]['result']
        else:
            return {"status": "Error", "result": 'Circuit not found'}

    def get_data(self, name, device=None):
        """Get the dict of labels and counts from the output of get_job.
        results are the list of results
        name is the name or index of one circuit."""
        if not device:
            device = self.__last_device_backend
        return self.__quantum_program["circuits"][name]['execution'][device][
            'result']['data']

    def get_counts(self, name, device=None):
        """Get the dict of labels and counts from the output of get_job.
        name is the name or index of one circuit."""
        if not device:
            device = self.__last_device_backend
        try:
            return self.__quantum_program["circuits"][name]['execution'][
                device]['result']['data']['counts']
        except KeyError:
            return {"status": "Error", "result": 'Error in circuit name'}

    def plotter(self,
                name,
                device=None,
                method="histogram",
                number_to_keep=None):
        """Plot the results
        method: histogram/qsphere
        circuit: Print one circuit
        """
        data = self.get_counts(name, device)

        if method == "histogram":
            basicplotter.plot_histogram(data, number_to_keep)
        else:
            pass
            # TODO: add basicplotter.plot_qsphere(data) for unitary simulator

    def average_data(self, name, observable):
        """Compute the mean value of an diagonal observable.

        Takes in an observable in dictionary format and then
        calculates the sum_i value(i) P(i) where value(i) is the value of
        the observable for state i.

        returns a double
        """
        counts = self.get_counts(name)
        temp = 0
        tot = sum(counts.values())
        for key in counts:
            if key in observable:
                temp += counts[key] * observable[key] / tot
        return temp
 def _init_api(self, QE_TOKEN, QE_URL):
     api = IBMQuantumExperience(QE_TOKEN, {"url": QE_URL}, verify=True)
     qiskit.backends.discover_remote_backends(api)
Пример #31
0
sys.path.append('IBMQuantumExperience')
sys.path.append('../IBMQuantumExperience')
# pylint: disable=C0413
try:
    if sys.version_info.major > 2:  # Python 3
        from IBMQuantumExperience.IBMQuantumExperience import IBMQuantumExperience  # noqa
    else:  # Python 2
        from IBMQuantumExperience import IBMQuantumExperience  # noqa
    from IBMQuantumExperience.IBMQuantumExperience import ApiError
    from IBMQuantumExperience.IBMQuantumExperience import BadBackendError  # noq
except:
    sys.stderr.write(
        "IBMQuantumExperience library not installed. Use : pip install IBMQuantumExperience"
    )
    sys.exit(0)

api = IBMQuantumExperience(sys.argv[1])
# my_credits = api.get_my_credits()
# print "Credits: ", ast.literal_eval(json.dumps(my_credits))
# print "Backend: ",api.available_backend_simulators()[0]['name']

# qasm = 'OPENQASM 2.0;\n\ninclude "qelib1.inc";\nqreg q[5];\ncreg c[5];\nh q[0];\ncx q[0],q[2];\nmeasure q[0] -> c[0];\nmeasure q[2] -> c[1];\n'
# qasm = 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[5];\ncreg c[5];\nh q[0];\nx q[1];\ncx q[0],q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];'
# print "qasm: ",qasm

backend = api.available_backend_simulators()[0]['name']
shots = sys.argv[2]
experiment = api.run_experiment(qasm, backend, shots)
print ast.literal_eval(json.dumps(experiment))
class QuantumProgram(object):
    """Quantum Program Class.

     Class internal properties.

     Elements that are not python identifiers or string constants are denoted
     by "--description (type)--". For example, a circuit's name is denoted by
     "--circuit name (string)--" and might have the value "teleport".

     Internal::

        __quantum_registers (list[dic]): An dictionary of quantum registers
            used in the quantum program.
            __quantum_registers =
                {
                --register name (string)--: QuantumRegistor,
                }
        __classical_registers (list[dic]): An ordered list of classical registers
            used in the quantum program.
            __classical_registers =
                {
                --register name (string)--: ClassicalRegistor,
                }
        __quantum_program (dic): An dictionary of quantum circuits
            __quantum_program =
                {
                --circuit name (string)--:  --circuit object --,
                }
        __init_circuit (obj): A quantum circuit object for the initial quantum
            circuit
        __ONLINE_BACKENDS (list[str]): A list of online backends
        __LOCAL_BACKENDS (list[str]): A list of local backends
     """
    # -- FUTURE IMPROVEMENTS --
    # TODO: for status results make ALL_CAPS (check) or some unified method
    # TODO: Jay: coupling_map, basis_gates will move into a config object

    # only exists once you set the api to use the online backends
    __api = {}
    __api_config = {}

    def __init__(self, specs=None):
        self.__quantum_registers = {}
        self.__classical_registers = {}
        self.__quantum_program = {} # stores all the quantum programs
        self.__init_circuit = None # stores the intial quantum circuit of the
        # program
        self.__ONLINE_BACKENDS = []
        self.__LOCAL_BACKENDS = self.local_backends()
        self.mapper = mapper
        if specs:
            self.__init_specs(specs)

    ###############################################################
    # methods to initiate an build a quantum program
    ###############################################################

    def __init_specs(self, specs, verbose=False):
        """Populate the Quantum Program Object with initial Specs.

        Args:
            specs (dict):
                    Q_SPECS = {
                        "circuits": [{
                            "name": "Circuit",
                            "quantum_registers": [{
                                "name": "qr",
                                "size": 4
                            }],
                            "classical_registers": [{
                                "name": "cr",
                                "size": 4
                            }]
                        }],
            verbose (bool): controls how information is returned.

        Returns:
            Sets up a quantum circuit.
        """
        quantumr = []
        classicalr = []
        if "circuits" in specs:
            for circuit in specs["circuits"]:
                quantumr = self.create_quantum_registers(
                    circuit["quantum_registers"])
                classicalr = self.create_classical_registers(
                    circuit["classical_registers"])
                self.create_circuit(name=circuit["name"], qregisters=quantumr,
                                    cregisters=classicalr)
        # TODO: Jay: I think we should return function handles for the registers
        # and circuit. So that we dont need to get them after we create them
        # with get_quantum_register etc

    def create_quantum_register(self, name, size, verbose=False):
        """Create a new Quantum Register.

        Args:
            name (str): the name of the quantum register
            size (int): the size of the quantum register
            verbose (bool): controls how information is returned.

        Returns:
            internal reference to a quantum register in __quantum_register s
        """
        if name in self.__quantum_registers:
            if size != len(self.__quantum_registers[name]):
                raise QISKitError("Can't make this register: Already in"
                                      " program with different size")
            if verbose == True:
                print(">> quantum_register exists:", name, size)
        else:
            if verbose == True:
                print(">> new quantum_register created:", name, size)
            self.__quantum_registers[name] = QuantumRegister(name, size)
        return self.__quantum_registers[name]

    def create_quantum_registers(self, register_array):
        """Create a new set of Quantum Registers based on a array of them.

        Args:
            register_array (list[dict]): An array of quantum registers in
                dictionay format::

                    "quantum_registers": [
                        {
                        "name": "qr",
                        "size": 4
                        },
                        ...
                    ]
        Returns:
            Array of quantum registers objects
        """
        new_registers = []
        for register in register_array:
            register = self.create_quantum_register(
                register["name"], register["size"])
            new_registers.append(register)
        return new_registers

    def create_classical_register(self, name, size, verbose=False):
        """Create a new Classical Register.

        Args:
            name (str): the name of the quantum register
            size (int): the size of the quantum register
            verbose (bool): controls how information is returned.
        Returns:
            internal reference to a quantum register in __quantum_register
        """
        if name in self.__classical_registers:
            if size != len(self.__classical_registers[name]):
                raise QISKitError("Can't make this register: Already in"
                                      " program with different size")
            if verbose == True:
                print(">> classical register exists:", name, size)
        else:
            if verbose == True:
                print(">> new classical register created:", name, size)
            self.__classical_registers[name] = ClassicalRegister(name, size)
        return self.__classical_registers[name]

    def create_classical_registers(self, registers_array):
        """Create a new set of Classical Registers based on a array of them.

        Args:
            register_array (list[dict]): An array of classical registers in
                dictionay fromat::

                    "classical_registers": [
                        {
                        "name": "qr",
                        "size": 4
                        },
                        ...
                    ]
        Returns:
            Array of clasical registers objects
        """
        new_registers = []
        for register in registers_array:
            new_registers.append(self.create_classical_register(
                register["name"], register["size"]))
        return new_registers

    def create_circuit(self, name, qregisters=None, cregisters=None):
        """Create a empty Quantum Circuit in the Quantum Program.

        Args:
            name (str): the name of the circuit
            qregisters list(object): is an Array of Quantum Registers by object
                reference
            cregisters list(object): is an Array of Classical Registers by
                object reference

        Returns:
            A quantum circuit is created and added to the Quantum Program
        """
        if not qregisters:
            qregisters = []
        if not cregisters:
            cregisters = []
        quantum_circuit = QuantumCircuit()
        if not self.__init_circuit:
            self.__init_circuit = quantum_circuit
        for register in qregisters:
            quantum_circuit.add(register)
        for register in cregisters:
            quantum_circuit.add(register)
        self.add_circuit(name, quantum_circuit)
        return self.__quantum_program[name]

    def add_circuit(self, name, quantum_circuit):
        """Add a new circuit based on an Object representation.

        Args:
            name (str): the name of the circuit to add.
            quantum_circuit: a quantum circuit to add to the program-name
        Returns:
            the quantum circuit is added to the object.
        """
        for qname, qreg in quantum_circuit.get_qregs().items():
            self.create_quantum_register(qname, len(qreg))
        for cname, creg in quantum_circuit.get_cregs().items():
            self.create_classical_register(cname, len(creg))
        self.__quantum_program[name] = quantum_circuit

    def load_qasm_file(self, qasm_file, name=None, verbose=False):
        """ Load qasm file into the quantum program.

        Args:
            qasm_file (str): a string for the filename including its location.
            name (str or None, optional): the name of the quantum circuit after
                loading qasm text into it. If no name is give the name is of
                the text file.
            verbose (bool, optional): controls how information is returned.
        Retuns:
            Adds a quantum circuit with the gates given in the qasm file to the
            quantum program and returns the name to be used to get this circuit
        """
        if not os.path.exists(qasm_file):
            raise QISKitError('qasm file "{0}" not found'.format(qasm_file))
        if not name:
            name = os.path.splitext(os.path.basename(qasm_file))[0]
        node_circuit = qasm.Qasm(filename=qasm_file).parse() # Node (AST)
        if verbose == True:
            print("circuit name: " + name)
            print("******************************")
            print(node_circuit.qasm())
        # current method to turn it a DAG quantum circuit.
        basis_gates = "u1,u2,u3,cx,id"  # QE target basis
        unrolled_circuit = unroll.Unroller(node_circuit,
                                           unroll.CircuitBackend(basis_gates.split(",")))
        circuit_unrolled = unrolled_circuit.execute()
        self.add_circuit(name, circuit_unrolled)
        return name

    def load_qasm_text(self, qasm_string, name=None,  verbose=False):
        """ Load qasm string in the quantum program.

        Args:
            qasm_string (str): a string for the file name.
            name (str): the name of the quantum circuit after loading qasm
                text into it. If no name is give the name is of the text file.
            verbose (bool): controls how information is returned.
        Retuns:
            Adds a quantum circuit with the gates given in the qasm string to the
            quantum program.
        """
        node_circuit = qasm.Qasm(data=qasm_string).parse() # Node (AST)
        if not name:
            # Get a random name if none is give
            name = "".join([random.choice(string.ascii_letters+string.digits)
                           for n in range(10)])
        if verbose == True:
            print("circuit name: " + name)
            print("******************************")
            print(node_circuit.qasm())
        # current method to turn it a DAG quantum circuit.
        basis_gates = "u1,u2,u3,cx,id"  # QE target basis
        unrolled_circuit = unroll.Unroller(node_circuit,
                                           unroll.CircuitBackend(basis_gates.split(",")))
        circuit_unrolled = unrolled_circuit.execute()
        self.add_circuit(name, circuit_unrolled)
        return name

    ###############################################################
    # methods to get elements from a QuantumProgram
    ###############################################################

    def get_quantum_register(self, name):
        """Return a Quantum Register by name.

        Args:
            name (str): the name of the quantum circuit
        Returns:
            The quantum registers with this name
        """
        try:
            return self.__quantum_registers[name]
        except KeyError:
            raise KeyError('No quantum register "{0}"'.format(name))

    def get_classical_register(self, name):
        """Return a Classical Register by name.

        Args:
            name (str): the name of the quantum circuit
        Returns:
            The classical registers with this name
        """
        try:
            return self.__classical_registers[name]
        except KeyError:
            raise KeyError('No classical register "{0}"'.format(name))

    def get_quantum_register_names(self):
        """Return all the names of the quantum Registers."""
        return self.__quantum_registers.keys()

    def get_classical_register_names(self):
        """Return all the names of the classical Registers."""
        return self.__classical_registers.keys()

    def get_circuit(self, name):
        """Return a Circuit Object by name
        Args:
            name (str): the name of the quantum circuit
        Returns:
            The quantum circuit with this name
        """
        try:
            return self.__quantum_program[name]
        except KeyError:
            raise KeyError('No quantum circuit "{0}"'.format(name))

    def get_circuit_names(self):
        """Return all the names of the quantum circuits."""
        return self.__quantum_program.keys()

    def get_qasm(self, name):
        """Get qasm format of circuit by name.

        Args:
            name (str): name of the circuit

        Returns:
            The quantum circuit in qasm format
        """
        quantum_circuit = self.get_circuit(name)
        return quantum_circuit.qasm()

    def get_qasms(self, list_circuit_name):
        """Get qasm format of circuit by list of names.

        Args:
            list_circuit_name (list[str]): names of the circuit

        Returns:
            List of quantum circuit in qasm format
        """
        qasm_source = []
        for name in list_circuit_name:
            qasm_source.append(self.get_qasm(name))
        return qasm_source

    def get_initial_circuit(self):
        """Return the initialization Circuit."""
        return self.__init_circuit

    ###############################################################
    # methods for working with backends
    ###############################################################

    def set_api(self, token, url, verify=True):
        """ Setup the API.

        Does not catch exceptions from IBMQuantumExperience.

        Args:
            Token (str): The token used to register on the online backend such
                as the quantum experience.
            URL (str): The url used for online backend such as the quantum
                experience.
        Returns:
            Nothing but fills the __ONLINE_BACKENDS, __api, and __api_config
        """
        self.__api = IBMQuantumExperience(token, {"url": url}, verify)
        self.__ONLINE_BACKENDS = self.online_backends()
        self.__api_config["token"] = token
        self.__api_config["url"] =  {"url": url}

    def get_api_config(self):
        """Return the program specs."""
        return self.__api_config

    def get_api(self):
        """Returns a function handle to the API."""
        return self.__api

    def save(self, file_name=None, beauty=False):
        """ Save Quantum Program in a Json file.

        Args:
            file_name (str): file name and path.
            beauty (boolean): save the text with indent 4 to make it readable.

        Returns:
            The dictionary with the status and result of the operation

        Raises:
            When you don't provide a correct file name
                raise a LookupError.
            When something happen with the file management
                raise a LookupError.
        """
        if file_name is None:
            error = {"status": "Error", "result": "Not filename provided"}
            raise LookupError(error['result'])

        if beauty:
            indent = 4
        else:
            indent = 0

        elemements_to_save = self.__quantum_program
        elements_saved = {}

        for circuit in elemements_to_save:
            elements_saved[circuit] = {}
            elements_saved[circuit]["qasm"] = elemements_to_save[circuit].qasm()

        try:
            with open(file_name, 'w') as save_file:
                json.dump(elements_saved, save_file, indent = indent)
            return {'status': 'Done', 'result': elemements_to_save}
        except ValueError:
            error = {'status': 'Error', 'result': 'Some Problem happened to save the file'}
            raise LookupError(error['result'])

    def load(self, file_name=None):
        """ Load Quantum Program Json file into the Quantum Program object.

        Args:
            file_name (str): file name and path.

        Returns:
            The dictionary with the status and result of the operation

        Raises:
            When you don't provide a correct file name
                raise a LookupError.
            When something happen with the file management
                raise a LookupError.
        """
        if file_name is None:
            error = {"status": "Error", "result": "Not filename provided"}
            raise LookupError(error['result'])

        elemements_to_load = {}

        try:
            with open(file_name, 'r') as load_file:
                elemements_loaded = json.load(load_file)

            for circuit in elemements_loaded:
                circuit_qasm = elemements_loaded[circuit]["qasm"]
                elemements_loaded[circuit] = qasm.Qasm(data=circuit_qasm).parse()
            self.__quantum_program = elemements_loaded

            return {"status": 'Done', 'result': self.__quantum_program}

        except ValueError:
            error = {'status': 'Error', 'result': 'Some Problem happened to load the file'}
            raise LookupError(error['result'])

    def available_backends(self):
        """All the backends that are seen by QISKIT."""
        return self.__ONLINE_BACKENDS + self.__LOCAL_BACKENDS

    def local_backends(self):
        """Get the local backends."""
        return simulators._localsimulator.local_backends()

    def online_backends(self):
        """Get the online backends.

        Queries network API if it exists and gets the backends that are online.

        Returns:
            List of online backends if the online api has been set or an empty
            list of it has not been set.
        """
        if self.get_api():
            return [backend['name'] for backend in self.__api.available_backends() ]
        else:
            return []

    def online_simulators(self):
        """Gets online simulators via QX API calls.

        Returns:
            List of online simulator names.
        """
        simulators = []
        if self.get_api():
            for backend in self.__api.available_backends():
                if backend['simulator']:
                    simulators.append(backend['name'])
        return simulators

    def online_devices(self):
        """Gets online devices via QX API calls.

        Returns:
            List of online simulator names.
        """
        devices = []
        if self.get_api():
            for backend in self.__api.available_backends():
                if not backend['simulator']:
                    devices.append(backend['name'])
        return devices

    def get_backend_status(self, backend):
        """Return the online backend status.

        It uses QX API call or by local backend is the name of the
        local or online simulator or experiment.

        Args:
            banckend (str): The backend to check
        """

        if backend in self.__ONLINE_BACKENDS:
            return self.__api.backend_status(backend)
        elif  backend in self.__LOCAL_BACKENDS:
            return {'available': True}
        else:
            err_str = 'the backend "{0}" is not available'.format(backend)
            raise ValueError(err_str)

    def get_backend_configuration(self, backend, list_format=False):
        """Return the configuration of the backend.

        The return is via QX API call.

        Args:
            backend (str):  Name of the backend.

        Returns:
            The configuration of the named backend.

        Raises:
            If a configuration for the named backend can't be found
            raise a LookupError.
        """
        if self.get_api():
            configuration_edit = {}
            for configuration in self.__api.available_backends():
                if configuration['name'] == backend:
                    for key in configuration:
                        new_key = convert(key)
                        # TODO: removed these from the API code
                        if new_key not in ['id', 'serial_number', 'topology_id',
                                           'status', 'coupling_map']:
                            configuration_edit[new_key] = configuration[key]
                        if new_key == 'coupling_map':
                            if configuration[key] == 'all-to-all':
                                configuration_edit[new_key] = \
                                    configuration[key]
                            else:
                                if not list_format:
                                    cmap = mapper.coupling_list2dict(
                                                configuration[key])
                                else:
                                    cmap = configuration[key]
                                configuration_edit[new_key] = cmap
                    return configuration_edit
        for configuration in simulators.local_configuration:
            if configuration['name'] == backend:
                return configuration
        raise LookupError(
            'backend configuration for "{0}" not found'.format(backend))

    def get_backend_calibration(self, backend):
        """Return the online backend calibrations.

        The return is via QX API call.

        Args:
            backend (str):  Name of the backend.

        Returns:
            The configuration of the named backend.

        Raises:
            If a configuration for the named backend can't be found
            raise a LookupError.
        """
        if backend in self.__ONLINE_BACKENDS:
            calibrations = self.__api.backend_calibration(backend)
            calibrations_edit = {}
            for key, vals in calibrations.items():
                new_key = convert(key)
                calibrations_edit[new_key] = vals
            return calibrations_edit
        elif  backend in self.__LOCAL_BACKENDS:
            return {'backend': backend, 'calibrations': None}
        else:
            raise LookupError(
                'backend calibration for "{0}" not found'.format(backend))

    def get_backend_parameters(self, backend):
        """Return the online backend parameters.

        The return is via QX API call.

        Args:
            backend (str):  Name of the backend.

        Returns:
            The configuration of the named backend.

        Raises:
            If a configuration for the named backend can't be found
            raise a LookupError.
        """
        if backend in self.__ONLINE_BACKENDS:
            parameters = self.__api.backend_parameters(backend)
            parameters_edit = {}
            for key, vals in parameters.items():
                new_key = convert(key)
                parameters_edit[new_key] = vals
            return parameters_edit
        elif backend in self.__LOCAL_BACKENDS:
            return {'backend': backend, 'parameters': None}
        else:
            raise LookupError(
                'backend parameters for "{0}" not found'.format(backend))

    ###############################################################
    # methods to compile quantum programs into 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,
                qobjid=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 (DAG 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 qobjid:
            qobjid = "".join([random.choice(string.ascii_letters+string.digits)
                              for n in range(30)])
        qobj['id'] = qobjid
        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)
            dag_circuit = self._unroller_code(self.__quantum_program[name],
                                              basis_gates=basis_gates)
            final_layout = None
            # if a coupling map is given compile to the map
            if coupling_map:
                if not silent:
                    print("pre-mapping properties: %s"
                          % dag_circuit.property_summary())
                # Insert swap gates
                coupling = self.mapper.Coupling(coupling_map)
                if not silent:
                    print("initial layout: %s" % initial_layout)
                dag_circuit, final_layout = self.mapper.swap_mapper(
                    dag_circuit, coupling, initial_layout, trials=20, verbose=False)
                if not silent:
                    print("final layout: %s" % final_layout)
                # Expand swaps
                dag_circuit = self._unroller_code(dag_circuit)
                # Change cx directions
                dag_circuit = mapper.direction_mapper(dag_circuit, coupling)
                # Simplify cx gates
                mapper.cx_cancellation(dag_circuit)
                # Simplify single qubit gates
                dag_circuit = mapper.optimize_1q_gates(dag_circuit)
                if not silent:
                    print("post-mapping properties: %s"
                          % dag_circuit.property_summary())

            # making the job to be added to qojj
            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"] = random.getrandbits(128) # int.from_bytes(os.urandom(4), byteorder="big")
            else:
                job["config"]["seed"] = seed
            # the compuled circuit to be run saved as a dag
            job["compiled_circuit"] = self._dag2json(dag_circuit)
            job["compiled_circuit_qasm"] = dag_circuit.qasm(qeflag=True)
            # add job to the qobj
            qobj["circuits"].append(job)
        return qobj

    def get_execution_list(self, qobj, verbose=False):
        """Print the compiled circuits that are ready to run.

        Args:
            verbose (bool): controls how much is returned.
        """
        if not qobj:
            if verbose:
                print("no exectuions to run")
        execution_list_all = {}
        execution_list = []
        if verbose:
            print("id: %s" % qobj['id'])
            print("backend: %s" % qobj['config']['backend'])
            print("qobj config:")
            for key in qobj['config']:
                if key != 'backend':
                    print(' '+ key + ': ' + str(qobj['config'][key]))
        for circuit in qobj['circuits']:
            execution_list.append(circuit["name"])
            if verbose:
                print('  circuit name: ' + circuit["name"])
                print('  circuit config:')
                for key in circuit['config']:
                    print('   '+ key + ': ' + str(circuit['config'][key]))
        return execution_list

    def get_compiled_configuration(self, qobj, name):
        """Get the compiled layout for the named circuit and backend.

        Args:
            name (str):  the circuit name
            qobj (str): the name of the qobj

        Returns:
            the config of the circuit.
        """
        try:
            for index in range(len(qobj["circuits"])):
                if qobj["circuits"][index]['name'] == name:
                    return qobj["circuits"][index]["config"]
        except KeyError:
            raise QISKitError('No compiled configurations for circuit "{0}"'.format(name))

    def get_compiled_qasm(self, qobj, name):
        """Print the compiled cricuit in qasm format.

        Args:
            qobj (str): the name of the qobj
            name (str): name of the quantum circuit

        """
        try:
            for index in range(len(qobj["circuits"])):
                if qobj["circuits"][index]['name'] == name:
                    return qobj["circuits"][index]["compiled_circuit_qasm"]
        except KeyError:
            raise QISKitError('No compiled qasm for circuit "{0}"'.format(name))

    def _dag2json(self, dag_circuit):
        """Make a Json representation of the circuit.

        Takes a circuit dag and returns json circuit obj. This is an internal
        function.

        Args:
            dag_ciruit (dag object): a dag representation of the circuit

        Returns:
            the json version of the dag
        """
        # TODO: Jay: I think this needs to become a method like .qasm() for the DAG.
        circuit_string = dag_circuit.qasm(qeflag=True)
        basis_gates = "u1,u2,u3,cx,id"  # QE target basis
        unroller = unroll.Unroller(qasm.Qasm(data=circuit_string).parse(), unroll.JsonBackend(basis_gates.split(",")))
        json_circuit = unroller.execute()
        return json_circuit

    def _unroller_code(self, dag_ciruit, basis_gates=None):
        """ Unroll the code.

        Circuit is the circuit to unroll using the DAG representation.
        This is an internal function.

        Args:
            dag_ciruit (dag object): a dag representation of the circuit
            basis_gates (str): a comma seperated string and are the base gates,
                               which by default are: u1,u2,u3,cx,id
        Return:
            dag_ciruit (dag object): a dag representation of the circuit
                                     unrolled to basis gates
        """
        if not basis_gates:
            basis_gates = "u1,u2,u3,cx,id"  # QE target basis
        unrolled_circuit = unroll.Unroller(qasm.Qasm(data=dag_ciruit.qasm()).parse(),
                                           unroll.DAGBackend(basis_gates.split(",")))
        dag_circuit_unrolled = unrolled_circuit.execute()
        return dag_circuit_unrolled

    ###############################################################
    # methods to run quantum programs (run )
    ###############################################################

    def run(self, qobj, wait=5, timeout=60, silent=True):
        """Run a program (a pre-compiled quantum program).

        All input for run comes from qobj

        Args:
            qobj(dict): the dictionary of the quantum object to run
            wait (int): wait time is how long to check if the job is completed
            timeout (int): is time until the execution stops
            silent (bool): is an option to print out the running information or
            not

        Returns:
            status done and populates the internal __quantum_program with the
            data

        """
        backend = qobj['config']['backend']
        if not silent:
            print("running on backend: %s" % (backend))
        if backend in self.__ONLINE_BACKENDS:
            max_credits = qobj["config"]["max_credits"]
            shots = qobj["config"]["shots"]
            jobs = []
            for job in qobj["circuits"]:
                jobs.append({'qasm': job["compiled_circuit_qasm"]})
            output = self.__api.run_job(jobs, backend, shots, max_credits)
            if 'error' in output:
                raise ResultError(output['error'])
            qobj_result = self._wait_for_job(output['id'], wait=wait, timeout=timeout, silent=silent)
        else:
            # making a list of jobs just for local backends. Name is droped
            # but the list is made ordered
            jobs = []
            for job in qobj["circuits"]:
                jobs.append({"compiled_circuit": job["compiled_circuit"],
                            "config": {**job["config"], **qobj["config"]}})
            qobj_result = self._run_local_simulator(backend, jobs, silent)
        if qobj_result['status'] == 'COMPLETED':
            assert len(qobj["circuits"]) == len(qobj_result['result']), (
                'Internal error in QuantumProgram.run(), job_result')
        results = Result(qobj_result, qobj)
        return results

    def _wait_for_job(self, jobid, wait=5, timeout=60, silent=True):
        """Wait until all online ran jobs are 'COMPLETED'.

        Args:
            jobids:  is a list of id strings.
            wait (int):  is the time to wait between requests, in seconds
            timeout (int):  is how long we wait before failing, in seconds
            silent (bool): is an option to print out the running information or
            not

        Returns:
             Dictionary of form::

                 job_result_return =
                     [
                        {
                         "data": DATA,
                         "status": DATA,
                         },
                         ...
                     ]
        """
        timer = 0
        timeout_over = False
        job_result = self.__api.get_job(jobid)
        if 'status' not in job_result:
            from pprint import pformat
            raise QISKitError("get_job didn't return status: %s" % (pformat(job)))
        while job_result['status'] == 'RUNNING':
            if timer >= timeout:
                return {"status": "ERROR", "result": ["Time Out"]}
            time.sleep(wait)
            timer += wait
            if not silent:
                print("status = %s (%d seconds)" % (job_result['status'], timer))
            job_result = self.__api.get_job(jobid)

            if 'status' not in job_result:
                from pprint import pformat
                raise QISKitError("get_job didn't return status: %s" % (pformat(job_result)))
            if job_result['status'] == 'ERROR_CREATING_JOB' or job_result['status'] == 'ERROR_RUNNING_JOB':
                return {"status": "ERROR", "result": [job_result['status']]}

        # Get the results
        job_result_return = []
        for index in range(len(job_result["qasms"])):
            job_result_return.append({"data": job_result["qasms"][index]["data"],
                                     "status": job_result["qasms"][index]["status"]})
        return {'status': job_result['status'], 'result': job_result_return}

    def _run_local_simulator(self, backend, jobs, silent=True):
        """Run a program of compiled quantum circuits on the local machine.

        Args:
          backend (str): the name of the local simulator to run
          jobs: list of dicts {"compiled_circuit": simulator input data,
                "config": integer num shots}

        Returns:
          Dictionary of form,
          job_results =
            [
                {
                "data": DATA,
                "status": DATA,
                },
                ...
            ]
        """
        job_results = []
        for job in jobs:
            local_simulator = simulators.LocalSimulator(backend, job)
            local_simulator.run(silent=silent)
            this_result = local_simulator.result()
            job_results.append(this_result)
        return {'status': 'COMPLETED', 'result': job_results}

    def execute(self, name_of_circuits, backend="local_qasm_simulator",
                config=None, wait=5, timeout=60, silent=True, basis_gates=None,
                coupling_map=None, initial_layout=None, shots=1024,
                max_credits=3, seed=None):

        """Execute, compile, and run an array of quantum circuits).

        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
            wait (int): wait time is how long to check if the job is completed
            timeout (int): is time until the execution stops
            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:
            status done and populates the internal __quantum_program with the
            data
        """
        # TODO: Jay: currently basis_gates, coupling_map, intial_layout, shots,
        # max_credits, and seed are extra inputs but I would like them to go
        # into the config
        qobj = self.compile(name_of_circuits, backend=backend, config=config,
                     silent=silent, basis_gates=basis_gates,
                     coupling_map=coupling_map, initial_layout=initial_layout,
                     shots=shots, max_credits=max_credits, seed=seed)
        result = self.run(qobj, wait=wait, timeout=timeout, silent=silent)
        return result