Beispiel #1
0
def sample(*, config_file, profile, endpoint, region, client_type, solver_def,
           biases, couplings, random_problem, num_reads, label, sampling_params,
           verbose, json_output, output):
    """Submit Ising-formulated problem and return samples."""

    # we'll limit max line len in non-verbose mode
    maxlen = None if verbose else 120

    # parse params (TODO: move to click validator)
    params = {}
    if sampling_params is not None:
        try:
            params = json.loads(sampling_params)
            assert isinstance(params, dict)
        except:
            raise CLIError("sampling parameters required as JSON-encoded "
                           "map of param names to values", code=99)

    if num_reads is not None:
        params.update(num_reads=num_reads)

    if label:
        params.update(label=label)

    # TODO: add other params, like timeout?
    config = dict(
        config_file=config_file, profile=profile,
        endpoint=endpoint, region=region,
        client=client_type, solver=solver_def)

    client, solver = _get_client_solver(config, output)

    if random_problem:
        linear, quadratic = generate_random_ising_problem(solver)
    else:
        try:
            linear = ast.literal_eval(biases) if biases else {}
            if isinstance(linear, Sequence):
                linear = dict(enumerate(linear))
        except Exception as e:
            raise CLIError(f"Invalid biases: {e}", code=99)
        try:
            quadratic = ast.literal_eval(couplings) if couplings else {}
        except Exception as e:
            raise CLIError(f"Invalid couplings: {e}", code=99)

    output("Using qubit biases: {linear}", linear=list(linear.items()), maxlen=maxlen)
    output("Using qubit couplings: {quadratic}", quadratic=list(quadratic.items()), maxlen=maxlen)
    output("Sampling parameters: {sampling_params}", sampling_params=params)

    response = _sample(
        solver, problem=(linear, quadratic), params=params, output=output)

    if verbose:
        output("Result: {response!r}", response=response.result())

    output("Samples: {samples!r}", samples=response.samples, maxlen=maxlen)
    output("Occurrences: {num_occurrences!r}", num_occurrences=response.num_occurrences, maxlen=maxlen)
    output("Energies: {energies!r}", energies=response.energies, maxlen=maxlen)
Beispiel #2
0
def _write_config(config: ConfigParser, config_file: str):
    """Write config to config_file."""

    config_base = os.path.dirname(config_file)
    if config_base and not os.path.exists(config_base):
        try:
            os.makedirs(config_base)
        except Exception as e:
            raise CLIError(f"Error creating configuration path: {e!r}", code=1)

    try:
        with open(config_file, 'w') as fp:
            config.write(fp)
    except Exception as e:
        raise CLIError(f"Error writing to configuration file: {e!r}", code=2)
Beispiel #3
0
def _sample(solver, problem, params, output):
    """Blocking sample call with error handling and using custom printer."""

    try:
        response = solver.sample_ising(*problem, **params)
        problem_id = response.wait_id()
        output("Submitted problem ID: {problem_id}", problem_id=problem_id)
        response.wait()
    except RequestTimeout:
        raise CLIError("API connection timed out.", 8)
    except PollingTimeout:
        raise CLIError("Polling timeout exceeded.", 9)
    except Exception as e:
        raise CLIError("Sampling error: {!r}".format(e), 10)

    return response
Beispiel #4
0
def _get_client_solver(config, output=None):
    """Helper function to return an instantiated client, and solver, validating
    parameters in the process, while wrapping errors in `CLIError` and using
    `output` writer as a centralized printer.
    """
    if output is None:
        output = click.echo

    # get client
    try:
        client = Client.from_config(**config)
    except Exception as e:
        raise CLIError("Invalid configuration: {}".format(e), code=1)

    config_file = config.get('config_file')
    if config_file:
        output("Using configuration file: {config_file}", config_file=config_file)

    profile = config.get('profile')
    if profile:
        output("Using profile: {profile}", profile=profile)

    output("Using endpoint: {endpoint}", endpoint=client.endpoint)
    output("Using region: {region}", region=client.region)

    # get solver
    try:
        solver = client.get_solver()
    except SolverAuthenticationError:
        raise CLIError("Authentication error. Check credentials in your configuration file.", 2)
    except SolverNotFoundError:
        raise CLIError("Solver not available.", 6)
    except (InvalidAPIResponseError, UnsupportedSolverError):
        raise CLIError("Invalid or unexpected API response.", 3)
    except RequestTimeout:
        raise CLIError("API connection timed out.", 4)
    except requests.exceptions.SSLError as e:
        # we need to handle `ssl.SSLError` wrapped in several exceptions,
        # with differences between py2/3; greping the message is the easiest way
        if 'CERTIFICATE_VERIFY_FAILED' in str(e):
            raise CLIError(
                "Certificate verification failed. Please check that your API endpoint "
                "is correct. If you are connecting to a private or third-party D-Wave "
                "system that uses self-signed certificate(s), please see "
                "https://support.dwavesys.com/hc/en-us/community/posts/360018930954.", 5)
        raise CLIError("Unexpected SSL error while fetching solver: {!r}".format(e), 5)
    except Exception as e:
        raise CLIError("Unexpected error while fetching solver: {!r}".format(e), 5)

    output("Using solver: {solver_id}", solver_id=solver.id)

    return (client, solver)
Beispiel #5
0
def ping(*, config_file, profile, endpoint, region, client_type, solver_def,
         sampling_params, request_timeout, polling_timeout, label, json_output,
         output):
    """Ping the QPU by submitting a single-qubit problem."""

    # parse params (TODO: move to click validator)
    params = {}
    if sampling_params is not None:
        try:
            params = json.loads(sampling_params)
            assert isinstance(params, dict)
        except:
            raise CLIError("sampling parameters required as JSON-encoded "
                           "map of param names to values", code=99)

    if label:
        params.update(label=label)

    config = dict(
        config_file=config_file, profile=profile,
        endpoint=endpoint, region=region,
        client=client_type, solver=solver_def,
        request_timeout=request_timeout, polling_timeout=polling_timeout)

    t0 = timer()
    client, solver = _get_client_solver(config, output)

    # generate problem
    if hasattr(solver, 'nodes'):
        # structured solver: use the first existing node
        problem = ({min(solver.nodes): 0}, {})
    else:
        # unstructured solver doesn't constrain problem graph
        problem = ({0: 1}, {})

    t1 = timer()
    response = _sample(solver, problem, params, output)

    t2 = timer()
    output("\nWall clock time:")
    output(" * Solver definition fetch: {wallclock_solver_definition:.3f} ms", wallclock_solver_definition=(t1-t0)*1000.0)
    output(" * Problem submit and results fetch: {wallclock_sampling:.3f} ms", wallclock_sampling=(t2-t1)*1000.0)
    output(" * Total: {wallclock_total:.3f} ms", wallclock_total=(t2-t0)*1000.0)
    if response.timing:
        output("\nQPU timing:")
        for component, duration in sorted(response.timing.items()):
            output(" * %(name)s = {%(name)s} us" % {"name": component}, **{component: duration})
    else:
        output("\nQPU timing data not available.")
Beispiel #6
0
def _ping(config_file, profile, solver_def, request_timeout, polling_timeout,
          output):
    """Helper method for the ping command that uses `output()` for info output
    and raises `CLIError()` on handled errors.

    This function is invariant to output format and/or error signaling mechanism.
    """

    config = dict(config_file=config_file, profile=profile, solver=solver_def)
    if request_timeout is not None:
        config.update(request_timeout=request_timeout)
    if polling_timeout is not None:
        config.update(polling_timeout=polling_timeout)
    try:
        client = Client.from_config(**config)
    except Exception as e:
        raise CLIError("Invalid configuration: {}".format(e), code=1)
    if config_file:
        output("Using configuration file: {config_file}",
               config_file=config_file)
    if profile:
        output("Using profile: {profile}", profile=profile)
    output("Using endpoint: {endpoint}", endpoint=client.endpoint)

    t0 = timer()
    try:
        solver = client.get_solver()
    except SolverAuthenticationError:
        raise CLIError(
            "Authentication error. Check credentials in your configuration file.",
            2)
    except SolverNotFoundError:
        raise CLIError("Solver not available.", 6)
    except (InvalidAPIResponseError, UnsupportedSolverError):
        raise CLIError("Invalid or unexpected API response.", 3)
    except RequestTimeout:
        raise CLIError("API connection timed out.", 4)
    except requests.exceptions.SSLError as e:
        # we need to handle `ssl.SSLError` wrapped in several exceptions,
        # with differences between py2/3; greping the message is the easiest way
        if 'CERTIFICATE_VERIFY_FAILED' in str(e):
            raise CLIError(
                "Certificate verification failed. Please check that your API endpoint "
                "is correct. If you are connecting to a private or third-party D-Wave "
                "system that uses self-signed certificate(s), please see "
                "https://support.dwavesys.com/hc/en-us/community/posts/360018930954.",
                5)
        raise CLIError(
            "Unexpected SSL error while fetching solver: {!r}".format(e), 5)
    except Exception as e:
        raise CLIError(
            "Unexpected error while fetching solver: {!r}".format(e), 5)

    if hasattr(solver, 'nodes'):
        # structured solver: use the first existing node
        problem = ({min(solver.nodes): 0}, {})
    else:
        # unstructured solver doesn't constrain problem graph
        problem = ({0: 1}, {})

    t1 = timer()
    output("Using solver: {solver_id}", solver_id=solver.id)

    try:
        future = solver.sample_ising(*problem)
        timing = future.timing
    except RequestTimeout:
        raise CLIError("API connection timed out.", 8)
    except PollingTimeout:
        raise CLIError("Polling timeout exceeded.", 9)
    except Exception as e:
        raise CLIError("Sampling error: {!r}".format(e), 10)
    output("Submitted problem ID: {problem_id}", problem_id=future.id)

    t2 = timer()
    output("\nWall clock time:")
    output(" * Solver definition fetch: {wallclock_solver_definition:.3f} ms",
           wallclock_solver_definition=(t1 - t0) * 1000.0)
    output(" * Problem submit and results fetch: {wallclock_sampling:.3f} ms",
           wallclock_sampling=(t2 - t1) * 1000.0)
    output(" * Total: {wallclock_total:.3f} ms",
           wallclock_total=(t2 - t0) * 1000.0)
    if timing:
        output("\nQPU timing:")
        for component, duration in timing.items():
            output(" * %(name)s = {%(name)s} us" % {"name": component},
                   **{component: duration})
    else:
        output("\nQPU timing data not available.")
def _ping(config_file, profile, request_timeout, polling_timeout, output):
    """Helper method for the ping command that uses `output()` for info output
    and raises `CLIError()` on handled errors.

    This function is invariant to output format and/or error signaling mechanism.
    """

    config = dict(config_file=config_file, profile=profile)
    if request_timeout is not None:
        config.update(request_timeout=request_timeout)
    if polling_timeout is not None:
        config.update(polling_timeout=polling_timeout)
    try:
        client = Client.from_config(**config)
    except Exception as e:
        raise CLIError("Invalid configuration: {}".format(e), code=1)
    if config_file:
        output("Using configuration file: {config_file}", config_file=config_file)
    if profile:
        output("Using profile: {profile}", profile=profile)
    output("Using endpoint: {endpoint}", endpoint=client.endpoint)

    t0 = timer()
    try:
        solvers = client.get_solvers()
    except SolverAuthenticationError:
        raise CLIError("Authentication error. Check credentials in your configuration file.", 2)
    except (InvalidAPIResponseError, UnsupportedSolverError):
        raise CLIError("Invalid or unexpected API response.", 3)
    except RequestTimeout:
        raise CLIError("API connection timed out.", 4)
    except Exception as e:
        raise CLIError("Unexpected error while fetching solvers: {!r}".format(e), 5)

    try:
        solver = client.get_solver()
    except (ValueError, KeyError):
        # if not otherwise defined (ValueError), or unavailable (KeyError),
        # just use the first solver
        if solvers:
            _, solver = next(iter(solvers.items()))
        else:
            raise CLIError("No solvers available.", 6)
    except RequestTimeout:
        raise CLIError("API connection timed out.", 7)

    t1 = timer()
    output("Using solver: {solver_id}", solver_id=solver.id)

    try:
        future = solver.sample_ising({0: 1}, {})
        timing = future.timing
    except RequestTimeout:
        raise CLIError("API connection timed out.", 8)
    except PollingTimeout:
        raise CLIError("Polling timeout exceeded.", 9)
    except Exception as e:
        raise CLIError("Sampling error: {!r}".format(e), 10)
    finally:
        output("Submitted problem ID: {problem_id}", problem_id=future.id)

    t2 = timer()

    output("\nWall clock time:")
    output(" * Solver definition fetch: {wallclock_solver_definition:.3f} ms", wallclock_solver_definition=(t1-t0)*1000.0)
    output(" * Problem submit and results fetch: {wallclock_sampling:.3f} ms", wallclock_sampling=(t2-t1)*1000.0)
    output(" * Total: {wallclock_total:.3f} ms", wallclock_total=(t2-t0)*1000.0)
    output("\nQPU timing:")
    for component, duration in timing.items():
        output(" * %(name)s = {%(name)s} us" % {"name": component}, **{component: duration})