(self)
Divide and conquer strategy to compute the cells covering the non-dominated region.

        Generic version: works for an arbitrary number of objectives.
Divide and conquer strategy to compute the cells covering the non-dominated region.
Divide and conquer strategy to compute the cells covering the non - dominated region .
def divide_conquer_nd(self):
        """
        Divide and conquer strategy to compute the cells covering the non-dominated region.

        Generic version: works for an arbitrary number of objectives.
        """
        outdim = self.Y.shape[1]

        # The divide and conquer algorithm operates on a pseudo Pareto set
        # that is a mapping of the real Pareto set to discrete values
        pseudo_pf = np.argsort(self.front.value, axis=0) + 1  # +1 as index zero is reserved for the ideal point

        # Extend front with the ideal and anti-ideal point
        min_pf = np.min(self.front.value, axis=0) - 1
        max_pf = np.max(self.front.value, axis=0) + 1

        pf_ext = np.vstack((min_pf, self.front.value, max_pf))  # Needed for early stopping check (threshold)
        pf_ext_idx = np.vstack((np.zeros(outdim, dtype=np_int_type),
                                pseudo_pf,
                                np.ones(outdim, dtype=np_int_type) * self.front.shape[0] + 1))

        # Start with one cell covering the whole front
        dc = [(np.zeros(outdim, dtype=np_int_type),
               (int(pf_ext_idx.shape[0]) - 1) * np.ones(outdim, dtype=np_int_type))]
        
        total_size = np.prod(max_pf - min_pf)

        # Start divide and conquer until we processed all cells
        while dc:
            # Process test cell
            cell = dc.pop()

            arr = np.arange(outdim)
            lb  = pf_ext[pf_ext_idx[cell[0], arr], arr]
            ub  = pf_ext[pf_ext_idx[cell[1], arr], arr]

            # Acceptance test:
            if self._is_test_required((ub - stability) < self.front.value):
                # Cell is a valid integral bound: store
                self.bounds.append(pf_ext_idx[cell[0], np.arange(outdim)],
                                   pf_ext_idx[cell[1], np.arange(outdim)])
            # Reject test:
            elif self._is_test_required((lb + stability) < self.front.value):
                # Cell can not be discarded: calculate the size of the cell
                dc_dist = cell[1] - cell[0]
                hc = BoundedVolumes(pf_ext[pf_ext_idx[cell[0], np.arange(outdim)], np.arange(outdim)],
                                    pf_ext[pf_ext_idx[cell[1], np.arange(outdim)], np.arange(outdim)])

                # Only divide when it is not an unit cell and the volume is above the approx. threshold
                if np.any(dc_dist > 1) and np.all((hc.size()[0] / total_size) > self.threshold):
                    # Divide the test cell over its largest dimension
                    edge_size, idx = np.max(dc_dist), np.argmax(dc_dist)
                    edge_size1 = int(np.round(edge_size / 2.0))
                    edge_size2 = edge_size - edge_size1

                    # Store divided cells
                    ub = np.copy(cell[1])
                    ub[idx] -= edge_size1
                    dc.append((np.copy(cell[0]), ub))

                    lb = np.copy(cell[0])
                    lb[idx] += edge_size2
                    dc.append((lb, np.copy(cell[1])))
def divide_conquer_nd ( self ) : outdim = self . Y . shape [ 1 ] # The divide and conquer algorithm operates on a pseudo Pareto set # that is a mapping of the real Pareto set to discrete values pseudo_pf = np . argsort ( self . front . value , axis = 0 ) + 1 # +1 as index zero is reserved for the ideal point # Extend front with the ideal and anti-ideal point min_pf = np . min ( self . front . value , axis = 0 ) - 1 max_pf = np . max ( self . front . value , axis = 0 ) + 1 pf_ext = np . vstack ( ( min_pf , self . front . value , max_pf ) ) # Needed for early stopping check (threshold) pf_ext_idx = np . vstack ( ( np . zeros ( outdim , dtype = np_int_type ) , pseudo_pf , np . ones ( outdim , dtype = np_int_type ) * self . front . shape [ 0 ] + 1 ) ) # Start with one cell covering the whole front dc = [ ( np . zeros ( outdim , dtype = np_int_type ) , ( int ( pf_ext_idx . shape [ 0 ] ) - 1 ) * np . ones ( outdim , dtype = np_int_type ) ) ] total_size = np . prod ( max_pf - min_pf ) # Start divide and conquer until we processed all cells while dc : # Process test cell cell = dc . pop ( ) arr = np . arange ( outdim ) lb = pf_ext [ pf_ext_idx [ cell [ 0 ] , arr ] , arr ] ub = pf_ext [ pf_ext_idx [ cell [ 1 ] , arr ] , arr ] # Acceptance test: if self . _is_test_required ( ( ub - stability ) < self . front . value ) : # Cell is a valid integral bound: store self . bounds . append ( pf_ext_idx [ cell [ 0 ] , np . arange ( outdim ) ] , pf_ext_idx [ cell [ 1 ] , np . arange ( outdim ) ] ) # Reject test: elif self . _is_test_required ( ( lb + stability ) < self . front . value ) : # Cell can not be discarded: calculate the size of the cell dc_dist = cell [ 1 ] - cell [ 0 ] hc = BoundedVolumes ( pf_ext [ pf_ext_idx [ cell [ 0 ] , np . arange ( outdim ) ] , np . arange ( outdim ) ] , pf_ext [ pf_ext_idx [ cell [ 1 ] , np . arange ( outdim ) ] , np . arange ( outdim ) ] ) # Only divide when it is not an unit cell and the volume is above the approx. threshold if np . any ( dc_dist > 1 ) and np . all ( ( hc . size ( ) [ 0 ] / total_size ) > self . threshold ) : # Divide the test cell over its largest dimension edge_size , idx = np . max ( dc_dist ) , np . argmax ( dc_dist ) edge_size1 = int ( np . round ( edge_size / 2.0 ) ) edge_size2 = edge_size - edge_size1 # Store divided cells ub = np . copy ( cell [ 1 ] ) ub [ idx ] -= edge_size1 dc . append ( ( np . copy ( cell [ 0 ] ) , ub ) ) lb = np . copy ( cell [ 0 ] ) lb [ idx ] += edge_size2 dc . append ( ( lb , np . copy ( cell [ 1 ] ) ) )