Last active
January 19, 2021 08:02
-
-
Save toshihikoyanase/c79a944377c4b1d5b8f448d9ffe339e9 to your computer and use it in GitHub Desktop.
A prototypical implementation of MOTPE with constraints
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def _dominates_both_feasible(extended: np.ndarray, const_extended: np.ndarray) -> np.ndarray: | |
return np.logical_and( | |
np.logical_and( | |
np.all(const_extended <= 0, axis=2), | |
np.all(np.swapaxes(const_extended, 0, 1) <= 0, axis=2), | |
), np.logical_and( | |
np.all(extended <= np.swapaxes(extended, 0, 1), axis=2), | |
np.any(extended < np.swapaxes(extended, 0, 1), axis=2), | |
) | |
) | |
def _dominates_by_feasibility(const_extended: np.ndarray) -> np.ndarray: | |
return np.logical_and( | |
np.all(const_extended <= 0, axis=2), | |
np.any(np.swapaxes(const_extended, 0, 1) > 0, axis=2), | |
) | |
def _dominates_by_total_violation(const_extended: np.ndarray) -> np.ndarray: | |
inv_const_extended = np.swapaxes(const_extended, 0, 1) | |
return np.logical_and( | |
np.logical_and( | |
np.any(const_extended > 0, axis=2), | |
np.any(inv_const_extended > 0, axis=2), | |
), | |
np.sum(const_extended, axis=2) < np.sum(inv_const_extended, axis=2) | |
) | |
def _constrained_dominates(extended: np.ndarray, const_extended: np.ndarray) -> np.ndarray: | |
return np.logical_or( | |
np.logical_or( | |
_dominates_both_feasible(extended, const_extended), | |
_dominates_by_feasibility(const_extended), | |
), | |
_dominates_by_total_violation(const_extended) | |
) | |
def _calculate_constrained_nondomination_rank(loss_vals: np.ndarray, constraint_vals: np.ndarray) -> np.ndarray: | |
const_vecs = constraint_vals.copy() | |
const_vecs[const_vecs < 0] = 0 | |
const_max = max(np.max(const_vecs), 1) | |
vecs = loss_vals.copy() | |
# Normalize values | |
lb = vecs.min(axis=0, keepdims=True) | |
ub = vecs.max(axis=0, keepdims=True) | |
vecs = (vecs - lb) / (ub - lb) | |
ranks = np.zeros(len(vecs)) | |
num_unranked = len(vecs) | |
rank = 0 | |
while num_unranked > 0: | |
extended = np.tile(vecs, (vecs.shape[0], 1, 1)) | |
const_extended = np.tile(const_vecs, (const_vecs.shape[0], 1, 1)) | |
counts = np.sum( | |
_constrained_dominates(extended, const_extended), | |
axis=1, | |
) | |
vecs[counts == 0] = 1.1 # mark as ranked | |
const_vecs[counts == 0] = const_max # marked as ranked | |
ranks[counts == 0] = rank | |
rank += 1 | |
num_unranked -= np.sum(counts == 0) | |
return ranks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def _calculate_nondomination_rank(loss_vals: np.ndarray) -> np.ndarray: | |
vecs = loss_vals.copy() | |
# Normalize values | |
lb = vecs.min(axis=0, keepdims=True) | |
ub = vecs.max(axis=0, keepdims=True) | |
vecs = (vecs - lb) / (ub - lb) | |
ranks = np.zeros(len(vecs)) | |
num_unranked = len(vecs) | |
rank = 0 | |
while num_unranked > 0: | |
extended = np.tile(vecs, (vecs.shape[0], 1, 1)) | |
counts = np.sum( | |
np.logical_and( | |
np.all(extended <= np.swapaxes(extended, 0, 1), axis=2), | |
np.any(extended < np.swapaxes(extended, 0, 1), axis=2), | |
), | |
axis=1, | |
) | |
vecs[counts == 0] = 1.1 # mark as ranked | |
ranks[counts == 0] = rank | |
rank += 1 | |
num_unranked -= np.sum(counts == 0) | |
return ranks |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment