evox.problems.numerical.dtlz 源代码

import torch

from evox.core import Problem
from evox.operators.sampling import grid_sampling, uniform_sampling


[文档] class DTLZ(Problem): """ Base class for DTLZ test suite problems in multi-objective optimization. Inherit this class to implement specific DTLZ problem variants. :param d: Number of decision variables. :param m: Number of objectives. :param ref_num: Number of reference points used in the problem. """ def __init__(self, d: int = None, m: int = None, ref_num: int = 1000): """Override the setup method to initialize the parameters""" super().__init__() self.d = d self.m = m self.ref_num = ref_num self.sample, _ = uniform_sampling(self.ref_num * self.m, self.m) # Assuming UniformSampling is defined self.device = self.sample.device
[文档] def evaluate(self, X: torch.Tensor) -> torch.Tensor: """ Abstract method to evaluate the objective values for given decision variables. :param X: A tensor of shape (n, d), where n is the number of solutions and d is the number of decision variables. :return: A tensor of shape (n, m) representing the objective values for each solution. """ raise NotImplementedError()
[文档] def pf(self): """ Return the Pareto front for the problem. :return: A tensor representing the Pareto front. """ f = self.sample / 2 return f
[文档] class DTLZ1(DTLZ): def __init__(self, d: int = 7, m: int = 3, ref_num: int = 1000): super().__init__(d, m, ref_num)
[文档] def evaluate(self, X: torch.Tensor) -> torch.Tensor: m = self.m n, d = X.size() g = 100 * ( d - m + 1 + torch.sum( (X[:, m - 1 :] - 0.5) ** 2 - torch.cos(20 * torch.pi * (X[:, m - 1 :] - 0.5)), dim=1, keepdim=True, ) ) flip_cumprod = torch.flip( torch.cumprod( torch.cat([torch.ones((n, 1), device=X.device), X[:, : m - 1]], dim=1), dim=1, ), dims=[1], ) rest_part = torch.cat( [ torch.ones((n, 1), device=X.device), 1 - torch.flip(X[:, : m - 1], dims=[1]), ], dim=1, ) f = 0.5 * (1 + g) * flip_cumprod * rest_part return f
[文档] class DTLZ2(DTLZ): def __init__(self, d: int = 12, m: int = 3, ref_num: int = 1000): super().__init__(d, m, ref_num)
[文档] def evaluate(self, X: torch.Tensor) -> torch.Tensor: m = self.m g = torch.sum((X[:, m - 1 :] - 0.5) ** 2, dim=1, keepdim=True) f = ( (1 + g) * torch.flip( torch.cumprod( torch.cat( [ torch.ones((X.size(0), 1), device=X.device), torch.maximum( torch.cos(X[:, : m - 1] * torch.pi / 2), torch.tensor(0.0, device=X.device), ), ], dim=1, ), dim=1, ), dims=[1], ) * torch.cat( [ torch.ones((X.size(0), 1), device=X.device), torch.sin(torch.flip(X[:, : m - 1], dims=[1]) * torch.pi / 2), ], dim=1, ) ) return f
[文档] def pf(self): f = self.sample f = f / torch.sqrt(f.pow(2).sum(dim=1, keepdim=True)) return f
[文档] class DTLZ3(DTLZ2): def __init__(self, d: int = 12, m: int = 3, ref_num: int = 1000): super().__init__(d, m, ref_num)
[文档] def evaluate(self, X: torch.Tensor) -> torch.Tensor: n, d = X.size() m = self.m g = 100 * ( d - m + 1 + torch.sum( (X[:, m - 1 :] - 0.5) ** 2 - torch.cos(20 * torch.pi * (X[:, m - 1 :] - 0.5)), dim=1, keepdim=True, ) ) f = ( (1 + g) * torch.flip( torch.cumprod( torch.cat( [ torch.ones((n, 1), device=X.device), torch.maximum( torch.cos(X[:, : m - 1] * torch.pi / 2), torch.tensor(0.0, device=X.device), ), ], dim=1, ), dim=1, ), dims=[1], ) * torch.cat( [ torch.ones((n, 1), device=X.device), torch.sin(torch.flip(X[:, : m - 1], dims=[1]) * torch.pi / 2), ], dim=1, ) ) return f
[文档] class DTLZ4(DTLZ2): def __init__(self, d: int = 12, m: int = 3, ref_num: int = 1000): super().__init__(d, m, ref_num)
[文档] def evaluate(self, X: torch.Tensor) -> torch.Tensor: m = self.m Xfront = X[:, : m - 1].pow(100) Xrear = X[:, m - 1:].clone() # X[:, : m - 1] = X[:, : m - 1].pow(100) g = torch.sum((Xrear - 0.5) ** 2, dim=1, keepdim=True) f = ( (1 + g) * torch.flip( torch.cumprod( torch.cat( [ torch.ones((g.size(0), 1), device=X.device), torch.maximum( torch.cos(Xfront * torch.pi / 2), torch.tensor(0.0, device=X.device), ), ], dim=1, ), dim=1, ), dims=[1], ) * torch.cat( [ torch.ones((g.size(0), 1), device=X.device), torch.sin(torch.flip(Xfront, dims=[1]) * torch.pi / 2), ], dim=1, ) ) return f
[文档] class DTLZ5(DTLZ): def __init__(self, d: int = 12, m: int = 3, ref_num: int = 1000): super().__init__(d, m, ref_num)
[文档] def evaluate(self, X: torch.Tensor) -> torch.Tensor: m = self.m g = torch.sum((X[:, m - 1 :] - 0.5) ** 2, dim=1, keepdim=True) temp = g.repeat(1, m - 2) Xfront = X[:, : m - 1].clone() Xfront[:, 1:] = (1 + 2 * temp * Xfront[:, 1:]) / (2 + 2 * temp) f = ( (1 + g) * torch.flip( torch.cumprod( torch.cat( [ torch.ones((g.size(0), 1), device=X.device), torch.maximum( torch.cos(Xfront * torch.pi / 2), torch.tensor(0.0, device=X.device), ), ], dim=1, ), dim=1, ), dims=[1], ) * torch.cat( [ torch.ones((g.size(0), 1), device=X.device), torch.sin(torch.flip(Xfront, dims=[1]) * torch.pi / 2), ], dim=1, ) ) return f
[文档] def pf(self): n = self.ref_num * self.m f = torch.vstack( ( torch.hstack( ( torch.arange(0, 1, 1.0 / (n - 1), device=self.device), torch.tensor(1.0, device=self.device), ) ), torch.hstack( ( torch.arange(1, 0, -1.0 / (n - 1), device=self.device), torch.tensor(0.0, device=self.device), ) ), ) ).T f = f / torch.tile(torch.sqrt(torch.sum(f**2, dim=1, keepdim=True)), (1, f.size(1))) for i in range(self.m - 2): f = torch.cat((f[:, 0:1], f), dim=1) f = f / torch.sqrt(torch.tensor(2.0, device=self.device)) ** torch.tile( torch.hstack( ( torch.tensor(self.m - 2, device=self.device), torch.arange(self.m - 2, -1, -1, device=self.device), ) ), (f.size(0), 1), ) return f
[文档] class DTLZ6(DTLZ): def __init__(self, d: int = 12, m: int = 3, ref_num: int = 1000): super().__init__(d, m, ref_num)
[文档] def evaluate(self, X: torch.Tensor) -> torch.Tensor: m = self.m g = torch.sum((X[:, m - 1 :] ** 0.1), dim=1, keepdim=True) temp = torch.tile(g, (1, m - 2)) Xfront = X[:, : m - 1].clone() Xfront[:, 1:] = (1 + 2 * temp * Xfront[:, 1:]) / (2 + 2 * temp) f = ( torch.tile(1 + g, (1, m)) * torch.flip( torch.cumprod( torch.cat( [ torch.ones((X.size(0), 1), device=X.device), torch.maximum( torch.cos(Xfront * torch.pi / 2), torch.tensor(0.0, device=X.device), ), ], dim=1, ), dim=1, ), dims=[1], ) * torch.cat( [ torch.ones((X.size(0), 1), device=X.device), torch.sin(torch.flip(Xfront, dims=[1]) * torch.pi / 2), ], dim=1, ) ) return f
[文档] def pf(self): n = self.ref_num * self.m # Ensure the tensor is created on the same device (use X.device if needed) f = torch.vstack( ( torch.hstack( ( torch.arange(0, 1, 1.0 / (n - 1), device=self.device), torch.tensor(1.0, device=self.device), ) ), torch.hstack( ( torch.arange(1, 0, -1.0 / (n - 1), device=self.device), torch.tensor(0.0, device=self.device), ) ), ) ).T f = f / torch.tile(torch.sqrt(torch.sum(f**2, dim=1, keepdim=True)), (1, f.size(1))) for i in range(self.m - 2): f = torch.cat((f[:, 0:1], f), dim=1) f = f / torch.sqrt(torch.tensor(2.0, device=self.device)) ** torch.tile( torch.hstack( ( torch.tensor(self.m - 2, device=self.device), torch.arange(self.m - 2, -1, -1, device=self.device), ) ), (f.size(0), 1), ) return f
[文档] class DTLZ7(DTLZ): def __init__(self, d: int = 21, m: int = 3, ref_num: int = 1000): super().__init__(d, m, ref_num) self.sample, _ = grid_sampling(self.ref_num * self.m, self.m - 1)
[文档] def evaluate(self, X: torch.Tensor) -> torch.Tensor: n, d = X.size() m = self.m f = torch.zeros((n, m), device=X.device) g = 1 + 9 * torch.mean(X[:, m - 1 :], dim=1, keepdim=True) term = torch.sum( X[:, : m - 1] / (1 + torch.tile(g, (1, m - 1))) * (1 + torch.sin(3 * torch.pi * X[:, : m - 1])), dim=1, keepdim=True, ) f = torch.cat([X[:, : m - 1].clone(), (1 + g) * (m - term)], dim=1) return f
[文档] def pf(self): interval = torch.tensor([0.0, 0.251412, 0.631627, 0.859401], dtype=torch.float, device=self.device) median = (interval[1] - interval[0]) / (interval[3] - interval[2] + interval[1] - interval[0]).to(self.device) x = self.sample.to(self.device) mask_less_equal_median = x <= median mask_greater_median = x > median x = torch.where( mask_less_equal_median, x * (interval[1] - interval[0]) / median + interval[0], x, ) x = torch.where( mask_greater_median, (x - median) * (interval[3] - interval[2]) / (1 - median) + interval[2], x, ) last_col = 2 * (self.m - torch.sum(x / 2 * (1 + torch.sin(3 * torch.pi * x)), dim=1, keepdim=True)) pf = torch.cat([x, last_col], dim=1) return pf