示例#1
0
    def optimize_rendezvous_points(self):
        # self.show_state()
        round_count = 1
        while self._unbalanced():
            logger.debug("Running optimization round %d", round_count)
            round_count += 1

            if round_count > 100:
                raise TimeoutError("TOCS optimization got lost")

            average_length = self.average_tour_length()

            for clust in self.clusters:
                logger.debug("Examining %s", clust)
                if much_greater_than(average_length, clust.tour_length,
                                     r=self._length_threshold):
                    # Handle the case where we need to move the cluster's RP
                    # closer to the centroid.
                    self._grow_cluster(clust, average_length)

                elif much_greater_than(clust.tour_length, average_length,
                                       r=self._length_threshold):
                    # Handle the case where we need to move the cluster's RP
                    # closer to the cluster itself.
                    self._shrink_cluster(clust, average_length)

                else:
                    continue
示例#2
0
    def _unbalanced(self):
        """
        Determine if any clusters have tours which are dramatically smaller or
        larger than the average tour length over all clusters.

        :return: True if the clusters are unbalanced and need adjustment
        :return: False if the clusters are all close to even tour lengths
        :rtype: bool
        """
        average_length = self.average_tour_length()
        logger.debug("Average tour length: %s", average_length)
        for clust in self.clusters:
            logger.debug("%s tour length: %s", clust, clust.tour_length)

            max_tour = clust.tour_length
            max_tour += np.linalg.norm(
                clust.rendezvous_point.location.nd - self.center)

            if max_tour < average_length:
                logger.debug("Cannot optimize %s in this round", clust)
                continue

            if much_greater_than(average_length, clust.tour_length,
                                 r=self._length_threshold):
                return True

            elif much_greater_than(clust.tour_length, average_length,
                                   r=self._length_threshold):
                return True

        return False
示例#3
0
    def compute_paths(self):
        self.find_cells()
        self.create_virtual_clusters()

        # Check for the case where Em >> Ec
        clusters = list()
        for vc in self.virtual_clusters:
            cluster = LoafCluster(self.env)
            cluster.cluster_id = vc.cluster_id
            for cell in vc.cells:
                cluster.add(cell)
            clusters.append(cluster)

        self.update_anchors(clusters)

        e_c = np.sum([
            self.energy_model.total_comms_energy(cluster)
            for cluster in clusters
        ])  # * pq.J

        e_m = np.sum([
            self.energy_model.total_movement_energy(cluster)
            for cluster in clusters
        ])  # * pq.J

        logger.debug("Em is %s", e_m)
        logger.debug("Ec is %s", e_c)

        if much_greater_than(e_m, e_c):
            logger.debug("Em >> Ec, running special case")
            self.em_is_large = True
            self.clusters = clusters
            self.update_anchors()
            return self

        elif much_greater_than(e_c, e_m):
            logger.debug("Ec >> Em, running special case")
            self.ec_is_large = True
            self.clusters = clusters
            self.update_anchors()
            self.optimize_large_ec()

        else:
            logger.debug("Proceeding with standard optimization")
            self.greedy_expansion()
            self.optimization()

        # self.greedy_expansion()
        # self.optimization()

        return self
示例#4
0
    def _shrink_cluster(self, clust, average_length):
        """
        Update a cluster's rendezvous point so as to bring it "further" from
        the centroid cluster. This effectively shrinks the cluster's tour. The
        process of moving the RP is repeated until the cluster's tour length
        is no longer "much smaller" than the average tour length.

        :param clust: Cluster to consider
        :type clust: ToCSCluster
        :param average_length: Average tour length of all clusters
        :type average_length: pq.quantity.Quantity
        :return: None
        """

        while much_greater_than(clust.tour_length, average_length,
                                r=self._length_threshold):
            current_rp_loc = clust.rendezvous_point.location.nd

            # Calculate the vector between the current RP and the center of the
            # centroid cluster. Then just scale it up.
            new_rp_loc = current_rp_loc - self.center
            new_rp_loc *= 1.25
            new_rp_loc += self.center

            # Handle the case where a cluster's tour cannot be optimized any
            # further.
            if np.allclose(new_rp_loc, current_rp_loc):
                break

            # Now assign the new location to the existing RP object (just saves
            # us object creation).
            self._update_rp_pos(clust, new_rp_loc)

            # Now reassign segments if needed
            self._reassign_segments_to_central(clust)
示例#5
0
    def _grow_cluster(self, clust, average_length):
        """
        Update a cluster's rendezvous point so as to bring it "closer" to the
        centroid cluster. This effectively grows the cluster's tour. The
        process of moving the RP is repeated until the cluster's tour length
        is no longer "much larger" than the average tour length.

        :param clust: Cluster to consider
        :type clust: ToCSCluster
        :param average_length: Average tour length of all clusters
        :type average_length: pq.quantity.Quantity
        :return: None
        """

        while much_greater_than(average_length, clust.tour_length,
                                r=self._length_threshold):
            current_rp_loc = clust.rendezvous_point.location.nd

            # Calculate the vector between the current RP and the center of the
            # centroid cluster. Then just scale it down.
            new_rp_loc = current_rp_loc - self.center
            new_rp_loc *= 0.75
            new_rp_loc += self.center

            if np.allclose(current_rp_loc, new_rp_loc):
                break

            # Now assign the new location to the existing RP object (just saves
            # us object creation).
            self._update_rp_pos(clust, new_rp_loc)

            # Now reassign segments if the cluster's RP is closer to the
            # centroid than an actual segment within the central cluster.
            self._reassign_segments_to_cluster(clust)