Skip to content

init problems without instance files #74

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 5, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 40 additions & 12 deletions moead_framework/problem/combinatorial/knapsack.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import numpy as np
from moead_framework.problem.problem import Problem
from moead_framework.solution.one_dimension_solution import OneDimensionSolution


class KnapsackProblem(Problem):
Expand All @@ -25,27 +24,49 @@ class KnapsackProblem(Problem):
>>> # Print all objectives values of the solution
>>> print(solution.F)
"""
def __init__(self, number_of_objective, instance_file):
"""
Constructor of the problem

:param number_of_objective: {integer}
:param instance_file: {string} txt file of the instance: http://www-desir.lip6.fr/~lustt/Research.html#MOKP
def __init__(self, number_of_objective, instance_file=None, weights=None, profits=None, capacities=None):
f"""
Constructor of the problem.
You can initialize the problem directly by using an instance file or by setting parameters : weights,
profits and capacities.

:param number_of_objective: {int}
:param instance_file: {str} txt file of the instance: http://www-desir.lip6.fr/~lustt/Research.html#MOKP
:param weights: {list} weights of all objects available in knapsacks
:param profits: {list} profits of all objects available in knapsacks
:param capacities: {list} capacities of each knapsack
"""
super().__init__(number_of_objective)

self.instance_file = instance_file
self.weights = []
self.profits = []
self.capacities = []
self.instance_file = None

if instance_file is not None:
self.init_with_instance_file(instance_file=instance_file)
elif (weights is not None) & (profits is not None) & (capacities is not None):
self.init_with_data(weights=weights, profits=profits, capacities=capacities)
else:
msg = "The constructor needs either the instance_file parameter or the weights, " \
"profits and capacities parameters"
raise ValueError(msg)

self.number_of_objects = len(self.weights[0])

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(self.instance_file, 'r')
file_content = list(map(str.strip, file.readlines()))
file_content = file_content[2:]

index_to_split_one = file_content.index("=")
indexes_to_split = [index_to_split_one]
for i in range(1, self.number_of_objective - 1):
indexes_to_split.append(index_to_split_one * (i+1) + 1)
indexes_to_split.append(index_to_split_one * (i + 1) + 1)

kps = np.split(np.array(file_content), indexes_to_split)

Expand All @@ -63,10 +84,17 @@ def __init__(self, number_of_objective, instance_file):

self.weights.append(w)
self.profits.append(p)

self.number_of_objects = len(self.weights[0])
file.close()

def init_with_data(self, weights, profits, capacities):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you assert that weights, profits, capacities are equal?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do in the new commit : b9201d4

if isinstance(weights, list) & isinstance(profits, list) & isinstance(capacities, list):
self.weights = weights
self.profits = profits
self.capacities = capacities
else:
raise TypeError("The parameters weights, profits and capacities must be list.")


def f(self, function_id, decision_vector):
"""
Evaluate the decision_vector for the objective function_id
Expand Down
59 changes: 51 additions & 8 deletions moead_framework/problem/combinatorial/mubqp.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import numpy as np
from moead_framework.problem.problem import Problem
from moead_framework.solution.one_dimension_solution import OneDimensionSolution


class Mubqp(Problem):
Expand Down Expand Up @@ -28,12 +27,41 @@ class Mubqp(Problem):

dtype = int

def __init__(self, instance_file):
"""
Constructor of the problem
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: {string} text file generated by the mubqp generator : http://mocobench.sourceforge.net/index.php?n=Problem.RMNK#Code
: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:
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()
Expand All @@ -46,12 +74,27 @@ def __init__(self, instance_file):
self.n = int(definition[4])
self.d = float(definition[5])
file_content = file_content[2:]

super().__init__(objective_number=self.m)

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.")

def f(self, function_id, decision_vector):
"""
Evaluate the decision_vector for the objective function_id
Expand Down
67 changes: 60 additions & 7 deletions moead_framework/problem/combinatorial/rmnk.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import numpy as np
from moead_framework.problem.problem import Problem
from moead_framework.solution.one_dimension_solution import OneDimensionSolution


class Rmnk(Problem):
Expand Down Expand Up @@ -30,12 +29,47 @@ class Rmnk(Problem):

dtype = int

def __init__(self, instance_file):
def __init__(self, instance_file=None, rho=None, m=None, n=None, k=None, links=None, tables=None):
f"""
Constructor of the problem.
You can initialize the problem directly by using an instance file or by setting parameters : rho, m, n, k, links and tables.
http://mocobench.sourceforge.net/index.php?n=Problem.RMNK#Format

:param instance_file: {str} text file generated by the rmnk generator : http://mocobench.sourceforge.net/index.php?n=Problem.RMNK#Code
:param rho: {float} the objective correlation coefficient
:param m: {int} the number of objective functions
:param n: {int} the length of solutions
:param k: {list} the number of epistatic links (non-linearity)
:param links: {list} describe the epistatic structure between variables
:param tables: {list} describe the fitness contribution
"""
Constructor of the problem
self.rho = None
self.m = None
self.n = None
self.k = None
self.links = None
self.tables = None
self.instance_file = None

if instance_file is not None:
self.init_with_instance_file(instance_file=instance_file)
elif (rho is not None) & (m is not None) & (n is not None) & (k is not None) & (links is not None) & (
tables is not None):
self.init_with_data(rho=rho, m=m, n=n, k=k, links=links, tables=tables)
else:
msg = "The constructor needs either the instance_file parameter or the following parameters : " \
"rho, m, n, k, links and tables."
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.")

:param instance_file: {string} text file generated by the rmnk generator : http://mocobench.sourceforge.net/index.php?n=Problem.RMNK#Code
"""
file = open(instance_file, 'r')
file_content = list(map(str.strip, file.readlines()))
file_content = file_content[3:]
Expand All @@ -52,15 +86,34 @@ def __init__(self, instance_file):

self.tables = np.zeros((self.m, self.n, 1 << (self.k + 1)))


file_content = file_content[2:]
line = self.load_links(file_content)

file_content = file_content[line+1:]
file_content = file_content[line + 1:]
self.load_tables(file_content)

file.close()

def init_with_data(self, rho, m, n, k, links, tables):

if isinstance(m, int) & isinstance(n, int) & isinstance(k, int):
self.m = m
self.n = n
self.k = k
else:
raise TypeError("The parameters m, n and k must be positive integers.")

if isinstance(rho, (int, float)):
self.rho = rho
else:
raise TypeError("The parameter rho must be a float.")

if isinstance(links, list) & isinstance(tables, list):
self.links = links
self.tables = tables
else:
raise TypeError("The parameters links and tables must be list.")

def f(self, function_id, decision_vector):
"""
Evaluate the decision_vector for the objective function_id
Expand Down
21 changes: 17 additions & 4 deletions moead_framework/test/problem/test_knapsack.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,23 @@ def setUp(self):
instance = project_path + '/../data/instances/MOKP_250_2.dat'
self.problem = KnapsackProblem(number_of_objective=number_of_objective, instance_file=instance)

def test_instance(self):
"""Test parameters"""
self.assertEqual(self.problem.number_of_objective, 2)
self.assertEqual(self.problem.number_of_objects, 250)
def test_instance_file(self):
"""Test constructor with instance file"""
project_path = os.path.dirname(os.path.abspath(__file__))

problem = KnapsackProblem(number_of_objective=2, instance_file=project_path + '/../data/instances/MOKP_250_2.dat')
self.assertEqual(problem.number_of_objective, 2)
self.assertEqual(problem.number_of_objects, 250)

def test_instance_data(self):
"""Test constructor with data"""
weights = [[20, 11, 80, 50], [48, 19, 20, 38]]
profits = [[2, 10, 73, 20], [34, 4, 83, 28]]
capacities = [110, 90]

problem = KnapsackProblem(number_of_objective=2, weights=weights, profits=profits, capacities=capacities)
self.assertEqual(problem.number_of_objective, 2)
self.assertEqual(problem.number_of_objects, 4)

def test_generate_random_solution(self):
"""Test the function 'generate_random_solution'"""
Expand Down
Loading