Source code for moead_framework.problem.combinatorial.mubqp

import numpy as np
from moead_framework.problem.problem import Problem


[docs]class Mubqp(Problem): """ Implementation of the Multiobjective Unconstrained Binary Quadratic Programming problem. The problem is compatible with files generated by the mocobench generator http://mocobench.sourceforge.net/index.php?n=Problem.MUBQP Example: >>> from moead_framework.problem.combinatorial import Mubqp >>> >>> instance_file = "moead_framework/test/data/instances/mubqp_0_2_25_0.8_0.dat" >>> mubqp = Mubqp(instance_file=instance_file) >>> >>> # Generate a new solution >>> solution = mubqp.generate_random_solution() >>> >>> # Print all decision variables of the solution >>> print(solution.decision_vector) >>> >>> # Print all objectives values of the solution >>> print(solution.F) """ dtype = float
[docs] def __init__(self, instance_file=None, rho=None, m=None, n=None, qs=None): f""" Constructor of the problem. You can initialize the problem directly by using an instance file or by setting parameters : rho, m, n and qs. :param instance_file: {str} text file generated by the mubqp generator : http://mocobench.sourceforge.net/index.php?n=Problem.MUBQP#Code :param rho: {float} the objective correlation coefficient :param m: {int} the number of objective functions :param n: {int} the length of solutions :param qs: {list} the matrix coefficients of each matrix: one matrix for each objective. """ self.instance_file = None self.rho = None self.m = None self.n = None self.d = None self.qs = None if instance_file is not None: if not isinstance(instance_file, str): raise TypeError("The expected type of `instance_file` is `str`") self.init_with_instance_file(instance_file=instance_file) elif (rho is not None) & (m is not None) & (n is not None) & (qs is not None): self.init_with_data(rho=rho, m=m, n=n, qs=qs) else: msg = "The constructor needs either the instance_file parameter or the following parameters : " \ "rho, m, n and qs." raise ValueError(msg) super().__init__(objective_number=self.m)
def init_with_instance_file(self, instance_file): if isinstance(instance_file, str): self.instance_file = instance_file else: raise TypeError("The instance_file parameter must be a string.") file = open(instance_file, 'r') file_content = list(map(str.strip, file.readlines())) file.close() file_content = file_content[6:] definition = file_content[0].split(" ") self.rho = float(definition[2]) self.m = int(definition[3]) self.n = int(definition[4]) self.d = float(definition[5]) file_content = file_content[2:] self.qs = np.zeros((self.m, self.n, self.n)) self.load_qs(file_content) def init_with_data(self, rho, m, n, qs): if isinstance(qs, list): self.qs = qs else: raise TypeError("The parameter qs must be a list.") if isinstance(m, int) & isinstance(n, int): self.m = m self.n = n else: raise TypeError("The parameters m and n must be positive integers.") if isinstance(rho, float): self.rho = rho else: raise TypeError("The parameter m rho must be a float.")
[docs] def f(self, function_id: int, decision_vector:np.ndarray): """ Evaluate the decision_vector for the objective function_id :param function_id: {integer} index of the objective :param decision_vector: {:class:`~moead_framework.solution.one_dimension_solution.OneDimensionSolution`} solution to evaluate :return: {float} fitness value """ if not isinstance(function_id, int): raise TypeError("The expected type of `function_id` is `int`") if not isinstance(decision_vector, np.ndarray): raise TypeError("The expected type of `decision_vector` is `np.ndarray`") fit = 0 for i in range(self.n): if decision_vector[i] == 1: for j in range(i+1): if decision_vector[j] == 1: fit += self.qs[function_id][i][j] return - fit
[docs] def generate_random_solution(self): """ Generate a random solution for the current problem :return: {:class:`~moead_framework.solution.one_dimension_solution.OneDimensionSolution`} """ return self.evaluate(x=np.random.randint(0, 2, self.n).tolist()[:])
[docs] def load_qs(self, file_content): """ Load values of the instance file :param file_content: {list<float>} content of the instance file :return: """ line = 0 for i in range(self.n): for j in range(self.n): s = file_content[line].split(" ") line += 1 for n in range(self.m): self.qs[n][i][j] = int(s[n]) pass