コード例 #1
0
    def test_redistribute_to_one_route(self):
        r1 = [0, 1, 4, 6, 0]
        rd1_redistribute = RouteData(r1, route_l(r1, self.D),
                                     route_d(r1, self.d), None)
        r2 = [0, 2, 3, 5, 7, 0]
        rd2_recieving = RouteData(r2, route_l(r2, self.D), route_d(r2, self.d),
                                  None)

        result = do_redistribute_move(rd1_redistribute,
                                      rd2_recieving,
                                      self.D,
                                      strategy=LSOPT.FIRST_ACCEPT)
        self.assertEqual(
            len(result), 3,
            "The redistribute operator should return the redistributed and the new combined routes and the delta"
        )
        self.assertEqual(
            result[1].route, [0, 2, 3, 5, 7, 1, 4, 6, 0],
            "It should be possible to insert all and they sould be appended to the route"
        )

        result = do_redistribute_move(rd1_redistribute,
                                      rd2_recieving,
                                      self.D,
                                      strategy=LSOPT.BEST_ACCEPT)
        self.assertEqual(
            len(result), 3,
            "The redistribute operator should return the redistributed and the new combined routes and the delta"
        )
        self.assertEqual(result[1].route, [0, 1, 2, 3, 4, 5, 6, 7, 0],
                         "It should be possible to insert all")
コード例 #2
0
 def _insert_one(self,
                 strategy,
                 result_target,
                 msg_if_fail,
                 C=None,
                 L=None,
                 to_insert=2):
     r1 = [0, 1, 3, 4, 0]
     rd1 = RouteData(r1, route_l(r1, self.D), route_d(r1, self.d), None)
     _, result_rd, result_delta = do_insert_move(to_insert,
                                                 rd1,
                                                 self.D,
                                                 C=C,
                                                 d=self.d,
                                                 L=L,
                                                 strategy=strategy)
     result_route = None if (result_rd is None) else result_rd.route
     self.assertEqual(result_route, result_target, msg_if_fail)
     if result_delta is not None:
         self.assertAlmostEqual(
             rd1.cost + result_delta,
             result_rd.cost,
             msg="The delta based and stored objective functions differ")
         self.assertAlmostEqual(
             rd1.cost + result_delta,
             route_l(result_rd.route, self.D),
             msg=
             "The delta based and recalculated objective functions differ")
コード例 #3
0
 def test_updated_route_cost(self):
     new_r1d, new_r2d, delta = self._make_improving_move()
     self.assertEqual(
         route_l(new_r1d[0], self.D), new_r1d[1],
         "original route cost + savings should match recalculated route cost"
     )
     self.assertEqual(
         route_l(new_r2d[0], self.D), new_r2d[1],
         "original route cost + savings should match recalculated route cost"
     )
コード例 #4
0
 def _make_improving_move(self, r1, r2, C=None, d=None, L=None):
     D = self.D
     r1rd = RouteData(r1, route_l(r1, D), route_d(r1, d), None)
     r2rd = RouteData(r2, route_l(r2, D), route_d(r2, d), None)
     return do_2optstar_move(r1rd,
                             r2rd,
                             D,
                             d=d,
                             C=C,
                             L=L,
                             strategy=LSOPT.BEST_ACCEPT)
コード例 #5
0
 def _make_improving_move(self, C=None, d=None, L=None):
     D = self.D
     r1 = [0, 5, 6, 4, 0]
     r2 = [0, 1, 2, 3, 7, 0]
     r1rd = RouteData(r1, route_l(r1, D), route_d(r1, d), None)
     r2rd = RouteData(r2, route_l(r2, D), route_d(r2, d), None)
     return do_2point_move(r1rd,
                           r2rd,
                           D,
                           d=d,
                           C=C,
                           L=L,
                           strategy=LSOPT.BEST_ACCEPT)
コード例 #6
0
 def test_non_improving_move(self):
     D = self.D
     r1 = [0, 5, 6, 7, 0]
     r2 = [0, 1, 2, 3, 4, 0]
     r1d = RouteData(r1, route_l(r1, D), 3, r1[:-1])
     r2d = RouteData(r2, route_l(r2, D), 4, r2[:-1])
     result = do_2point_move(r1d, r2d, D)
     self.assertEqual(
         result, (None, None, None),
         "r1, r2 configuration should already be at local optima")
     result = do_2point_move(r2d, r1d, D)
     self.assertEqual(
         result, (None, None, None),
         "r1, r2 configuration should already be at local optima")
コード例 #7
0
    def test_until_no_improvements_move(self):
        D = self.D
        r1 = [0, 4, 6, 1, 0]
        r2 = [0, 7, 2, 3, 5, 0]
        r1d = RouteData(r1, route_l(r1, D), -1, r1[:-1])
        r2d = RouteData(r2, route_l(r2, D), -1, r2[:-1])
        while True:
            result = do_2point_move(r1d, r2d, D)
            if result[0] is None:
                break
            # unpack result
            r1d, r2d, delta = result

        # unconstrained should run until other route is empty
        self.assertEqual(r2d[0], [0, 1, 2, 3, 4, 0],
                         "should reach a local optima")
コード例 #8
0
    def test_insert_from_empty(self):
        rd1 = RouteData()
        r2 = [0, 1, 3, 4, 0]
        rd2 = RouteData(r2, route_l(r2, self.D), route_d(r2, self.d), None)

        _, result_rd, result_delta = do_insert_move(rd1, rd2, self.D)
        self.assertEqual(result_rd.route, [0, 1, 3, 4, 0],
                         "All should be inserted")
コード例 #9
0
    def test_redistribute_to_two_routes(self):
        r1 = [0, 1, 4, 6, 0]
        rd1_redistribute = RouteData(r1, route_l(r1, self.D),
                                     route_d(r1, self.d), None)
        r2 = [0, 2, 3, 0]
        rd2_recieving = RouteData(r2, route_l(r2, self.D), route_d(r2, self.d),
                                  None)

        r3 = [0, 7, 5, 0]
        rd3_recieving = RouteData(r3, route_l(r3, self.D), route_d(r3, self.d),
                                  None)

        # depending on how the recombinations are made, the results differ
        FI = LSOPT.FIRST_ACCEPT
        BE = LSOPT.BEST_ACCEPT
        tests = [(0, "FIRST", FI, ([0, 2, 3, 1, 4, 0], [0, 7, 5, 6, 0])),
                 (0, "BEST", BE, ([0, 1, 2, 3, 4, 0], [0, 7, 6, 5, 0])),
                 (1, "FIRST", FI, ([0, 2, 3, 4, 1, 0], [0, 7, 5, 6, 0])),
                 (1, "BEST", BE, ([0, 1, 2, 3, 4, 0], [0, 7, 6, 5, 0])),
                 (2, "FIRST", FI, ([0, 2, 3, 1, 4, 0], [0, 7, 5, 6, 0])),
                 (2, "BEST", BE, ([0, 1, 2, 3, 4, 0], [0, 7, 6, 5, 0])),
                 (3, "FIRST", FI, ([0, 2, 3, 4, 1, 0], [0, 7, 5, 6, 0])),
                 (3, "BEST", BE, ([0, 1, 2, 3, 4, 0], [0, 7, 6, 5, 0]))]
        for recombination_level, strategy_name, strategy, target_result in tests:
            result = do_redistribute_move(
                rd1_redistribute, [rd2_recieving, rd3_recieving],
                self.D,
                C=4.0,
                d=self.d,
                strategy=strategy,
                recombination_level=recombination_level)
            #print("QUALITY", strategy_name, "/", recombination_level, "delta", result[-1])
            self.assertEqual(
                len(result), 4,
                "The redistribute operator should return the redistributed and the new combined routes and the delta"
            )
            self.assertEqual(
                result[1].route, target_result[0],
                "It should be possible to insert all and they sould be appended to the route on recombination level %d with strategy %s"
                % (recombination_level, strategy_name))
            self.assertEqual(
                result[2].route, target_result[1],
                "It should be possible to insert all and they sould be appended to the route on recombination level %d with strategy %s"
                % (recombination_level, strategy_name))
コード例 #10
0
    def _insert_many(self,
                     strategy,
                     result_target,
                     msg_if_fail,
                     C=None,
                     L=None):
        to_insert = [3, 2]
        r1 = [0] + to_insert + [0]
        rd1 = RouteData(r1, route_l(r1, self.D), route_d(r1, self.d), None)
        r2 = [0, 1, 4, 0]
        rd2 = RouteData(r2, route_l(r2, self.D), route_d(r2, self.d), None)

        _, list_input_result_rd, list_input_result_delta = do_insert_move(
            to_insert, rd2, self.D, C=C, d=self.d, L=L, strategy=strategy)
        _, rd_input_result_rd, rd_input_result_delta = do_insert_move(
            rd1, rd2, self.D, C=C, d=self.d, L=L, strategy=strategy)
        list_input_result_route = None if (
            list_input_result_rd is None) else list_input_result_rd.route
        rd_input_result_route = None if (
            rd_input_result_rd is None) else rd_input_result_rd.route
        self.assertEqual(list_input_result_route, result_target, msg_if_fail)
        self.assertEqual(
            list_input_result_route, rd_input_result_route,
            "Inserting from a list or RouteData should lead to same result")
        if list_input_result_delta is not None:
            self.assertAlmostEqual(
                rd2.cost + list_input_result_delta,
                list_input_result_rd.cost,
                msg="The delta based and stored objective functions differ")
            self.assertAlmostEqual(
                rd2.cost + list_input_result_delta,
                route_l(list_input_result_rd.route, self.D),
                msg=
                "The delta based and recalculated objective functions differ")
        if rd_input_result_delta is not None:
            self.assertAlmostEqual(
                rd2.cost + rd_input_result_delta,
                rd_input_result_rd.cost,
                msg="The delta based and stored objective functions differ")
            self.assertAlmostEqual(
                rd2.cost + rd_input_result_delta,
                route_l(rd_input_result_rd.route, self.D),
                msg=
                "The delta based and recalculated objective functions differ")
コード例 #11
0
    def test_redistribute_does_not_fit(self):
        demands = [0.0, 1, 1, 1, 1, 1, 1, 1]
        r1 = [0, 1, 2, 0]
        rd1_redistribute = RouteData(r1, route_l(r1, self.D),
                                     route_d(r1, demands), None)
        r2 = [0, 3, 4, 5, 6, 7, 0]
        rd2_recieving = RouteData(r2, route_l(r2, self.D),
                                  route_d(r2, demands), None)

        result = do_redistribute_move(rd1_redistribute, [rd2_recieving],
                                      self.D,
                                      C=6.0,
                                      d=self.d,
                                      strategy=LSOPT.BEST_ACCEPT,
                                      recombination_level=1)

        # Fails -> None,None...None is returned (no partial fits)
        self.assertTrue(
            all(rp == None for rp in result),
            "The redistribute operator should return the redistributed and the new combined routes and the delta"
        )
コード例 #12
0
    def test_redistribute_find_best_fit(self):
        demands = [0.0, 1, 1, 2, 3, 1, 3, 1]
        r1 = [0, 1, 4, 6, 0]
        rd1_redistribute = RouteData(r1, route_l(r1, self.D),
                                     route_d(r1, demands), None)
        r2 = [0, 2, 3, 0]
        rd2_recieving = RouteData(r2, route_l(r2, self.D),
                                  route_d(r2, demands), None)

        r3 = [0, 5, 0]
        rd3_recieving = RouteData(r3, route_l(r3, self.D),
                                  route_d(r3, demands), None)

        r4 = [0, 7, 0]
        rd4_recieving = RouteData(r4, route_l(r4, self.D),
                                  route_d(r4, demands), None)

        result = do_redistribute_move(
            rd1_redistribute, [rd2_recieving, rd3_recieving, rd4_recieving],
            self.D,
            C=4.0,
            d=demands,
            strategy=LSOPT.BEST_ACCEPT,
            recombination_level=1)

        self.assertEqual(
            len(result), 5,
            "The redistribute operator should return the redistributed and the new combined routes and the delta"
        )
        self.assertEqual(result[0].route, [0, 0],
                         "It should be possible to insert all customers")
        self.assertEqual(_normalise_route_order(result[1].route),
                         [0, 1, 2, 3, 0],
                         "n1 should be redistributed to first route")
        self.assertEqual(_normalise_route_order(result[2].route), [0, 4, 5, 0],
                         "n4 should be redistributed to first route")
        self.assertEqual(_normalise_route_order(result[3].route), [0, 6, 7, 0],
                         "n6 should be redistributed to first route")
コード例 #13
0
    def test_until_no_improvements_move(self):
        D = self.D
        r1 = [0, 1, 2, 3, 5, 6, 7, 0]
        r2 = [0, 4, 0]
        r1d = (r1, route_l(r1, D), 6, None)
        r2d = (r2, route_l(r2, D), 1, None)

        loop_count = 0
        while True:
            result = do_1point_move(r1d, r2d, D)
            if result[2] is None:
                break
            # unpack result
            r1d, r2d, delta = result
            loop_count += 1

            self.assertTrue(
                loop_count < 8, "Too many operations, potential " +
                "infinite improvement loop")

        # unconstrained should run until other route is empty
        self.assertEqual(r2d[0], [0, 1, 2, 3, 4, 0],
                         "should reach a local optima")
コード例 #14
0
 def test_respect_route_cost_constraint(self):
     r2 = [0, 1, 2, 3, 0]
     result = self._make_improving_move(L=route_l(r2, self.D) + 1.0)
     self.assertEqual(
         result, (None, None, None),
         "no move should be made due to violation of C constraint")