├── 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 |
22 |
23 |
24 |
25 |
26 | ---
27 |
28 | ### Example 1
29 | The following Gifs show an exemplary sampling process for example 1.
30 |
31 |
32 |
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 |
40 |
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 |
--------------------------------------------------------------------------------