Source code for jmetal.problem.singleobjective.unconstrained

import math

import numpy as np

from jmetal.core.problem import BinaryProblem, FloatProblem
from jmetal.core.solution import BinarySolution, FloatSolution

"""
.. module:: unconstrained
   :platform: Unix, Windows
   :synopsis: Unconstrained test problems for single-objective optimization

.. moduleauthor:: Antonio J. Nebro <antonio@lcc.uma.es>, Antonio Benítez-Hidalgo <antonio.b@uma.es>
"""


[docs] class OneMax(BinaryProblem): """The OneMax problem is a simple optimization problem that counts the number of ones in a binary string. The objective is to maximize the number of ones in the binary string, which is equivalent to minimizing the negative count of ones. Args: number_of_bits: The length of the binary string (default: 256) """ def __init__(self, number_of_bits: int = 256): super(OneMax, self).__init__() self.number_of_bits = number_of_bits self.number_of_bits_per_variable = [number_of_bits] # For backward compatibility self.obj_directions = [self.MINIMIZE] # We'll use negative count for minimization self.obj_labels = ["Ones"]
[docs] def number_of_variables(self) -> int: return self.number_of_bits # Each bit is treated as a variable
[docs] def number_of_objectives(self) -> int: return 1
[docs] def number_of_constraints(self) -> int: return 0
[docs] def evaluate(self, solution: BinarySolution) -> BinarySolution: # Count the number of ones in the binary string counter_of_ones = np.count_nonzero(solution.bits) # Store the negative count to be minimized (equivalent to maximizing the positive count) solution.objectives[0] = -float(counter_of_ones) return solution
[docs] def create_solution(self) -> BinarySolution: # Create a new binary solution with the specified number of bits solution = BinarySolution( number_of_variables=self.number_of_bits, number_of_objectives=self.number_of_objectives() ) # Initialize with random bits (using numpy for better performance) solution.bits = np.random.choice([True, False], size=self.number_of_bits) return solution
[docs] def name(self) -> str: return "OneMax"
[docs] class Sphere(FloatProblem): def __init__(self, number_of_variables: int = 10): super(Sphere, self).__init__() self.obj_directions = [self.MINIMIZE] self.obj_labels = ["f(x)"] self.lower_bound = [-5.12 for _ in range(number_of_variables)] self.upper_bound = [5.12 for _ in range(number_of_variables)] FloatSolution.lower_bound = self.lower_bound FloatSolution.upper_bound = self.upper_bound
[docs] def number_of_objectives(self) -> int: return 1
[docs] def number_of_constraints(self) -> int: return 0
[docs] def evaluate(self, solution: FloatSolution) -> FloatSolution: total = 0.0 for x in solution.variables: total += x * x solution.objectives[0] = total return solution
[docs] def name(self) -> str: return "Sphere"
[docs] class Rastrigin(FloatProblem): def __init__(self, number_of_variables: int = 10): super(Rastrigin, self).__init__() self.obj_directions = [self.MINIMIZE] self.obj_labels = ["f(x)"] self.lower_bound = [-5.12 for _ in range(number_of_variables)] self.upper_bound = [5.12 for _ in range(number_of_variables)] FloatSolution.lower_bound = self.lower_bound FloatSolution.upper_bound = self.upper_bound
[docs] def number_of_objectives(self) -> int: return 1
[docs] def number_of_constraints(self) -> int: return 0
[docs] def evaluate(self, solution: FloatSolution) -> FloatSolution: a = 10.0 result = a * len(solution.variables) x = solution.variables for i in range(len(solution.variables)): result += x[i] * x[i] - a * math.cos(2 * math.pi * x[i]) solution.objectives[0] = result return solution
[docs] def name(self) -> str: return "Rastrigin"
[docs] class SubsetSum(BinaryProblem): def __init__(self, C: int, W: list): """The goal is to find a subset S of W whose elements sum is closest to (without exceeding) C. This is a single-objective problem where we want to: 1. Maximize the sum of selected elements (without exceeding C) Args: C: The target sum (large integer) W: List of non-negative integers to select from """ super(SubsetSum, self).__init__() self.C = C self.W = np.array(W, dtype=float) # Convert to numpy array for vectorized operations self.number_of_bits = len(self.W) self.obj_directions = [self.MAXIMIZE] self.obj_labels = ["Sum"]
[docs] def number_of_variables(self) -> int: return self.number_of_bits # Each bit represents whether an item is selected
[docs] def number_of_objectives(self) -> int: return 1
[docs] def number_of_constraints(self) -> int: return 0
[docs] def evaluate(self, solution: BinarySolution) -> BinarySolution: # Get the mask of selected items (bits that are True) selected_mask = solution.bits # Calculate total sum of selected items total_sum = np.sum(self.W[selected_mask]) # Penalize solutions that exceed the target sum C if total_sum > self.C: # Apply a penalty that increases with how much we exceed C total_sum = self.C - (total_sum - self.C) if total_sum < 0.0: total_sum = 0.0 # Store the negative sum to be maximized solution.objectives[0] = -total_sum return solution
[docs] def create_solution(self) -> BinarySolution: # Create a new binary solution with one bit per item in W solution = BinarySolution( number_of_variables=self.number_of_bits, number_of_objectives=self.number_of_objectives() ) # Initialize with random bits (each bit represents whether an item is selected) solution.bits = np.random.choice([True, False], size=self.number_of_bits) return solution
[docs] def name(self) -> str: return "Subset Sum"