From fc094f6d661fec91bdc2b7e5ee023deaf9053945 Mon Sep 17 00:00:00 2001 From: Geoffrey Pruvost Date: Thu, 17 Sep 2020 12:33:14 +0200 Subject: [PATCH] v0.5.4 : add new combinatorial problem : mubqp --- .../problem/combinatorial/mubqp.py | 61 ++ .../test/data/mubqp_0_2_25_0.8_0.dat | 633 ++++++++++++++++++ moead_framework/test/problem/test_ubqp.py | 52 ++ setup.py | 2 +- 4 files changed, 747 insertions(+), 1 deletion(-) create mode 100644 moead_framework/problem/combinatorial/mubqp.py create mode 100644 moead_framework/test/data/mubqp_0_2_25_0.8_0.dat create mode 100644 moead_framework/test/problem/test_ubqp.py diff --git a/moead_framework/problem/combinatorial/mubqp.py b/moead_framework/problem/combinatorial/mubqp.py new file mode 100644 index 0000000..ddfac89 --- /dev/null +++ b/moead_framework/problem/combinatorial/mubqp.py @@ -0,0 +1,61 @@ +import numpy as np +from moead_framework.problem.problem import Problem +from moead_framework.solution.one_dimension_solution import OneDimensionSolution + + +class Mubqp(Problem): + + def __init__(self, instance_file): + 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:] + + super().__init__(objective_number=self.m) + + self.qs = np.zeros((self.m, self.n, self.n)) + self.load_qs(file_content) + + def f(self, function_id, solution): + fit = 0 + + for i in range(self.n): + if solution[i] == 1: + for j in range(i+1): + if solution[j] == 1: + fit += self.qs[function_id][i][j] + + return fit + + def generate_random_solution(self, evaluate=True): + return self.generate_solution(array=np.random.randint(0, 2, self.n).tolist()[:], evaluate=evaluate) + + def generate_solution(self, array, evaluate=True): + x = OneDimensionSolution(np.array(array, dtype=int)) + + for j in range(self.function_numbers): + if evaluate: + x.F.append(self.f(j, x.solution)) + else: + x.F.append(None) + + return x + + def load_qs(self, array): + line = 0 + for i in range(self.n): + for j in range(self.n): + s = array[line].split(" ") + line += 1 + for n in range(self.m): + self.qs[n][i][j] = int(s[n]) + pass + diff --git a/moead_framework/test/data/mubqp_0_2_25_0.8_0.dat b/moead_framework/test/data/mubqp_0_2_25_0.8_0.dat new file mode 100644 index 0000000..e03d61d --- /dev/null +++ b/moead_framework/test/data/mubqp_0_2_25_0.8_0.dat @@ -0,0 +1,633 @@ +c file generated by mubqpGenerator.R with seed 0 the 09/15/2020 16:49:21 +c version 1.0 +c +c one column for each dimension +c each matrix is given by: c(1,1) ... c(N,1) c(1,2) ... c(N,2) ... c(N,N) +c +p MUBQP 0 2 25 0.8 +p matrices +23 79 +-93 -26 +12 82 +84 80 +86 32 +0 0 +-19 -65 +-20 -23 +21 0 +95 98 +35 55 +-65 -58 +98 -75 +-46 -23 +86 -24 +17 -32 +84 20 +-59 -63 +45 34 +-33 -78 +58 -18 +76 29 +87 11 +75 58 +28 -5 +-83 39 +-43 72 +48 -51 +0 0 +68 4 +0 0 +0 0 +0 0 +-18 -48 +-8 53 +98 75 +-76 68 +-79 -33 +90 78 +0 0 +60 92 +-9 43 +38 -35 +-69 -59 +-17 -76 +-7 -71 +0 0 +93 75 +76 59 +0 0 +0 0 +-32 -29 +84 99 +-97 -57 +41 -4 +-37 20 +21 46 +-64 -14 +64 -97 +-67 -79 +-68 28 +57 -1 +0 0 +-31 -9 +98 -58 +-53 19 +-55 -85 +-57 29 +27 20 +0 0 +12 2 +0 0 +0 0 +0 0 +80 49 +-16 73 +-4 11 +41 -9 +17 -64 +0 0 +24 -57 +-92 79 +45 56 +-51 -17 +27 -33 +71 -32 +0 0 +-12 -22 +43 79 +-13 48 +-27 81 +0 0 +0 0 +-83 -62 +94 45 +0 0 +0 0 +0 0 +75 18 +-38 68 +82 57 +0 0 +0 0 +12 4 +27 -74 +79 44 +0 0 +0 90 +-38 -38 +58 91 +33 -32 +-19 -67 +92 2 +66 2 +47 -91 +-43 71 +66 -74 +73 26 +-32 38 +56 11 +-69 -9 +0 0 +30 -71 +58 -58 +40 -73 +-53 89 +-52 87 +56 21 +94 -78 +56 0 +-82 87 +2 -37 +62 58 +-1 -67 +-59 51 +-94 -66 +-41 -78 +68 -66 +0 0 +-7 -64 +-84 54 +0 0 +96 -25 +-90 -72 +0 0 +60 -56 +0 0 +-6 -35 +-2 36 +12 -76 +-87 86 +0 0 +-26 -8 +44 98 +-79 63 +0 0 +0 0 +38 44 +19 -1 +0 0 +-30 25 +-63 -38 +-18 99 +91 91 +-28 56 +-73 52 +81 -41 +94 62 +-57 -27 +30 -69 +-39 94 +19 -65 +-92 -23 +-77 -46 +-49 -66 +-60 45 +-66 -87 +-74 -16 +65 -43 +-89 -84 +84 -6 +97 -33 +15 -45 +-47 67 +0 0 +-44 -7 +-9 12 +45 -54 +-12 -16 +-93 73 +21 -1 +-38 13 +0 0 +0 0 +72 66 +29 93 +-23 -71 +0 0 +0 0 +20 -38 +66 -70 +89 -63 +-59 80 +-9 45 +-55 56 +0 0 +-71 -29 +0 0 +35 -5 +-41 -38 +0 0 +-47 3 +0 0 +0 0 +-11 87 +46 76 +-35 -86 +41 8 +-81 60 +-9 -90 +-85 84 +27 -41 +16 22 +0 0 +0 0 +0 0 +-60 -11 +-73 -72 +34 32 +-52 97 +0 0 +40 -5 +14 -12 +0 0 +-86 -67 +4 38 +33 91 +90 -21 +-5 -52 +56 -13 +32 38 +28 -69 +91 89 +-35 0 +0 0 +0 0 +61 88 +94 -67 +0 0 +0 0 +36 -89 +85 38 +15 33 +4 94 +96 70 +0 0 +-6 -7 +-91 46 +74 -63 +0 0 +-79 28 +6 42 +30 -74 +-31 86 +-79 52 +-85 99 +-14 -94 +57 -44 +-73 -91 +0 0 +45 24 +71 91 +11 -34 +-27 -77 +0 0 +71 47 +61 14 +-59 81 +-50 -23 +-26 -90 +49 66 +13 -73 +74 46 +-63 39 +93 29 +0 0 +0 0 +48 -81 +-99 5 +-97 -18 +0 0 +-34 90 +0 0 +0 0 +-38 6 +50 42 +97 -51 +35 30 +-50 30 +44 -1 +-25 -10 +57 86 +-17 50 +0 0 +-6 -21 +70 -79 +-76 -31 +0 0 +0 0 +51 -32 +-7 -89 +60 -57 +93 -73 +70 24 +9 27 +-5 88 +-86 -26 +51 66 +63 -37 +52 -87 +-67 34 +62 -40 +0 0 +-96 -55 +81 72 +60 88 +36 69 +0 0 +-14 -81 +96 18 +0 0 +63 60 +54 25 +0 0 +-51 -60 +-92 34 +-69 4 +0 0 +48 -16 +-17 -75 +0 0 +0 0 +0 0 +-53 1 +59 -15 +80 84 +-3 1 +0 0 +-66 12 +33 -66 +0 0 +-23 80 +-16 35 +18 -85 +-77 6 +0 0 +49 -6 +-17 57 +-16 -14 +-95 -71 +5 53 +-58 21 +4 41 +0 0 +0 0 +-48 -90 +-23 10 +64 -90 +0 0 +-42 66 +0 0 +-78 8 +80 -46 +76 -24 +75 67 +-7 35 +-73 80 +88 -74 +32 -62 +-6 -55 +89 -10 +0 0 +16 -59 +0 0 +-50 45 +81 42 +0 0 +55 99 +97 -14 +76 51 +-58 100 +0 0 +0 0 +0 0 +0 0 +36 -91 +-94 -88 +27 -31 +-17 25 +0 0 +10 -30 +0 0 +79 49 +-95 35 +0 0 +76 -94 +43 -23 +-92 92 +92 9 +17 83 +78 43 +0 0 +0 0 +-37 -93 +0 0 +31 46 +-34 82 +99 56 +-11 15 +-90 75 +-39 1 +7 -73 +12 -2 +44 -13 +-37 29 +-34 -30 +-86 49 +97 96 +-2 -93 +0 0 +22 -53 +23 -47 +53 -93 +-23 -20 +53 26 +88 -85 +-72 95 +21 -55 +16 -98 +0 0 +75 98 +0 0 +-26 80 +83 57 +0 0 +20 -34 +0 0 +0 0 +-22 -76 +-82 -93 +-93 -68 +72 53 +0 0 +83 -88 +-37 -67 +0 0 +43 58 +66 -87 +-98 -12 +1 44 +-23 77 +61 94 +-87 -92 +-78 64 +-9 -42 +-7 -14 +-61 85 +20 -46 +12 50 +0 0 +-35 -38 +-100 84 +-25 -18 +78 -17 +-60 51 +-45 64 +-29 -64 +-7 75 +-45 -48 +36 -62 +89 -98 +-43 -12 +-20 25 +0 0 +78 79 +0 0 +90 8 +-57 93 +-71 -87 +54 22 +11 60 +0 0 +-61 -20 +0 0 +-11 -34 +-52 6 +4 -12 +-14 -59 +0 0 +49 -44 +-6 -47 +0 0 +21 91 +-88 -92 +29 16 +-92 31 +73 2 +-61 99 +-41 79 +84 -41 +-87 -47 +79 64 +0 0 +43 53 +0 0 +28 41 +44 -6 +7 94 +28 -61 +0 0 +33 -69 +29 -67 +43 0 +84 -18 +47 -38 +0 0 +19 7 +45 81 +13 -67 +99 -19 +0 0 +0 0 +-22 -67 +35 86 +-1 -68 +-97 -8 +97 -100 +-55 -19 +0 0 +0 0 +-64 -23 +12 -27 +0 0 +-35 63 +-66 -77 +77 -17 +-37 43 +-79 -40 +-8 54 +69 10 +-76 86 +93 -49 +77 -75 +56 28 +27 -15 +-91 -23 +98 38 +0 37 +16 1 +-52 47 +0 0 +90 60 +38 67 +28 80 +-90 -11 +-65 -34 +0 0 +-63 -19 +0 0 +-69 32 +0 0 +-16 -42 +-82 -67 +-11 5 +-88 -45 +0 0 +0 0 +0 0 +-26 -50 +89 -55 +56 -23 +74 -43 +-30 -34 +74 -25 +5 -45 +-68 -73 +98 53 +0 0 +0 0 +67 58 +0 0 +-52 -31 +25 -23 +9 -65 +-18 23 +74 -87 +-72 87 +-79 29 +-59 91 +-40 48 +46 -91 +-100 48 +0 0 +3 70 +60 72 +-34 35 +28 47 +31 -44 +-13 89 +22 -92 +-37 -94 +0 0 +54 64 +-81 -73 +-33 -30 +-87 7 +94 -37 +-73 -96 +2 76 +0 0 +-7 40 +0 0 +88 -40 +0 0 +0 0 diff --git a/moead_framework/test/problem/test_ubqp.py b/moead_framework/test/problem/test_ubqp.py new file mode 100644 index 0000000..788e6db --- /dev/null +++ b/moead_framework/test/problem/test_ubqp.py @@ -0,0 +1,52 @@ +import random +import os +import unittest + +from moead_framework.problem.combinatorial.mubqp import Mubqp + + +class UbqpTest(unittest.TestCase): + """Test the 'rmnk' problem.""" + + def setUp(self): + """Init""" + project_path = os.path.dirname(os.path.abspath(__file__)) + self.problem = Mubqp(project_path + '/../data/mubqp_0_2_25_0.8_0.dat') + + def test_instance(self): + """Test parameters""" + self.assertEqual(self.problem.rho, 0) + self.assertEqual(self.problem.m, 2) + self.assertEqual(self.problem.n, 25) + self.assertEqual(self.problem.d, 0.8) + + def test_generate_random_solution(self): + """Test the function 'generate_random_solution'""" + random_solution = self.problem.generate_random_solution() + + self.assertEqual(len(random_solution.solution), 25) + self.assertEqual(len(random_solution.F), 2) + + for item in random_solution.solution: + self.assertIn(item, [0, 1]) + + def test_evaluation(self): + """Test evaluation""" + array = [] + + for i in range(100): + if i % 3 == 0: + array.append(0) + else: + array.append(1) + + solution = self.problem.generate_solution(array) + + self.assertEqual(solution.F[0], 290.0) + self.assertEqual(solution.F[1], 856.0) + + + + + + diff --git a/setup.py b/setup.py index d958c01..74a42fb 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="moead-framework", - version="0.5.3", + version="0.5.4", author="Geoffrey Pruvost", author_email="geoffrey@pruvost.xyz", description="MOEA/D Framework in Python 3",