コード例 #1
0
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)
コード例 #2
0
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))
コード例 #3
0
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)
コード例 #4
0
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])