def test_coord_cost(self): d_mat = np.array([[1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 1, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 0, 1, 1, 0], [0, 0, 0, 0, 0, 0, 1, 1]]) d_list = ["a", "b", "c", "d", "e", "f", "g", "h"] d = DSMMatrix(d_mat, activity_labels=d_list) c_mat = np.diag(np.ones([8])) c = ClusterMatrix.from_mat(c_mat) pow_cc = 1 cg = ClusterGenerator(dsm_mat=d) initial_cost = ClusterGenerator._coord_cost(d, c, cg.params) assert (initial_cost == 64) d_mat = np.array([[1, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0, 0], [1, 0, 0, 1, 0, 0, 1, 0], [0, 0, 1, 1, 1, 0, 0, 0], [0, 0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0, 1, 1]]) d_list = ["a", "b", "c", "d", "e", "f", "g", "h"] d = DSMMatrix(d_mat, activity_labels=d_list) c_mat = np.diag(np.ones([8])) c = ClusterMatrix.from_mat(c_mat) pow_cc = 1 # cg = ClusterGenerator(dsm_mat = d) initial_cost = ClusterGenerator._coord_cost(d, c, cg.params) assert (initial_cost == 80)
def test_delete_clusters_3(self): c_mat = np.array([ [1, 1, 0, 0, 0], [0, 0, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], ]) c = ClusterMatrix.from_mat(c_mat) cg = ClusterGenerator(default_size=8) new_c = cg.delete_clusters(c) new_c_size = new_c.cluster_size new_c_result_mat = np.array([ [1, 1, 0, 0, 0], [0, 0, 1, 1, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], ]) new_c_result = ClusterMatrix.from_mat(new_c_result_mat) new_c_size_result = np.array([2, 3, 0, 0, 0]) assert np.equal(new_c.mat, new_c_result.mat).all() assert np.equal(new_c_size, new_c_size_result).all()
def test_invariance(self): # Checks that a new cluster matrix (once reordered) is invariant under reordering c_mat = np.array([[1, 1, 0], [1, 0, 1], [1, 1, 1]]) c = ClusterMatrix.from_mat(c_mat) new_c_mat = ClusterMatrix.reorder(c) # import pdb; pdb.set_trace() newer_c_mat = ClusterMatrix.reorder(new_c_mat) # print(newer_c_mat.mat) assert (newer_c_mat.mat == new_c_mat.mat).all()
def test_reorder1(self): c_mat = np.array([[1, 1, 0], [1, 0, 1], [1, 1, 1]]) c = ClusterMatrix.from_mat(c_mat) new_c_mat = ClusterMatrix.reorder(c) # print("Original: ") # print(c.mat) # print("Reordered: ") # print(new_c_mat.mat) # print("Reordered size: ") # print(new_c_mat.cluster_size) val_comp = new_c_mat.mat == np.array([c_mat[2], c_mat[1], c_mat[0]]) size_comp = new_c_mat.cluster_size == np.array([3, 2, 2]) assert val_comp.all() assert size_comp.all()
def delete_clusters(self, cluster_mat): cluster_matrix = ClusterMatrix.from_mat(cluster_mat.mat) n_clusters = cluster_matrix.mat.shape[0] n_elements = cluster_matrix.mat.shape[1] # import pdb; pdb.set_trace() cluster_size = cluster_mat.cluster_size new_cluster_mat = ClusterMatrix.from_mat( np.zeros([n_clusters, n_elements])) new_cluster_size = np.zeros([n_clusters]) # import pdb; pdb.set_trace() # If clusters are equal or cluster j is completely contained in i # Delete cluster j ij_grid = [(i, j) for i in range(n_clusters) for j in range(i + 1, n_clusters)] for i, j in ij_grid: if cluster_size[i] >= cluster_size[j] and cluster_size[j] > 0: if (np.logical_and(cluster_matrix.mat[i,:], \ cluster_matrix.mat[j,:]) == cluster_matrix.mat[j,:]).all(): cluster_matrix.mat[j, :] = 0 cluster_size[j] = 0 for i, j in ij_grid: if cluster_size[i] < cluster_size[j] and cluster_size[j] > 0: if (np.logical_and(cluster_matrix.mat[i,:], \ cluster_matrix.mat[j,:]) == cluster_matrix.mat[i,:] ).all(): cluster_matrix.mat[i, :] = 0 cluster_size[i] = 0 # Delete clusters with no tasks non_empty_cluster_index = np.array(cluster_size != 0) new_cluster_mat.mat[ 0:np.sum(non_empty_cluster_index), :] = cluster_matrix.mat[ non_empty_cluster_index.flatten(), :] new_cluster_size[0:np.sum(non_empty_cluster_index)] = cluster_size[ non_empty_cluster_index.flatten()] new_cluster_mat.cluster_size = new_cluster_size # new_cluster_mat.update_cluster_size() return new_cluster_mat
def test_coord_cost_2(self): d_mat = np.array([[1, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0, 0], [1, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]) d_list = ["a", "b", "c", "d", "e", "f", "g", "h"] d = DSMMatrix(d_mat, activity_labels=d_list) c_mat = np.array([[1., 0., 1., 0., 0., 0., 0., 0.], [0., 1., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 1., 0., 0., 0., 0.], [0., 0., 0., 0., 1., 0., 0., 0.], [0., 0., 0., 0., 0., 1., 0., 0.], [0., 0., 0., 0., 0., 0., 1., 0.], [0., 0., 0., 0., 0., 0., 0., 1.], [0., 0., 0., 0., 0., 0., 0., 0.]]) c = ClusterMatrix.from_mat(c_mat) pow_cc = 1 cg = ClusterGenerator(dsm_mat=d) # import pdb; pdb.set_trace() initial_cost = ClusterGenerator._coord_cost(d, c, cg.params) print(initial_cost) assert (initial_cost == 20)
def test_reorder2(self): c_mat_2 = np.array([[1, 1, 0], [0, 1, 0], [1, 1, 1]]) c_2 = ClusterMatrix.from_mat(c_mat_2) new_c_mat_2 = ClusterMatrix.reorder(c_2) # print("Original: ") # print(c_2.mat) # print("Reordered: ") # print(new_c_mat_2.mat) # print("Reordered size: ") # print(new_c_mat_2.cluster_size) val_comp_2 = new_c_mat_2.mat == np.array( [c_mat_2[2], c_mat_2[0], c_mat_2[1]]) size_comp_2 = new_c_mat_2.cluster_size == np.array([3, 2, 1]) assert val_comp_2.all() assert size_comp_2.all()
def test_delete_clusters_2(self): c_mat = np.diag(np.ones([5])) c_mat[1, 0] = 1 c = ClusterMatrix.from_mat(c_mat) cg = ClusterGenerator(default_size=8) # import pdb; pdb.set_trace() new_c = cg.delete_clusters(c) new_c_size = new_c.cluster_size new_c_result_mat = np.array([ [1, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1], [0, 0, 0, 0, 0], ]) new_c_result = ClusterMatrix.from_mat(new_c_result_mat) new_c_size_result = np.array([2, 1, 1, 1, 0]) assert np.equal(new_c.mat, new_c_result.mat).all() assert np.equal(new_c_size, new_c_size_result).all()
def test_delete_clusters(self): c_mat = np.diag(np.ones([8])) c_mat[0, 3] = 1 c_mat[5, 3] = 1 c = ClusterMatrix.from_mat(c_mat) c_size = np.array([[2], [1], [1], [1], [1], [2], [1], [1]]) cg = ClusterGenerator(default_size=8) new_c = cg.delete_clusters(c) new_c_size = new_c.cluster_size new_c_result_mat = np.array([[1, 0, 0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0]]) new_c_result = ClusterMatrix.from_mat(new_c_result_mat) new_c_size_result = np.array([2, 1, 1, 1, 2, 1, 1, 0]) assert np.equal(new_c.mat, new_c_result.mat).all() assert np.equal(new_c_size, new_c_size_result).all()
def test_bid(self): d_mat = np.array([[1, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 1, 0, 0], [1, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]) d_list = ["a", "b", "c", "d", "e", "f", "g", "h"] d = DSMMatrix(d_mat, activity_labels=d_list) c_mat = np.diag(np.ones([8])) c = ClusterMatrix.from_mat(c_mat) cg = ClusterGenerator(dsm_mat=d) cg.params = ClusterParameters(pow_cc=1, pow_bid=1, pow_dep=4, max_cluster_size=16, rand_accept=32, rand_bid=32, times=2, stable_limit=2, max_repeat=10) elmt = 7 cluster_bid = cg._make_bid(elmt, d, c) # print(cluster_bid) assert np.equal(cluster_bid, np.zeros([8, 1])).all() d_mat2 = np.array([[1, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0, 0], [1, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]) d2 = DSMMatrix(d_mat2, activity_labels=d_list) cg2 = ClusterGenerator(dsm_mat=d2) cg2.params = ClusterParameters(pow_cc=1, pow_bid=1, pow_dep=4, max_cluster_size=16, rand_accept=32, rand_bid=32, times=2, stable_limit=2, max_repeat=10) elmt = 0 cluster_bid_2 = cg2._make_bid(elmt, d, c) # print("CB2: ", cluster_bid_2) assert np.equal(cluster_bid_2, np.array([[0], [0], [16], [1], [0], [0], [0], [0]])).all()
async def do_cluster(): app_state.generator = ClusterGenerator(dsm_mat=app_state.dsm) c_orig = app_state.generator.cluster(app_state.dsm) total_coord_cost = app_state.generator.total_coord_cost cost_history = app_state.generator.cost_history c = ClusterMatrix.reorder(c_orig) new_dsm = DSMMatrix.reorder_by_cluster(app_state.dsm, c) d_new_g = DSMMatrix.place_diag(new_dsm) app_state.cluster_result = c app_state.dsm_result = d_new_g app_state.dsm_annotated = DSMMatrix.annotate_clusters(d_new_g, c) return { "dsm": app_state.dsm_result.tojson(), "labels": app_state.dsm_result.labels, "cluster": app_state.cluster_result.tojson(), "dsm_a": app_state.dsm_annotated.tojson(), }
def annotate_clusters(DSM_matrix, cluster_matrix): assert isinstance(DSM_matrix, DSMMatrix) assert isinstance(cluster_matrix, ClusterMatrix) new_ds_mat = DSMMatrix(np.zeros(DSM_matrix.mat.shape)) new_ds_mat.mat = DSM_matrix.mat new_clu_mat = ClusterMatrix.from_mat(np.zeros(cluster_matrix.mat.shape)) new_clu_mat.mat = cluster_matrix.mat new_ds_mat.mat -= 1; cluster_count = 1 s_i = 0 for c_i in range(cluster_matrix.mat.shape[0]): n_el = np.sum(cluster_matrix.mat[c_i,:], axis=0, dtype=np.int) for i in range(s_i, s_i+n_el): for j in range(s_i, s_i+n_el): new_ds_mat.mat[i,j] = cluster_count if DSM_matrix.mat[i,j] >= 0 else 0 s_i += n_el cluster_count += 1 return new_ds_mat
def test_cluster(self): d_mat = np.array([[1, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0, 0, 0], [1, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]) d_list = ["a", "b", "c", "d", "e", "f", "g", "h"] d = DSMMatrix(d_mat, activity_labels=d_list) cg = ClusterGenerator(default_size=8) # try: cluster_matrix = cg.cluster(d) total_coord_cost = cg.total_coord_cost cost_history = cg.cost_history # except: # extype, value, tb = sys.exc_info() # traceback.print_exc() # pdb.post_mortem(tb) # pdb.runcall(DSMMatrix.reorder_by_cluster, DSM_matrix, cluster_matrix) c_mat_result = np.array([[1, 0, 1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]) c_result = ClusterMatrix.from_mat(c_mat_result) c_size_result = np.array([[2], [1], [2], [1], [1], [1], [0], [0]]) print(cluster_matrix.mat) # import pdb; pdb.set_trace() # assert np.equal(cluster_matrix.mat, c_result.mat).all() initial_cost = ClusterGenerator._coord_cost(d, cluster_matrix, cg.params) print("Cost: " + str(initial_cost)) assert (initial_cost == 14 or initial_cost == 16)
def test_reorder2(self): d_mat_2 = np.array([[1, 0, 0, 1], [0, 0, 0, 0], [1, 0, 1, 0], [0, 0, 1, 1]]) d_list_2 = ["1", "2", "3", "4"] d_2 = DSMMatrix(d_mat_2, d_list_2) # print("Original DSM: ") # print(d_2.mat) c_mat_2 = np.array([[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]]) c_2 = ClusterMatrix.from_mat(c_mat_2) # print("Original Cluster: ") # print(c_2.mat) new_d_mat_2 = DSMMatrix.reorder_by_cluster(d_2, c_2) # print("Reordered DSM: ") # print(new_d_mat_2.mat) # print(new_d_mat_2.labels) val_comp_2 = new_d_mat_2.mat == np.array([[0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 0, 0], [1, 0, 0, 0]]) lab_comp_2 = new_d_mat_2.labels == ['4', '3', '2', '1'] assert val_comp_2.all() assert lab_comp_2
def __init__(self, dsm_mat=None, default_size=2): if isinstance(dsm_mat, DSMMatrix): self._dsm_mat = dsm_mat else: self._dsm_mat = DSMMatrix.from_size(default_size) # Set clustering control parameters max_size = self._dsm_mat.mat.shape[0] self._params = set_default_cluster_parameters(max_size) # Initialise matrices and arrays self._DSM_size = self._dsm_mat.mat.shape[1] self._n_clusters = max_size self._cost_history = np.zeros([10000, 1]) self._history_index = 0 self._cluster_matrix_history = [] self._cluster_size_history = [] self._total_coord_cost_history = [] self._cost_history = np.array([]) self._total_coord_cost = 0 self._cluster_result = ClusterMatrix.from_mat( np.zeros([max_size, max_size]))
def test_reorder1(self): # d_mat = np.identity(3) d_mat = np.array([[1, 0, 0, 0], [0, 0, 0, 0], [1, 0, 1, 0], [0, 0, 1, 1]]) d_list = ["1", "2", "3", "4"] d = DSMMatrix(d_mat, d_list) # print("Original DSM: ") # print(d.mat) c_mat = np.array([[1, 0, 1, 1], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]) c = ClusterMatrix.from_mat(c_mat) # print("Original Cluster: ") # print(c.mat) new_d_mat = DSMMatrix.reorder_by_cluster(d, c) # print("Reordered DSM: ") # print(new_d_mat.mat) # print(new_d_mat.labels) val_comp_1 = new_d_mat.mat == np.array([[0, 0, 0, 0], [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0]]) lab_comp_1 = new_d_mat.labels == ['1', '3', '4', '2'] assert val_comp_1.all() assert lab_comp_1
plt.show() if __name__ == "__main__": d_mat = np.array([ [1, 0, 1, 0, 0, 1, 0, 1], [1, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0, 1], [0, 0, 1, 1, 0, 0, 0, 1], [0, 0, 0, 0, 1, 1, 0, 0], [0, 1, 0, 0, 0, 1, 1, 0], [1, 0, 0, 1, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0, 0, 1] ]) d = DSMMatrix(d_mat) c_mat = np.array([ [0, 0, 0, 1, 0, 1, 0, 0], [1, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0] ]) c = ClusterMatrix.from_mat(c_mat) graph_matrix(d, cluster_matrix=c) graph_matrix(c) block_exit()
def cluster(self, DSM_matrix): assert isinstance(DSM_matrix, DSMMatrix) DSM_size = DSM_matrix.mat.shape[1] n_clusters = DSM_size max_repeat = 10 # Initialise states/history coordination_cost = np.zeros([DSM_size, 1]) cluster_size = np.zeros([DSM_size, 1]) new_cluster_mat = ClusterMatrix.from_mat( np.zeros([n_clusters, n_clusters])) # new_cluster_size = np.zeros([DSM_size,1]) cluster_bid = np.zeros([DSM_size, 1]) new_cluster_bid = np.zeros([DSM_size, 1]) new_coordination_cost = np.zeros([DSM_size, 1]) rnd_elmt_arr = np.zeros([DSM_size, 1]) cluster_list = np.zeros([DSM_size, 1]) # # Initialise cluster matrix (note this is already initialised at the start of the function, need to decide whether to use or not) cluster_diagonals = np.ones([1, self._n_clusters]) cluster_mat = ClusterMatrix.from_mat( np.diag(cluster_diagonals.flatten())) cluster_mat.update_cluster_size() # cluster_size = np.ones([self._n_clusters, 1]) # # Initial clustering starting cost total_coord_cost = ClusterGenerator._coord_cost( DSM_matrix, cluster_mat, self._params) best_coord_cost = total_coord_cost # # Initialise cost history cost_history = [] # cost_history = np.zeros([10000, 1]) history_index = 0 # # Store the best cluster matrix and corresponding cost and size best_curr_cost = total_coord_cost best_curr_cluster_mat = cluster_mat best_curr_cluster_size = cluster_mat.cluster_size # Initialise control parameters stable = 0 # toggle to indicate if the algorithm has met the stability criteria change = 0 # toggle to indicate if a change should be made accept1 = 0 # toggle to indicate if the solution should be acccepted first_run = 1 # toggle to indicate if it is the first run through attempt = 0 # index to count the number of passes through the algorithm # Initialise best cost history self._cluster_matrix_history = [] self._cluster_size_history = [] self._total_coord_cost_history = [] self._cluster_matrix_history.append(cluster_mat) self._cluster_size_history.append(cluster_size) self._total_coord_cost_history.append(total_coord_cost) # import pdb; pdb.set_trace() while total_coord_cost > best_coord_cost and attempt <= max_repeat or first_run == 1: if first_run == 0: self._cluster_matrix_history.append(cluster_mat) self._cluster_size_history.append(cluster_size) self._total_coord_cost_history.append(total_coord_cost) total_coord_cost = best_curr_cost cluster_mat = best_curr_cluster_mat.copy() # cluster_mat.cluster_size = best_curr_cluster_size.copy() # cluster_mat.update_cluster_size() # cluster_size = best_curr_cluster_size.copy() history_index = history_index + 1 # cost_history[history_index,0] = total_coord_cost cost_history.append(total_coord_cost) first_run = 0 stable = 0 accept1 = 0 change = 0 print("Attempt: " + str(attempt)) while stable <= self._params.stable_limit: for k in range(DSM_size * self._params.times): # print("Total coord cost: " + str(total_coord_cost) + ", stable: " + str(stable) + ", change: ", str(change)) cluster_mat.update_cluster_size() elmt = np.ceil(np.random.randint(low=0, high=DSM_size - 1)) elmt = int(elmt) cluster_bid = self._make_bid(elmt, DSM_matrix, cluster_mat) best_cluster_bid = np.max(cluster_bid) second_best_cluster_bid = np.max(cluster_bid[ cluster_bid != best_cluster_bid]) if cluster_bid[ cluster_bid != best_cluster_bid].shape[0] else 0 if np.floor(self._params.rand_bid * np.random.uniform()) == 0: best_cluster_bid = second_best_cluster_bid if best_cluster_bid > 0: # Determine if the bid is acceptable cluster_list[:, 0] = 0 # Determine the list of clusters affected cluster_list[0:n_clusters, 0] = np.logical_and( (cluster_bid == best_cluster_bid).flatten(), (cluster_mat.mat[:, elmt] == 0).flatten()) # copy the cluster matrix into new matrices new_cluster_mat = cluster_mat.copy() # new_cluster_size = cluster_size # proceed with cluster changes in the new cluster new_cluster_mat.mat[ 0:n_clusters, elmt] = np.logical_or( new_cluster_mat.mat[0:n_clusters, elmt].flatten(), cluster_list.flatten()) new_cluster_mat.update_cluster_size() # new_cluster_size[0:n_clusters,0] = new_cluster_size[0:n_clusters,0] + (cluster_list == 1).flatten()*1 # import pdb; pdb.set_trace() # delete duplicate and empty clusters new_cluster_mat = self.delete_clusters(new_cluster_mat) # determine the change in the coordination cost new_total_coord_cost = ClusterGenerator._coord_cost( DSM_matrix, new_cluster_mat, self._params) if new_total_coord_cost <= total_coord_cost: accept1 = 1 else: # still accept 1 out of approx random_accept times if (np.floor(self._params.rand_accept * np.random.uniform()) == 0): accept1 = 1 # if we are going to accept a total cost that is not less than our current cost # then # save the current cost as the best current cost found so far (only if the current cost # is lower than any best current cost previously saved) because we may not find # a cost that is better than the current cost. # When we think we are finished we will check the final cost against any best cost # if the final cost is not better than the lowest cost found, then we will move back to that best cost if total_coord_cost < best_curr_cost: best_curr_cost = total_coord_cost best_curr_cluster_mat = cluster_mat best_curr_cluster_size = cluster_mat.cluster_size else: accept1 = 0 if accept1 == 1: accept1 = 0 # Update the clusters total_coord_cost = new_total_coord_cost cluster_mat = new_cluster_mat.copy() # cluster_size = new_cluster_size history_index += 1 # cost_history[history_index,0] = total_coord_cost cost_history.append(total_coord_cost) if (best_coord_cost > total_coord_cost): best_coord_cost = total_coord_cost change += 1 # Test the system for instability if change > 0: stable = 0 change = 0 else: stable += 1 pass attempt += 1 pass self._cluster_result = cluster_mat self._cost_history = np.array(cost_history) self._total_coord_cost = total_coord_cost return cluster_mat pass
def _coord_cost(DSM_matrix, cluster_matrix, params): """ Calculate the coordination cost of the cluster matrix. This routine checks all DSM interactions and adds to a total the cost of all intra-cluster interactions. Interactions outside of clusters are assigned a higher cost. As per Thebeau (2000) the cost formula is, for each interdependent/coupled activity i and j: (In cluster) (DSM[i] + DSM[j])*cluster_size[cluster_n]^pow_cc (Out of cluster) (DSM[i] + DSM[j])*DSM_size^pow_cc Sum each term to obtain the total. """ assert isinstance(DSM_matrix, DSMMatrix) assert isinstance(cluster_matrix, ClusterMatrix) assert isinstance(params, ClusterParameters) if params: pow_cc = params.pow_cc else: pow_cc = 1 # get the number of clusters and size of the DSM n_clusters = cluster_matrix.mat.shape[0] DSM_size = cluster_matrix.mat.shape[1] # initialise coordination costs total_coord_cost = 0 coordination_cost = np.zeros([1, DSM_size]) # dummy variable for reorder function DSM_labels = [str(x + 1) for x in range(DSM_size)] # reorder the DSM according to the cluster matrix new_DSM_matrix = DSMMatrix.reorder_by_cluster(DSM_matrix, cluster_matrix) new_DSM_size = new_DSM_matrix.mat.shape[0] num_cluster_elements = np.sum(cluster_matrix.mat, axis=1, dtype=np.int) n = 0 # indexing starts from zero new_cluster_mat = ClusterMatrix.from_mat( np.zeros([new_DSM_size, new_DSM_size])) # Create a new cluster matrix that matches the reordered DSM matrix # # formerly n_clusters - changed due to shape # Check again to replicate MATLAB functionality - this is not a permanent fix for i in range(n_clusters): if i < new_DSM_size: new_cluster_mat.mat[i, n:n + num_cluster_elements[i]] = np.ones( [1, num_cluster_elements[i]]) n += num_cluster_elements[i] else: new_cluster_mat.mat = np.vstack([ new_cluster_mat.mat, np.zeros(new_cluster_mat.mat.shape[1]) ]) new_cluster_mat.mat[i, n:n + num_cluster_elements[i]] = np.ones( [1, num_cluster_elements[i]]) n += num_cluster_elements[i] # import pdb; pdb.set_trace() # get new cluster size array matching matrix # new_cluster_size = np.sum(new_cluster_mat.mat, axis=1) new_cluster_mat.update_cluster_size() # replace old data with new data for cost calculation DSM_matrix = new_DSM_matrix DSM_size = new_DSM_size cluster_matrix = new_cluster_mat # cluster_size = new_cluster_size # get the number of clusters and size of the DSM n_clusters = cluster_matrix.mat.shape[0] DSM_size = cluster_matrix.mat.shape[1] total_coord_cost = 0 coordination_cost = np.zeros([DSM_size, 1]) # Calculate the cost of the solution for i in range(DSM_size): for j in range(i + 1, DSM_size): if DSM_matrix.mat[i, j] > 0 or DSM_matrix.mat[j, i] > 0: cost_total = 0 for cluster_index in range(n_clusters): if cluster_matrix.mat[cluster_index, i] + cluster_matrix.mat[ cluster_index, j] == 2: # cost_total += (DSM_matrix.mat[i,j] + DSM_matrix.mat[j,i]) * cluster_size[cluster_index]**pow_cc cost_total += (DSM_matrix.mat[i, j] + DSM_matrix.mat[j, i] ) * cluster_matrix.cluster_size[ cluster_index]**pow_cc if cost_total > 0: cost_c = cost_total else: cost_c = (DSM_matrix.mat[i, j] + DSM_matrix.mat[j, i]) * DSM_size**pow_cc coordination_cost[i] += cost_c total_coord_cost = np.sum(coordination_cost) return total_coord_cost