From d64cf4d0ac3019b858bc0504d0ecb6775f10ab9d Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Wed, 8 Jul 2020 16:26:43 +0200 Subject: [PATCH] Update optimizing part in MedianPreimageGeneratorCML. --- gklearn/ged/learning/__init__.py | 9 + gklearn/ged/learning/cost_matrices_learner.py | 148 +++++ gklearn/ged/learning/costs_learner.py | 175 ++++++ gklearn/preimage/median_preimage_generator_cml.py | 632 ++-------------------- 4 files changed, 365 insertions(+), 599 deletions(-) create mode 100644 gklearn/ged/learning/__init__.py create mode 100644 gklearn/ged/learning/cost_matrices_learner.py create mode 100644 gklearn/ged/learning/costs_learner.py diff --git a/gklearn/ged/learning/__init__.py b/gklearn/ged/learning/__init__.py new file mode 100644 index 0000000..f867ab3 --- /dev/null +++ b/gklearn/ged/learning/__init__.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Jul 7 16:07:25 2020 + +@author: ljia +""" + +from gklearn.ged.learning.cost_matrices_learner import CostMatricesLearner \ No newline at end of file diff --git a/gklearn/ged/learning/cost_matrices_learner.py b/gklearn/ged/learning/cost_matrices_learner.py new file mode 100644 index 0000000..a0d8091 --- /dev/null +++ b/gklearn/ged/learning/cost_matrices_learner.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Jul 7 11:42:48 2020 + +@author: ljia +""" +import numpy as np +import cvxpy as cp +import time +from gklearn.ged.learning.costs_learner import CostsLearner +from gklearn.ged.util import compute_geds_cml + + +class CostMatricesLearner(CostsLearner): + + + def __init__(self, edit_cost='CONSTANT', triangle_rule=False, allow_zeros=True, parallel=False, verbose=2): + super().__init__(parallel, verbose) + self._edit_cost = edit_cost + self._triangle_rule = triangle_rule + self._allow_zeros = allow_zeros + + + def fit(self, X, y): + if self._edit_cost == 'LETTER': + raise Exception('Cannot compute for cost "LETTER".') + elif self._edit_cost == 'LETTER2': + raise Exception('Cannot compute for cost "LETTER2".') + elif self._edit_cost == 'NON_SYMBOLIC': + raise Exception('Cannot compute for cost "NON_SYMBOLIC".') + elif self._edit_cost == 'CONSTANT': # @todo: node/edge may not labeled. + if not self._triangle_rule and self._allow_zeros: + w = cp.Variable(X.shape[1]) + cost_fun = cp.sum_squares(X @ w - y) + constraints = [w >= [0.0 for i in range(X.shape[1])]] + prob = cp.Problem(cp.Minimize(cost_fun), constraints) + self.execute_cvx(prob) + edit_costs_new = w.value + residual = np.sqrt(prob.value) + elif self._triangle_rule and self._allow_zeros: # @todo + x = cp.Variable(nb_cost_mat.shape[1]) + cost_fun = cp.sum_squares(nb_cost_mat @ x - dis_k_vec) + constraints = [x >= [0.0 for i in range(nb_cost_mat.shape[1])], + np.array([1.0, 0.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, + np.array([0.0, 1.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, + np.array([0.0, 0.0, 0.0, 1.0, 0.0, 0.0]).T@x >= 0.01, + np.array([0.0, 0.0, 0.0, 0.0, 1.0, 0.0]).T@x >= 0.01, + np.array([1.0, 1.0, -1.0, 0.0, 0.0, 0.0]).T@x >= 0.0, + np.array([0.0, 0.0, 0.0, 1.0, 1.0, -1.0]).T@x >= 0.0] + prob = cp.Problem(cp.Minimize(cost_fun), constraints) + self.__execute_cvx(prob) + edit_costs_new = x.value + residual = np.sqrt(prob.value) + elif not self._triangle_rule and not self._allow_zeros: # @todo + x = cp.Variable(nb_cost_mat.shape[1]) + cost_fun = cp.sum_squares(nb_cost_mat @ x - dis_k_vec) + constraints = [x >= [0.01 for i in range(nb_cost_mat.shape[1])]] + prob = cp.Problem(cp.Minimize(cost_fun), constraints) + self.__execute_cvx(prob) + edit_costs_new = x.value + residual = np.sqrt(prob.value) + elif self._triangle_rule and not self._allow_zeros: # @todo + x = cp.Variable(nb_cost_mat.shape[1]) + cost_fun = cp.sum_squares(nb_cost_mat @ x - dis_k_vec) + constraints = [x >= [0.01 for i in range(nb_cost_mat.shape[1])], + np.array([1.0, 1.0, -1.0, 0.0, 0.0, 0.0]).T@x >= 0.0, + np.array([0.0, 0.0, 0.0, 1.0, 1.0, -1.0]).T@x >= 0.0] + prob = cp.Problem(cp.Minimize(cost_fun), constraints) + self.__execute_cvx(prob) + edit_costs_new = x.value + residual = np.sqrt(prob.value) + else: + raise Exception('The edit cost "', self._ged_options['edit_cost'], '" is not supported for update progress.') + + self._cost_list.append(edit_costs_new) + + + def init_geds_and_nb_eo(self, y, graphs): + time0 = time.time() + self._cost_list.append(np.concatenate((self._ged_options['node_label_costs'], + self._ged_options['edge_label_costs']))) + ged_vec, self._nb_eo = self.compute_geds_and_nb_eo(graphs) + self._residual_list.append(np.sqrt(np.sum(np.square(np.array(ged_vec) - y)))) + self._runtime_list.append(time.time() - time0) + + if self._verbose >= 2: + print('Current node label costs:', self._cost_list[-1][0:len(self._ged_options['node_label_costs'])]) + print('Current edge label costs:', self._cost_list[-1][len(self._ged_options['node_label_costs']):]) + print('Residual list:', self._residual_list) + + + def update_geds_and_nb_eo(self, y, graphs, time0): + self._ged_options['node_label_costs'] = self._cost_list[-1][0:len(self._ged_options['node_label_costs'])] + self._ged_options['edge_label_costs'] = self._cost_list[-1][len(self._ged_options['node_label_costs']):] + ged_vec, self._nb_eo = self.compute_geds_and_nb_eo(graphs) + self._residual_list.append(np.sqrt(np.sum(np.square(np.array(ged_vec) - y)))) + self._runtime_list.append(time.time() - time0) + + + def compute_geds_and_nb_eo(self, graphs): + ged_vec, ged_mat, n_edit_operations = compute_geds_cml(graphs, options=self._ged_options, parallel=self._parallel, verbose=(self._verbose > 1)) + return ged_vec, np.array(n_edit_operations) + + + def check_convergency(self): + self._ec_changed = False + for i, cost in enumerate(self._cost_list[-1]): + if cost == 0: + if self._cost_list[-2][i] > self._epsilon_ec: + self._ec_changed = True + break + elif abs(cost - self._cost_list[-2][i]) / cost > self._epsilon_ec: + self._ec_changed = True + break +# if abs(cost - edit_cost_list[-2][i]) > self.__epsilon_ec: +# ec_changed = True +# break + self._residual_changed = False + if self._residual_list[-1] == 0: + if self._residual_list[-2] > self._epsilon_residual: + self._residual_changed = True + elif abs(self._residual_list[-1] - self._residual_list[-2]) / self._residual_list[-1] > self._epsilon_residual: + self._residual_changed = True + self._converged = not (self._ec_changed or self._residual_changed) + if self._converged: + self._itrs_without_update += 1 + else: + self._itrs_without_update = 0 + self._num_updates_ecs += 1 + + + def print_current_states(self): + print() + print('-------------------------------------------------------------------------') + print('States of iteration', self._itrs + 1) + print('-------------------------------------------------------------------------') +# print('Time spend:', self.__runtime_optimize_ec) + print('Total number of iterations for optimizing:', self._itrs + 1) + print('Total number of updating edit costs:', self._num_updates_ecs) + print('Was optimization of edit costs converged:', self._converged) + print('Did edit costs change:', self._ec_changed) + print('Did residual change:', self._residual_changed) + print('Iterations without update:', self._itrs_without_update) + print('Current node label costs:', self._cost_list[-1][0:len(self._ged_options['node_label_costs'])]) + print('Current edge label costs:', self._cost_list[-1][len(self._ged_options['node_label_costs']):]) + print('Residual list:', self._residual_list) + print('-------------------------------------------------------------------------') \ No newline at end of file diff --git a/gklearn/ged/learning/costs_learner.py b/gklearn/ged/learning/costs_learner.py new file mode 100644 index 0000000..9c77fc5 --- /dev/null +++ b/gklearn/ged/learning/costs_learner.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Jul 7 11:30:31 2020 + +@author: ljia +""" +import numpy as np +import cvxpy as cp +import time +from gklearn.utils import Timer + + +class CostsLearner(object): + + + def __init__(self, parallel, verbose): + ### To set. + self._parallel = parallel + self._verbose = verbose + # For update(). + self._time_limit_in_sec = 0 + self._max_itrs = 100 + self._max_itrs_without_update = 3 + self._epsilon_residual = 0.01 + self._epsilon_ec = 0.1 + ### To compute. + self._residual_list = [] + self._runtime_list = [] + self._cost_list = [] + self._nb_eo = None + # For update(). + self._itrs = 0 + self._converged = False + self._num_updates_ecs = 0 + self._ec_changed = None + self._residual_changed = None + self._itrs_without_update = 0 + ### Both set and get. + self._ged_options = None + + + def fit(self, X, y): + pass + + + def preprocess(self): + pass # @todo: remove the zero numbers of edit costs. + + + def postprocess(self): + for i in range(len(self._cost_list[-1])): + if -1e-9 <= self._cost_list[-1][i] <= 1e-9: + self._cost_list[-1][i] = 0 + if self._cost_list[-1][i] < 0: + raise ValueError('The edit cost is negative.') + + + def set_update_params(self, **kwargs): + self._time_limit_in_sec = kwargs.get('time_limit_in_sec', self._time_limit_in_sec) + self._max_itrs = kwargs.get('max_itrs', self._max_itrs) + self._max_itrs_without_update = kwargs.get('max_itrs_without_update', self._max_itrs_without_update) + self._epsilon_residual = kwargs.get('epsilon_residual', self._epsilon_residual) + self._epsilon_ec = kwargs.get('epsilon_ec', self._epsilon_ec) + + + def update(self, y, graphs, ged_options, **kwargs): + # Set parameters. + self._ged_options = ged_options + if kwargs != {}: + self.set_update_params(**kwargs) + + # The initial iteration. + if self._verbose >= 2: + print('\ninitial:') + self.init_geds_and_nb_eo(y, graphs) + + self._converged = False + self._itrs_without_update = 0 + self._itrs = 0 + self._num_updates_ecs = 0 + timer = Timer(self._time_limit_in_sec) + # Run iterations from initial edit costs. + while not self.termination_criterion_met(self._converged, timer, self._itrs, self._itrs_without_update): + if self._verbose >= 2: + print('\niteration', self._itrs + 1) + time0 = time.time() + + # Fit GED space to the target space. + self.preprocess() + self.fit(self._nb_eo, y) + self.postprocess() + + # Compute new GEDs and numbers of edit operations. + self.update_geds_and_nb_eo(y, graphs, time0) + + # Check convergency. + self.check_convergency() + + # Print current states. + if self._verbose >= 2: + self.print_current_states() + + self._itrs += 1 + + + def init_geds_and_nb_eo(self, y, graphs): + pass + + + def update_geds_and_nb_eo(self, y, graphs, time0): + pass + + + def compute_geds_and_nb_eo(self, graphs): + pass + + + def check_convergency(self): + pass + + + def print_current_states(self): + pass + + + def termination_criterion_met(self, converged, timer, itr, itrs_without_update): + if timer.expired() or (itr >= self._max_itrs if self._max_itrs >= 0 else False): +# if self.__state == AlgorithmState.TERMINATED: +# self.__state = AlgorithmState.INITIALIZED + return True + return converged or (itrs_without_update > self._max_itrs_without_update if self._max_itrs_without_update >= 0 else False) + + + def execute_cvx(self, prob): + try: + prob.solve(verbose=(self._verbose>=2)) + except MemoryError as error0: + if self._verbose >= 2: + print('\nUsing solver "OSQP" caused a memory error.') + print('the original error message is\n', error0) + print('solver status: ', prob.status) + print('trying solver "CVXOPT" instead...\n') + try: + prob.solve(solver=cp.CVXOPT, verbose=(self._verbose>=2)) + except Exception as error1: + if self._verbose >= 2: + print('\nAn error occured when using solver "CVXOPT".') + print('the original error message is\n', error1) + print('solver status: ', prob.status) + print('trying solver "MOSEK" instead. Notice this solver is commercial and a lisence is required.\n') + prob.solve(solver=cp.MOSEK, verbose=(self._verbose>=2)) + else: + if self._verbose >= 2: + print('solver status: ', prob.status) + else: + if self._verbose >= 2: + print('solver status: ', prob.status) + if self._verbose >= 2: + print() + + + def get_results(self): + results = {} + results['residual_list'] = self._residual_list + results['runtime_list'] = self._runtime_list + results['cost_list'] = self._cost_list + results['nb_eo'] = self._nb_eo + results['itrs'] = self._itrs + results['converged'] = self._converged + results['num_updates_ecs'] = self._num_updates_ecs + results['ec_changed'] = self._ec_changed + results['residual_changed'] = self._residual_changed + results['itrs_without_update'] = self._itrs_without_update + return results \ No newline at end of file diff --git a/gklearn/preimage/median_preimage_generator_cml.py b/gklearn/preimage/median_preimage_generator_cml.py index 161475a..5ac1e94 100644 --- a/gklearn/preimage/median_preimage_generator_cml.py +++ b/gklearn/preimage/median_preimage_generator_cml.py @@ -10,15 +10,12 @@ import time import random import multiprocessing import networkx as nx -import cvxpy as cp -import itertools from gklearn.preimage import PreimageGenerator from gklearn.preimage.utils import compute_k_dis -from gklearn.ged.util import compute_geds_cml from gklearn.ged.env import GEDEnv +from gklearn.ged.learning import CostMatricesLearner from gklearn.ged.median import MedianGraphEstimatorPy from gklearn.ged.median import constant_node_costs, mge_options_to_string -from gklearn.utils import Timer, SpecialLabel from gklearn.utils.utils import get_graph_kernel_by_name @@ -28,7 +25,7 @@ class MedianPreimageGeneratorCML(PreimageGenerator): def __init__(self, dataset=None): PreimageGenerator.__init__(self, dataset=dataset) - # arguments to set. + ### arguments to set. self.__mge = None self.__ged_options = {} self.__mge_options = {} @@ -38,6 +35,7 @@ class MedianPreimageGeneratorCML(PreimageGenerator): self.__parallel = True self.__n_jobs = multiprocessing.cpu_count() self.__ds_name = None + # for cml. self.__time_limit_in_sec = 0 self.__max_itrs = 100 self.__max_itrs_without_update = 3 @@ -45,7 +43,7 @@ class MedianPreimageGeneratorCML(PreimageGenerator): self.__epsilon_ec = 0.1 self.__allow_zeros = True # self.__triangle_rule = True - # values to compute. + ### values to compute. self.__runtime_optimize_ec = None self.__runtime_generate_preimage = None self.__runtime_total = None @@ -57,12 +55,13 @@ class MedianPreimageGeneratorCML(PreimageGenerator): self.__k_dis_set_median = None self.__k_dis_gen_median = None self.__k_dis_dataset = None - self.__itrs = 0 - self.__converged = False - self.__num_updates_ecc = 0 self.__node_label_costs = None self.__edge_label_costs = None - # values that can be set or to be computed. + # for cml. + self.__itrs = 0 + self.__converged = False + self.__num_updates_ecs = 0 + ### values that can be set or to be computed. self.__edit_cost_constants = [] self.__gram_matrix_unnorm = None self.__runtime_precompute_gm = None @@ -154,7 +153,7 @@ class MedianPreimageGeneratorCML(PreimageGenerator): print('================================================================================') print('Finished generation of preimages.') print('--------------------------------------------------------------------------------') - print('The optimized edit cost constants:', self.__edit_cost_constants) + print('The optimized edit costs:', self.__edit_cost_constants) print('SOD of the set median:', self.__sod_set_median) print('SOD of the generalized median:', self.__sod_gen_median) print('Distance in kernel space for set median:', self.__k_dis_set_median) @@ -165,7 +164,7 @@ class MedianPreimageGeneratorCML(PreimageGenerator): print('Time to generate pre-images:', self.__runtime_generate_preimage) print('Total time:', self.__runtime_total) print('Total number of iterations for optimizing:', self.__itrs) - print('Total number of updating edit costs:', self.__num_updates_ecc) + print('Total number of updating edit costs:', self.__num_updates_ecs) print('Is optimization of edit costs converged:', self.__converged) print('================================================================================') print() @@ -185,7 +184,7 @@ class MedianPreimageGeneratorCML(PreimageGenerator): results['k_dis_dataset'] = self.__k_dis_dataset results['itrs'] = self.__itrs results['converged'] = self.__converged - results['num_updates_ecc'] = self.__num_updates_ecc + results['num_updates_ecc'] = self.__num_updates_ecs results['mge'] = {} results['mge']['num_decrease_order'] = self.__mge.get_num_times_order_decreased() results['mge']['num_increase_order'] = self.__mge.get_num_times_order_increased() @@ -302,598 +301,33 @@ class MedianPreimageGeneratorCML(PreimageGenerator): dis_k_vec.append(dis_k_mat[i, j]) dis_k_vec = np.array(dis_k_vec) - # init ged. - if self._verbose >= 2: - print('\ninitial:') - time0 = time.time() - graphs = [self.__clean_graph(g) for g in self._dataset.graphs] - self.__edit_cost_constants = self.__init_ecc + # Set GEDEnv options. +# graphs = [self.__clean_graph(g) for g in self._dataset.graphs] +# self.__edit_cost_constants = self.__init_ecc options = self.__ged_options.copy() - options['edit_cost_constants'] = self.__edit_cost_constants # @todo + options['edit_cost_constants'] = self.__edit_cost_constants # @todo: not needed. options['node_labels'] = self._dataset.node_labels options['edge_labels'] = self._dataset.edge_labels - options['node_attrs'] = self._dataset.node_attrs - options['edge_attrs'] = self._dataset.edge_attrs +# options['node_attrs'] = self._dataset.node_attrs +# options['edge_attrs'] = self._dataset.edge_attrs options['node_label_costs'] = self.__node_label_costs options['edge_label_costs'] = self.__edge_label_costs - ged_vec_init, ged_mat, n_edit_operations = compute_geds_cml(graphs, options=options, parallel=self.__parallel, verbose=(self._verbose > 1)) - residual_list = [np.sqrt(np.sum(np.square(np.array(ged_vec_init) - dis_k_vec)))] - time_list = [time.time() - time0] - edit_cost_list = [self.__init_ecc] - nb_cost_mat = np.array(n_edit_operations) - nb_cost_mat_list = [nb_cost_mat] - if self._verbose >= 2: - print('Current edit cost constants:', self.__edit_cost_constants) - print('Residual list:', residual_list) - - # run iteration from initial edit costs. - self.__converged = False - itrs_without_update = 0 - self.__itrs = 0 - self.__num_updates_ecc = 0 - timer = Timer(self.__time_limit_in_sec) - while not self.__termination_criterion_met(self.__converged, timer, self.__itrs, itrs_without_update): - if self._verbose >= 2: - print('\niteration', self.__itrs + 1) - time0 = time.time() - # "fit" geds to distances in feature space by tuning edit costs using theLeast Squares Method. -# np.savez('results/xp_fit_method/fit_data_debug' + str(self.__itrs) + '.gm', -# nb_cost_mat=nb_cost_mat, dis_k_vec=dis_k_vec, -# n_edit_operations=n_edit_operations, ged_vec_init=ged_vec_init, -# ged_mat=ged_mat) - self.__edit_cost_constants, _ = self.__update_ecc(nb_cost_mat, dis_k_vec) - for i in range(len(self.__edit_cost_constants)): - if -1e-9 <= self.__edit_cost_constants[i] <= 1e-9: - self.__edit_cost_constants[i] = 0 - if self.__edit_cost_constants[i] < 0: - raise ValueError('The edit cost is negative.') - # for i in range(len(self.__edit_cost_constants)): - # if self.__edit_cost_constants[i] < 0: - # self.__edit_cost_constants[i] = 0 - - # compute new GEDs and numbers of edit operations. - options = self.__ged_options.copy() # np.array([self.__edit_cost_constants[0], self.__edit_cost_constants[1], 0.75]) - options['edit_cost_constants'] = self.__edit_cost_constants # @todo - options['node_labels'] = self._dataset.node_labels - options['edge_labels'] = self._dataset.edge_labels - options['node_attrs'] = self._dataset.node_attrs - options['edge_attrs'] = self._dataset.edge_attrs - ged_vec, ged_mat, n_edit_operations = compute_geds_cml(graphs, options=options, parallel=self.__parallel, verbose=(self._verbose > 1)) - residual_list.append(np.sqrt(np.sum(np.square(np.array(ged_vec) - dis_k_vec)))) - time_list.append(time.time() - time0) - edit_cost_list.append(self.__edit_cost_constants) - nb_cost_mat = np.array(n_edit_operations) - nb_cost_mat_list.append(nb_cost_mat) - - # check convergency. - ec_changed = False - for i, cost in enumerate(self.__edit_cost_constants): - if cost == 0: - if edit_cost_list[-2][i] > self.__epsilon_ec: - ec_changed = True - break - elif abs(cost - edit_cost_list[-2][i]) / cost > self.__epsilon_ec: - ec_changed = True - break -# if abs(cost - edit_cost_list[-2][i]) > self.__epsilon_ec: -# ec_changed = True -# break - residual_changed = False - if residual_list[-1] == 0: - if residual_list[-2] > self.__epsilon_residual: - residual_changed = True - elif abs(residual_list[-1] - residual_list[-2]) / residual_list[-1] > self.__epsilon_residual: - residual_changed = True - self.__converged = not (ec_changed or residual_changed) - if self.__converged: - itrs_without_update += 1 - else: - itrs_without_update = 0 - self.__num_updates_ecc += 1 - - # print current states. - if self._verbose >= 2: - print() - print('-------------------------------------------------------------------------') - print('States of iteration', self.__itrs + 1) - print('-------------------------------------------------------------------------') -# print('Time spend:', self.__runtime_optimize_ec) - print('Total number of iterations for optimizing:', self.__itrs + 1) - print('Total number of updating edit costs:', self.__num_updates_ecc) - print('Was optimization of edit costs converged:', self.__converged) - print('Did edit costs change:', ec_changed) - print('Did residual change:', residual_changed) - print('Iterations without update:', itrs_without_update) - print('Current edit cost constants:', self.__edit_cost_constants) - print('Residual list:', residual_list) - print('-------------------------------------------------------------------------') - - self.__itrs += 1 - - - def __termination_criterion_met(self, converged, timer, itr, itrs_without_update): - if timer.expired() or (itr >= self.__max_itrs if self.__max_itrs >= 0 else False): -# if self.__state == AlgorithmState.TERMINATED: -# self.__state = AlgorithmState.INITIALIZED - return True - return converged or (itrs_without_update > self.__max_itrs_without_update if self.__max_itrs_without_update >= 0 else False) - - - def __update_ecc(self, nb_cost_mat, dis_k_vec, rw_constraints='inequality'): - # if self.__ds_name == 'Letter-high': - if self.__ged_options['edit_cost'] == 'LETTER': - raise Exception('Cannot compute for cost "LETTER".') - pass - # # method 1: set alpha automatically, just tune c_vir and c_eir by - # # LMS using cvxpy. - # alpha = 0.5 - # coeff = 100 # np.max(alpha * nb_cost_mat[:,4] / dis_k_vec) - ## if np.count_nonzero(nb_cost_mat[:,4]) == 0: - ## alpha = 0.75 - ## else: - ## alpha = np.min([dis_k_vec / c_vs for c_vs in nb_cost_mat[:,4] if c_vs != 0]) - ## alpha = alpha * 0.99 - # param_vir = alpha * (nb_cost_mat[:,0] + nb_cost_mat[:,1]) - # param_eir = (1 - alpha) * (nb_cost_mat[:,4] + nb_cost_mat[:,5]) - # nb_cost_mat_new = np.column_stack((param_vir, param_eir)) - # dis_new = coeff * dis_k_vec - alpha * nb_cost_mat[:,3] - # - # x = cp.Variable(nb_cost_mat_new.shape[1]) - # cost = cp.sum_squares(nb_cost_mat_new * x - dis_new) - # constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])]] - # prob = cp.Problem(cp.Minimize(cost), constraints) - # prob.solve() - # edit_costs_new = x.value - # edit_costs_new = np.array([edit_costs_new[0], edit_costs_new[1], alpha]) - # residual = np.sqrt(prob.value) - - # # method 2: tune c_vir, c_eir and alpha by nonlinear programming by - # # scipy.optimize.minimize. - # w0 = nb_cost_mat[:,0] + nb_cost_mat[:,1] - # w1 = nb_cost_mat[:,4] + nb_cost_mat[:,5] - # w2 = nb_cost_mat[:,3] - # w3 = dis_k_vec - # func_min = lambda x: np.sum((w0 * x[0] * x[3] + w1 * x[1] * (1 - x[2]) \ - # + w2 * x[2] - w3 * x[3]) ** 2) - # bounds = ((0, None), (0., None), (0.5, 0.5), (0, None)) - # res = minimize(func_min, [0.9, 1.7, 0.75, 10], bounds=bounds) - # edit_costs_new = res.x[0:3] - # residual = res.fun - # method 3: tune c_vir, c_eir and alpha by nonlinear programming using cvxpy. - - - # # method 4: tune c_vir, c_eir and alpha by QP function - # # scipy.optimize.least_squares. An initial guess is required. - # w0 = nb_cost_mat[:,0] + nb_cost_mat[:,1] - # w1 = nb_cost_mat[:,4] + nb_cost_mat[:,5] - # w2 = nb_cost_mat[:,3] - # w3 = dis_k_vec - # func = lambda x: (w0 * x[0] * x[3] + w1 * x[1] * (1 - x[2]) \ - # + w2 * x[2] - w3 * x[3]) ** 2 - # res = optimize.root(func, [0.9, 1.7, 0.75, 100]) - # edit_costs_new = res.x - # residual = None - elif self.__ged_options['edit_cost'] == 'LETTER2': - # # 1. if c_vi != c_vr, c_ei != c_er. - # nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4,5]] - # x = cp.Variable(nb_cost_mat_new.shape[1]) - # cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - ## # 1.1 no constraints. - ## constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])]] - # # 1.2 c_vs <= c_vi + c_vr. - # constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])], - # np.array([1.0, 1.0, -1.0, 0.0, 0.0]).T@x >= 0.0] - ## # 2. if c_vi == c_vr, c_ei == c_er. - ## nb_cost_mat_new = nb_cost_mat[:,[0,3,4]] - ## nb_cost_mat_new[:,0] += nb_cost_mat[:,1] - ## nb_cost_mat_new[:,2] += nb_cost_mat[:,5] - ## x = cp.Variable(nb_cost_mat_new.shape[1]) - ## cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - ## # 2.1 no constraints. - ## constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])]] - ### # 2.2 c_vs <= c_vi + c_vr. - ### constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])], - ### np.array([2.0, -1.0, 0.0]).T@x >= 0.0] - # - # prob = cp.Problem(cp.Minimize(cost_fun), constraints) - # prob.solve() - # edit_costs_new = [x.value[0], x.value[0], x.value[1], x.value[2], x.value[2]] - # edit_costs_new = np.array(edit_costs_new) - # residual = np.sqrt(prob.value) - if not self.__triangle_rule and self.__allow_zeros: - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])], - np.array([1.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 1.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 1.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 0.0, 1.0]).T@x >= 0.01] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = x.value - residual = np.sqrt(prob.value) - elif self.__triangle_rule and self.__allow_zeros: - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])], - np.array([1.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 1.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 1.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 0.0, 1.0]).T@x >= 0.01, - np.array([1.0, 1.0, -1.0, 0.0, 0.0]).T@x >= 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = x.value - residual = np.sqrt(prob.value) - elif not self.__triangle_rule and not self.__allow_zeros: - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])]] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - prob.solve() - edit_costs_new = x.value - residual = np.sqrt(prob.value) - # elif method == 'inequality_modified': - # # c_vs <= c_vi + c_vr. - # nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4,5]] - # x = cp.Variable(nb_cost_mat_new.shape[1]) - # cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - # constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])], - # np.array([1.0, 1.0, -1.0, 0.0, 0.0]).T@x >= 0.0] - # prob = cp.Problem(cp.Minimize(cost_fun), constraints) - # prob.solve() - # # use same costs for insertion and removal rather than the fitted costs. - # edit_costs_new = [x.value[0], x.value[0], x.value[1], x.value[2], x.value[2]] - # edit_costs_new = np.array(edit_costs_new) - # residual = np.sqrt(prob.value) - elif self.__triangle_rule and not self.__allow_zeros: - # c_vs <= c_vi + c_vr. - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])], - np.array([1.0, 1.0, -1.0, 0.0, 0.0]).T@x >= 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = x.value - residual = np.sqrt(prob.value) - elif rw_constraints == '2constraints': # @todo: rearrange it later. - # c_vs <= c_vi + c_vr and c_vi == c_vr, c_ei == c_er. - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])], - np.array([1.0, 1.0, -1.0, 0.0, 0.0]).T@x >= 0.0, - np.array([1.0, -1.0, 0.0, 0.0, 0.0]).T@x == 0.0, - np.array([0.0, 0.0, 0.0, 1.0, -1.0]).T@x == 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - prob.solve() - edit_costs_new = x.value - residual = np.sqrt(prob.value) - - elif self.__ged_options['edit_cost'] == 'NON_SYMBOLIC': - is_n_attr = np.count_nonzero(nb_cost_mat[:,2]) - is_e_attr = np.count_nonzero(nb_cost_mat[:,5]) - - if self.__ds_name == 'SYNTHETICnew': # @todo: rearrenge this later. - # nb_cost_mat_new = nb_cost_mat[:,[0,1,2,3,4]] - nb_cost_mat_new = nb_cost_mat[:,[2,3,4]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - # constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])], - # np.array([0.0, 0.0, 0.0, 1.0, -1.0]).T@x == 0.0] - # constraints = [x >= [0.0001 for i in range(nb_cost_mat_new.shape[1])]] - constraints = [x >= [0.0001 for i in range(nb_cost_mat_new.shape[1])], - np.array([0.0, 1.0, -1.0]).T@x == 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - prob.solve() - # print(x.value) - edit_costs_new = np.concatenate((np.array([0.0, 0.0]), x.value, - np.array([0.0]))) - residual = np.sqrt(prob.value) - - elif not self.__triangle_rule and self.__allow_zeros: - if is_n_attr and is_e_attr: - nb_cost_mat_new = nb_cost_mat[:,[0,1,2,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])], - np.array([1.0, 0.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 1.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 1.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 0.0, 1.0, 0.0]).T@x >= 0.01] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = x.value - residual = np.sqrt(prob.value) - elif is_n_attr and not is_e_attr: - nb_cost_mat_new = nb_cost_mat[:,[0,1,2,3,4]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])], - np.array([1.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 1.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 1.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 0.0, 1.0]).T@x >= 0.01] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = np.concatenate((x.value, np.array([0.0]))) - residual = np.sqrt(prob.value) - elif not is_n_attr and is_e_attr: - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])], - np.array([1.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 1.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 1.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 1.0, 0.0]).T@x >= 0.01] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = np.concatenate((x.value[0:2], np.array([0.0]), x.value[2:])) - residual = np.sqrt(prob.value) - else: - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])]] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = np.concatenate((x.value[0:2], np.array([0.0]), - x.value[2:], np.array([0.0]))) - residual = np.sqrt(prob.value) - elif self.__triangle_rule and self.__allow_zeros: - if is_n_attr and is_e_attr: - nb_cost_mat_new = nb_cost_mat[:,[0,1,2,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])], - np.array([1.0, 0.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 1.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 1.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 0.0, 1.0, 0.0]).T@x >= 0.01, - np.array([1.0, 1.0, -1.0, 0.0, 0.0, 0.0]).T@x >= 0.0, - np.array([0.0, 0.0, 0.0, 1.0, 1.0, -1.0]).T@x >= 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = x.value - residual = np.sqrt(prob.value) - elif is_n_attr and not is_e_attr: - nb_cost_mat_new = nb_cost_mat[:,[0,1,2,3,4]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])], - np.array([1.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 1.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 1.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 0.0, 1.0]).T@x >= 0.01, - np.array([1.0, 1.0, -1.0, 0.0, 0.0]).T@x >= 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = np.concatenate((x.value, np.array([0.0]))) - residual = np.sqrt(prob.value) - elif not is_n_attr and is_e_attr: - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.0 for i in range(nb_cost_mat_new.shape[1])], - np.array([1.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 1.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 1.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 1.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 1.0, 1.0, -1.0]).T@x >= 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = np.concatenate((x.value[0:2], np.array([0.0]), x.value[2:])) - residual = np.sqrt(prob.value) - else: - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])]] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = np.concatenate((x.value[0:2], np.array([0.0]), - x.value[2:], np.array([0.0]))) - residual = np.sqrt(prob.value) - elif not self.__triangle_rule and not self.__allow_zeros: - if is_n_attr and is_e_attr: - nb_cost_mat_new = nb_cost_mat[:,[0,1,2,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])]] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = x.value - residual = np.sqrt(prob.value) - elif is_n_attr and not is_e_attr: - nb_cost_mat_new = nb_cost_mat[:,[0,1,2,3,4]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])]] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = np.concatenate((x.value, np.array([0.0]))) - residual = np.sqrt(prob.value) - elif not is_n_attr and is_e_attr: - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])]] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = np.concatenate((x.value[0:2], np.array([0.0]), x.value[2:])) - residual = np.sqrt(prob.value) - else: - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])]] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = np.concatenate((x.value[0:2], np.array([0.0]), - x.value[2:], np.array([0.0]))) - residual = np.sqrt(prob.value) - elif self.__triangle_rule and not self.__allow_zeros: - # c_vs <= c_vi + c_vr. - if is_n_attr and is_e_attr: - nb_cost_mat_new = nb_cost_mat[:,[0,1,2,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])], - np.array([1.0, 1.0, -1.0, 0.0, 0.0, 0.0]).T@x >= 0.0, - np.array([0.0, 0.0, 0.0, 1.0, 1.0, -1.0]).T@x >= 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = x.value - residual = np.sqrt(prob.value) - elif is_n_attr and not is_e_attr: - nb_cost_mat_new = nb_cost_mat[:,[0,1,2,3,4]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])], - np.array([1.0, 1.0, -1.0, 0.0, 0.0]).T@x >= 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = np.concatenate((x.value, np.array([0.0]))) - residual = np.sqrt(prob.value) - elif not is_n_attr and is_e_attr: - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4,5]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])], - np.array([0.0, 0.0, 1.0, 1.0, -1.0]).T@x >= 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = np.concatenate((x.value[0:2], np.array([0.0]), x.value[2:])) - residual = np.sqrt(prob.value) - else: - nb_cost_mat_new = nb_cost_mat[:,[0,1,3,4]] - x = cp.Variable(nb_cost_mat_new.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat_new @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat_new.shape[1])]] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = np.concatenate((x.value[0:2], np.array([0.0]), - x.value[2:], np.array([0.0]))) - residual = np.sqrt(prob.value) - - elif self.__ged_options['edit_cost'] == 'CONSTANT': # @todo: node/edge may not labeled. - if not self.__triangle_rule and self.__allow_zeros: - x = cp.Variable(nb_cost_mat.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat @ x - dis_k_vec) - constraints = [x >= [0.0 for i in range(nb_cost_mat.shape[1])], - np.array([1.0, 0.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 1.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 1.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 0.0, 1.0, 0.0]).T@x >= 0.01] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = x.value - residual = np.sqrt(prob.value) - elif self.__triangle_rule and self.__allow_zeros: - x = cp.Variable(nb_cost_mat.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat @ x - dis_k_vec) - constraints = [x >= [0.0 for i in range(nb_cost_mat.shape[1])], - np.array([1.0, 0.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 1.0, 0.0, 0.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 1.0, 0.0, 0.0]).T@x >= 0.01, - np.array([0.0, 0.0, 0.0, 0.0, 1.0, 0.0]).T@x >= 0.01, - np.array([1.0, 1.0, -1.0, 0.0, 0.0, 0.0]).T@x >= 0.0, - np.array([0.0, 0.0, 0.0, 1.0, 1.0, -1.0]).T@x >= 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = x.value - residual = np.sqrt(prob.value) - elif not self.__triangle_rule and not self.__allow_zeros: - x = cp.Variable(nb_cost_mat.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat.shape[1])]] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = x.value - residual = np.sqrt(prob.value) - elif self.__triangle_rule and not self.__allow_zeros: - x = cp.Variable(nb_cost_mat.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat @ x - dis_k_vec) - constraints = [x >= [0.01 for i in range(nb_cost_mat.shape[1])], - np.array([1.0, 1.0, -1.0, 0.0, 0.0, 0.0]).T@x >= 0.0, - np.array([0.0, 0.0, 0.0, 1.0, 1.0, -1.0]).T@x >= 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = x.value - residual = np.sqrt(prob.value) - else: - raise Exception('The edit cost "', self.__ged_options['edit_cost'], '" is not supported for update progress.') - # # method 1: simple least square method. - # edit_costs_new, residual, _, _ = np.linalg.lstsq(nb_cost_mat, dis_k_vec, - # rcond=None) - - # # method 2: least square method with x_i >= 0. - # edit_costs_new, residual = optimize.nnls(nb_cost_mat, dis_k_vec) - - # method 3: solve as a quadratic program with constraints. - # P = np.dot(nb_cost_mat.T, nb_cost_mat) - # q_T = -2 * np.dot(dis_k_vec.T, nb_cost_mat) - # G = -1 * np.identity(nb_cost_mat.shape[1]) - # h = np.array([0 for i in range(nb_cost_mat.shape[1])]) - # A = np.array([1 for i in range(nb_cost_mat.shape[1])]) - # b = 1 - # x = cp.Variable(nb_cost_mat.shape[1]) - # prob = cp.Problem(cp.Minimize(cp.quad_form(x, P) + q_T@x), - # [G@x <= h]) - # prob.solve() - # edit_costs_new = x.value - # residual = prob.value - np.dot(dis_k_vec.T, dis_k_vec) - - # G = -1 * np.identity(nb_cost_mat.shape[1]) - # h = np.array([0 for i in range(nb_cost_mat.shape[1])]) - x = cp.Variable(nb_cost_mat.shape[1]) - cost_fun = cp.sum_squares(nb_cost_mat @ x - dis_k_vec) - constraints = [x >= [0.0 for i in range(nb_cost_mat.shape[1])], - # np.array([1.0, 1.0, -1.0, 0.0, 0.0]).T@x >= 0.0] - np.array([1.0, 1.0, -1.0, 0.0, 0.0, 0.0]).T@x >= 0.0, - np.array([0.0, 0.0, 0.0, 1.0, 1.0, -1.0]).T@x >= 0.0] - prob = cp.Problem(cp.Minimize(cost_fun), constraints) - self.__execute_cvx(prob) - edit_costs_new = x.value - residual = np.sqrt(prob.value) - - # method 4: - - return edit_costs_new, residual - - - def __execute_cvx(self, prob): - try: - prob.solve(verbose=(self._verbose>=2)) - except MemoryError as error0: - if self._verbose >= 2: - print('\nUsing solver "OSQP" caused a memory error.') - print('the original error message is\n', error0) - print('solver status: ', prob.status) - print('trying solver "CVXOPT" instead...\n') - try: - prob.solve(solver=cp.CVXOPT, verbose=(self._verbose>=2)) - except Exception as error1: - if self._verbose >= 2: - print('\nAn error occured when using solver "CVXOPT".') - print('the original error message is\n', error1) - print('solver status: ', prob.status) - print('trying solver "MOSEK" instead. Notice this solver is commercial and a lisence is required.\n') - prob.solve(solver=cp.MOSEK, verbose=(self._verbose>=2)) - else: - if self._verbose >= 2: - print('solver status: ', prob.status) - else: - if self._verbose >= 2: - print('solver status: ', prob.status) - if self._verbose >= 2: - print() + # Learner cost matrices. + # Initialize cost learner. + cml = CostMatricesLearner(edit_cost='CONSTANT', triangle_rule=False, allow_zeros=True, parallel=self.__parallel, verbose=self._verbose) # @todo + cml.set_update_params(time_limit_in_sec=self.__time_limit_in_sec, max_itrs=self.__max_itrs, max_itrs_without_update=self.__max_itrs_without_update, epsilon_residual=self.__epsilon_residual, epsilon_ec=self.__epsilon_ec) + # Run cost learner. + cml.update(dis_k_vec, self._dataset.graphs, options) + + # Get results. + results = cml.get_results() + self.__converged = results['converged'] + self.__itrs = results['itrs'] + self.__num_updates_ecs = results['num_updates_ecs'] + cost_list = results['cost_list'] + self.__node_label_costs = cost_list[-1][0:len(self.__node_label_costs)] + self.__edge_label_costs = cost_list[-1][len(self.__node_label_costs):] def __gmg_bcu(self):