class FeatureBasedSolverSelection(unittest.TestCase): """Test Client.get_solvers(**filters).""" def setUp(self): # mock solvers self.qpu1 = StructuredSolver( client=None, data={ "properties": { "supported_problem_types": ["qubo", "ising"], "qubits": [0, 1, 2], "couplers": [[0, 1], [0, 2], [1, 2]], "num_qubits": 3, "num_reads_range": [0, 100], "parameters": { "num_reads": "Number of samples to return.", "postprocess": "either 'sampling' or 'optimization'" }, "topology": { "type": "chimera", "shape": [16, 16, 4] }, "category": "qpu", "tags": ["lower_noise"] }, "id": "qpu1", "description": "QPU Chimera solver", "status": "online", "avg_load": 0.1 }) self.qpu2 = StructuredSolver( client=None, data={ "properties": { "supported_problem_types": ["qubo", "ising"], "qubits": [0, 1, 2, 3, 4], "couplers": [[0, 1], [0, 2], [1, 2], [2, 3], [3, 4]], "num_qubits": 5, "num_reads_range": [0, 200], "parameters": { "num_reads": "Number of samples to return.", "flux_biases": "Supported ...", "anneal_schedule": "Supported ..." }, "topology": { "type": "pegasus", "shape": [6, 6, 12] }, "category": "qpu", "vfyc": True }, "id": "qpu2", "description": "QPU Pegasus solver", "avg_load": 0.2 }) self.software = StructuredSolver( client=None, data={ "properties": { "supported_problem_types": ["qubo", "ising"], "qubits": [0, 1], "couplers": [[0, 1]], "num_qubits": 7, "num_reads_range": [0, 1000], "parameters": { "num_reads": "Number of samples to return." }, "vfyc": False, "topology": { "type": "chimera", "shape": [4, 4, 4] }, "category": "software", # the following are only present in this solver "some_set": [1, 2], "some_range": [1, 2], "some_string": "x", "tags": ["tag"] }, "id": "sw_solver1", "description": "Software solver", "avg_load": 0.7 }) self.hybrid = UnstructuredSolver(client=None, data={ "properties": { "supported_problem_types": ["bqm"], "maximum_number_of_variables": 10000, "maximum_time_limit_hrs": 24.0, "minimum_time_limit": [[1, 3.0], [1024, 3.0], [4096, 10.0], [10000, 40.0]], "quota_conversion_rate": 20, "parameters": { "time_limit": "" }, "category": "hybrid", }, "id": "hybrid_v1", "description": "Hybrid solver" }) self.qpu_solvers = [self.qpu1, self.qpu2] self.software_solvers = [self.software] self.hybrid_solvers = [self.hybrid] self.structured_solvers = self.qpu_solvers + self.software_solvers self.unstructured_solvers = self.hybrid_solvers self.solvers = self.structured_solvers + self.unstructured_solvers # mock client self.client = Client('endpoint', 'token') self.client._fetch_solvers = lambda **kw: self.solvers def shutDown(self): self.client.close() def assertSolvers(self, container, members): self.assertEqual(set(container), set(members)) def test_default(self): self.assertSolvers(self.client.get_solvers(), self.solvers) def test_online(self): self.assertSolvers(self.client.get_solvers(online=True), self.solvers) self.assertSolvers(self.client.get_solvers(online=False), []) def test_derived_category_properties(self): self.assertSolvers(self.client.get_solvers(qpu=True), self.qpu_solvers) self.assertSolvers(self.client.get_solvers(qpu=False), self.software_solvers + self.hybrid_solvers) self.assertSolvers(self.client.get_solvers(software=True), self.software_solvers) self.assertSolvers(self.client.get_solvers(software=False), self.qpu_solvers + self.hybrid_solvers) self.assertSolvers(self.client.get_solvers(hybrid=True), self.hybrid_solvers) self.assertSolvers(self.client.get_solvers(hybrid=False), self.qpu_solvers + self.software_solvers) # Test fallback for legacy solvers without the `category` property # TODO: remove when all production solvers are updated def test_derived_category_properties_without_category(self): "Category-based filtering works without explicit `category` property." @contextmanager def multi_solver_properties_patch(solvers, update): """Update properties for all `solvers` at once.""" patchers = [mock.patch.dict(s.properties, update) for s in solvers] try: yield (p.start() for p in patchers) finally: return (p.stop() for p in patchers) with mock.patch.object(self.software, 'id', 'c4-sw_solver3'): # patch categories and re-run the category-based filtering test with multi_solver_properties_patch(self.solvers, {'category': ''}): self.test_derived_category_properties() # verify patching with multi_solver_properties_patch(self.solvers, {'category': 'x'}): with self.assertRaises(AssertionError): self.test_derived_category_properties() def test_category(self): self.assertSolvers(self.client.get_solvers(category='qpu'), self.qpu_solvers) self.assertSolvers(self.client.get_solvers(category='software'), self.software_solvers) self.assertSolvers(self.client.get_solvers(category='hybrid'), self.hybrid_solvers) def test_name(self): self.assertSolvers(self.client.get_solvers(name='qpu1'), [self.qpu1]) self.assertSolvers(self.client.get_solvers(name='qpu2'), [self.qpu2]) self.assertSolvers(self.client.get_solvers(name='solver'), []) self.assertSolvers(self.client.get_solvers(name='olver1'), []) self.assertSolvers(self.client.get_solvers(name__regex='.*1'), [self.qpu1, self.software, self.hybrid]) self.assertSolvers(self.client.get_solvers(name__regex='.*_v1'), [self.hybrid]) self.assertSolvers(self.client.get_solvers(name__regex='.*[12].*'), self.solvers) self.assertSolvers(self.client.get_solvers(name__regex='qpu[12]'), [self.qpu1, self.qpu2]) self.assertSolvers(self.client.get_solvers(name__regex='^qpu(1|2)$'), [self.qpu1, self.qpu2]) def test_num_qubits(self): self.assertSolvers(self.client.get_solvers(num_qubits=5), [self.qpu2]) self.assertSolvers(self.client.get_solvers(num_active_qubits=2), [self.software]) self.assertSolvers( self.client.get_solvers(num_active_qubits__in=[2, 3]), [self.qpu1, self.software]) def test_lower_noise_derived_property(self): self.assertSolvers(self.client.get_solvers(lower_noise=True), [self.qpu1]) self.assertSolvers(self.client.get_solvers(lower_noise=False), [self.qpu2, self.software]) def test_parameter_availability_check(self): self.assertSolvers( self.client.get_solvers(postprocess__available=True), [self.qpu1]) self.assertSolvers(self.client.get_solvers(postprocess=True), [self.qpu1]) self.assertSolvers( self.client.get_solvers(parameters__contains='flux_biases'), [self.qpu2]) self.assertSolvers( self.client.get_solvers(parameters__contains='num_reads'), self.structured_solvers) def test_property_availability_check(self): self.assertSolvers(self.client.get_solvers(vfyc__available=True), [self.qpu2, self.software]) self.assertSolvers(self.client.get_solvers(vfyc__eq=True), [self.qpu2]) self.assertSolvers(self.client.get_solvers(vfyc=True), [self.qpu2]) # inverse of vfyc=True self.assertSolvers(self.client.get_solvers(vfyc__in=[False, None]), [self.qpu1, self.software, self.hybrid]) # vfyc unavailable or unadvertized self.assertSolvers(self.client.get_solvers(vfyc__available=False), [self.qpu1, self.hybrid]) self.assertSolvers(self.client.get_solvers(vfyc__eq=False), [self.software]) self.assertSolvers(self.client.get_solvers(vfyc=False), [self.software]) # non-existing params/props have value of None self.assertSolvers(self.client.get_solvers(vfyc__eq=None), [self.qpu1, self.hybrid]) self.assertSolvers(self.client.get_solvers(vfyc=None), [self.qpu1, self.hybrid]) def test_availability_combo(self): self.assertSolvers( self.client.get_solvers(vfyc=False, flux_biases=True), []) self.assertSolvers( self.client.get_solvers(vfyc=True, flux_biases=True), [self.qpu2]) def test_relational_ops(self): self.assertSolvers(self.client.get_solvers(num_qubits=3), [self.qpu1]) self.assertSolvers(self.client.get_solvers(num_qubits__eq=3), [self.qpu1]) self.assertSolvers(self.client.get_solvers(num_qubits=4), []) self.assertSolvers(self.client.get_solvers(num_qubits=5), [self.qpu2]) self.assertSolvers(self.client.get_solvers(num_qubits__gte=2), self.structured_solvers) self.assertSolvers(self.client.get_solvers(num_qubits__gte=5), [self.qpu2, self.software]) self.assertSolvers(self.client.get_solvers(num_qubits__gt=5), [self.software]) self.assertSolvers(self.client.get_solvers(num_qubits__lte=8), self.structured_solvers) self.assertSolvers(self.client.get_solvers(num_qubits__lte=7), self.structured_solvers) self.assertSolvers(self.client.get_solvers(num_qubits__lt=7), [self.qpu1, self.qpu2]) # skip solver if LHS value not defined (None) self.assertSolvers(self.client.get_solvers(avg_load__gt=0), [self.qpu1, self.qpu2, self.software]) self.assertSolvers(self.client.get_solvers(avg_load__gte=0), [self.qpu1, self.qpu2, self.software]) self.assertSolvers(self.client.get_solvers(avg_load__lt=1), [self.qpu1, self.qpu2, self.software]) self.assertSolvers(self.client.get_solvers(avg_load__lte=1), [self.qpu1, self.qpu2, self.software]) self.assertSolvers(self.client.get_solvers(avg_load=0.7), [self.software]) self.assertSolvers(self.client.get_solvers(avg_load__eq=0.7), [self.software]) self.assertSolvers(self.client.get_solvers(avg_load=None), [self.hybrid]) self.assertSolvers(self.client.get_solvers(avg_load__eq=None), [self.hybrid]) def test_range_ops(self): # value within range self.assertSolvers(self.client.get_solvers(num_qubits__within=[3, 7]), self.structured_solvers) self.assertSolvers(self.client.get_solvers(num_qubits__within=[3, 5]), [self.qpu1, self.qpu2]) self.assertSolvers(self.client.get_solvers(num_qubits__within=[2, 4]), [self.qpu1]) self.assertSolvers(self.client.get_solvers(num_qubits__within=(2, 4)), [self.qpu1]) self.assertSolvers(self.client.get_solvers(num_qubits__within=(4, 2)), [self.qpu1]) # range within (covered by) range self.assertSolvers( self.client.get_solvers(num_reads_range__within=(0, 500)), [self.qpu1, self.qpu2]) self.assertSolvers( self.client.get_solvers(num_reads_range__within=(1, 500)), []) # invalid LHS self.assertSolvers(self.client.get_solvers(some_range__within=[0, 2]), [self.software]) # range covering a value (value included in range) self.assertSolvers(self.client.get_solvers(num_reads_range__covers=0), self.structured_solvers) self.assertSolvers( self.client.get_solvers(num_reads_range__covers=150), [self.qpu2, self.software]) self.assertSolvers( self.client.get_solvers(num_reads_range__covers=550), [self.software]) self.assertSolvers( self.client.get_solvers(num_reads_range__covers=1000), [self.software]) self.assertSolvers( self.client.get_solvers(num_reads_range__covers=1001), []) # range covering a range self.assertSolvers( self.client.get_solvers(num_reads_range__covers=(10, 90)), self.structured_solvers) self.assertSolvers( self.client.get_solvers(num_reads_range__covers=(110, 200)), [self.qpu2, self.software]) # invalid LHS self.assertSolvers(self.client.get_solvers(some_range__covers=1.5), [self.software]) def test_membership_ops(self): # property contains self.assertSolvers( self.client.get_solvers(supported_problem_types__contains="qubo"), self.structured_solvers) self.assertSolvers( self.client.get_solvers(supported_problem_types__contains="undef"), []) self.assertSolvers( self.client.get_solvers(supported_problem_types__contains="bqm"), self.unstructured_solvers) self.assertSolvers(self.client.get_solvers(couplers__contains=[0, 1]), [self.qpu1, self.qpu2, self.software]) self.assertSolvers(self.client.get_solvers(couplers__contains=[0, 2]), [self.qpu1, self.qpu2]) # property in self.assertSolvers(self.client.get_solvers(num_qubits__in=[3, 5]), [self.qpu1, self.qpu2]) self.assertSolvers(self.client.get_solvers(num_qubits__in=[7]), [self.software]) self.assertSolvers(self.client.get_solvers(num_qubits__in=[]), []) # invalid LHS self.assertSolvers(self.client.get_solvers(some_set__contains=1), [self.software]) self.assertSolvers(self.client.get_solvers(avg_load__in=[None]), [self.hybrid]) self.assertSolvers( self.client.get_solvers(avg_load__in=[None, 0.1, 0.2, 0.7]), self.solvers) def test_set_ops(self): # property issubset self.assertSolvers( self.client.get_solvers( supported_problem_types__issubset=("qubo", "ising", "bqm", "other")), self.solvers) self.assertSolvers( self.client.get_solvers( supported_problem_types__issubset=["qubo", "ising", "bqm"]), self.solvers) self.assertSolvers( self.client.get_solvers( supported_problem_types__issubset=["bqm", "ising", "qubo"]), self.solvers) self.assertSolvers( self.client.get_solvers( supported_problem_types__issubset={"ising", "qubo", "bqm"}), self.solvers) self.assertSolvers( self.client.get_solvers( supported_problem_types__issubset=("unicorn", "ising", "other")), []) self.assertSolvers( self.client.get_solvers( supported_problem_types__issubset={"ising", "qubo"}), self.structured_solvers) self.assertSolvers( self.client.get_solvers( supported_problem_types__issubset={"bqm", "other"}), self.unstructured_solvers) # property issuperset self.assertSolvers(self.client.get_solvers(qubits__issuperset={0, 1}), self.structured_solvers) self.assertSolvers(self.client.get_solvers(qubits__issuperset={1, 2}), [self.qpu1, self.qpu2]) # unhashable types self.assertSolvers( self.client.get_solvers(couplers__issuperset=[[0, 1]]), self.structured_solvers) self.assertSolvers( self.client.get_solvers(couplers__issuperset={(0, 1)}), self.structured_solvers) self.assertSolvers( self.client.get_solvers(couplers__issuperset={(0, 1), (0, 2)}), [self.qpu1, self.qpu2]) self.assertSolvers( self.client.get_solvers(couplers__issuperset={(0, 1), (0, 2), (2, 3)}), [self.qpu2]) self.assertSolvers( self.client.get_solvers( couplers__issuperset={(0, 1), (0, 2), (2, 3), (0, 5)}), []) # invalid LHS self.assertSolvers( self.client.get_solvers(some_set__issubset={0, 1, 2}), [self.software]) self.assertSolvers(self.client.get_solvers(some_set__issuperset={1}), [self.software]) def test_regex(self): self.assertSolvers( self.client.get_solvers(num_reads__regex='.*number.*'), []) self.assertSolvers( self.client.get_solvers(num_reads__regex='.*Number.*'), self.structured_solvers) self.assertSolvers( self.client.get_solvers(num_reads__regex='Number.*'), self.structured_solvers) self.assertSolvers(self.client.get_solvers(num_reads__regex='Number'), []) # invalid LHS self.assertSolvers(self.client.get_solvers(some_string__regex='x'), [self.software]) def test_range_boolean_combo(self): self.assertSolvers(self.client.get_solvers(num_qubits=3, vfyc=True), []) self.assertSolvers( self.client.get_solvers(num_qubits__gte=3, vfyc=True), [self.qpu2]) self.assertSolvers( self.client.get_solvers(num_qubits__lte=4, vfyc=True), []) self.assertSolvers( self.client.get_solvers(num_qubits__within=(3, 6), flux_biases=True), [self.qpu2]) self.assertSolvers( self.client.get_solvers(num_qubits=5, flux_biases=True), [self.qpu2]) def test_nested_properties_leaf_lookup(self): self.assertSolvers(self.client.get_solvers(topology__type="chimera"), [self.qpu1, self.software]) self.assertSolvers(self.client.get_solvers(topology__type="pegasus"), [self.qpu2]) self.assertSolvers( self.client.get_solvers(topology__type__eq="pegasus"), [self.qpu2]) self.assertSolvers(self.client.get_solvers(topology__shape=[6, 6, 12]), [self.qpu2]) self.assertSolvers( self.client.get_solvers(topology__type="chimera", topology__shape__contains=16), [self.qpu1]) def test_nested_properties_intermediate_key_lookup(self): self.assertSolvers(self.client.get_solvers(topology__contains="shape"), self.structured_solvers) self.assertSolvers( self.client.get_solvers(topology={ "type": "pegasus", "shape": [6, 6, 12] }), [self.qpu2]) def test_anneal_schedule(self): self.assertSolvers( self.client.get_solvers(anneal_schedule__available=True), [self.qpu2]) self.assertSolvers(self.client.get_solvers(anneal_schedule=True), [self.qpu2]) def test_solvers_deprecation(self): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") self.client.solvers() self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) def test_order_by_edgecases(self): # default: sort by avg_load self.assertEqual(self.client.get_solvers(), [self.qpu1, self.qpu2, self.software, self.hybrid]) # explicit no sort self.assertEqual(self.client.get_solvers(order_by=None), self.solvers) self.assertEqual(self.client.get_solvers(order_by=''), self.solvers) self.assertEqual(self.client.get_solvers(order_by=False), self.solvers) # reverse without sorting self.assertEqual(self.client.get_solvers(order_by='-'), list(reversed(self.solvers))) # invalid type of `order_by` with self.assertRaises(TypeError): self.client.get_solvers(order_by=1) with self.assertRaises(TypeError): self.client.get_solvers(order_by=list) def test_order_by_respects_default_solver(self): """order_by used in isolation should not affect default_solver filters (issue #401)""" with Client('endpoint', 'token', solver=dict(name='qpu2')) as client: # mock the network call to fetch all solvers client._fetch_solvers = lambda **kw: self.solvers # the default solver was set on client init self.assertEqual(client.get_solver(), self.qpu2) # the default solver should not change when we add order_by self.assertEqual(client.get_solver(order_by='id'), self.qpu2) with Client('endpoint', 'token', solver=dict(category='qpu')) as client: # mock the network call to fetch all solvers client._fetch_solvers = lambda **kw: self.solvers # test default order_by is avg_load self.assertEqual(client.get_solver(), self.qpu1) # but we can change it, without affecting solver filters self.assertEqual(client.get_solver(order_by='-avg_load'), self.qpu2) def test_order_by_in_default_solver(self): """order_by can be specified as part of default_solver filters (issue #407)""" with Client('endpoint', 'token', solver=dict(order_by='id')) as client: # mock the network call to fetch all solvers client._fetch_solvers = lambda **kw: self.solvers # the default solver was set on client init self.assertEqual(client.get_solver(), self.hybrid) # the default solver can be overridden self.assertEqual(client.get_solver(order_by='-id'), self.software) with Client('endpoint', 'token', solver=dict(qpu=True, order_by='-num_active_qubits')) as client: # mock the network call to fetch all solvers client._fetch_solvers = lambda **kw: self.solvers # the default solver was set on client init self.assertEqual(client.get_solver(), self.qpu2) # adding order_by doesn't change other default solver features self.assertEqual(client.get_solver(order_by='num_active_qubits'), self.qpu1) def test_order_by_string(self): # sort by Solver inferred properties self.assertEqual(self.client.get_solvers(order_by='id'), [self.hybrid, self.qpu1, self.qpu2, self.software]) self.assertEqual(self.client.get_solvers(order_by='qpu'), [self.software, self.hybrid, self.qpu1, self.qpu2]) self.assertEqual(self.client.get_solvers(order_by='num_qubits'), self.solvers) self.assertEqual(self.client.get_solvers(order_by='num_active_qubits'), [self.software, self.qpu1, self.qpu2, self.hybrid]) # sort by solver property self.assertEqual( self.client.get_solvers(order_by='properties.num_qubits'), self.solvers) # sort (and reverse sort) by upper bound of a range property self.assertEqual( self.client.get_solvers(order_by='properties.num_reads_range[1]'), self.solvers) self.assertEqual( self.client.get_solvers(order_by='-properties.num_reads_range[1]'), [self.hybrid, self.software, self.qpu2, self.qpu1]) # check solvers with None values for key end up last self.assertEqual(self.client.get_solvers(order_by='properties.vfyc'), [self.software, self.qpu2, self.qpu1, self.hybrid]) self.assertEqual(self.client.get_solvers(order_by='-properties.vfyc'), [self.hybrid, self.qpu1, self.qpu2, self.software]) # check invalid keys don't fail, and effectively don't sort the list self.assertEqual(self.client.get_solvers(order_by='non_existing_key'), self.solvers) self.assertEqual(self.client.get_solvers(order_by='-non_existing_key'), list(reversed(self.solvers))) def test_order_by_callable(self): # sort by Solver inferred properties self.assertEqual( self.client.get_solvers(order_by=lambda solver: solver.id), [self.hybrid, self.qpu1, self.qpu2, self.software]) self.assertEqual( self.client.get_solvers(order_by=lambda solver: solver.avg_load), [self.qpu1, self.qpu2, self.software, self.hybrid]) # sort by solver property self.assertEqual( self.client.get_solvers( order_by=lambda solver: solver.properties.get('num_qubits')), self.solvers) # sort None`s last (here: False, True, None) self.assertEqual( self.client.get_solvers( order_by=lambda solver: solver.properties.get('vfyc')), [self.software, self.qpu2, self.qpu1, self.hybrid]) # test no sort self.assertEqual(self.client.get_solvers(order_by=lambda solver: None), self.solvers)
class FeatureBasedSolverSelection(unittest.TestCase): """Test Client.get_solvers(**filters).""" def setUp(self): # mock solvers self.solver1 = Solver(client=None, data={ "properties": { "supported_problem_types": ["qubo", "ising"], "qubits": [0, 1, 2], "couplers": [[0, 1], [0, 2], [1, 2]], "num_qubits": 3, "num_reads_range": [0, 100], "parameters": { "num_reads": "Number of samples to return.", "postprocess": "either 'sampling' or 'optimization'" } }, "id": "solver1", "description": "A test solver 1", "status": "online" }) self.solver2 = Solver(client=None, data={ "properties": { "supported_problem_types": ["qubo", "ising"], "qubits": [0, 1, 2, 3, 4], "couplers": [[0, 1], [0, 2], [1, 2], [2, 3], [3, 4]], "num_qubits": 5, "num_reads_range": [0, 200], "parameters": { "num_reads": "Number of samples to return.", "flux_biases": "Supported ...", "anneal_schedule": "Supported ..." }, "vfyc": True }, "id": "solver2", "description": "A test solver 2" }) self.solver3 = Solver(client=None, data={ "properties": { "supported_problem_types": ["qubo", "ising"], "qubits": [0, 1], "couplers": [[0, 1]], "num_qubits": 7, "num_reads_range": [0, 1000], "parameters": {"num_reads": "Number of samples to return."}, "vfyc": False }, "id": "c4-sw_solver3", "description": "A test of software solver" }) self.solvers = [self.solver1, self.solver2, self.solver3] # mock client self.client = Client('endpoint', 'token') self.client._fetch_solvers = lambda **kw: self.solvers def shutDown(self): self.client.close() def assertSolvers(self, container, members): self.assertEqual(set(container), set(members)) def test_default(self): self.assertSolvers(self.client.get_solvers(), self.solvers) def test_online(self): self.assertSolvers(self.client.get_solvers(online=True), self.solvers) self.assertSolvers(self.client.get_solvers(online=False), []) def test_qpu_software(self): self.assertSolvers(self.client.get_solvers(qpu=True), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(software=False), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(qpu=False), [self.solver3]) self.assertSolvers(self.client.get_solvers(software=True), [self.solver3]) def test_name(self): self.assertSolvers(self.client.get_solvers(name='solver1'), [self.solver1]) self.assertSolvers(self.client.get_solvers(name='solver2'), [self.solver2]) self.assertSolvers(self.client.get_solvers(name='solver'), []) self.assertSolvers(self.client.get_solvers(name='olver1'), []) self.assertSolvers(self.client.get_solvers(name__regex='.*1'), [self.solver1]) self.assertSolvers(self.client.get_solvers(name__regex='.*[12].*'), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(name__regex='solver[12]'), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(name__regex='^solver(1|2)$'), [self.solver1, self.solver2]) def test_num_qubits(self): self.assertSolvers(self.client.get_solvers(num_qubits=5), [self.solver2]) self.assertSolvers(self.client.get_solvers(num_active_qubits=2), [self.solver3]) self.assertSolvers(self.client.get_solvers(num_active_qubits__in=[2, 3]), [self.solver1, self.solver3]) def test_parameter_availability_check(self): self.assertSolvers(self.client.get_solvers(postprocess__available=True), [self.solver1]) self.assertSolvers(self.client.get_solvers(postprocess=True), [self.solver1]) self.assertSolvers(self.client.get_solvers(parameters__contains='flux_biases'), [self.solver2]) self.assertSolvers(self.client.get_solvers(parameters__contains='num_reads'), self.solvers) def test_property_availability_check(self): self.assertSolvers(self.client.get_solvers(vfyc__available=True), [self.solver2, self.solver3]) self.assertSolvers(self.client.get_solvers(vfyc__eq=True), [self.solver2]) self.assertSolvers(self.client.get_solvers(vfyc=True), [self.solver2]) # inverse of vfyc=True self.assertSolvers(self.client.get_solvers(vfyc__in=[False, None]), [self.solver1, self.solver3]) # vfyc unavailable or unadvertized self.assertSolvers(self.client.get_solvers(vfyc__available=False), [self.solver1]) self.assertSolvers(self.client.get_solvers(vfyc__eq=False), [self.solver3]) self.assertSolvers(self.client.get_solvers(vfyc=False), [self.solver3]) # non-existing params/props have value of None self.assertSolvers(self.client.get_solvers(vfyc__eq=None), [self.solver1]) self.assertSolvers(self.client.get_solvers(vfyc=None), [self.solver1]) def test_availability_combo(self): self.assertSolvers(self.client.get_solvers(vfyc=False, flux_biases=True), []) self.assertSolvers(self.client.get_solvers(vfyc=True, flux_biases=True), [self.solver2]) def test_relational_ops(self): self.assertSolvers(self.client.get_solvers(num_qubits=3), [self.solver1]) self.assertSolvers(self.client.get_solvers(num_qubits__eq=3), [self.solver1]) self.assertSolvers(self.client.get_solvers(num_qubits=4), []) self.assertSolvers(self.client.get_solvers(num_qubits=5), [self.solver2]) self.assertSolvers(self.client.get_solvers(num_qubits__gte=2), self.solvers) self.assertSolvers(self.client.get_solvers(num_qubits__gte=5), [self.solver2, self.solver3]) self.assertSolvers(self.client.get_solvers(num_qubits__gt=5), [self.solver3]) self.assertSolvers(self.client.get_solvers(num_qubits__lte=8), self.solvers) self.assertSolvers(self.client.get_solvers(num_qubits__lte=7), self.solvers) self.assertSolvers(self.client.get_solvers(num_qubits__lt=7), [self.solver1, self.solver2]) def test_range_ops(self): # value within range self.assertSolvers(self.client.get_solvers(num_qubits__within=[3, 7]), self.solvers) self.assertSolvers(self.client.get_solvers(num_qubits__within=[3, 5]), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(num_qubits__within=[2, 4]), [self.solver1]) self.assertSolvers(self.client.get_solvers(num_qubits__within=(2, 4)), [self.solver1]) self.assertSolvers(self.client.get_solvers(num_qubits__within=(4, 2)), [self.solver1]) # range within (covered by) range self.assertSolvers(self.client.get_solvers(num_reads_range__within=(0, 500)), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(num_reads_range__within=(1, 500)), []) # range covering a value (value included in range) self.assertSolvers(self.client.get_solvers(num_reads_range__covers=0), self.solvers) self.assertSolvers(self.client.get_solvers(num_reads_range__covers=150), [self.solver2, self.solver3]) self.assertSolvers(self.client.get_solvers(num_reads_range__covers=550), [self.solver3]) self.assertSolvers(self.client.get_solvers(num_reads_range__covers=1000), [self.solver3]) self.assertSolvers(self.client.get_solvers(num_reads_range__covers=1001), []) # range covering a range self.assertSolvers(self.client.get_solvers(num_reads_range__covers=(10, 90)), self.solvers) self.assertSolvers(self.client.get_solvers(num_reads_range__covers=(110, 200)), [self.solver2, self.solver3]) def test_membership_ops(self): # property contains self.assertSolvers(self.client.get_solvers(supported_problem_types__contains="qubo"), self.solvers) self.assertSolvers(self.client.get_solvers(supported_problem_types__contains="undef"), []) self.assertSolvers(self.client.get_solvers(couplers__contains=[0, 1]), self.solvers) self.assertSolvers(self.client.get_solvers(couplers__contains=[0, 2]), [self.solver1, self.solver2]) # property in self.assertSolvers(self.client.get_solvers(num_qubits__in=[3, 5]), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(num_qubits__in=[7]), [self.solver3]) self.assertSolvers(self.client.get_solvers(num_qubits__in=[]), []) def test_set_ops(self): # property issubset self.assertSolvers(self.client.get_solvers(supported_problem_types__issubset=("qubo", "ising", "other")), self.solvers) self.assertSolvers(self.client.get_solvers(supported_problem_types__issubset=["qubo", "ising"]), self.solvers) self.assertSolvers(self.client.get_solvers(supported_problem_types__issubset=["ising", "qubo"]), self.solvers) self.assertSolvers(self.client.get_solvers(supported_problem_types__issubset={"ising", "qubo"}), self.solvers) self.assertSolvers(self.client.get_solvers(supported_problem_types__issubset=("unicorn", "ising", "other")), []) # property issuperset self.assertSolvers(self.client.get_solvers(qubits__issuperset={0, 1}), self.solvers) self.assertSolvers(self.client.get_solvers(qubits__issuperset={1, 2}), [self.solver1, self.solver2]) # unhashable types self.assertSolvers(self.client.get_solvers(couplers__issuperset=[[0, 1]]), self.solvers) self.assertSolvers(self.client.get_solvers(couplers__issuperset={(0, 1)}), self.solvers) self.assertSolvers(self.client.get_solvers(couplers__issuperset={(0, 1), (0, 2)}), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(couplers__issuperset={(0, 1), (0, 2), (2, 3)}), [self.solver2]) self.assertSolvers(self.client.get_solvers(couplers__issuperset={(0, 1), (0, 2), (2, 3), (0, 5)}), []) def test_regex(self): self.assertSolvers(self.client.get_solvers(num_reads__regex='.*number.*'), []) self.assertSolvers(self.client.get_solvers(num_reads__regex='.*Number.*'), self.solvers) self.assertSolvers(self.client.get_solvers(num_reads__regex='Number.*'), self.solvers) self.assertSolvers(self.client.get_solvers(num_reads__regex='Number'), []) def test_range_boolean_combo(self): self.assertSolvers(self.client.get_solvers(num_qubits=3, vfyc=True), []) self.assertSolvers(self.client.get_solvers(num_qubits__gte=3, vfyc=True), [self.solver2]) self.assertSolvers(self.client.get_solvers(num_qubits__lte=4, vfyc=True), []) self.assertSolvers(self.client.get_solvers(num_qubits__within=(3, 6), flux_biases=True), [self.solver2]) self.assertSolvers(self.client.get_solvers(num_qubits=5, flux_biases=True), [self.solver2]) def test_anneal_schedule(self): self.assertSolvers(self.client.get_solvers(anneal_schedule__available=True), [self.solver2]) self.assertSolvers(self.client.get_solvers(anneal_schedule=True), [self.solver2]) def test_solvers_deprecation(self): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") self.client.solvers() self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
class FeatureBasedSolverSelection(unittest.TestCase): """Test Client.get_solvers(**filters).""" def setUp(self): # mock solvers self.solver1 = Solver(client=None, data={ "properties": { "supported_problem_types": ["qubo", "ising"], "qubits": [0, 1, 2], "couplers": [[0, 1], [0, 2], [1, 2]], "num_qubits": 3, "num_reads_range": [0, 100], "parameters": { "num_reads": "Number of samples to return.", "postprocess": "either 'sampling' or 'optimization'" }, "topology": { "type": "chimera", "shape": [16, 16, 4] }, "tags": ["lower_noise"] }, "id": "solver1", "description": "A test solver 1", "status": "online" }) self.solver2 = Solver(client=None, data={ "properties": { "supported_problem_types": ["qubo", "ising"], "qubits": [0, 1, 2, 3, 4], "couplers": [[0, 1], [0, 2], [1, 2], [2, 3], [3, 4]], "num_qubits": 5, "num_reads_range": [0, 200], "parameters": { "num_reads": "Number of samples to return.", "flux_biases": "Supported ...", "anneal_schedule": "Supported ..." }, "topology": { "type": "pegasus", "shape": [6, 6, 12] }, "vfyc": True }, "id": "solver2", "description": "A test solver 2" }) self.solver3 = Solver( client=None, data={ "properties": { "supported_problem_types": ["qubo", "ising"], "qubits": [0, 1], "couplers": [[0, 1]], "num_qubits": 7, "num_reads_range": [0, 1000], "parameters": { "num_reads": "Number of samples to return." }, "vfyc": False, "topology": { "type": "chimera", "shape": [4, 4, 4] }, # the following are only present in this solver "some_set": [1, 2], "some_range": [1, 2], "some_string": "x", "tags": ["tag"] }, "id": "c4-sw_solver3", "description": "A test of software solver", "avg_load": 0.7 }) self.solvers = [self.solver1, self.solver2, self.solver3] # mock client self.client = Client('endpoint', 'token') self.client._fetch_solvers = lambda **kw: self.solvers def shutDown(self): self.client.close() def assertSolvers(self, container, members): self.assertEqual(set(container), set(members)) def test_default(self): self.assertSolvers(self.client.get_solvers(), self.solvers) def test_online(self): self.assertSolvers(self.client.get_solvers(online=True), self.solvers) self.assertSolvers(self.client.get_solvers(online=False), []) def test_qpu_software(self): self.assertSolvers(self.client.get_solvers(qpu=True), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(software=False), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(qpu=False), [self.solver3]) self.assertSolvers(self.client.get_solvers(software=True), [self.solver3]) def test_name(self): self.assertSolvers(self.client.get_solvers(name='solver1'), [self.solver1]) self.assertSolvers(self.client.get_solvers(name='solver2'), [self.solver2]) self.assertSolvers(self.client.get_solvers(name='solver'), []) self.assertSolvers(self.client.get_solvers(name='olver1'), []) self.assertSolvers(self.client.get_solvers(name__regex='.*1'), [self.solver1]) self.assertSolvers(self.client.get_solvers(name__regex='.*[12].*'), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(name__regex='solver[12]'), [self.solver1, self.solver2]) self.assertSolvers( self.client.get_solvers(name__regex='^solver(1|2)$'), [self.solver1, self.solver2]) def test_num_qubits(self): self.assertSolvers(self.client.get_solvers(num_qubits=5), [self.solver2]) self.assertSolvers(self.client.get_solvers(num_active_qubits=2), [self.solver3]) self.assertSolvers( self.client.get_solvers(num_active_qubits__in=[2, 3]), [self.solver1, self.solver3]) def test_lower_noise_derived_property(self): self.assertSolvers(self.client.get_solvers(lower_noise=True), [self.solver1]) self.assertSolvers(self.client.get_solvers(lower_noise=False), [self.solver2, self.solver3]) def test_parameter_availability_check(self): self.assertSolvers( self.client.get_solvers(postprocess__available=True), [self.solver1]) self.assertSolvers(self.client.get_solvers(postprocess=True), [self.solver1]) self.assertSolvers( self.client.get_solvers(parameters__contains='flux_biases'), [self.solver2]) self.assertSolvers( self.client.get_solvers(parameters__contains='num_reads'), self.solvers) def test_property_availability_check(self): self.assertSolvers(self.client.get_solvers(vfyc__available=True), [self.solver2, self.solver3]) self.assertSolvers(self.client.get_solvers(vfyc__eq=True), [self.solver2]) self.assertSolvers(self.client.get_solvers(vfyc=True), [self.solver2]) # inverse of vfyc=True self.assertSolvers(self.client.get_solvers(vfyc__in=[False, None]), [self.solver1, self.solver3]) # vfyc unavailable or unadvertized self.assertSolvers(self.client.get_solvers(vfyc__available=False), [self.solver1]) self.assertSolvers(self.client.get_solvers(vfyc__eq=False), [self.solver3]) self.assertSolvers(self.client.get_solvers(vfyc=False), [self.solver3]) # non-existing params/props have value of None self.assertSolvers(self.client.get_solvers(vfyc__eq=None), [self.solver1]) self.assertSolvers(self.client.get_solvers(vfyc=None), [self.solver1]) def test_availability_combo(self): self.assertSolvers( self.client.get_solvers(vfyc=False, flux_biases=True), []) self.assertSolvers( self.client.get_solvers(vfyc=True, flux_biases=True), [self.solver2]) def test_relational_ops(self): self.assertSolvers(self.client.get_solvers(num_qubits=3), [self.solver1]) self.assertSolvers(self.client.get_solvers(num_qubits__eq=3), [self.solver1]) self.assertSolvers(self.client.get_solvers(num_qubits=4), []) self.assertSolvers(self.client.get_solvers(num_qubits=5), [self.solver2]) self.assertSolvers(self.client.get_solvers(num_qubits__gte=2), self.solvers) self.assertSolvers(self.client.get_solvers(num_qubits__gte=5), [self.solver2, self.solver3]) self.assertSolvers(self.client.get_solvers(num_qubits__gt=5), [self.solver3]) self.assertSolvers(self.client.get_solvers(num_qubits__lte=8), self.solvers) self.assertSolvers(self.client.get_solvers(num_qubits__lte=7), self.solvers) self.assertSolvers(self.client.get_solvers(num_qubits__lt=7), [self.solver1, self.solver2]) # skip solver if LHS value not defined (None) self.assertSolvers(self.client.get_solvers(avg_load__gt=0), [self.solver3]) self.assertSolvers(self.client.get_solvers(avg_load__gte=0), [self.solver3]) self.assertSolvers(self.client.get_solvers(avg_load__lt=1), [self.solver3]) self.assertSolvers(self.client.get_solvers(avg_load__lte=1), [self.solver3]) self.assertSolvers(self.client.get_solvers(avg_load=0.7), [self.solver3]) self.assertSolvers(self.client.get_solvers(avg_load__eq=0.7), [self.solver3]) self.assertSolvers(self.client.get_solvers(avg_load=None), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(avg_load__eq=None), [self.solver1, self.solver2]) def test_range_ops(self): # value within range self.assertSolvers(self.client.get_solvers(num_qubits__within=[3, 7]), self.solvers) self.assertSolvers(self.client.get_solvers(num_qubits__within=[3, 5]), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(num_qubits__within=[2, 4]), [self.solver1]) self.assertSolvers(self.client.get_solvers(num_qubits__within=(2, 4)), [self.solver1]) self.assertSolvers(self.client.get_solvers(num_qubits__within=(4, 2)), [self.solver1]) # range within (covered by) range self.assertSolvers( self.client.get_solvers(num_reads_range__within=(0, 500)), [self.solver1, self.solver2]) self.assertSolvers( self.client.get_solvers(num_reads_range__within=(1, 500)), []) # invalid LHS self.assertSolvers(self.client.get_solvers(some_range__within=[0, 2]), [self.solver3]) # range covering a value (value included in range) self.assertSolvers(self.client.get_solvers(num_reads_range__covers=0), self.solvers) self.assertSolvers( self.client.get_solvers(num_reads_range__covers=150), [self.solver2, self.solver3]) self.assertSolvers( self.client.get_solvers(num_reads_range__covers=550), [self.solver3]) self.assertSolvers( self.client.get_solvers(num_reads_range__covers=1000), [self.solver3]) self.assertSolvers( self.client.get_solvers(num_reads_range__covers=1001), []) # range covering a range self.assertSolvers( self.client.get_solvers(num_reads_range__covers=(10, 90)), self.solvers) self.assertSolvers( self.client.get_solvers(num_reads_range__covers=(110, 200)), [self.solver2, self.solver3]) # invalid LHS self.assertSolvers(self.client.get_solvers(some_range__covers=1.5), [self.solver3]) def test_membership_ops(self): # property contains self.assertSolvers( self.client.get_solvers(supported_problem_types__contains="qubo"), self.solvers) self.assertSolvers( self.client.get_solvers(supported_problem_types__contains="undef"), []) self.assertSolvers(self.client.get_solvers(couplers__contains=[0, 1]), self.solvers) self.assertSolvers(self.client.get_solvers(couplers__contains=[0, 2]), [self.solver1, self.solver2]) # property in self.assertSolvers(self.client.get_solvers(num_qubits__in=[3, 5]), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(num_qubits__in=[7]), [self.solver3]) self.assertSolvers(self.client.get_solvers(num_qubits__in=[]), []) # invalid LHS self.assertSolvers(self.client.get_solvers(some_set__contains=1), [self.solver3]) self.assertSolvers(self.client.get_solvers(avg_load__in=[None]), [self.solver1, self.solver2]) self.assertSolvers(self.client.get_solvers(avg_load__in=[None, 0.7]), self.solvers) def test_set_ops(self): # property issubset self.assertSolvers( self.client.get_solvers( supported_problem_types__issubset=("qubo", "ising", "other")), self.solvers) self.assertSolvers( self.client.get_solvers( supported_problem_types__issubset=["qubo", "ising"]), self.solvers) self.assertSolvers( self.client.get_solvers( supported_problem_types__issubset=["ising", "qubo"]), self.solvers) self.assertSolvers( self.client.get_solvers( supported_problem_types__issubset={"ising", "qubo"}), self.solvers) self.assertSolvers( self.client.get_solvers( supported_problem_types__issubset=("unicorn", "ising", "other")), []) # property issuperset self.assertSolvers(self.client.get_solvers(qubits__issuperset={0, 1}), self.solvers) self.assertSolvers(self.client.get_solvers(qubits__issuperset={1, 2}), [self.solver1, self.solver2]) # unhashable types self.assertSolvers( self.client.get_solvers(couplers__issuperset=[[0, 1]]), self.solvers) self.assertSolvers( self.client.get_solvers(couplers__issuperset={(0, 1)}), self.solvers) self.assertSolvers( self.client.get_solvers(couplers__issuperset={(0, 1), (0, 2)}), [self.solver1, self.solver2]) self.assertSolvers( self.client.get_solvers(couplers__issuperset={(0, 1), (0, 2), (2, 3)}), [self.solver2]) self.assertSolvers( self.client.get_solvers( couplers__issuperset={(0, 1), (0, 2), (2, 3), (0, 5)}), []) # invalid LHS self.assertSolvers( self.client.get_solvers(some_set__issubset={0, 1, 2}), [self.solver3]) self.assertSolvers(self.client.get_solvers(some_set__issuperset={1}), [self.solver3]) def test_regex(self): self.assertSolvers( self.client.get_solvers(num_reads__regex='.*number.*'), []) self.assertSolvers( self.client.get_solvers(num_reads__regex='.*Number.*'), self.solvers) self.assertSolvers( self.client.get_solvers(num_reads__regex='Number.*'), self.solvers) self.assertSolvers(self.client.get_solvers(num_reads__regex='Number'), []) # invalid LHS self.assertSolvers(self.client.get_solvers(some_string__regex='x'), [self.solver3]) def test_range_boolean_combo(self): self.assertSolvers(self.client.get_solvers(num_qubits=3, vfyc=True), []) self.assertSolvers( self.client.get_solvers(num_qubits__gte=3, vfyc=True), [self.solver2]) self.assertSolvers( self.client.get_solvers(num_qubits__lte=4, vfyc=True), []) self.assertSolvers( self.client.get_solvers(num_qubits__within=(3, 6), flux_biases=True), [self.solver2]) self.assertSolvers( self.client.get_solvers(num_qubits=5, flux_biases=True), [self.solver2]) def test_nested_properties_leaf_lookup(self): self.assertSolvers(self.client.get_solvers(topology__type="chimera"), [self.solver1, self.solver3]) self.assertSolvers(self.client.get_solvers(topology__type="pegasus"), [self.solver2]) self.assertSolvers( self.client.get_solvers(topology__type__eq="pegasus"), [self.solver2]) self.assertSolvers(self.client.get_solvers(topology__shape=[6, 6, 12]), [self.solver2]) self.assertSolvers( self.client.get_solvers(topology__type="chimera", topology__shape__contains=16), [self.solver1]) def test_nested_properties_intermediate_key_lookup(self): self.assertSolvers(self.client.get_solvers(topology__contains="shape"), self.solvers) self.assertSolvers( self.client.get_solvers(topology={ "type": "pegasus", "shape": [6, 6, 12] }), [self.solver2]) def test_anneal_schedule(self): self.assertSolvers( self.client.get_solvers(anneal_schedule__available=True), [self.solver2]) self.assertSolvers(self.client.get_solvers(anneal_schedule=True), [self.solver2]) def test_solvers_deprecation(self): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") self.client.solvers() self.assertEqual(len(w), 1) self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) def test_order_by_edgecases(self): # default: sort by avg_load self.assertEqual(self.client.get_solvers(), [self.solver3, self.solver1, self.solver2]) # explicit no sort self.assertEqual(self.client.get_solvers(order_by=None), self.solvers) self.assertEqual(self.client.get_solvers(order_by=''), self.solvers) self.assertEqual(self.client.get_solvers(order_by=False), self.solvers) # reverse without sorting self.assertEqual(self.client.get_solvers(order_by='-'), list(reversed(self.solvers))) # invalid type of `order_by` with self.assertRaises(TypeError): self.client.get_solvers(order_by=1) with self.assertRaises(TypeError): self.client.get_solvers(order_by=list) def test_order_by_string(self): # sort by Solver inferred properties self.assertEqual(self.client.get_solvers(order_by='id'), [self.solver3, self.solver1, self.solver2]) self.assertEqual(self.client.get_solvers(order_by='qpu'), [self.solver3, self.solver1, self.solver2]) self.assertEqual(self.client.get_solvers(order_by='num_qubits'), self.solvers) self.assertEqual(self.client.get_solvers(order_by='num_active_qubits'), [self.solver3, self.solver1, self.solver2]) # sort by solver property self.assertEqual( self.client.get_solvers(order_by='properties.num_qubits'), self.solvers) # sort (and reverse sort) by upper bound of a range property self.assertEqual( self.client.get_solvers(order_by='properties.num_reads_range[1]'), self.solvers) self.assertEqual( self.client.get_solvers(order_by='-properties.num_reads_range[1]'), [self.solver3, self.solver2, self.solver1]) # check solvers with None values for key end up last self.assertEqual(self.client.get_solvers(order_by='properties.vfyc'), [self.solver3, self.solver2, self.solver1]) self.assertEqual(self.client.get_solvers(order_by='-properties.vfyc'), [self.solver1, self.solver2, self.solver3]) # check invalid keys don't fail, and effectively don't sort the list self.assertEqual(self.client.get_solvers(order_by='non_existing_key'), self.solvers) self.assertEqual(self.client.get_solvers(order_by='-non_existing_key'), list(reversed(self.solvers))) def test_order_by_callable(self): # sort by Solver inferred properties self.assertEqual( self.client.get_solvers(order_by=lambda solver: solver.id), [self.solver3, self.solver1, self.solver2]) self.assertEqual( self.client.get_solvers(order_by=lambda solver: solver.num_qubits), self.solvers) # sort by solver property self.assertEqual( self.client.get_solvers( order_by=lambda solver: solver.properties['num_qubits']), self.solvers) # sort None`s last (here: False, True, None) self.assertEqual( self.client.get_solvers( order_by=lambda solver: solver.properties.get('vfyc')), [self.solver3, self.solver2, self.solver1]) # test no sort self.assertEqual(self.client.get_solvers(order_by=lambda solver: None), self.solvers)
class FeatureBasedSolverSelection(unittest.TestCase): """Test Client.solvers().""" def setUp(self): # mock solvers self.solver1 = Solver(client=None, data={ "properties": { "supported_problem_types": ["qubo", "ising"], "qubits": [0, 1, 2], "couplers": [[0, 1], [0, 2], [1, 2]], "num_qubits": 3, "parameters": {"num_reads": "Number of samples to return."} }, "id": "solver1", "description": "A test solver 1" }) self.solver2 = Solver(client=None, data={ "properties": { "supported_problem_types": ["qubo", "ising"], "qubits": [0, 1, 2, 3, 4], "couplers": [[0, 1], [0, 2], [1, 2], [2, 3], [3, 4]], "num_qubits": 5, "parameters": { "num_reads": "Number of samples to return.", "flux_biases": "Supported ..." }, "vfyc": True }, "id": "solver2", "description": "A test solver 2" }) self.solvers = [self.solver1, self.solver2] # mock client self.client = Client('endpoint', 'token') self.client._solvers = { self.solver1.id: self.solver1, self.solver2.id: self.solver2 } self.client._all_solvers_ready = True def shutDown(self): self.client.close() def assertSolvers(self, container, members): return set(container) == set(members) def test_default(self): self.assertSolvers(self.client.solvers(), self.solvers) def test_one_boolean(self): self.assertSolvers(self.client.solvers(vfyc=False), [self.solver1]) self.assertSolvers(self.client.solvers(vfyc=True), [self.solver2]) self.assertSolvers(self.client.solvers(flux_biases=False), [self.solver1]) self.assertSolvers(self.client.solvers(flux_biases=True), [self.solver2]) def test_boolean_combo(self): self.assertSolvers(self.client.solvers(vfyc=False, flux_biases=True), []) self.assertSolvers(self.client.solvers(vfyc=True, flux_biases=True), [self.solver2]) def test_int_range(self): self.assertSolvers(self.client.solvers(num_qubits=3), [self.solver1]) self.assertSolvers(self.client.solvers(num_qubits=4), []) self.assertSolvers(self.client.solvers(num_qubits=5), [self.solver2]) self.assertSolvers(self.client.solvers(num_qubits=[3, 5]), self.solvers) self.assertSolvers(self.client.solvers(num_qubits=[2, None]), self.solvers) self.assertSolvers(self.client.solvers(num_qubits=[None, 6]), self.solvers) self.assertSolvers(self.client.solvers(num_qubits=[2, 4]), [self.solver1]) self.assertSolvers(self.client.solvers(num_qubits=[4, None]), [self.solver2]) def test_range_boolean_combo(self): self.assertSolvers(self.client.solvers(num_qubits=3, vfyc=True), []) self.assertSolvers(self.client.solvers(num_qubits=[3, None], vfyc=True), [self.solver2]) self.assertSolvers(self.client.solvers(num_qubits=[None, 4], vfyc=True), []) self.assertSolvers(self.client.solvers(num_qubits=[None, 4], flux_biases=False), [self.solver1]) self.assertSolvers(self.client.solvers(num_qubits=5, flux_biases=True), [self.solver2])