├── LICENSE ├── README.md ├── docs ├── TestCase1_Image.pdf ├── TestCase1_Image.png ├── TestCase1_MetaVor.gif ├── TestCase1_Vor.gif ├── TestCase2_Image.pdf ├── TestCase2_Image.png ├── TestCase2_Meta.gif ├── TestCase3_Image.pdf ├── TestCase3_Image.png └── TestCase3_Meta.gif ├── main.m └── src ├── Autocorrelation_functions ├── Cubic_spline_matrix.m ├── Matern32_matrix.m ├── Matern52_matrix.m └── Read_me_autofunctions.txt ├── Error_Saver.m ├── OK_model.m ├── TPLHD ├── createTPLHD.m ├── reshapeSeed.m ├── resizeTPLHD.m ├── scale.m ├── scaled_TPLHD.m └── tplhsdesign.m ├── adaptive_sampling_process.m ├── chooseSamplingMethod.m ├── help_functions ├── Read_me_helpfunctions.py ├── intersite_proj_th.m ├── lhs_scaled.m ├── randomVoronoi.m ├── scale_to_unity.m ├── scale_vector_from_unity.m └── scale_vector_to_unity.m ├── initial_metamodel.m ├── optimizationTools.m └── response_functions ├── Read_me_responsefunctions.txt ├── Test1.m ├── Test2.m └── Test3.m /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jan N Fuhg 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AdaptiveMIVor 2 | The Monte Carlo-intersite Voronoi (MiVor) adaptive scheme is an adaptive sampling technqiue for ordinary Kriging. 3 | 4 | The following library provides a Matlab implementation of the MiVor algorithm. In order to show applicability of the method three different test cases with different degrees of complexity are provided within this framework. 5 | 6 | ## Getting Started 7 | 8 | We encourage those who are interested in using this code to run the main file and pick a test case. 9 | 10 | ### Prerequisites 11 | 12 | Matlab version R2017a or higher. 13 | 14 | ## Examples 15 | 16 | The three following working examples similarly to what is found in the paper are included in this code for which the classification boundary limit is set to 0.0 for each case. 17 | 18 | --- 19 | 20 |

21 | Example 1 22 | Example 1 23 | Example 1 24 |

25 | 26 | --- 27 | 28 | ### Example 1 29 | The following Gifs show an exemplary sampling process for example 1. 30 |

31 | ODE Demo 32 | ODE Demo 33 | 34 |

35 | 36 | ### Adaptive sampling process Examples 2 and 3 37 | The following Gifs show an exemplary sampling process for example 2 and 3 respectively. 38 |

39 | ODE Demo 40 | ODE Demo 41 |

42 | 43 | 44 | --- 45 | 46 | # References 47 | 48 | Please cite this code with: 49 | 50 | Fuhg, Jan N., and Amelie Fau. "An innovative adaptive kriging approach for efficient binary classification of mechanical problems." arXiv preprint arXiv:1907.01490 (2019). 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /docs/TestCase1_Image.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuhgJan/AdaptiveMIVor/5eeb9244abf677075659ae7ae0b153ddff60b9af/docs/TestCase1_Image.pdf -------------------------------------------------------------------------------- /docs/TestCase1_Image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuhgJan/AdaptiveMIVor/5eeb9244abf677075659ae7ae0b153ddff60b9af/docs/TestCase1_Image.png -------------------------------------------------------------------------------- /docs/TestCase1_MetaVor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuhgJan/AdaptiveMIVor/5eeb9244abf677075659ae7ae0b153ddff60b9af/docs/TestCase1_MetaVor.gif -------------------------------------------------------------------------------- /docs/TestCase1_Vor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuhgJan/AdaptiveMIVor/5eeb9244abf677075659ae7ae0b153ddff60b9af/docs/TestCase1_Vor.gif -------------------------------------------------------------------------------- /docs/TestCase2_Image.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuhgJan/AdaptiveMIVor/5eeb9244abf677075659ae7ae0b153ddff60b9af/docs/TestCase2_Image.pdf -------------------------------------------------------------------------------- /docs/TestCase2_Image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuhgJan/AdaptiveMIVor/5eeb9244abf677075659ae7ae0b153ddff60b9af/docs/TestCase2_Image.png -------------------------------------------------------------------------------- /docs/TestCase2_Meta.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuhgJan/AdaptiveMIVor/5eeb9244abf677075659ae7ae0b153ddff60b9af/docs/TestCase2_Meta.gif -------------------------------------------------------------------------------- /docs/TestCase3_Image.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuhgJan/AdaptiveMIVor/5eeb9244abf677075659ae7ae0b153ddff60b9af/docs/TestCase3_Image.pdf -------------------------------------------------------------------------------- /docs/TestCase3_Image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuhgJan/AdaptiveMIVor/5eeb9244abf677075659ae7ae0b153ddff60b9af/docs/TestCase3_Image.png -------------------------------------------------------------------------------- /docs/TestCase3_Meta.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuhgJan/AdaptiveMIVor/5eeb9244abf677075659ae7ae0b153ddff60b9af/docs/TestCase3_Meta.gif -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | clear all; 2 | addpath(genpath('src')) 3 | 4 | % Define exploration rate and decrease factor 5 | global exploration; 6 | global decrease_factor; 7 | global n_of_Variables 8 | 9 | exploration = 0.15; 10 | decrease_factor = 1.1; 11 | 12 | 13 | n_of_Variables = 2; 14 | 15 | %% Test function 16 | % Test Case 1 17 | [ y, lb, ub ,x, M ] = Test1(); 18 | % Test Case 2 19 | % [ y, lb, ub ,x, M ] = Test2(); 20 | % Test Case 3 21 | % [ y, lb, ub ,x, M ] = Test2(); 22 | 23 | 24 | 25 | 26 | %% Create responses 27 | for i=1:size(x,1) 28 | y(i,1) = M(x(i,:)); 29 | end 30 | 31 | % Limit to distinguish classes in 2d 32 | class_limit = 0.0; 33 | 34 | % Scale parameter samples to unity 35 | x = scale_vector_to_unity(lb, ub, x); 36 | 37 | % Number of adaptive samples 38 | number_of_adaptive_iterations = 150; 39 | 40 | % Number of repetitive iterations 41 | max_iteration = 1; 42 | 43 | 44 | A_sampling =[lb';ub']; 45 | [output] = chooseSamplingMethod(M,x, y, A_sampling, number_of_adaptive_iterations,max_iteration,class_limit); 46 | save('SavedOutput.mat','output') 47 | -------------------------------------------------------------------------------- /src/Autocorrelation_functions/Cubic_spline_matrix.m: -------------------------------------------------------------------------------- 1 | function [ R ] = Cubic_spline_matrix( x1,x2,theta ) 2 | % Create autocorrelation matrix with cubic spline kernel 3 | 4 | n = size(x1,2); 5 | m1 = size(x1,1); 6 | m2 = size(x2,1); 7 | 8 | R = -inf*(ones(m1,m2)); 9 | for i=1: m1 10 | 11 | for j=1:m2 12 | R_val = 1; 13 | for p=1:n 14 | xi = theta(p) * abs(x1(i,p)-x2(j,p)); 15 | if (0.0 <= xi) && (xi <= 0.2) 16 | val = 1 - 15*xi^2 + 30* xi^3; 17 | elseif (0.2 < xi) && (xi < 1.0) 18 | val = 1.25 * (1 - xi)^3; 19 | elseif xi >= 1.0 20 | val = 0.0; 21 | end 22 | R_val = R_val* val; 23 | end 24 | R(i,j) = R_val; 25 | end 26 | end 27 | 28 | 29 | end -------------------------------------------------------------------------------- /src/Autocorrelation_functions/Matern32_matrix.m: -------------------------------------------------------------------------------- 1 | function [ R ] = Matern32_matrix( x1,x2,theta ) 2 | % Create autocorrelation matrix with Matern32 kernel 3 | 4 | n = size(x1,2); 5 | m1 = size(x1,1); 6 | m2 = size(x2,1); 7 | 8 | R = -inf*(ones(m1,m2)); 9 | for i=1: m1 10 | 11 | for j=1:m2 12 | R_val = 1; 13 | for p=1:n 14 | r = x1(i,p)-x2(j,p); 15 | kval = (sqrt(3)*abs(r))/theta(p); 16 | val = (1+ kval)*exp(-kval); 17 | R_val = R_val* val; 18 | end 19 | R(i,j) = R_val; 20 | end 21 | end 22 | 23 | 24 | % n = size(x1,2); 25 | % R = 1; 26 | % for i=1:n 27 | % r = x1(i)-x2(i); 28 | % kval = (sqrt(3)*abs(r))/theta(i); 29 | % val = (1+ kval)*exp(-kval); 30 | % R = R* val; 31 | % end 32 | 33 | 34 | 35 | 36 | 37 | end 38 | -------------------------------------------------------------------------------- /src/Autocorrelation_functions/Matern52_matrix.m: -------------------------------------------------------------------------------- 1 | function [ R ] = Matern52_matrix( x1,x2,theta ) 2 | % Create autocorrelation matrix with Matern52 kernel 3 | 4 | n = size(x1,2); 5 | m1 = size(x1,1); 6 | m2 = size(x2,1); 7 | 8 | R = -inf*(ones(m1,m2)); 9 | for i=1: m1 10 | 11 | for j=1:m2 12 | R_val = 1; 13 | for p=1:n 14 | r = x1(i,p)-x2(j,p); 15 | kval = (sqrt(5)*abs(r))/theta(p); 16 | val = (1+ kval + (5*(r^2))/(3*(theta(p)^2)))*exp(-kval); 17 | R_val = R_val* val; 18 | end 19 | R(i,j) = R_val; 20 | end 21 | end 22 | 23 | 24 | 25 | end 26 | 27 | -------------------------------------------------------------------------------- /src/Autocorrelation_functions/Read_me_autofunctions.txt: -------------------------------------------------------------------------------- 1 | This folder contains the functions used for creating the autocorrelation matrices. 2 | -------------------------------------------------------------------------------- /src/Error_Saver.m: -------------------------------------------------------------------------------- 1 | classdef Error_Saver 2 | properties 3 | error_data; 4 | end 5 | 6 | methods 7 | function obj = Error_Saver() 8 | obj.error_data = table; 9 | 10 | end 11 | 12 | function obj = update(obj,it,X,Y,percentAbove, percentBelow) 13 | MAE_val = MeanAE(X,Y); 14 | RMAE_val = RMAE(X,Y); 15 | RMSE_val = RMSE(X,Y); 16 | R_sq_val = R_sq(X,Y); 17 | i= size(obj.error_data,1); 18 | obj.error_data(i+1,:)= {it ,MAE_val , RMAE_val, RMSE_val, R_sq_val, percentAbove, percentBelow }; 19 | if i==0 20 | obj.error_data.Properties.VariableNames = {'Iterator','MAE','RMAE','RMSE', 'R_sq', 'percentAbove', 'percentBelow'}; 21 | end 22 | end 23 | 24 | 25 | function plot_data(obj) 26 | data = obj.error_data.Variables; 27 | Iterator = data(:,1); 28 | MeanAE = data(:,2); 29 | RMAE = data(:,3); 30 | RMSE = data(:,4); 31 | R_sq = data(:,5); 32 | 33 | figure 34 | plot(Iterator, MeanAE, 'LineWidth', 2.0); hold on; 35 | plot(Iterator, RMAE, 'LineWidth', 2.0); hold on; 36 | plot(Iterator, RMSE, 'LineWidth', 2.0); hold on; 37 | plot(Iterator, R_sq, 'LineWidth', 2.0); hold off; 38 | legend('MAE','MeanAE','RMSE', 'R^2'); 39 | xlabel('Iterations'); 40 | 41 | end 42 | 43 | end 44 | 45 | 46 | end 47 | 48 | function error_val = standard(X) 49 | % root mean squared error 50 | m = numel(X); 51 | mean_response = (1/m)*(sum(X)); 52 | error_val = sqrt((1/(m))*(sum((X-mean_response).^2))); 53 | end 54 | 55 | function error_val = RMAE(X,Y) 56 | % relative maximum absolute error 57 | error_val = max(abs(X-Y))/standard(X); 58 | end 59 | 60 | 61 | function error_val = MeanAE(X,Y) 62 | % mean absolute error 63 | m= numel(X); 64 | error_val = (1/m)*(sum(abs(X-Y))); 65 | end 66 | 67 | 68 | function error_val = RMSE(X,Y) 69 | % root mean squared error 70 | m= numel(X); 71 | error_val = sqrt((1/m)*(sum((X-Y).^2))); 72 | end 73 | 74 | 75 | function error_val = R_sq(X,Y) 76 | % R_sq score 77 | m= numel(X); 78 | mean_response = (1/m)*(sum(X)); 79 | MSE_val = (sum((X-Y).^2)); 80 | 81 | divisor = sum((X-mean_response).^2); 82 | 83 | error_val = 1-(MSE_val/divisor); 84 | end -------------------------------------------------------------------------------- /src/OK_model.m: -------------------------------------------------------------------------------- 1 | classdef OK_model 2 | % Class for ordinary Kriging 3 | properties 4 | auto_correlation_function; 5 | X; 6 | Y; 7 | theta_opti_technique; 8 | 9 | m; 10 | F; 11 | theta; 12 | R; 13 | end 14 | 15 | 16 | methods 17 | %Constructor 18 | function obj=OK_model(af,x,y,opti) 19 | obj.auto_correlation_function = af; 20 | obj.X = x; % x = [x1 y1 z1; x2 y2 z2] 21 | obj.Y = y; 22 | obj.theta_opti_technique = opti; 23 | 24 | obj.m = size(x,1); 25 | obj.F = ones(size(1:obj.m))'; 26 | obj.theta = optimize_theta(obj); 27 | 28 | obj.R = compute_R(obj, obj.theta); 29 | end 30 | 31 | 32 | 33 | 34 | 35 | function R = compute_R(obj, theta) 36 | 37 | 38 | R = obj.auto_correlation_function(obj.X,obj.X, theta); 39 | 40 | 41 | %Analytical comparison of regularization methods for Gaussian 42 | %Processes, Mohammadi 43 | if sum(isnan(R(:))) 44 | disp('NAN values') 45 | end 46 | 47 | k = cond(R); 48 | if k > 10^(12) 49 | min_lambda = min(eigs(R)); 50 | max_lambda = max(eigs(R)); 51 | 52 | kmax = 10^10; 53 | tau_sq = (max_lambda - kmax * min_lambda)/(kmax-1); 54 | 55 | R = R+ tau_sq*eye(size(R,1)); 56 | end 57 | 58 | 59 | end 60 | 61 | 62 | function beta_hat = compute_beta_hat(obj,R) 63 | beta_hat = ((obj.F'*(R\obj.F))\obj.F') * (R\obj.Y); 64 | end 65 | 66 | function sigma_sq_hat = compute_sigma_sq_hat(obj,R,beta_hat) 67 | sigma_sq_hat = (1/obj.m) *(obj.Y- obj.F*beta_hat)' * (R\(obj.Y- obj.F*beta_hat)); 68 | end 69 | 70 | 71 | function r0 = compute_r0(obj,theta,x0) 72 | r0= obj.auto_correlation_function(obj.X,x0,theta); 73 | end 74 | 75 | function mu_hat = compute_mu_hat(obj,R,beta_hat,x0,theta) 76 | r0 = compute_r0(obj,theta,x0); 77 | mu_hat = beta_hat + r0' * (R\(obj.Y - obj.F*beta_hat)); 78 | end 79 | 80 | function sigma_Y_sq_hat = compute_sigma_Y_sq_hat(obj,sigma_sq_hat,x0,theta,R) 81 | r0 = compute_r0(obj,theta,x0); 82 | u0 = obj.F' * (R\r0) - 1; 83 | sigma_Y_sq_hat = sigma_sq_hat * (1 - r0' * (R\r0) + u0 * ((obj.F' * (R\obj.F))\u0)); 84 | end 85 | 86 | function theta = optimize_theta(obj) 87 | 88 | AA = []; 89 | b = []; 90 | Aeq = []; 91 | beq = []; 92 | 93 | n = size(obj.X,2); 94 | for k=1:n 95 | iter =1; 96 | clear distance 97 | for i=1:obj.m 98 | for j=1:obj.m 99 | if ~(i == j) 100 | distance(iter) = abs(obj.X(i,k) - obj.X(j,k)); 101 | iter = iter +1; 102 | end 103 | end 104 | end 105 | max_distance = max(distance); 106 | min_distance = min(distance); 107 | 108 | lb(k) = 0.00005*min_distance; 109 | if lb(k) == 0.0 110 | lb(k) = 10^(-5); 111 | end 112 | ub(k) = max_distance; 113 | end 114 | 115 | fun = @obj.computeMLE; 116 | theta = optimizationTools(fun,obj.theta_opti_technique,AA,b,Aeq,beq,lb,ub,[]); 117 | 118 | end 119 | 120 | 121 | function Psi = computeMLE(obj,theta) 122 | R_matrix = compute_R(obj, theta); 123 | beta_hat = compute_beta_hat(obj,R_matrix); 124 | 125 | sigma_sq_hat = compute_sigma_sq_hat(obj,R_matrix,beta_hat); 126 | 127 | Psi = 0.5 * (obj.m*log(sigma_sq_hat) + log(det(R_matrix))); 128 | 129 | end 130 | 131 | 132 | 133 | 134 | function [mu_hat,sigma_Y_sq_hat] = construct_modell(obj,x0) 135 | 136 | beta_hat = compute_beta_hat(obj,obj.R); 137 | sigma_sq_hat = compute_sigma_sq_hat(obj,obj.R,beta_hat); 138 | for i=1:numel(x0(:,1)) 139 | mu_hat(i) = compute_mu_hat(obj,obj.R,beta_hat,x0(i,:),obj.theta); 140 | sigma_Y_sq_hat(i) = compute_sigma_Y_sq_hat(obj,sigma_sq_hat,x0(i,:),obj.theta,obj.R); 141 | end 142 | end 143 | 144 | 145 | %% adaptive sampling methods 146 | 147 | function x_new = adaptive_sampling(obj,method,A,class_Limit) 148 | if strcmp(method,'MiVor') 149 | x_new = MiVor_function(obj,A,class_Limit); 150 | elseif strcmp(method,'EIGF') 151 | x_new = doEIGF(obj,A); 152 | end 153 | 154 | function [S] = SFVCT_S(obj) 155 | for i=1:obj.m 156 | clear distance_min 157 | iter = 1; 158 | for j=1:obj.m 159 | 160 | if ~(i==j) 161 | distance_min(iter) = norm(obj.X(i,:) - obj.X(j,:)); 162 | iter = iter +1; 163 | end 164 | end 165 | distance(i) = min(distance_min); 166 | end 167 | 168 | max_distance = max(distance); 169 | 170 | S= 0.5 *max_distance; 171 | end 172 | 173 | function newPoint =doVarianceForPoint(obj,points) 174 | % disp('Variance') 175 | beta_hat = compute_beta_hat(obj,obj.R); 176 | sigma_sq_hat = compute_sigma_sq_hat(obj,obj.R,beta_hat); 177 | % Distance = inf; 178 | sigma_Y_sq_hat_Max = -inf; 179 | for ll=1:size(points,1) 180 | sigma_Y_sq_hat = compute_sigma_Y_sq_hat(obj,sigma_sq_hat,points(ll,:),obj.theta,obj.R); 181 | if sigma_Y_sq_hat > sigma_Y_sq_hat_Max 182 | sigma_Y_sq_hat_Max = sigma_Y_sq_hat; 183 | newPointTemp = points(ll,:); 184 | end 185 | end 186 | 187 | newPoint = newPointTemp; 188 | 189 | end 190 | 191 | 192 | function [newPoint,points] = findNewPointInHighestVolume(obj,C, indexOfInterest,class_Limit) 193 | X_without_indexOfInterest = obj.X; 194 | Y_without_indexOfInterest = obj.Y; 195 | X_without_indexOfInterest(indexOfInterest,:) = []; 196 | Y_without_indexOfInterest(indexOfInterest,:) = []; 197 | [indexNeighbor,~] = knnsearch(X_without_indexOfInterest,obj.X(indexOfInterest,:),'K',2*size(X_without_indexOfInterest,2)); 198 | 199 | points = C{indexOfInterest,2}; 200 | % Check if one of the closest points is lower Limit 201 | closestPoints_class2 = 0; 202 | % closestPoints_class2Sum = 0; 203 | for kk=1:numel(indexNeighbor) 204 | if Y_without_indexOfInterest(indexNeighbor(kk)) < class_Limit 205 | class2_pointOfINterest = indexNeighbor(kk); 206 | closestPoints_class2 = 1; 207 | break; 208 | end 209 | end 210 | 211 | if closestPoints_class2 212 | disp('Closest point lower limit found!') 213 | Distance = inf; 214 | for ll=1:size(points,1) 215 | d = norm(X_without_indexOfInterest(class2_pointOfINterest) - points(ll,:)); 216 | if d< Distance 217 | Distance = d; 218 | newPointTemp = points(ll,:); 219 | end 220 | end 221 | else 222 | newPointTemp =doVarianceForPoint(obj,points); 223 | end 224 | newPoint = newPointTemp; 225 | 226 | end 227 | 228 | 229 | 230 | function x_new = DoMIPT(obj,A) 231 | % addpath('help_functions') 232 | n = numel(A(1,:)); 233 | lb = A(1,:); 234 | ub = A(2,:); 235 | p = lhs_scaled(500 *n* obj.m,lb,ub); 236 | 237 | alpha = 0.5; 238 | dmin = (2*alpha)/ obj.m; 239 | MIPT_val = -inf; 240 | 241 | 242 | for i=1:size(p,1) 243 | val = intersite_proj_th(dmin, obj.X,p(i,:)); 244 | if val > MIPT_val 245 | MIPT_val = val; 246 | x_new = p(i,:); 247 | end 248 | end 249 | end 250 | 251 | function x_new = MiVor_function(obj,A, class_Limit) 252 | % addpath('help_functions') 253 | global exploration; 254 | global decrease_factor; 255 | IndexClass1 = find(obj.Y >=class_Limit); 256 | IndexClass2 = find(obj.Y 1 310 | % disp('Too Close') 311 | [~,D] = knnsearch(obj.X,newPoint,'K',obj.m); 312 | rr = rand(); 313 | if rr>0.2 314 | newPoint =doVarianceForPoint(obj,points); 315 | else 316 | newPoint = DoMIPT(obj,A); 317 | end 318 | end 319 | 320 | 321 | end 322 | x_new = newPoint; 323 | 324 | h =figure(1); 325 | voronoi(obj.X(:,1),obj.X(:,2)); hold on; 326 | scatter(obj.X(IndexClass1,1),obj.X(IndexClass1,2),80,'b','filled'); hold on; 327 | scatter(obj.X(IndexClass2,1),obj.X(IndexClass2,2),80,'y','filled'); hold on; 328 | scatter(x_new(:,1),x_new(:,2),100,'k','filled'); hold off; 329 | lgd = legend({'Voronoi points','Voronoi cells','Sample belonging to Class 1', 'Sample belonging to Class 2', 'New found point'}, 'Location','southoutside'); 330 | lgd.NumColumns = 2; 331 | xlim([0 1]) 332 | ylim([0 1]) 333 | xlabel('$x_{1}$','Interpreter','Latex') 334 | ylabel('$x_{2}$','Interpreter','Latex') 335 | set(gca,'FontSize',16) 336 | set(gcf, 'Renderer', 'painters', 'Position',[0 200 700 500]); 337 | drawnow 338 | 339 | 340 | end 341 | 342 | 343 | 344 | 345 | %% EIGF 346 | function x_new = doEIGF(obj,A) 347 | AA = []; 348 | b = []; 349 | Aeq = []; 350 | beq = []; 351 | lb = A(1,:); 352 | ub = A(2,:); 353 | strategy = 'AN'; 354 | 355 | fun = @(x) adaptive_EIGF(obj,x); 356 | 357 | x_new = optimizationTools(fun,strategy,AA,b,Aeq,beq,lb,ub,[]); 358 | 359 | end 360 | 361 | 362 | function EIGF_min = adaptive_EIGF(obj,x) 363 | 364 | beta_hat = compute_beta_hat(obj,obj.R); 365 | sigma_sq_hat = compute_sigma_sq_hat(obj,obj.R,beta_hat); 366 | 367 | mu_hat = compute_mu_hat(obj,obj.R,beta_hat,x,obj.theta); 368 | sigma_Y_sq_hat = compute_sigma_Y_sq_hat(obj,sigma_sq_hat,x,obj.theta,obj.R); 369 | 370 | 371 | 372 | k = dsearchn(obj.X,x); 373 | EIGF = (mu_hat - obj.Y(k))^(2) + sigma_Y_sq_hat; 374 | 375 | EIGF_min=-EIGF; 376 | end 377 | 378 | 379 | 380 | end 381 | end 382 | end 383 | 384 | 385 | -------------------------------------------------------------------------------- /src/TPLHD/createTPLHD.m: -------------------------------------------------------------------------------- 1 | function X = createTPLHD(seed, ns, npStar, ndStar, nv) 2 | % inputs: seed - initial seed design (points within 1 and ns) 3 | % ns - number of points in the seed design 4 | % npStar - number of points of the Latin hypercube (LH) 5 | % nd - number of divisions of the LH 6 | % nv - number of variables in the LH 7 | % outputs: X - Latin hypercube design created by the translational 8 | % propagation algorithm 9 | % we warn that this function has to be properly translated to other 10 | % programming languages to avoid problems with memory allocation 11 | X = seed; 12 | d = ones(1, nv); % just for memory allocation 13 | for c1 = 1 : nv % shifting one direction at a time 14 | seed = X; % update seed with the latest points added 15 | d(1 : (c1 - 1)) = ndStar^(c1 - 2); 16 | d(c1) = npStar/ndStar; 17 | d((c1 + 1) : end) = ndStar^(c1 - 1); 18 | for c2 = 2 : ndStar % fill each of the divisions 19 | ns = length(seed(:,1)); % update seed size 20 | for c3 = 1 : ns 21 | seed(c3,:) = seed(c3,:) + d; 22 | end 23 | X = vertcat(X, seed); 24 | end 25 | end 26 | return 27 | -------------------------------------------------------------------------------- /src/TPLHD/reshapeSeed.m: -------------------------------------------------------------------------------- 1 | function seed = reshapeSeed(seed , ns, npStar, ndStar, nv) 2 | % inputs: seed - initial seed design (points within 1 and ns) 3 | % ns - number of points in the seed design 4 | % npStar - number of points of the Latin hypercube (LH) 5 | % nd - number of divisions of the LH 6 | % nv - number of variables in the LH 7 | % outputs: seed - seed design properly scaled 8 | if ns == 1 9 | seed = ones(1, nv); % arbitrarily put at the origin 10 | else 11 | uf = ns*ones(1, nv); 12 | ut = ( (npStar / ndStar) - ndStar*(nv - 1) + 1 )*ones(1, nv); 13 | rf = uf - 1; 14 | rt = ut - 1; 15 | a = rt./rf; 16 | b = ut - a.*uf; 17 | for c1 = 1 : ns 18 | seed(c1,:) = a.*seed(c1,:) + b; 19 | end 20 | seed = round(seed); % to make sure that the numbers are integer 21 | end 22 | return 23 | 24 | -------------------------------------------------------------------------------- /src/TPLHD/resizeTPLHD.m: -------------------------------------------------------------------------------- 1 | function X = resizeTPLHD(X, npStar, np, nv) 2 | % inputs: X - initial Latin hypercube design 3 | % npStar - number of points in the initial X 4 | % np - number of points in the final X 5 | % nv - number of variables 6 | % outputs: X - final X, properly shrunk 7 | center = npStar*ones(1,nv)/2; % center of the design space 8 | % distance between each point of X and the center of the design space 9 | distance = zeros(npStar, 1); 10 | for c1 = 1 : npStar 11 | distance(c1) = norm( ( X(c1,:) - center) ); 12 | end 13 | [dummy, idx] = sort(distance); 14 | X = X( idx(1:np), : ); % resize X to np points 15 | % re-establish the LH conditions 16 | Xmin = min(X); 17 | for c1 = 1 : nv 18 | % place X in the origin 19 | X = sortrows(X, c1); 20 | X(:,c1) = X(:,c1) - Xmin(c1) + 1; 21 | % eliminate empty coordinates 22 | flag = 0; 23 | while flag == 0; 24 | mask = (X(:,c1) ~= ([1:np]')); 25 | flag = isequal(mask,zeros(np,1)); 26 | X(:,c1) = X(:,c1) - (X(:,c1) ~= ([1:np]')); 27 | end 28 | end 29 | return 30 | -------------------------------------------------------------------------------- /src/TPLHD/scale.m: -------------------------------------------------------------------------------- 1 | function scaled_value = scale(c,d,x) 2 | % c lower, d upper 3 | scaled_value= c + (d-c) * x; 4 | end 5 | 6 | -------------------------------------------------------------------------------- /src/TPLHD/scaled_TPLHD.m: -------------------------------------------------------------------------------- 1 | function S = scaled_TPLHD(n,lb,ub) 2 | 3 | S = tplhsdesign(n, numel(lb), 1, 1)./n; 4 | % S = [zeros(size(S(1,:))) ;S]; 5 | for i=1:numel(lb) 6 | c = lb(i); 7 | d = ub(i); 8 | 9 | S(:,i) = scale(c,d,S(:,i)); 10 | end 11 | 12 | end 13 | 14 | -------------------------------------------------------------------------------- /src/TPLHD/tplhsdesign.m: -------------------------------------------------------------------------------- 1 | function X = tplhsdesign(np, nv, seed, ns) 2 | % inputs: np - number of points of the desired Latin hypercube (LH) 3 | % nv - number of variables in the LH 4 | % seed - initial seed design (points within 1 and ns) 5 | % ns - number of points in the seed design 6 | % outputs: X - Latin hypercube created using the translational 7 | % propagation algorithm 8 | % define the size of the TPLHD to be created first 9 | nd = ( np/ns)^( 1/nv ); % number of divisions, nd 10 | ndStar = ceil( nd ); 11 | if (ndStar > nd) 12 | nb = ndStar^nv; % it is necessary to create a bigger TPLHD 13 | else 14 | nb = np/ns; % it is NOT necessary to create a bigger TPLHD 15 | end 16 | npStar = nb*ns; % size of the TPLHD to be created first 17 | % reshape seed to properly create the first design 18 | seed = reshapeSeed(seed , ns, npStar, ndStar, nv); 19 | % create TPLHD with npStar points 20 | X = createTPLHD(seed, ns, npStar, ndStar, nv); 21 | % resize TPLH if necessary 22 | npStar > np; 23 | if (npStar > np) 24 | X = resizeTPLHD(X, npStar, np, nv); 25 | end 26 | return 27 | 28 | -------------------------------------------------------------------------------- /src/adaptive_sampling_process.m: -------------------------------------------------------------------------------- 1 | function [stored_metamodels,single_errors] = adaptive_sampling_process(metamodel_ini,M,adaptive_method,A_sampling,number_of_adaptive_iterations, class_limit) 2 | % inputs: 3 | % metamodel_ini - initial metamodel 4 | % M - respone function 5 | % adaptive_method - adaptive sampling technique 6 | % A_sampling - parameter space 7 | % number_of_adaptive_iterations - maximum number of iterations 8 | % class_limit - Sets limit value to distinguish classes in 2d 9 | % 10 | % outputs: 11 | % stored_metamodels - stored metamodels 12 | % single_errors - errors of each adaptive step 13 | global n_of_Variables 14 | 15 | 16 | %addpath('help_functions') 17 | iter = 1; 18 | stored_metamodels{1} = metamodel_ini; 19 | metamodel = metamodel_ini; 20 | 21 | 22 | lb = A_sampling(1,:); 23 | ub = A_sampling(2,:); 24 | 25 | lb_unity = zeros(size(lb)); 26 | ub_unity = ones(size(ub)); 27 | A_sampling_unity =[lb_unity;ub_unity]; 28 | 29 | Y = metamodel_ini.Y; 30 | X = metamodel_ini.X; 31 | 32 | initNumber = size(X,1); 33 | 34 | data_errors = Error_Saver(); 35 | 36 | 37 | 38 | no_test_points = 5000 * n_of_Variables; 39 | test_points = lhs_scaled(no_test_points,A_sampling(1,:),A_sampling(2,:)); 40 | 41 | for i=1:no_test_points 42 | test_points_response(i) = M(test_points(i,:)); 43 | if test_points_response(i) >= class_limit 44 | classificationVec(i) = 1; 45 | else 46 | classificationVec(i) = 0; 47 | end 48 | end 49 | 50 | 51 | test_points = scale_vector_to_unity(lb, ub, test_points); 52 | y = test_points_response; 53 | 54 | shouldBeClass1 = numel(find(y >= class_limit)); 55 | shouldBeClass2 = numel(find(y < class_limit)); 56 | close all; 57 | 58 | if n_of_Variables ==2 59 | xd = (max(test_points(:,1))-min(test_points(:,1)))/200; 60 | yd =(max(test_points(:,2))-min(test_points(:,2)))/200; 61 | [xq,yq] = meshgrid(min(test_points(:,1)):xd:max(test_points(:,1)),min(test_points(:,2)):yd:max(test_points(:,2))); 62 | 63 | mymap = [0.8 0.8 0.8; 64 | 1 0 0]; 65 | 66 | % drawnow 67 | end 68 | 69 | while (iter < number_of_adaptive_iterations) 70 | clear y_new x_new 71 | x_new = metamodel.adaptive_sampling(adaptive_method,A_sampling_unity, class_limit); 72 | 73 | ST = ['New found point: ', num2str(x_new)]; 74 | disp(ST); 75 | 76 | x_new_scaled = scale_vector_from_unity(lb,ub,x_new); 77 | 78 | 79 | for ss=1:size(x_new_scaled,1) 80 | y_new(ss,1) = M(x_new_scaled(ss,:)); 81 | end 82 | 83 | Y = [Y; y_new]; 84 | X = [X; x_new]; 85 | 86 | metamodel = OK_model(metamodel.auto_correlation_function,X,Y,metamodel.theta_opti_technique); 87 | 88 | 89 | iter = iter+1; 90 | 91 | %% Errors 92 | 93 | NumberCorrectClass1 = 0; 94 | NumberCorrectClass2 = 0; 95 | for i=1:no_test_points 96 | 97 | [metamodel_response(i),~] = metamodel.construct_modell(test_points(i,:)); 98 | if metamodel_response(i) >= class_limit 99 | classificationVec_pred(i) = 1; 100 | else 101 | classificationVec_pred(i) = 0; 102 | end 103 | 104 | if (test_points_response(i) >= class_limit) && (metamodel_response(i) >= class_limit) 105 | NumberCorrectClass1 = NumberCorrectClass1+1; 106 | elseif (test_points_response(i) < class_limit) && (metamodel_response(i) < class_limit) 107 | NumberCorrectClass2 = NumberCorrectClass2 +1; 108 | end 109 | end 110 | 111 | PercentAbove = NumberCorrectClass1/shouldBeClass1; 112 | PercentBelow = NumberCorrectClass2/shouldBeClass2; 113 | 114 | data_errors=data_errors.update(metamodel.m,test_points_response , metamodel_response, PercentAbove, PercentBelow ); 115 | ST =[adaptive_method, ' m = ', num2str(size(X,1)), ' Average RMSE value : ', num2str(data_errors.error_data.RMSE(end))]; 116 | disp(ST); 117 | ST =[adaptive_method, ' m = ', num2str(size(X,1)), ' Correct Class 1 in %: ', num2str(PercentAbove*100)]; 118 | disp(ST); 119 | ST =[adaptive_method, ' m = ', num2str(size(X,1)), ' Correct Class 2 in %: ', num2str(PercentBelow*100)]; 120 | disp(ST); 121 | 122 | 123 | 124 | 125 | 126 | if n_of_Variables ==2 127 | currentSize = size(metamodel.X,1); 128 | vqreal =griddata(test_points(:,1),test_points(:,2),classificationVec,xq,yq); 129 | h= figure(2); 130 | subplot(2,1,1) 131 | s = surf(xq,yq,vqreal); hold on; 132 | colormap(mymap); 133 | title('Target') 134 | xlabel('$x_{1}$','Interpreter','Latex') 135 | ylabel('$x_{2}$','Interpreter','Latex') 136 | set(gca,'FontSize',16) 137 | s.EdgeColor ='none'; 138 | view(2); 139 | 140 | 141 | vqpred = griddata(test_points(:,1),test_points(:,2),classificationVec_pred,xq,yq); 142 | subplot(2,1,2) 143 | 144 | s = surf(xq,yq,vqpred); hold on; 145 | scatter3(metamodel.X(1:end-1,1),metamodel.X(1:end-1,2), 100*ones(size(metamodel.X(1:end-1,1),1),1),60,'b','filled'); hold on; 146 | scatter3(metamodel.X(end,1),metamodel.X(end,2), 100,100,'k','filled'); hold off; 147 | colormap(mymap); 148 | title('Prediction and Samples') 149 | xlabel('$x_{1}$','Interpreter','Latex') 150 | ylabel('$x_{2}$','Interpreter','Latex') 151 | set(gca,'FontSize',16) 152 | set(gcf, 'Position',[850 1000 500 500]); 153 | s.EdgeColor = 'none'; 154 | view(2); 155 | drawnow 156 | 157 | 158 | end 159 | 160 | stored_metamodels{iter} = metamodel; 161 | single_errors = {adaptive_method,data_errors}; 162 | 163 | 164 | 165 | end 166 | 167 | 168 | end 169 | -------------------------------------------------------------------------------- /src/chooseSamplingMethod.m: -------------------------------------------------------------------------------- 1 | function [output] = chooseSamplingMethod(M, x, y,A_sampling, number_of_adaptive_iterations,max_iteration, class_limit) 2 | % inputs: 3 | % M - response function 4 | % x - samples in parametric space 5 | % y - observations 6 | % A_sampling - parameter space 7 | % number_of_adaptive_iterations - maximum number of iterations 8 | % max_iteration - number of repetitions 9 | % class_limit - Sets limit value to distinguish classes in 2d 10 | % 11 | % outputs: 12 | % output - adaptive method, stored metamodels, final errors, single error 13 | 14 | % MiVor method 15 | adaptive_methods{1} ='MiVor'; 16 | 17 | % Expected improvement for global fit 18 | adaptive_methods{2} ='EIGF'; 19 | 20 | % Fit Kriging to initial dataset and obtain error values 21 | adaptive_methods{3} ='Initial_error'; 22 | 23 | % Choose one or multiple sampling techniques by setting j value. Can be 24 | % parallelized via parfor. 25 | for j=1:1 26 | close all 27 | for i=1:max_iteration 28 | St = ['Computation of ', adaptive_methods{j},' Iteration number: ', num2str(i), ' of ', num2str(max_iteration)]; 29 | disp(St) 30 | 31 | [stored_metamodels{i}, final_errors{i}, single_errors{1,i}] = initial_metamodel(M,A_sampling,adaptive_methods{j}, x, y,number_of_adaptive_iterations, class_limit); 32 | 33 | end 34 | 35 | output{j,1}= {adaptive_methods{j}, stored_metamodels, final_errors,single_errors}; 36 | 37 | end 38 | 39 | 40 | end 41 | 42 | -------------------------------------------------------------------------------- /src/help_functions/Read_me_helpfunctions.py: -------------------------------------------------------------------------------- 1 | This folder contains some useful functions used for the adaptive scheme. 2 | -------------------------------------------------------------------------------- /src/help_functions/intersite_proj_th.m: -------------------------------------------------------------------------------- 1 | function val = intersite_proj_th(dmin, X,p) 2 | % intersite proj TH method 3 | 4 | for i=1:size(X,1) 5 | if norm((X(i,:) - p),-inf) < dmin 6 | val =0; 7 | end 8 | end 9 | val = inf; 10 | for i=1:size(X,1) 11 | calc = norm(X(i,:) - p); 12 | if calc < val 13 | val = calc; 14 | end 15 | end 16 | end -------------------------------------------------------------------------------- /src/help_functions/lhs_scaled.m: -------------------------------------------------------------------------------- 1 | function [X_scaled]=lhs_scaled(n,lb,ub) 2 | % Create n samples with Matlab's Latin hypercube method within bounds lb and ub 3 | p=length(lb); 4 | [M,N]=size(lb); 5 | if M= class_limit)); 43 | shouldBeClass2 = numel(find(test_points_response < class_limit)); 44 | NumberCorrectClass1 = 0; 45 | NumberCorrectClass2 = 0; 46 | for i=1:no_test_points 47 | [metamodel_response(i),~] = stored_metamodels{numel(stored_metamodels)}.construct_modell(test_points(i,:)); 48 | if (test_points_response(i) >= class_limit) && (metamodel_response(i) >= class_limit) 49 | NumberCorrectClass1 = NumberCorrectClass1+1; 50 | elseif (test_points_response(i) < class_limit) && (metamodel_response(i) < class_limit) 51 | NumberCorrectClass2 = NumberCorrectClass2 +1; 52 | end 53 | end 54 | 55 | PercentAbove = NumberCorrectClass1/shouldBeClass1; 56 | PercentBelow = NumberCorrectClass2/shouldBeClass2; 57 | 58 | 59 | final_errors=data_errors.update(stored_metamodels{numel(stored_metamodels)}.m,test_points_response , metamodel_response,PercentAbove, PercentBelow); 60 | 61 | end 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/optimizationTools.m: -------------------------------------------------------------------------------- 1 | function x_opti = optimizationTools(fun,strategy,AA,b,Aeq,beq,lb,ub,nonlcon) 2 | % General function that connects to different matlab optimization schemes 3 | n = numel(lb); 4 | if strcmp(strategy,'fmincon') 5 | options = optimoptions('fmincon','Display','none'); 6 | addpath('help_functions') 7 | x0 = scale_rand(1,lb,ub); 8 | x_opti = fmincon(fun,x0,AA,b,Aeq,beq,lb,ub,nonlcon,options); 9 | elseif strcmp(strategy,'PSO') 10 | options = optimoptions('particleswarm','SwarmSize',800*n,'Display','off'); 11 | options.HybridFcn = @fmincon; 12 | [x_opti] = particleswarm(fun,n,lb,ub,options); 13 | elseif strcmp(strategy,'GA') 14 | options = gaoptimset('PopulationSize',10000*n,'Display','off'); 15 | % options.HybridFcn = @fmincon; 16 | x_opti = ga(fun,n,AA,b,Aeq,beq,lb,ub,nonlcon,options); 17 | elseif strcmp(strategy,'AN') 18 | 19 | options = optimoptions('simulannealbnd','Display','none','FunctionTolerance', 1e-08); 20 | exitflag = 0; 21 | while exitflag~= 1 22 | x0 = (lb+ub)/2; 23 | [x_opti, ~, exitflag, ~]= simulannealbnd(fun,x0,lb,ub,options); 24 | ub = ub/1.1; 25 | end 26 | end 27 | end 28 | 29 | -------------------------------------------------------------------------------- /src/response_functions/Read_me_responsefunctions.txt: -------------------------------------------------------------------------------- 1 | The folder contains test functions and response functions. 2 | -------------------------------------------------------------------------------- /src/response_functions/Test1.m: -------------------------------------------------------------------------------- 1 | function [ y, lb, ub ,x, M ] = Test1() 2 | 3 | 4 | n = 2; 5 | lb = 0*ones(n,1); % lower bound 6 | ub = 2*ones(n,1); 7 | 8 | 9 | % Initial samples 10 | x = scaled_TPLHD(5,lb,ub); 11 | 12 | M = @(xx) test1_fun(xx); 13 | 14 | y = zeros(size(x,1),1); 15 | for i=1:size(x,1) 16 | y(i,1) = M(x(i,:)); 17 | end 18 | 19 | 20 | 21 | end 22 | 23 | 24 | function [y] = test1_fun(xx) 25 | x1 = xx(1); 26 | x2 = xx(2); 27 | 28 | 29 | 30 | 31 | if x1 < 0.5 32 | fact2 = -(x1^1+(x2-1)^2); 33 | else 34 | fact2 = -3*(x1^2+(x2-1)^2)-0.1; 35 | end 36 | y = fact2 + 0.55; 37 | 38 | end 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/response_functions/Test2.m: -------------------------------------------------------------------------------- 1 | function [ y, lb, ub ,x, M ] = Test2() 2 | 3 | 4 | n = 2; 5 | lb = 0*ones(n,1); % lower bound 6 | ub = 2*ones(n,1); 7 | 8 | 9 | % Initial samples 10 | x = scaled_TPLHD(5,lb,ub); 11 | 12 | M = @(xx) test2_fun(xx); 13 | 14 | y = zeros(size(x,1),1); 15 | for i=1:size(x,1) 16 | y(i,1) = M(x(i,:)); 17 | end 18 | 19 | 20 | 21 | end 22 | 23 | function [y] = test2_fun(xx) 24 | x1 = xx(1); 25 | x2 = xx(2); 26 | 27 | fact1 = (sin(x1^2-x2^2))^2 - 0.5; 28 | fact2 = (1 + 0.001*(x1^2+x2^2))^2; 29 | 30 | y = (fact1/fact2) - 0.25; 31 | 32 | end 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/response_functions/Test3.m: -------------------------------------------------------------------------------- 1 | function [ y, lb, ub ,x, M ] = Test3() 2 | 3 | 4 | n = 2; 5 | lb = [1; 0]; %lower bound 6 | ub = [2;1.95]; %upper bound 7 | % Initial samples 8 | x = scaled_TPLHD(20,lb,ub); 9 | 10 | M = @(xx) test3_fun(xx); 11 | 12 | y = zeros(size(x,1),1); 13 | for i=1:size(x,1) 14 | y(i,1) = M(x(i,:)); 15 | end 16 | 17 | 18 | 19 | end 20 | 21 | function [y] = test3_fun(xx) 22 | %% Modified DropWave function 23 | x1 = xx(1); 24 | x2 = xx(2); 25 | 26 | 27 | if x2 > x1 28 | y = 1- abs(x1 * x2) ; 29 | else 30 | fact1 = 1+ cos(12*sqrt(x1^2 + x2^2)); 31 | fact2 = 0.5*(x1^2 + x2^2)+2; 32 | 33 | y = -(fact1/fact2) + 0.05; 34 | end 35 | 36 | 37 | end 38 | --------------------------------------------------------------------------------