def test_wait_many(self): """Submit a batch of problems then use `wait_multiple` to wait on all of them.""" # Connect client = Client(config_url, config_token) solver = client.get_solver(config_solver) # Build a linear problem linear = [0] * (max(solver.nodes) + 1) for index in solver.nodes: linear[index] = random.choice([-1, 1]) # Build a quad = {key: random.choice([-1, 1]) for key in solver.undirected_edges} result_list = [] for _ in range(100): results = solver.sample_ising(linear, quad, num_reads=40) result_list.append([results, linear, quad]) dwave.cloud.computation.Future.wait_multiple( [f[0] for f in result_list]) for results, _, _ in result_list: self.assertTrue(results.done()) for results, linear, quad in result_list: # Did we get the right number of samples? self.assertTrue(40 == sum(results.occurrences)) # Make sure the number of occurrences and energies are all correct for energy, state in zip(results.energies, results.samples): self.assertTrue(energy == evaluate_ising(linear, quad, state))
def test_submit_partial_problem(self): """Submit a problem with only some of the terms set.""" # Connect client = Client(config_url, config_token) solver = client.get_solver(config_solver) # Build a linear problem linear = [0] * (max(solver.nodes) + 1) for index in solver.nodes: linear[index] = random.choice([-1, 1]) # Build a quad = {key: random.choice([-1, 1]) for key in solver.undirected_edges} # Remove half the qubits nodes = list(solver.nodes) for index in nodes[0:len(nodes) // 2]: linear[index] = 0 quad = { key: value for key, value in quad.items() if index not in key } # Solve the problem self._submit_and_check(solver, linear, quad)
def test_submit_batch(self): """Submit batch of problems.""" # Connect client = Client(config_url, config_token) solver = client.get_solver(config_solver) result_list = [] for _ in range(100): # Build a linear problem linear = [0] * (max(solver.nodes) + 1) for index in solver.nodes: linear[index] = random.choice([-1, 1]) # Build a quad = { key: random.choice([-1, 1]) for key in solver.undirected_edges } results = solver.sample_ising(linear, quad, num_reads=10) result_list.append([results, linear, quad]) for results, linear, quad in result_list: # Did we get the right number of samples? self.assertTrue(10 == sum(results.occurrences)) # Make sure the number of occurrences and energies are all correct for energy, state in zip(results.energies, results.samples): self.assertTrue(energy == evaluate_ising(linear, quad, state))
def test_load_solver_missing_data(self): """Try to load a solver that has incomplete data.""" with requests_mock.mock() as m: m.get(solver1_url, text=solver_object(solver_name, True)) client = Client(url, token) with self.assertRaises(InvalidAPIResponseError): client.get_solver(solver_name)
def test_submit_invalid_parameter(self): """Ensure that the parameters are populated.""" client = Client(config_url, config_token) solver = client.get_solver(config_solver) assert 'not_a_parameter' not in solver.parameters with self.assertRaises(KeyError): solver.sample_ising({}, {}, not_a_parameter=True)
def test_bad_token(self): """Connect with a bad token.""" with requests_mock.mock() as m: setup_server(m) with self.assertRaises(IOError): client = Client(url, bad_token) client.get_solvers()
def test_as_completed(self): """Submit a batch of problems then use `as_completed` to iterate over all of them.""" # Connect client = Client(config_url, config_token) solver = client.get_solver(config_solver) # Build a problem linear = [0] * (max(solver.nodes) + 1) for index in solver.nodes: linear[index] = random.choice([-1, 1]) quad = {key: random.choice([-1, 1]) for key in solver.undirected_edges} # Sample the solution 100x40 times computations = [ solver.sample_ising(linear, quad, num_reads=40) for _ in range(100) ] # Go over computations, one by one, as they're done and check they're OK for computation in dwave.cloud.computation.Future.as_completed( computations): self.assertTrue(computation.done()) self.assertTrue(40 == sum(computation.occurrences)) for energy, state in zip(computation.energies, computation.samples): self.assertTrue(energy == evaluate_ising(linear, quad, state))
def test_load_missing_solver(self): """Try to load a solver that does not exist.""" with requests_mock.mock() as m: m.get(requests_mock.ANY, status_code=404) client = Client(url, token) with self.assertRaises(KeyError): client.get_solver(solver_name)
def test_solver_filtering_in_client(self): self.assertTrue( Client.is_solver_handled( Solver(None, json.loads(solver_object('test'))))) self.assertFalse( Client.is_solver_handled( Solver(None, json.loads(solver_object('c4-sw_'))))) self.assertFalse(None)
def test_load_solver_broken_response(self): """Try to load a solver for which the server has returned a truncated response.""" with requests_mock.mock() as m: body = solver_object(solver_name) m.get(solver1_url, text=body[0:len(body) // 2]) client = Client(url, token) with self.assertRaises(ValueError): client.get_solver(solver_name)
def test_result_structure(self): client = Client(config_url, config_token) solver = client.get_solver(config_solver) computation = solver.sample_ising({}, {}) result = computation.result() self.assertIn('samples', result) self.assertIn('energies', result) self.assertIn('occurrences', result) self.assertIn('timing', result)
def test_submit_dict_problem(self): """Submit a problem using a dict for the linear terms.""" # Connect client = Client(config_url, config_token) solver = client.get_solver(config_solver) # Build a problem linear = {index: random.choice([-1, 1]) for index in solver.nodes} quad = {key: random.choice([-1, 1]) for key in solver.undirected_edges} # Solve the problem self._submit_and_check(solver, linear, quad)
def test_submit_linear_problem(self): """Submit a problem with all the linear terms populated.""" # Connect client = Client(config_url, config_token) solver = client.get_solver(config_solver) # Build a linear problem linear = [0] * (max(solver.nodes) + 1) for index in solver.nodes: linear[index] = 1 quad = {} # Solve the problem self._submit_and_check(solver, linear, quad)
def test_request_raw_list_with_numpy(self): """Submit a problem using a dict for the linear terms.""" # Connect client = Client(config_url, config_token) assert dwave.cloud.computation._numpy solver = client.get_solver(config_solver) solver.return_matrix = False # Build a problem linear = {index: random.choice([-1, 1]) for index in solver.nodes} quad = {key: random.choice([-1, 1]) for key in solver.undirected_edges} # Solve the problem self._submit_and_check(solver, linear, quad)
def test_solver_filtering_in_client(self): # base client self.assertTrue(Client.is_solver_handled(solver_object('test'))) self.assertTrue(Client.is_solver_handled(solver_object('c4-sw_'))) self.assertTrue(Client.is_solver_handled(None)) # qpu client self.assertTrue(QPUClient.is_solver_handled(solver_object('test'))) self.assertFalse(QPUClient.is_solver_handled(solver_object('c4-sw_'))) self.assertFalse(QPUClient.is_solver_handled(None)) # sw client self.assertFalse( SoftwareClient.is_solver_handled(solver_object('test'))) self.assertTrue( SoftwareClient.is_solver_handled(solver_object('c4-sw_'))) self.assertFalse(SoftwareClient.is_solver_handled(None))
def test_request_raw_matrix_with_no_numpy(self): """Submit a problem using a dict for the linear terms.""" # Connect client = Client(config_url, config_token) dwave.cloud.computation._numpy = False solver = client.get_solver(config_solver) solver.return_matrix = True # Build a problem linear = {index: random.choice([-1, 1]) for index in solver.nodes} quad = {key: random.choice([-1, 1]) for key in solver.undirected_edges} # Solve the problem with self.assertRaises(ValueError): self._submit_and_check(solver, linear, quad, answer_mode='raw')
def test_reverse_annealing(self): with Client(**config) as client: solver = client.get_solver() # skip if we don't have access to the initial_state parameter for reverse annealing if 'initial_state' not in solver.parameters: raise unittest.SkipTest anneal_schedule = [(0, 1), (55.00000000000001, 0.45), (155.0, 0.45), (210.0, 1)] # make some subset of the qubits active active = [v for v in solver.properties['qubits'] if v % 2] # make an initial state, ising problem initial_state = {v: 2 * bool(v % 3) - 1 for v in active} h = {v: 0.0 for v in active} J = {(u, v): -1 for (u, v) in solver.properties['couplers'] if v in h and u in h} # doesn't catch fire solver.sample_ising(h, J, anneal_schedule=anneal_schedule, initial_state=initial_state).samples
def test_submit_full_problem(self): """Submit a problem with all supported coefficients set.""" with Client(**config) as client: solver = client.get_solver() linear, quad = generate_random_ising_problem(solver) self._submit_and_check(solver, linear, quad)
def test_submit_linear_problem(self): """Submit a problem with all the linear terms populated.""" with Client(**config) as client: solver = client.get_solver() linear, quad = generate_random_ising_problem(solver) self._submit_and_check(solver, linear, {})
def test_cancel_batch(self): """Submit batch of problems, then cancel them.""" # Connect with Client(**config) as client: solver = client.get_solver() # Build a linear problem linear = [0] * (max(solver.nodes) + 1) for index in solver.nodes: linear[index] = random.choice([-1, 1]) # Build a quad = {key: random.choice([-1, 1]) for key in solver.undirected_edges} result_list = [] for _ in range(1000): results = solver.sample_ising(linear, quad, num_reads=10000) result_list.append([results, linear, quad]) [r[0].cancel() for r in result_list] for results, linear, quad in result_list: # Responses must be canceled or correct try: # Did we get the right number of samples? self.assertTrue(10000 == sum(results.occurrences)) # Make sure the number of occurrences and energies are all correct for energy, state in zip(results.energies, results.samples): self.assertTrue(energy == evaluate_ising(linear, quad, state)) except CanceledFutureError: pass
def test_cancel_with_id(self): """Make sure the cancel method submits to the right endpoint. When cancel is called after the submission is finished. """ submission_id = 'test-id' reply_body = '[%s]' % continue_reply(submission_id, 'solver') with Client('endpoint', 'token') as client: client.session = mock.Mock() client.session.get = lambda a: choose_reply( a, {'endpoint/problems/?id={}'.format(submission_id): reply_body}) client.session.delete = DeleteEvent.handle solver = Solver(client, solver_data('abc123')) future = solver.retrieve_problem(submission_id) future.cancel() try: self.assertTrue(future.id is not None) future.samples self.fail() except DeleteEvent as event: if event.url == 'endpoint/problems/': self.assertEqual(event.body, '["{}"]'.format(submission_id)) else: self.assertEqual( event.url, 'endpoint/problems/{}/'.format(submission_id))
def test_custom_options(self): """Test custom options (request_timeout, polling_timeout, permissive_ssl) are propagated to Client.""" request_timeout = 15 polling_timeout = 180 with mock.patch("dwave.cloud.config.open", iterable_mock_open(config_body), create=True): with Client.from_config('config_file', profile='custom') as client: # check permissive_ssl and timeouts custom params passed-thru self.assertFalse(client.session.verify) self.assertEqual(client.request_timeout, request_timeout) self.assertEqual(client.polling_timeout, polling_timeout) # verify client uses those properly def mock_send(*args, **kwargs): self.assertEqual(kwargs.get('timeout'), request_timeout) response = requests.Response() response.status_code = 200 response._content = b'{}' return response with mock.patch("requests.adapters.HTTPAdapter.send", mock_send): client.solvers()
def test_submit_continue_then_ok_reply(self): """Handle polling for a complete problem.""" with Client('endpoint', 'token') as client: client.session = mock.Mock() client.session.post = lambda a, _: choose_reply( a, { 'endpoint/problems/': '[%s]' % continue_reply( '123', 'abc123') }) client.session.get = lambda a: choose_reply( a, { 'endpoint/problems/?id=123': '[%s]' % complete_no_answer_reply('123', 'abc123'), 'endpoint/problems/123/': complete_reply('123', 'abc123') }) solver = Solver(client, solver_data('abc123')) # Build a problem linear = {index: 1 for index in solver.nodes} quad = {key: -1 for key in solver.undirected_edges} results = solver.sample_ising(linear, quad, num_reads=100) # self._check(results, linear, quad, 100)
def test_bad_token(self): """Connect with a bad token.""" with self.assertRaises(SolverAuthenticationError): invalid_config = config.copy() invalid_config.update(token='invalid-token') with Client(**invalid_config) as client: client.get_solvers()
def test_wait_many(self): """Submit a batch of problems then use `wait_multiple` to wait on all of them.""" with Client(**config) as client: solver = client.get_solver() linear, quad = generate_random_ising_problem(solver) result_list = [] for _ in range(100): results = solver.sample_ising(linear, quad, num_reads=40) result_list.append([results, linear, quad]) dwave.cloud.computation.Future.wait_multiple( [f[0] for f in result_list]) for results, _, _ in result_list: self.assertTrue(results.done()) for results, linear, quad in result_list: # Did we get the right number of samples? self.assertEqual(40, sum(results.occurrences)) # Make sure the number of occurrences and energies are all correct for energy, state in zip(results.energies, results.samples): self.assertAlmostEqual(energy, evaluate_ising(linear, quad, state))
def test_reverse_annealing_off_vartype(self): with Client(**config) as client: solver = client.get_solver() # skip if we don't have access to the initial_state parameter for reverse annealing if 'initial_state' not in solver.parameters: raise unittest.SkipTest anneal_schedule = [(0, 1), (55.00000000000001, 0.45), (155.0, 0.45), (210.0, 1)] # make some subset of the qubits active active = [v for v in solver.properties['qubits'] if v % 2] # ising state, qubo problem initial_state_ising = {v: 2 * bool(v % 3) - 1 for v in active} Q = {(v, v): 1 for v in active} fq = solver.sample_qubo(Q, anneal_schedule=anneal_schedule, initial_state=initial_state_ising) # qubo state, ising problem initial_state_qubo = {v: bool(v % 3) for v in active} h = {v: 1 for v in active} J = {} fi = solver.sample_ising(h, J, anneal_schedule=anneal_schedule, initial_state=initial_state_qubo) fq.samples fi.samples
def test_cancel_batch(self): """Submit batch of problems, then cancel them.""" with Client(**config) as client: solver = client.get_solver() linear, quad = generate_random_ising_problem(solver) max_num_reads = max( solver.properties.get('num_reads_range', [1, 100])) result_list = [] for _ in range(1000): results = solver.sample_ising(linear, quad, num_reads=max_num_reads) result_list.append([results, linear, quad]) [r[0].cancel() for r in result_list] for results, linear, quad in result_list: # Responses must be canceled or correct try: # Did we get the right number of samples? self.assertEqual(max_num_reads, sum(results.occurrences)) # Make sure the number of occurrences and energies are all correct for energy, state in zip(results.energies, results.samples): self.assertAlmostEqual( energy, evaluate_ising(linear, quad, state)) except CanceledFutureError: pass
def test_bad_url(self): """Connect with a bad URL.""" with requests_mock.mock() as m: setup_server(m) with self.assertRaises(IOError): with Client(bad_url, token) as client: client.get_solvers()
def test_submit_invalid_parameter(self): """Ensure that the parameters are populated.""" with Client(**config) as client: solver = client.get_solver() self.assertNotIn('not_a_parameter', solver.parameters) with self.assertRaises(KeyError): solver.sample_ising({}, {}, not_a_parameter=True)
def test_bad_url(self): """Connect with a bad URL.""" with self.assertRaises(IOError): invalid_config = config.copy() invalid_config.update(endpoint='invalid-endpoint') with Client(**invalid_config) as client: client.get_solvers()