예제 #1
0
    def test_largerSchedule(self):
        jobs = {
            'small1': [(1, 1)],
            'small2': [(2, 2)],
            'longJob': [(0, 1), (1, 1), (2, 1)]
        }
        max_time = 4

        # Get exact sample from Job Shop Scheduler BQM
        jss = JobShopScheduler(jobs, max_time)
        bqm = jss.get_bqm()
        response = ExactSolver().sample(bqm)
        response_sample = next(response.samples())

        # Verify that response_sample obeys constraints
        self.assertTrue(jss.csp.check(response_sample))

        # Create expected solution
        expected = {
            "small1_0,0": 1,
            "small2_0,0": 1,
            "longJob_0,0": 1,
            "longJob_1,1": 1,
            "longJob_2,2": 1
        }

        # Compare variable values
        self.compare(response_sample, expected)
예제 #2
0
    def test_simple_schedule_more_machines(self):
        jobs = {"j0": [(0, 1)], "j1": [(1, 1)], "j2": [(2, 1)]}
        max_time = 3

        # Get JSS BQM
        scheduler = JobShopScheduler(jobs, max_time)
        bqm = scheduler.get_bqm()

        # Expected solution
        expected = {"j0_0,0": 1, "j1_0,0": 1, "j2_0,0": 1}
        fill_with_zeros(expected, jobs, max_time)
        expected_energy = get_energy(expected, bqm)

        # Sampled solution
        # response = EmbeddingComposite(DWaveSampler()).sample(bqm, num_reads=10000)
        # response_sample, sample_energy, _, chain_break_fraction = next(response.data())
        # print("Chain Break Fraction: ", chain_break_fraction)
        # response = SimulatedAnnealingSampler().sample(bqm, num_reads=2000, beta_range=[0.01, 10])
        response = ExactSolver().sample(bqm)
        response_sample, sample_energy, _ = next(response.data())

        # Print response
        self.assertTrue(scheduler.csp.check(response_sample))
        self.assertEqual(expected_energy, sample_energy)
        self.compare(response_sample, expected)
예제 #3
0
    def test_denseSchedule(self):
        jobs = {
            "a": [(1, 2), (2, 2), (3, 2)],
            "b": [(3, 3), (2, 1), (1, 1)],
            "c": [(2, 2), (1, 3), (2, 1)]
        }
        max_time = 6
        jss = JobShopScheduler(jobs, max_time)
        jss.get_bqm()  # Run job shop scheduling constraints

        # Solution that obeys all constraints
        good_solution = {
            "a_0,0": 1,
            "a_1,2": 1,
            "a_2,4": 1,
            "b_0,0": 1,
            "b_1,4": 1,
            "b_2,5": 1,
            "c_0,0": 1,
            "c_1,2": 1,
            "c_2,5": 1
        }
        fill_with_zeros(good_solution, jobs, max_time)

        # Tasks a_1 and b_1 overlap in time on machine 2
        overlap_solution = {
            "a_0,0": 1,
            "a_1,2": 1,
            "a_2,4": 1,
            "b_0,0": 1,
            "b_1,3": 1,
            "b_2,5": 1,
            "c_0,0": 1,
            "c_1,2": 1,
            "c_2,5": 1
        }
        fill_with_zeros(overlap_solution, jobs, max_time)

        self.assertTrue(jss.csp.check(good_solution))
        self.assertFalse(jss.csp.check(overlap_solution))
예제 #4
0
    def test_relaxedSchedule(self):
        jobs = {"breakfast": [("cook", 2), ("eat", 1)], "music": [("play", 2)]}
        max_time = 7
        jss = JobShopScheduler(jobs, max_time)
        jss.get_bqm()  # Run job shop scheduling constraints

        # Solution obeys all constraints
        good_solution = {
            "breakfast_0,0": 1,
            "breakfast_1,4": 1,
            "music_0,3": 1
        }
        fill_with_zeros(good_solution, jobs, max_time)

        # 'breakfast' tasks are out of order
        bad_order_solution = {
            "breakfast_0,1": 1,
            "breakfast_1,0": 1,
            "music_0,0": 1
        }
        fill_with_zeros(bad_order_solution, jobs, max_time)

        self.assertTrue(jss.csp.check(good_solution))
        self.assertFalse(jss.csp.check(bad_order_solution))
예제 #5
0
    def test_tinySchedule(self):
        jobs = {"a": [(1, 1), (2, 1)], "b": [(2, 1)]}
        max_time = 2

        # Get exact sample from Job Shop Scheduler BQM
        jss = JobShopScheduler(jobs, max_time)
        bqm = jss.get_bqm()
        response = ExactSolver().sample(bqm)
        response_sample = next(response.samples())

        # Verify that response_sample obeys constraints
        self.assertTrue(jss.csp.check(response_sample))

        # Create expected solution
        expected = {"a_0,0": 1, "a_1,1": 1, "b_0,0": 1}

        # Compare variable values
        self.compare(response_sample, expected)
예제 #6
0
    def test_stitch_kwargs(self):
        """Ensure stitch_kwargs is being passed to dwavebinarycsp.stitch
        """
        jobs = {
            "sandwich": [("bread", 1), ("roast_beef", 1)],
            "french_toast": [("egg", 1), ("bread", 1)]
        }
        max_time = 3

        # Verify that reasonable stitch args result in a BQM
        good_stitch_kwargs = {"max_graph_size": 6, "min_classical_gap": 1.5}
        scheduler = JobShopScheduler(jobs, max_time)
        bqm = scheduler.get_bqm(good_stitch_kwargs)
        self.assertIsInstance(bqm, BinaryQuadraticModel)

        # ImpossibleBQM should be raised, as the max_graph size is too small
        bad_stitch_kwargs = {"max_graph_size": 0}
        scheduler = JobShopScheduler(jobs, max_time)
        self.assertRaises(ImpossibleBQM, scheduler.get_bqm, bad_stitch_kwargs)
예제 #7
0
    def test_dense_schedule(self):
        # jobs = {'small1': [(1, 1), (0, 2)],
        #         'small2': [(2, 2), (0, 1)],
        #         'longJob': [(0, 1), (1, 1), (2, 1)]}
        # max_time = 4
        jobs = {
            "j0": [(1, 2), (2, 2), (3, 2)],
            "j1": [(3, 4), (2, 1), (1, 1)],
            "j2": [(2, 2), (1, 3), (2, 1)]
        }
        max_time = 7

        # Get JSS BQM
        scheduler = JobShopScheduler(jobs, max_time)
        bqm = scheduler.get_bqm()

        # Expected solution
        expected = {
            "j0_0,0": 1,
            "j0_1,2": 1,
            "j0_2,4": 1,
            "j1_0,0": 1,
            "j1_1,4": 1,
            "j1_2,5": 1,
            "j2_0,0": 1,
            "j2_1,2": 1,
            "j2_2,5": 1
        }
        fill_with_zeros(expected, jobs, max_time)
        expected_energy = get_energy(expected, bqm)

        # Sampled solution
        # response = EmbeddingComposite(DWaveSampler()).sample(bqm, num_reads=10000)
        # response_sample, sample_energy, _, _ = next(response.data())
        # response = SimulatedAnnealingSampler().sample(bqm, num_reads=2000, beta_range=[0.01, 10])
        response = TabuSampler().sample(bqm, num_reads=2000)
        response_sample, sample_energy, _ = next(response.data())

        # Check response sample
        self.assertTrue(scheduler.csp.check(response_sample))
        self.assertEqual(expected_energy, sample_energy)
        self.compare(response_sample, expected)
예제 #8
0
    def test_time_dependent_biases(self):
        """Test that the time-dependent biases that encourage short schedules are applied
        appropriately
        """
        jobs = {"j1": [("m1", 2), ("m2", 2)], "j2": [("m1", 2)]}

        # Create mock object for stitch(..) output
        linear = {
            'j1_0,0': -2.0,
            'j1_0,1': -2.0,
            'j1_0,2': -2.0,
            'j1_1,2': -2.0,
            'j1_1,3': -2.0,
            'j1_1,4': -2.0,
            'j2_0,0': -6.0,
            'j2_0,1': -6.0,
            'j2_0,2': -6.0,
            'j2_0,3': -6.0,
            'j2_0,4': -6.0,
            'aux0': -8.0
        }
        quadratic = {
            ('j1_0,0', 'j1_0,1'): 4.0,
            ('j1_0,0', 'j1_0,2'): 4.0,
            ('j1_0,0', 'j2_0,0'): 4,
            ('j1_0,0', 'j2_0,1'): 2,
            ('j1_0,1', 'j1_0,2'): 4.0,
            ('j1_0,1', 'j1_1,2'): 2,
            ('j1_0,1', 'j2_0,1'): 4,
            ('j1_0,1', 'j2_0,2'): 2,
            ('j1_0,1', 'j2_0,0'): 2,
            ('j1_0,2', 'j1_1,2'): 2,
            ('j1_0,2', 'j1_1,3'): 2,
            ('j1_0,2', 'j2_0,2'): 4,
            ('j1_0,2', 'j2_0,3'): 2,
            ('j1_0,2', 'j2_0,1'): 2,
            ('j1_1,2', 'j1_1,3'): 4.0,
            ('j1_1,2', 'j1_1,4'): 4.0,
            ('j1_1,3', 'j1_1,4'): 4.0,
            ('j2_0,3', 'j2_0,2'): 4,
            ('j2_0,3', 'j2_0,4'): 4.0,
            ('j2_0,3', 'j2_0,0'): 4.0,
            ('j2_0,3', 'j2_0,1'): 4,
            ('j2_0,3', 'aux0'): 4.0,
            ('j2_0,2', 'j2_0,4'): 4.0,
            ('j2_0,2', 'j2_0,0'): 4.0,
            ('j2_0,2', 'j2_0,1'): 4.0,
            ('j2_0,2', 'aux0'): 4.0,
            ('j2_0,4', 'j2_0,0'): 4.0,
            ('j2_0,4', 'j2_0,1'): 4.0,
            ('j2_0,4', 'aux0'): 4.0,
            ('j2_0,0', 'j2_0,1'): 4.0,
            ('j2_0,0', 'aux0'): 4.0,
            ('j2_0,1', 'aux0'): 4.0
        }
        vartype = dwavebinarycsp.BINARY
        mock_stitched_bqm = BinaryQuadraticModel(linear, quadratic, 14.0,
                                                 vartype)

        scheduler = JobShopScheduler(jobs)
        with patch.object(dwavebinarycsp,
                          "stitch",
                          return_value=mock_stitched_bqm):
            bqm = scheduler.get_bqm()

        # Check linear biases
        # Note: I have grouped the tests by job-task and am comparing the linear biases between
        #   adjacent times. Tasks that finish before or at the lowerbound of the optimal schedule
        #   are not penalized with an additional bias; hence all these task-times should have the
        #   same bias.
        #   For example, the 0th task of job 2 (aka 'j2_0') will have the same linear
        #   bias for times 0 through 2 because with these start times, the task would complete
        #   before the optimal schedule lowerbound. (i.e. "j2_0,0", "j2_0,1", "j2_0,2" all have the
        #   same linear biases). The remaining task-times will have increasing biases with time, in
        #   this way, the shortest schedule is encouraged.
        self.assertEqual(bqm.linear['j2_0,0'], bqm.linear['j2_0,1'])
        self.assertEqual(bqm.linear['j2_0,1'], bqm.linear['j2_0,2'])
        self.assertLess(bqm.linear['j2_0,2'], bqm.linear['j2_0,3'])
        self.assertLess(bqm.linear['j2_0,3'], bqm.linear['j2_0,4'])

        self.assertEqual(bqm.linear['j1_0,0'], bqm.linear['j1_0,1'])
        self.assertEqual(bqm.linear['j1_0,1'], bqm.linear['j1_0,2'])

        self.assertLess(bqm.linear['j1_1,2'], bqm.linear['j1_1,3'])
        self.assertLess(bqm.linear['j1_1,3'], bqm.linear['j1_1,4'])

        # Check quadratic biases
        # Specifically, quadratic biases should not be penalized when encouraging shorter schedules
        # Note: Unable to simply compare dicts as BQM's quadraticview may re-order dict tuple-keys;
        #   hence, we're comparing BQM adjacencies.
        bqm_with_unchanged_quadratic = BinaryQuadraticModel({}, quadratic, 0,
                                                            vartype)
        self.assertEqual(bqm.adj, bqm_with_unchanged_quadratic.adj)