From 065f3b6bf9d12f6d66449ada845fc7dbd8cf7325 Mon Sep 17 00:00:00 2001
From: Anne-Liza <a.m.r.m.bruggeman@student.tudelft.nl>
Date: Wed, 6 Dec 2017 13:32:59 +0100
Subject: [PATCH] Changed coupling strength definition in mathematical problem
 generator

Former-commit-id: 23e22203dce424fbc37e3afa8eca1d8286550bba
---
 kadmos/graph/graph_data.py | 61 +++++++++++++++++++++++++-------------
 1 file changed, 41 insertions(+), 20 deletions(-)

diff --git a/kadmos/graph/graph_data.py b/kadmos/graph/graph_data.py
index cd5b35726..6debc890c 100644
--- a/kadmos/graph/graph_data.py
+++ b/kadmos/graph/graph_data.py
@@ -840,7 +840,9 @@ class RepositoryConnectivityGraph(DataGraph):
     def create_mathematical_problem(self, n_disciplines, coupling_strength, n_global_var=None, n_local_var=None,
                                     n_coupling_var=None, n_global_constraints=None, B=None, C=None, D=None, H=None,
                                     I=None, J=None, s=None, write_problem_to_textfile=False):
-        """Function to get a mathematical problem according to the variable complexity problem described in Zhang (2017)
+        """Function to get a mathematical problem according to the variable complexity problem as described in:
+        Zhang D., Song B., Wang P. and He Y. 'Performance Evaluation of MDO Architectures within a Variable
+        Complexity Problem', Mathematical Problems in Engineering, 2017.
 
         :param n_disciplines: Number of disciplines
         :param coupling_strength: percentage of couplings, 0 no couplings, 1 all possible couplings
@@ -874,7 +876,7 @@ class RepositoryConnectivityGraph(DataGraph):
 
         # Number of coupling variables per discipline
         if n_coupling_var is None:
-            n_coupling_var = [random.randint(1, 4) for _ in range(n_disciplines)]
+            n_coupling_var = [random.randint(1, 5) for _ in range(n_disciplines)]
         mathematical_problem['n_coupling_var'] = n_coupling_var
 
         # Number of global constraints
@@ -884,26 +886,43 @@ class RepositoryConnectivityGraph(DataGraph):
 
         # Create B-matrix: relation between the coupling variables
         if B is None:
+
+            # Initiate matrix
             B = np.zeros((sum(n_coupling_var), sum(n_coupling_var)))
-            B_diag = [random.randint(1, 5) for _ in range(sum(n_coupling_var))]
+
+            # Calculate the number of couplings based on the coupling strength
+            n_couplings = int(np.ceil(((sum(n_coupling_var)*n_disciplines) - sum(n_coupling_var)) * coupling_strength))
+
+            # Get a list with all possible couplings between variables and disciplines
+            possible_couplings = []
+            for discipline in range(n_disciplines):
+                for coupling_var in range(sum(n_coupling_var)):
+                    # An output variable of a discipline cannot be an input to the same discipline
+                    if sum(n_coupling_var[:discipline]) <= coupling_var < sum(n_coupling_var[:discipline + 1]):
+                        continue
+                    possible_couplings.append([coupling_var, discipline])
+
+            # Choose random couplings from all possible couplings
+            couplings = random.sample(range(len(possible_couplings)), n_couplings)
+
+            # Fill the B-matrix with the chosen couplings
+            for coupling in couplings:
+                discipline = possible_couplings[coupling][1]
+                for variable in range(n_coupling_var[discipline]):
+                    B[sum(n_coupling_var[:discipline]) + variable][possible_couplings[coupling][0]] = random.choice(
+                        range(-5, 0)+range(1, 6))  # Zero is not allowed
+
+            # To get a converging problem the B-matrix must be diagonally dominant
+            B_diag = np.sum(abs(B), axis=1)
+            B_diag = [entry + random.randint(1, 10) for entry in B_diag]
             i, j = np.indices(B.shape)
             B[i == j] = B_diag
-            n_couplings = int(
-                np.ceil((sum(n_coupling_var) ** 2 - sum(i ** 2 for i in n_coupling_var)) * coupling_strength))
-            discipline_matrix = np.zeros((sum(n_coupling_var), sum(n_coupling_var)))
-            for discipline in range(n_disciplines):
-                discipline_matrix[sum(n_coupling_var[:discipline]):sum(n_coupling_var[:discipline + 1]),
-                                  sum(n_coupling_var[:discipline]):sum(n_coupling_var[:discipline + 1])] = 1
-            z1, z2 = np.where(discipline_matrix == 0)
-            couplings = random.sample(range(len(z1)), n_couplings)
-            coupling_values = [random.randint(1, 5) for _ in range(n_couplings)]
-            for index, coupling in enumerate(couplings):
-                B[z1[coupling]][z2[coupling]] = coupling_values[index]
+
         mathematical_problem['B-matrix'] = B
 
         # Create C-matrix: relation between global design variables and coupling variables
         if C is None:
-            C = np.array([[float(random.randint(0, 5)) for _ in range(n_global_var)] for _ in
+            C = np.array([[float(random.randint(-5, 5)) for _ in range(n_global_var)] for _ in
                           range(sum(n_coupling_var))])
         mathematical_problem['C-matrix'] = C
 
@@ -914,24 +933,24 @@ class RepositoryConnectivityGraph(DataGraph):
                 for local_var in range(n_local_var[discipline]):
                     for coupling_var in range(n_coupling_var[discipline]):
                         D[sum(n_coupling_var[:discipline]) + coupling_var][sum(n_local_var[:discipline]) + local_var] =\
-                            random.randint(1, 5)
+                            random.choice(range(-5, 0)+range(1, 6))  # Zero is not allowed
         mathematical_problem['D-matrix'] = D
 
         # Create H-matrix: relation between global design variables and global constraints
         if H is None:
-            H = np.array([[float(random.randint(0, 5)) for _ in range(n_global_var)] for _ in
+            H = np.array([[float(random.randint(-5, 5)) for _ in range(n_global_var)] for _ in
                           range(n_global_constraints)])
         mathematical_problem['H-matrix'] = H
 
         # Create I-matrix: relation between local design variables and global constraints
         if I is None:
-            I = np.array([[float(random.randint(0, 5)) for _ in range(sum(n_local_var))] for _ in
+            I = np.array([[float(random.randint(-5, 5)) for _ in range(sum(n_local_var))] for _ in
                           range(n_global_constraints)])
         mathematical_problem['I-matrix'] = I
 
         # Create J-matrix: relation between coupling variables and global constraints
         if J is None:
-            J = np.array([[float(random.randint(0, 5)) for _ in range(sum(n_coupling_var))] for _ in
+            J = np.array([[float(random.randint(-5, 5)) for _ in range(sum(n_coupling_var))] for _ in
                           range(n_global_constraints)])
         mathematical_problem['J-matrix'] = J
 
@@ -964,7 +983,9 @@ class RepositoryConnectivityGraph(DataGraph):
                                    sum(n_local_var[:local_var_disc]) + local_var]
                         assert all(
                             v == 0 for v in values), 'Local variable x{0}{1} cannot be an input to discipline ' \
-                                                     'D{2}'.format(local_var_disc + 1, local_var + 1, discipline + 1)
+                                                     'D{2}, only to discipline D{0}'.format(local_var_disc + 1,
+                                                                                            local_var + 1,
+                                                                                            discipline + 1)
 
         # All function nodes are defined
         for discipline in range(n_disciplines):
-- 
GitLab