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)
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)
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
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)
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.")
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})