def _solve(self): num = self.num options = self.options solver = get_solver(options["solver"]) ls_class = get_line_search_class(options["line_search"]) total_size = int(num["dof"]) rhs = np.zeros((total_size, num["y"])) sol = np.zeros((total_size, num["y"])) d_sol = np.zeros((total_size, num["y"])) with self.printer._timed_context( "Solving initial startup problem (n=%i)" % total_size): approx_order = options["approx_order"] nonlinear_maxiter = options["nonlinear_maxiter"] options["approx_order"] = 2 options["nonlinear_maxiter"] = 1 self._run_newton_solver(sol) options["approx_order"] = approx_order options["nonlinear_maxiter"] = nonlinear_maxiter with self.printer._timed_context("Solving nonlinear problem (n=%i)" % total_size): self._run_newton_solver(sol) return sol
def _new_train(self): num = self.num xt, yt = self.training_points[None][0] jac = np.empty(num['radial'] * num['dof']) self.rbfc.compute_jac(num['radial'], xt.flatten(), jac) jac = jac.reshape((num['radial'], num['dof'])) mtx = np.zeros((num['dof'], num['dof'])) mtx[:num['radial'], :] = jac mtx[:, :num['radial']] = jac.T mtx[np.arange(num['radial']), np.arange(num['radial'])] += self.options['reg'] self.mtx = mtx rhs = np.zeros((num['dof'], num['y'])) rhs[:num['radial'], :] = yt sol = np.zeros((num['dof'], num['y'])) solver = get_solver('dense-lu') with self.printer._timed_context('Initializing linear solver'): solver._setup(mtx, self.printer) for ind_y in range(rhs.shape[1]): with self.printer._timed_context('Solving linear system (col. %i)' % ind_y): solver._solve(rhs[:, ind_y], sol[:, ind_y], ind_y=ind_y) self.sol = sol
def _run_newton_solver(self, sol): num = self.num options = self.options solver = get_solver(options["solver"]) ls_class = get_line_search_class(options["line_search"]) total_size = int(num["dof"]) rhs = np.zeros((total_size, num["y"])) d_sol = np.zeros((total_size, num["y"])) p = self.options["approx_order"] for ind_y in range(rhs.shape[1]): with self.printer._timed_context("Solving for output %i" % ind_y): yt_dict = self._get_yt_dict(ind_y) norm = self._opt_norm(sol[:, ind_y], p, yt_dict) fval = self._opt_func(sol[:, ind_y], p, yt_dict) self.printer( "Iteration (num., iy, grad. norm, func.) : %3i %3i %15.9e %15.9e" % (0, ind_y, norm, fval) ) iter_count = 0 while ( iter_count < options["nonlinear_maxiter"] and norm > options["solver_tolerance"] ): with self.printer._timed_context(): with self.printer._timed_context("Assembling linear system"): mtx = self._opt_hess(sol[:, ind_y], p, yt_dict) rhs[:, ind_y] = -self._opt_grad(sol[:, ind_y], p, yt_dict) with self.printer._timed_context("Initializing linear solver"): solver._setup(mtx, self.printer) with self.printer._timed_context("Solving linear system"): solver._solve(rhs[:, ind_y], d_sol[:, ind_y], ind_y=ind_y) func = lambda x: self._opt_func(x, p, yt_dict) grad = lambda x: self._opt_grad(x, p, yt_dict) # sol[:, ind_y] += d_sol[:, ind_y] ls = ls_class(sol[:, ind_y], d_sol[:, ind_y], func, grad) with self.printer._timed_context("Performing line search"): sol[:, ind_y] = ls(1.0) norm = self._opt_norm(sol[:, ind_y], p, yt_dict) fval = self._opt_func(sol[:, ind_y], p, yt_dict) self.printer( "Iteration (num., iy, grad. norm, func.) : %3i %3i %15.9e %15.9e" % (iter_count, ind_y, norm, fval) ) self.mtx = mtx iter_count += 1
def _fit(self): options = self.options nx = self.training_pts['exact'][0][0].shape[1] if isinstance(options['d0'], (int, float)): options['d0'] = [options['d0']] * nx options['d0'] = np.atleast_1d(options['d0']) num = {} # number of inputs and outputs num['x'] = self.training_pts['exact'][0][0].shape[1] num['y'] = self.training_pts['exact'][0][1].shape[1] # number of radial function terms num['radial'] = self.training_pts['exact'][0][0].shape[0] # number of polynomial terms if options['poly_degree'] == -1: num['poly'] = 0 elif options['poly_degree'] == 0: num['poly'] = 1 elif options['poly_degree'] == 1: num['poly'] = 1 + num['x'] num['dof'] = num['radial'] + num['poly'] self.num = num self.printer.max_print_depth = options['max_print_depth'] xt, yt = self.training_pts['exact'][0] jac = RBFlib.compute_jac(0, options['poly_degree'], num['x'], num['radial'], num['radial'], num['dof'], options['d0'], xt, xt) mtx = np.zeros((num['dof'], num['dof'])) mtx[:num['radial'], :] = jac mtx[:, :num['radial']] = jac.T mtx[np.arange(num['radial']), np.arange(num['radial'])] += options['reg'] rhs = np.zeros((num['dof'], num['y'])) rhs[:num['radial'], :] = yt sol = np.zeros((num['dof'], num['y'])) solver = get_solver('dense') with self.printer._timed_context('Initializing linear solver'): solver._initialize(mtx, self.printer) for ind_y in range(rhs.shape[1]): with self.printer._timed_context( 'Solving linear system (col. %i)' % ind_y): solver._solve(rhs[:, ind_y], sol[:, ind_y], ind_y=ind_y) self.sol = sol
def _predict_output_derivatives(self, x): # dy_dyt = dy_dw * (dR_dw)^{-1} * dR_dyt n = x.shape[0] nw = self.mtx.shape[0] nx = x.shape[1] ny = self.sol.shape[1] p = self.options["approx_order"] dy_dw = self._compute_prediction_mtx(x, 0) if self.full_dof2coeff is not None: dy_dw = dy_dw * self.full_dof2coeff dy_dw = dy_dw.todense() dR_dw = self.mtx dy_dyt = {} for kx in self.training_points[None]: nt = self.training_points[None][kx][0].shape[0] dR_dyt = np.zeros((nw, nt, ny)) for ind_y in range(ny): yt_dict = self._get_yt_dict(ind_y) dR_dyt[:, :, ind_y] = self._opt_dgrad_dyt(self.sol[:, ind_y], p, yt_dict, kx) solver = get_solver(self.options["derivative_solver"]) solver._setup(dR_dw, self.printer) dw_dyt = np.zeros((nw, nt, ny)) for ind_t in range(nt): for ind_y in range(ny): solver._solve(dR_dyt[:, ind_t, ind_y], dw_dyt[:, ind_t, ind_y], ind_y=ind_y) dw_dyt[:, ind_t, ind_y] *= -1.0 if kx == 0: dy_dyt[None] = np.einsum("ij,jkl->ikl", dy_dw, dw_dyt) else: dy_dyt[kx - 1] = np.einsum("ij,jkl->ikl", dy_dw, dw_dyt) return dy_dyt
def _solve(self, full_hess, full_jac_dict, mg_matrices): num = self.num options = self.options solver = get_solver(options['solver']) ls_class = get_line_search_class(options['line_search']) total_size = int(num['dof']) rhs = np.zeros((total_size, num['y'])) sol = np.zeros((total_size, num['y'])) d_sol = np.zeros((total_size, num['y'])) with self.printer._timed_context('Solving initial linear problem (n=%i)' % total_size): with self.printer._timed_context('Assembling linear system'): mtx = self._opt_hess_2(full_hess, full_jac_dict) for ind_y in range(num['y']): yt_dict = self._get_yt_dict(ind_y) rhs[:, ind_y] = -self._opt_grad(sol[:, ind_y], 2, full_hess, full_jac_dict, yt_dict) with self.printer._timed_context('Initializing linear solver'): solver._initialize(mtx, self.printer, mg_matrices=mg_matrices) for ind_y in range(rhs.shape[1]): with self.printer._timed_context('Solving linear system (col. %i)' % ind_y): solver._solve(rhs[:, ind_y], sol[:, ind_y], ind_y=ind_y) p = self.options['approx_order'] for ind_y in range(rhs.shape[1]): with self.printer._timed_context('Solving nonlinear problem (col. %i)' % ind_y): yt_dict = self._get_yt_dict(ind_y) if options['nln_max_iter'] > 0: norm = self._opt_norm(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict) fval = self._opt_func(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict) self.printer( 'Nonlinear (itn, iy, grad. norm, func.) : %3i %3i %15.9e %15.9e' % (0, ind_y, norm, fval)) for nln_iter in range(options['nln_max_iter']): with self.printer._timed_context(): with self.printer._timed_context('Assembling linear system'): mtx = self._opt_hess(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict) rhs[:, ind_y] = -self._opt_grad(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict) with self.printer._timed_context('Initializing linear solver'): solver._initialize(mtx, self.printer, mg_matrices=mg_matrices) with self.printer._timed_context('Solving linear system'): solver._solve(rhs[:, ind_y], d_sol[:, ind_y], ind_y=ind_y) func = lambda x: self._opt_func(x, p, full_hess, full_jac_dict, yt_dict) grad = lambda x: self._opt_grad(x, p, full_hess, full_jac_dict, yt_dict) ls = ls_class(sol[:, ind_y], d_sol[:, ind_y], func, grad) with self.printer._timed_context('Performing line search'): sol[:, ind_y] = ls(1.0) norm = self._opt_norm(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict) fval = self._opt_func(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict) self.printer( 'Nonlinear (itn, iy, grad. norm, func.) : %3i %3i %15.9e %15.9e' % (nln_iter + 1, ind_y, norm, fval)) if norm < 1e-16: break return sol
def _fit(self): """ Train the model """ sm_options = self.sm_options nx = self.training_pts['exact'][0][0].shape[1] ny = self.training_pts['exact'][0][1].shape[1] num = {} num['order_list'] = np.array(sm_options['order'], int) num['order'] = np.prod(num['order_list']) num['ctrl_list'] = np.array(sm_options['num_ctrl_pts'], int) num['ctrl'] = np.prod(num['ctrl_list']) num['knots_list'] = num['order_list'] + num['ctrl_list'] num['knots'] = np.sum(num['knots_list']) self.num = num mtx = scipy.sparse.csc_matrix((num['ctrl'], num['ctrl'])) rhs = np.zeros((num['ctrl'], ny)) xlimits = sm_options['xlimits'] for kx in self.training_pts['exact']: xt, yt = self.training_pts['exact'][kx] xmin = np.min(xt, axis=0) xmax = np.max(xt, axis=0) assert np.all( xlimits[:, 0] <= xmin), 'Training pts below min for %s' % kx assert np.all( xlimits[:, 1] >= xmax), 'Training pts above max for %s' % kx t = np.zeros(xt.shape) for ix in range(nx): t[:, ix] = (xt[:, ix] - xlimits[ix, 0]) /\ (xlimits[ix, 1] - xlimits[ix, 0]) nt = xt.shape[0] nnz = nt * num['order'] data, rows, cols = MBRlib.compute_jac(kx, 0, nx, nt, nnz, num['order_list'], num['ctrl_list'], t) if kx > 0: data /= xlimits[kx - 1, 1] - xlimits[kx - 1, 0] rect_mtx = scipy.sparse.csc_matrix((data, (rows, cols)), shape=(nt, num['ctrl'])) mtx = mtx + rect_mtx.T * rect_mtx rhs += rect_mtx.T * yt diag = sm_options['reg'] * np.ones(num['ctrl']) arange = np.arange(num['ctrl']) reg = scipy.sparse.csc_matrix((diag, (arange, arange))) mtx = mtx + reg sol = np.zeros(rhs.shape) solver = get_solver(sm_options['solver']) with self.printer._timed_context('Initializing linear solver'): solver._initialize(mtx, self.printer) for ind_y in range(rhs.shape[1]): with self.printer._timed_context( 'Solving linear system (col. %i)' % ind_y): solver._solve(rhs[:, ind_y], sol[:, ind_y], ind_y=ind_y) self.sol = sol
def _fit(self): """ Train the model """ sm_options = self.sm_options num = {} # number of inputs and outputs num['x'] = self.training_pts['exact'][0][0].shape[1] num['y'] = self.training_pts['exact'][0][1].shape[1] # number of elements num['elem_list'] = np.array(sm_options['num_elem'], int) num['elem'] = np.prod(num['elem_list']) # number of terms/coefficients per element num['term_list'] = 4 * np.ones(num['x'], int) num['term'] = np.prod(num['term_list']) # number of nodes num['uniq_list'] = num['elem_list'] + 1 num['uniq'] = np.prod(num['uniq_list']) # total number of training points (function values and derivatives) num['t'] = 0 for kx in self.training_pts['exact']: num['t'] += self.training_pts['exact'][kx][0].shape[0] if len(sm_options['smoothness']) == 0: sm_options['smoothness'] = [1.0] * num['x'] self.num = num self.printer.max_print_depth = sm_options['max_print_depth'] with self.printer._timed_context('Pre-computing matrices'): with self.printer._timed_context('Computing uniq2coeff'): full_uniq2coeff = self._compute_uniq2coeff( num['x'], num['elem_list'], num['elem'], num['term'], num['uniq']) with self.printer._timed_context('Computing local energy terms'): elem_hess = self._compute_local_hess() with self.printer._timed_context('Computing global energy terms'): full_hess = self._compute_global_hess(elem_hess, full_uniq2coeff) with self.printer._timed_context('Computing approximation terms'): full_jac_dict, reg_cons_dict = self._compute_approx_terms(full_uniq2coeff) if sm_options['solver'] == 'mg': mg_matrices = self._compute_mg_matrices() else: mg_matrices = [] block_names = ['dv'] block_sizes = [num['uniq'] * 2 ** num['x']] if sm_options['mode'] == 'exact': block_names += ['con_%s'%kx for kx in self.training_pts['exact']] block_sizes += [self.training_pts['exact'][kx][0].shape[0] for kx in self.training_pts['exact']] with self.printer._timed_context('Solving for degrees of freedom'): solver = get_solver(sm_options['solver']) ls_class = get_line_search_class(sm_options['line_search']) total_size = int(np.sum(block_sizes)) rhs = np.zeros((total_size, num['y'])) sol = np.zeros((total_size, num['y'])) d_sol = np.zeros((total_size, num['y'])) with self.printer._timed_context('Solving initial linear problem'): with self.printer._timed_context('Assembling linear system'): if sm_options['mode'] == 'approx': mtx = self._opt_hess_2(full_hess, full_jac_dict) for ind_y in range(num['y']): yt_dict = self._get_yt_dict(ind_y) rhs[:, ind_y] = -self._opt_grad(sol[:, ind_y], 2, full_hess, full_jac_dict, yt_dict) elif sm_options['mode'] == 'exact': sub_mtx_dict = {} sub_rhs_dict = {} sub_mtx_dict['dv', 'dv'] = scipy.sparse.csc_matrix(full_hess) sub_rhs_dict['dv'] = -full_hess * sol for kx in self.training_pts['exact']: full_jac = full_jac_dict[kx] xt, yt = self.training_pts['exact'][kx] reg_cons = reg_cons_dict[kx] sub_mtx_dict['con_%s'%kx, 'dv'] = full_jac sub_mtx_dict['dv', 'con_%s'%kx] = full_jac.T sub_mtx_dict['con_%s'%kx, 'con_%s'%kx] = reg_cons sub_rhs_dict['con_%s'%kx] = yt mtx, rhs = assemble_sparse_mtx( block_names, block_sizes, sub_mtx_dict, sub_rhs_dict) with self.printer._timed_context('Initializing linear solver'): solver._initialize(mtx, self.printer, mg_matrices=mg_matrices) for ind_y in range(rhs.shape[1]): with self.printer._timed_context('Solving linear system (col. %i)' % ind_y): solver._solve(rhs[:, ind_y], sol[:, ind_y], ind_y=ind_y) p = self.sm_options['approx_norm'] for ind_y in range(rhs.shape[1]): with self.printer._timed_context('Solving nonlinear problem (col. %i)' % ind_y): yt_dict = self._get_yt_dict(ind_y) if sm_options['max_nln_iter'] > 0: norm = self._opt_norm(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict) fval = self._opt_func(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict) self.printer( 'Nonlinear (itn, iy, grad. norm, func.) : %3i %3i %15.9e %15.9e' % (0, ind_y, norm, fval)) for nln_iter in range(sm_options['max_nln_iter']): with self.printer._timed_context(): with self.printer._timed_context('Assembling linear system'): mtx = self._opt_hess(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict) rhs[:, ind_y] = -self._opt_grad(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict) with self.printer._timed_context('Initializing linear solver'): solver._initialize(mtx, self.printer, mg_matrices=mg_matrices) with self.printer._timed_context('Solving linear system'): solver._solve(rhs[:, ind_y], d_sol[:, ind_y], ind_y=ind_y) func = lambda x: self._opt_func(x, p, full_hess, full_jac_dict, yt_dict) grad = lambda x: self._opt_grad(x, p, full_hess, full_jac_dict, yt_dict) ls = ls_class(sol[:, ind_y], d_sol[:, ind_y], func, grad) with self.printer._timed_context('Performing line search'): sol[:, ind_y] = ls(1.0) norm = self._opt_norm(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict) fval = self._opt_func(sol[:, ind_y], p, full_hess, full_jac_dict, yt_dict) self.printer( 'Nonlinear (itn, iy, grad. norm, func.) : %3i %3i %15.9e %15.9e' % (nln_iter + 1, ind_y, norm, fval)) if norm < 1e-3: break self.sol = full_uniq2coeff * sol[:num['uniq'] * 2 ** num['x'], :]