From 1c3fa6bc0d7200dd96c3d29819c4be60c6c97bb1 Mon Sep 17 00:00:00 2001 From: Lazloo Date: Mon, 9 Jan 2017 14:20:39 +0100 Subject: [PATCH] 20170109 Major Changes: - Inqeuality Constraint w.r.t. to objectives can now be applied for expected improvement - Modification in plotParetoFront and predictParetoFront regading the 2D case - Debugging of AnalyzeMixture Class - Heterodedastic noise can now be estimated (generateNoiseModel) - Major improvements in TaylorKriging (Kriging with non-linear mechanistic models) - Speedup in calculation of 2D expected hypervolume improvement Minor Changes: - Small changes w.r.t. to the tutorial - New color scheme avaiable: FZJ - use now surf instead of surf for 3D plots - the class BaysianOptimization was renamed to BaysianOptimizationClass Signed-off-by: Lazloo --- .../tutorialCreatingObject.html | 39 +- .../html/tutorialCreatingObject.html | 323 +++++ .../html/tutorialCreatingObject.png | Bin 0 -> 5570 bytes .../html/tutorialCreatingObject_01.png | Bin 0 -> 30363 bytes .../html/tutorialCreatingObject_02.png | Bin 0 -> 28013 bytes .../html/tutorialCreatingObject_03.png | Bin 0 -> 26985 bytes .../html/tutorialCreatingObject_04.png | Bin 0 -> 13033 bytes .../html/tutorialCreatingObject_05.png | Bin 0 -> 13259 bytes .../html/tutorialCreatingObject_06.png | Bin 0 -> 12376 bytes ...lCreatingObject_eq01953356565641195011.png | Bin 0 -> 11746 bytes ...lCreatingObject_eq02739421979046219838.png | Bin 0 -> 8830 bytes ...lCreatingObject_eq03670739675111899559.png | Bin 0 -> 10378 bytes ...lCreatingObject_eq06559173809755883972.png | Bin 0 -> 4178 bytes ...lCreatingObject_eq06622766184584322475.png | Bin 0 -> 13354 bytes ...lCreatingObject_eq07994915521862946370.png | Bin 0 -> 13699 bytes ...lCreatingObject_eq09582885264525567196.png | Bin 0 -> 11978 bytes ...lCreatingObject_eq14322275300694116907.png | Bin 0 -> 10866 bytes ...lCreatingObject_eq15217372810807509549.png | Bin 0 -> 7784 bytes .../ScriptsForDocu/tutorialCreatingObject.m | 6 +- dependencies/@AnalyzeKriging/AnalyzeKriging.m | 46 +- dependencies/@AnalyzeKriging/ColormapFZJ.txt | 1000 +++++++++++++++ .../@AnalyzeKriging/calcExpectedImprovement.m | 16 + .../calcExpectedImprovementFromPredictions.m | 66 - .../calcExpectedImprovement_MO.m | 22 +- .../calcMutualInterpolation_23D.m | 2 + .../@AnalyzeKriging/checkInputInterpolation.m | 2 + .../@AnalyzeKriging/defineBoundOfInputVar.m | 6 +- dependencies/@AnalyzeKriging/errorCheck.p | Bin 0 -> 1420 bytes .../@AnalyzeKriging/plotInterpolation_23D.m | 8 +- .../@AnalyzeKriging/plotParetoFront.m | 33 +- .../@AnalyzeKriging/predictParetoCurve.m | 121 +- .../setLBUBInputVarInterpolation.m | 17 +- dependencies/@AnalyzeMixture/AnalyzeMixture.m | 32 +- .../@AnalyzeMixture/calcInterpolation.m | 7 +- .../@AnalyzeMixture/calcInterpolation_nD.m | 10 +- .../@AnalyzeMixture/plotInterpolation_nD.m | 30 +- .../BayesianOptimizationClass.m} | 32 +- .../MCMCDistributionFctDRAM.m | 0 .../MCMCDistributionFctSlice.m | 0 .../calcNewSamplesViaMCMC.m | 0 .../modExpImprByOutputConstr.m | 55 + .../@KrigingSuperClass/KrigingSuperClass.m | 117 +- .../MarginalLikelihoodCovarPara.m | 7 +- .../calcCovarMatrixOfPredictions.m | 5 +- .../calcCovariogramMatrix.m | 47 +- .../@KrigingSuperClass/calcCrossOverQuality.m | 199 +-- .../doConditionalSimulation_ResAlgInEq.m | 180 +-- .../@KrigingSuperClass/estimateVariance.m | 13 +- .../@KrigingSuperClass/generateNoiseModel.m | 118 ++ .../generateRegressionGPModel.m | 2 +- dependencies/@KrigingSuperClass/prediction.m | 47 +- dependencies/@TaylorKriging/TaylorKriging.m | 10 +- .../calcKrigingParaEstimationObjFctVector.m | 21 +- .../estimateBasisFctParametersFsolve.m | 68 + .../GridTools/createNDGRID.m | 29 +- .../auxiliaryFunctions/HV_mod/calcEHIV_2D.m | 135 +- .../HV_mod/calcEHIV_2D_2016.m | 211 ++++ .../HV_mod/calcEHIV_3D_2016.m | 89 ++ .../auxiliaryFunctions/HV_mod/gaussEI.m | 4 + .../auxiliaryFunctions/HV_mod/gausscdf.m | 3 +- .../auxiliaryFunctions/HV_mod/gausspdf.m | 3 +- .../MatrixInversion/invupdateapp.m | 2 +- .../externalTools/mcmcstat/boxplotMCMCStat.m | 2 +- .../mexFiles/VChooseK/CompilingCommand.txt | 1 + .../mexFiles/VChooseK/VChooseK.c | 1114 +++++++++++++++++ .../mexFiles/VChooseK/VChooseK.m | 81 ++ .../mexFiles/VChooseK/VChooseK.mexa64 | Bin 0 -> 23336 bytes .../mexFiles/VChooseK/VChooseK.mexw64 | Bin 0 -> 17920 bytes .../mexFiles/VChooseK/VChooseKUncommented.c | 899 +++++++++++++ .../mexFiles/VChooseK/license.txt | 24 + .../mexFiles/VChooseK/test.m | 19 + 71 files changed, 4831 insertions(+), 492 deletions(-) create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject.html create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_01.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_02.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_03.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_04.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_05.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_06.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq01953356565641195011.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq02739421979046219838.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq03670739675111899559.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq06559173809755883972.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq06622766184584322475.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq07994915521862946370.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq09582885264525567196.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq14322275300694116907.png create mode 100644 Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq15217372810807509549.png create mode 100644 dependencies/@AnalyzeKriging/ColormapFZJ.txt delete mode 100644 dependencies/@AnalyzeKriging/calcExpectedImprovementFromPredictions.m create mode 100644 dependencies/@AnalyzeKriging/errorCheck.p rename dependencies/{@BayesianOptimization/BayesianOptimization.m => @BayesianOptimizationClass/BayesianOptimizationClass.m} (75%) rename dependencies/{@BayesianOptimization => @BayesianOptimizationClass}/MCMCDistributionFctDRAM.m (100%) rename dependencies/{@BayesianOptimization => @BayesianOptimizationClass}/MCMCDistributionFctSlice.m (100%) rename dependencies/{@BayesianOptimization => @BayesianOptimizationClass}/calcNewSamplesViaMCMC.m (100%) create mode 100644 dependencies/@BayesianOptimizationClass/modExpImprByOutputConstr.m create mode 100644 dependencies/@KrigingSuperClass/generateNoiseModel.m create mode 100644 dependencies/@TaylorKriging/estimateBasisFctParametersFsolve.m create mode 100644 dependencies/auxiliaryFunctions/HV_mod/calcEHIV_2D_2016.m create mode 100644 dependencies/auxiliaryFunctions/HV_mod/calcEHIV_3D_2016.m create mode 100644 dependencies/auxiliaryFunctions/HV_mod/gaussEI.m create mode 100644 dependencies/auxiliaryFunctions/mexFiles/VChooseK/CompilingCommand.txt create mode 100644 dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.c create mode 100644 dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.m create mode 100644 dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.mexa64 create mode 100644 dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.mexw64 create mode 100644 dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseKUncommented.c create mode 100644 dependencies/auxiliaryFunctions/mexFiles/VChooseK/license.txt create mode 100644 dependencies/auxiliaryFunctions/mexFiles/VChooseK/test.m diff --git a/Tutorial/ActualTutorial/CreatingObject/tutorialCreatingObject.html b/Tutorial/ActualTutorial/CreatingObject/tutorialCreatingObject.html index 753a348..7746fed 100644 --- a/Tutorial/ActualTutorial/CreatingObject/tutorialCreatingObject.html +++ b/Tutorial/ActualTutorial/CreatingObject/tutorialCreatingObject.html @@ -6,7 +6,7 @@ tutorialCreatingObject

Contents

Tutorial: How to create a Kriging Object

function [KrigingObj] = tutorialCreatingObject(varargin)
-

Initialisierung

% Decide if estimated Kriging model shall be visualized
+  

Contents

Tutorial: How to create a Kriging Object

function [KrigingObj] = tutorialCreatingObject(varargin)
+

Initialisierung

% Decide if estimated Kriging model shall be visualized
 if length(varargin)>=1&&~(varargin{1})
     visualizeResult = false;
 else
@@ -78,10 +78,10 @@
 nLevelsEachDimension = 6;
 input = createNDGRID(zeros(3,1),ones(3,1)*10,nLevelsEachDimension);
 output = tutorialFunction(input);
-

Test Function

The test function as follows:

$$f_{\rm{Test}} = \frac{10x_{1}}{5 + x_{1}}\sin\left( x_{2} \right) +
x_{3}$$

That is, the output is related to the first input variable by a Michaelis Menten curve(steep increase for small values followed by a plateau). The second input variable leads to oscillation and the third input variable leads to an linear monotonically increase. The effect of the first and second input are coupled with each other.

For a better visualization, pair-wise combination of input variables are plotted against the output. Remaining input variable was hold constant at the value of 2.

if visualizeResult
+

Test Function

The test function as follows:

$$f_{\rm{Test}} = \frac{10x_{1}}{5 + x_{1}}\sin\left( x_{2} \right) +
x_{3}$$

That is, the output is related to the first input variable by a Michaelis Menten curve(steep increase for small values followed by a plateau). The second input variable leads to oscillation and the third input variable leads to an linear monotonically increase. The effect of the first and second input are coupled with each other.

For a better visualization, pair-wise combination of input variables are plotted against the output. Remaining input variable was hold constant at the value of 2.

if visualizeResult
     visualizeTestFunction();
 end
-

Create Analysis Object

AnalyzeKriging inherites KrigingSuperClass and manages Kriging objects. AnalyzeKriging also contains all analysis tools.

KrigingObj = AnalyzeKriging;
+

Create Analysis Object

AnalyzeKriging inherites KrigingSuperClass and manages Kriging objects. AnalyzeKriging also contains all analysis tools.

KrigingObj = AnalyzeKriging;
 
 % Remember the Currently used object
 indexKrigingObj = 1;
@@ -89,9 +89,13 @@
 

Load input data and name input variables

  • Structure of the input variable has to be nDataPointsXnInputVariables
  • First input argument for "setInputVarNames" is the index of the Kriging object of current use
  • Second argument is string-array containing the names of the input variables
KrigingObj.KrigingObjects{indexKrigingObj}.setInputData(input)
 KrigingObj.setInputVarNames(indexKrigingObj,{'Input 1','Input 2','Input 3'})
 

Load output data. The output data container has to be a vector of the length nDataPoints

KrigingObj.KrigingObjects{indexKrigingObj}.setOutputData(output)
-

Create Kriging Object and estimate covariogram parameters

The backbone of Kriging is the estimation of the covariogram. The covariogram helps to estimate the covariance between the data points. In general, the covariogram considers only the distance between two points. The closer data points are the higher is their covariance. Kriging prediction is done by a linear combination of the provided data. Here, measurment data at points with high covariance values w.r.t. the point of interest are higher weighted.

Choose covariogram model:

$$1: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma^2\exp\left( - \left( \frac{0.5r}{2\theta^2} \right)\right), r=\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)^{T}\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)$

$$2: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{{Nugget}}^2 + \sigma^2\exp\left( - \left( \frac{0.5r}{2\theta^2} \right)\right), r=\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)^{T}\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)$

$$3:
\mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) =
\sigma_{{Nugget}}^2 + \sigma^2\exp\left( - \left( \frac{0.5r}{2\theta^2}
\right)\right),r = \sqrt{\sum_{l = 1}^{k}\frac{\left( x_{i,l} - x_{j,l} \right)^{p_{l}}}{\theta_{l}^{2}}}$$

$$4: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{{Nugget}}^2 + \sigma^2\exp\left( - \left( \frac{0.5r}{2\theta^2} \right)\right),r = \sqrt{\sum_{l = 1}^{k}\frac{\left( x_{i,l} - x_{j,l} \right)^{2}}{\theta_{l}^{2}}}$

$$5: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{{Nugget}}^{2} + \sigma^{2}\left( 1 + \frac{\left( \sqrt{3}r \right)}{\theta^{2}} \right)\exp\left( - \frac{\left( \sqrt{3}r \right)}{\theta^{2}} \right),r = \sqrt{\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)^{T}\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)}$

$$6: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{Nugget}^{2} + \sigma^{2}\left( 1 + \sqrt{3}r \right)\exp\left( - \sqrt{3}r \right),r = \sqrt{\sum_{l = 1}^{k}\frac{\left( x_{i,l} - x_{j,l} \right)^{2}}{\theta_{l}^{2}}}$

$$7: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{Nugget}^{2} + \sigma^{2}\left( 1 + \frac{\sqrt{5}r}{\theta^{2}} + \frac{5r^{2}}{3\theta^{2}} \right)\exp\left( - \frac{\sqrt{5}r}{\theta^{2}} \right), r = \ \sqrt{\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)^{T}\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)}$

$$8: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{Nugget}^{2} + \sigma^{2}\left( 1 + \sqrt{3}r + \frac{5}{3}r^{2} \right)\exp\left( - \sqrt{5}r \right), r = \sqrt{\sum_{l = 1}^{k}\frac{\left( x_{i,l} - x_{j,l} \right)^{2}}{\theta_{l}^{2}}}$

KrigingObj.KrigingObjects{indexKrigingObj}.setCovariogramModelChoice(5);
+

Create Kriging Object and estimate covariogram parameters

The backbone of Kriging is the estimation of the covariogram. The covariogram helps to estimate the covariance between the data points. In general, the covariogram considers only the distance between two points. The closer data points are the higher is their covariance. Kriging prediction is done by a linear combination of the provided data. Here, measurment data at points with high covariance values w.r.t. the point of interest are higher weighted.

Choose covariogram model:

$$1: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma^2\exp\left( - \left( \frac{0.5r}{2\theta^2} \right)\right), r=\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)^{T}\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)$

$$2: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{{Nugget}}^2 + \sigma^2\exp\left( - \left( \frac{0.5r}{2\theta^2} \right)\right), r=\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)^{T}\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)$

$$3:
\mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) =
\sigma_{{Nugget}}^2 + \sigma^2\exp\left( - \left( \frac{0.5r}{2\theta^2}
\right)\right),r = \sqrt{\sum_{l = 1}^{k}\frac{\left( x_{i,l} - x_{j,l} \right)^{p_{l}}}{\theta_{l}^{2}}}$$

$$4: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{{Nugget}}^2 + \sigma^2\exp\left( - \left( \frac{0.5r}{2\theta^2} \right)\right),r = \sqrt{\sum_{l = 1}^{k}\frac{\left( x_{i,l} - x_{j,l} \right)^{2}}{\theta_{l}^{2}}}$

$$5: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{{Nugget}}^{2} + \sigma^{2}\left( 1 + \frac{\left( \sqrt{3}r \right)}{\theta^{2}} \right)\exp\left( - \frac{\left( \sqrt{3}r \right)}{\theta^{2}} \right),r = \sqrt{\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)^{T}\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)}$

$$6: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{Nugget}^{2} + \sigma^{2}\left( 1 + \sqrt{3}r \right)\exp\left( - \sqrt{3}r \right),r = \sqrt{\sum_{l = 1}^{k}\frac{\left( x_{i,l} - x_{j,l} \right)^{2}}{\theta_{l}^{2}}}$

$$7: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{Nugget}^{2} + \sigma^{2}\left( 1 + \frac{\sqrt{5}r}{\theta^{2}} + \frac{5r^{2}}{3\theta^{2}} \right)\exp\left( - \frac{\sqrt{5}r}{\theta^{2}} \right), r = \ \sqrt{\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)^{T}\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)}$

$$8: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{Nugget}^{2} + \sigma^{2}\left( 1 + \sqrt{3}r + \frac{5}{3}r^{2} \right)\exp\left( - \sqrt{5}r \right), r = \sqrt{\sum_{l = 1}^{k}\frac{\left( x_{i,l} - x_{j,l} \right)^{2}}{\theta_{l}^{2}}}$

KrigingObj.KrigingObjects{indexKrigingObj}.setCovariogramModelChoice(5);
 

Choose basis function. Here we use a constant as basis function. The value of the constant is automatically estimated by Kriging

KrigingObj.KrigingObjects{indexKrigingObj}.setBasisFct('polynomial',0)
-

Matlab's statistic toolbox (2015b and newer) is able to efficiently estimate the covariogram parameters. This is in general very robust and should be used if possible

KrigingObj.KrigingObjects{indexKrigingObj}.setUseMatlabRegressionGP(true);
+

Matlab's statistic toolbox (2015b and newer) is able to efficiently estimate the covariogram parameters. This is in general very robust and should be used if possible

try
+    KrigingObj.KrigingObjects{indexKrigingObj}.setUseMatlabRegressionGP(true);
+catch ex
+    warning(ex.message)
+end
 

Alternatively, one of the integrated solver can be used. Here, an open source genetic algorithm is applied. Further possible solver choices are described in the documentation of makePrework . Upperbounds of covariogram parameters should be adjusted for efficiency reasons.

if ~KrigingObj.KrigingObjects{indexKrigingObj}.getUseMatlabRegressionGP()
     KrigingObj.setShowDetails(true)
     KrigingObj.KrigingObjects{indexKrigingObj}.setUBCovariogramModelParameters([100,100,1])
@@ -99,10 +103,10 @@
     KrigingObj.KrigingObjects{indexKrigingObj}.setUseSolver(2)
 end
 

Perform estimation

KrigingObj.KrigingObjects{1}.makePrework
-

Check Results

The following plots show the resulting Kriging prediction surfaces. Again, the input variables are pair-wise plotted against the output setting the value remaining input variable fix to 2. Red dots indicate the provided data.

if visualizeResult
+

Check Results

The following plots show the resulting Kriging prediction surfaces. Again, the input variables are pair-wise plotted against the output setting the value remaining input variable fix to 2. Red dots indicate the provided data.

if visualizeResult
     combinations = [1,2,3;1,3,2;2,3,1];
     KrigingObj.setShowBounds(false) % Show only prediction not the confidence tube
-    KrigingObj.setShowData(true) % Show provied data points
+    KrigingObj.setShowData(true) % Show provided data points
     for iComb = 1:3
         KrigingObj.calcInterpolation_3D(indexKrigingObj,...
                    combinations(iComb,1:2),combinations(iComb,3),2)
@@ -117,7 +121,14 @@
     KrigingObj.setShowBounds(true)
 end
 
end
-
tutorialCreatingObject

Contents

Tutorial: How to create a Kriging Object

function [KrigingObj] = tutorialCreatingObject(varargin)
+

Initialisierung

% Decide if estimated Kriging model shall be visualized
+if length(varargin)>=1&&~(varargin{1})
+    visualizeResult = false;
+else
+    visualizeResult = true;
+end
+
+% Generate Data on 6X6 grid in the range [0,10]
+nLevelsEachDimension = 6;
+input = createNDGRID(zeros(3,1),ones(3,1)*10,nLevelsEachDimension);
+output = tutorialFunction(input);
+

Test Function

The test function as follows:

$$f_{\rm{Test}} = \frac{10x_{1}}{5 + x_{1}}\sin\left( x_{2} \right) +
x_{3}$$

That is, the output is related to the first input variable by a Michaelis Menten curve(steep increase for small values followed by a plateau). The second input variable leads to oscillation and the third input variable leads to an linear monotonically increase. The effect of the first and second input are coupled with each other.

For a better visualization, pair-wise combination of input variables are plotted against the output. Remaining input variable was hold constant at the value of 2.

if visualizeResult
+    visualizeTestFunction();
+end
+

Create Analysis Object

AnalyzeKriging inherites KrigingSuperClass and manages Kriging objects. AnalyzeKriging also contains all analysis tools.

KrigingObj = AnalyzeKriging;
+
+% Remember the Currently used object
+indexKrigingObj = 1;
+

Initialize Kriging object:

  • The first input indicates the type of Kriging. Use 1 for Ordinary Kriging and 2 for Universal Kriging. Ordinary Kriging is a special type of Universal Kriging as it sets the basis function automatically to a constant. With Universal Kriging, you can use any function as basic function.
  • Second input is a string describing the output variable
KrigingObj.addKrigingObject(2,'Test Output')
+

Load input data and name input variables

  • Structure of the input variable has to be nDataPointsXnInputVariables
  • First input argument for "setInputVarNames" is the index of the Kriging object of current use
  • Second argument is string-array containing the names of the input variables
KrigingObj.KrigingObjects{indexKrigingObj}.setInputData(input)
+KrigingObj.setInputVarNames(indexKrigingObj,{'Input 1','Input 2','Input 3'})
+

Load output data. The output data container has to be a vector of the length nDataPoints

KrigingObj.KrigingObjects{indexKrigingObj}.setOutputData(output)
+

Create Kriging Object and estimate covariogram parameters

The backbone of Kriging is the estimation of the covariogram. The covariogram helps to estimate the covariance between the data points. In general, the covariogram considers only the distance between two points. The closer data points are the higher is their covariance. Kriging prediction is done by a linear combination of the provided data. Here, measurment data at points with high covariance values w.r.t. the point of interest are higher weighted.

Choose covariogram model:

$$1: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma^2\exp\left( - \left( \frac{0.5r}{2\theta^2} \right)\right), r=\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)^{T}\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)$

$$2: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{{Nugget}}^2 + \sigma^2\exp\left( - \left( \frac{0.5r}{2\theta^2} \right)\right), r=\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)^{T}\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)$

$$3:
\mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) =
\sigma_{{Nugget}}^2 + \sigma^2\exp\left( - \left( \frac{0.5r}{2\theta^2}
\right)\right),r = \sqrt{\sum_{l = 1}^{k}\frac{\left( x_{i,l} - x_{j,l} \right)^{p_{l}}}{\theta_{l}^{2}}}$$

$$4: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{{Nugget}}^2 + \sigma^2\exp\left( - \left( \frac{0.5r}{2\theta^2} \right)\right),r = \sqrt{\sum_{l = 1}^{k}\frac{\left( x_{i,l} - x_{j,l} \right)^{2}}{\theta_{l}^{2}}}$

$$5: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{{Nugget}}^{2} + \sigma^{2}\left( 1 + \frac{\left( \sqrt{3}r \right)}{\theta^{2}} \right)\exp\left( - \frac{\left( \sqrt{3}r \right)}{\theta^{2}} \right),r = \sqrt{\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)^{T}\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)}$

$$6: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{Nugget}^{2} + \sigma^{2}\left( 1 + \sqrt{3}r \right)\exp\left( - \sqrt{3}r \right),r = \sqrt{\sum_{l = 1}^{k}\frac{\left( x_{i,l} - x_{j,l} \right)^{2}}{\theta_{l}^{2}}}$

$$7: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{Nugget}^{2} + \sigma^{2}\left( 1 + \frac{\sqrt{5}r}{\theta^{2}} + \frac{5r^{2}}{3\theta^{2}} \right)\exp\left( - \frac{\sqrt{5}r}{\theta^{2}} \right), r = \ \sqrt{\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)^{T}\left( \mathbf{x}_{i} - \mathbf{x}_{j} \right)}$

$$8: \mathrm{cov}\left( \mathbf{x}_{i},\mathbf{x}_{j} \right) = \sigma_{Nugget}^{2} + \sigma^{2}\left( 1 + \sqrt{3}r + \frac{5}{3}r^{2} \right)\exp\left( - \sqrt{5}r \right), r = \sqrt{\sum_{l = 1}^{k}\frac{\left( x_{i,l} - x_{j,l} \right)^{2}}{\theta_{l}^{2}}}$

KrigingObj.KrigingObjects{indexKrigingObj}.setCovariogramModelChoice(5);
+

Choose basis function. Here we use a constant as basis function. The value of the constant is automatically estimated by Kriging

KrigingObj.KrigingObjects{indexKrigingObj}.setBasisFct('polynomial',0)
+

Matlab's statistic toolbox (2015b and newer) is able to efficiently estimate the covariogram parameters. This is in general very robust and should be used if possible

try
+    KrigingObj.KrigingObjects{indexKrigingObj}.setUseMatlabRegressionGP(true);
+catch ex
+    warning(ex.message)
+end
+

Alternatively, one of the integrated solver can be used. Here, an open source genetic algorithm is applied. Further possible solver choices are described in the documentation of makePrework . Upperbounds of covariogram parameters should be adjusted for efficiency reasons.

if ~KrigingObj.KrigingObjects{indexKrigingObj}.getUseMatlabRegressionGP()
+    KrigingObj.setShowDetails(true)
+    KrigingObj.KrigingObjects{indexKrigingObj}.setUBCovariogramModelParameters([100,100,1])
+    KrigingObj.KrigingObjects{indexKrigingObj}.setnIterationsSolver(1e2)
+    KrigingObj.KrigingObjects{indexKrigingObj}.setUseSolver(2)
+end
+

Perform estimation

KrigingObj.KrigingObjects{1}.makePrework
+

Check Results

The following plots show the resulting Kriging prediction surfaces. Again, the input variables are pair-wise plotted against the output setting the value remaining input variable fix to 2. Red dots indicate the provided data.

if visualizeResult
+    combinations = [1,2,3;1,3,2;2,3,1];
+    KrigingObj.setShowBounds(false) % Show only prediction not the confidence tube
+    KrigingObj.setShowData(true) % Show provided data points
+    for iComb = 1:3
+        KrigingObj.calcInterpolation_3D(indexKrigingObj,...
+                   combinations(iComb,1:2),combinations(iComb,3),2)
+        KrigingObj.plotInterpolation_3D(indexKrigingObj)
+        campos([-40.0176  -52.6198   92.8089])
+        grid on
+
+        % Set format appropriate for documentation
+        set(gcf,'Position', [100, 100, 330, 330/4*3]);
+        set(gca,'FontSize',10)
+    end
+    KrigingObj.setShowBounds(true)
+end
+
end
+
+ans = 
+
+  AnalyzeKriging with properties:
+
+    KrigingObjects: {[1×1 UniversalKriging]}
+
+
\ No newline at end of file diff --git a/Tutorial/ScriptsForDocu/html/tutorialCreatingObject.png b/Tutorial/ScriptsForDocu/html/tutorialCreatingObject.png new file mode 100644 index 0000000000000000000000000000000000000000..98179e22a87e2b1709018263970880ee7c8854f9 GIT binary patch literal 5570 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 literal 0 HcmV?d00001 diff --git a/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_01.png b/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_01.png new file mode 100644 index 0000000000000000000000000000000000000000..fe94fa64d08ccdcf1b5ce23863f8d8a719709931 GIT binary patch literal 30363 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 literal 0 HcmV?d00001 diff --git a/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_05.png b/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_05.png new file mode 100644 index 0000000000000000000000000000000000000000..9111181e453029c69f49ee99bb2edee6abae1da4 GIT binary patch literal 13259 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 N%JS-R)o(36{V&1z>Tm!6 literal 0 HcmV?d00001 diff --git a/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_06.png b/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_06.png new file mode 100644 index 0000000000000000000000000000000000000000..322205c73dcd0b21d3da43bb39f734bfc74e75e9 GIT binary patch literal 12376 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 qt^ODqOBRFXo?_Pu9X53;wNSBygd literal 0 HcmV?d00001 diff --git a/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq01953356565641195011.png b/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq01953356565641195011.png new file mode 100644 index 0000000000000000000000000000000000000000..238a4692f3dca458ad4ab97330e5a9f51b69821c GIT binary patch literal 11746 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%0A16kHfdY=)$qQxK8{$Kl0sbmC zj5hbcBO$@M_b!NtvA*5^_WBeSu;b*9^~Okid_2_7RBWRD<4@JAk4c2lG1Cdl!ypqu z$uod+5ikLSxxZA!^{Xh)#}Q| zpaUT`b$4~GsjW4HR53PI6;8DEtb*6J1Dr!cLp#gnT1pnC3kn~yEGjG{dZ&||17R@- zhYDwBf5?G9ynLtVU~7Wp2r7amMzAHyb`XISXnHs;)el6~-!J60LBKuo`?sy5BmR%X z1k)8qt8q3SEX3vE!9m-@6=7GT-7#Nw1N~NpYVO_QMzf09_c0 zaBzHvLq4Fr9i}QxbJicg3=3jeCYAK@8GT5xpl6-j-5)%>p`hxc!1)St3kFa%&MR`L z+rNO|X~cZb_L}!u+jN@C%YOj4Z|QbcBBc}h4pHG*!67uKPgzpA=2ljT!#n?>TvTOL zgc32J2ywe^{(N{9!;noa;#CO%1j8Un^9i*#w8}6PeESv#4C);NphyD~pCbkHfFfc_ z)PwobVh5s22eG84wl++Ef6dPRmx$wAU0@7H^;Y700yfIKAxV*4+Aum9eg z1WfRefRS~M3ouT8(y)bto)ZjFBtRp0A*?){MuYN#f`?R;?`zixrC`bo3E!{r@txh9 zt0lD2kPbCagR?JVN3p|5byx6H3*3i%Zjff_SyVwiV0HzisYyZP|_cyEu zL4!jIDWTzuRt}O)r-4Q9&O8b1y8=AX)mXK;nbH*9Xzk zHz*1QI_QCd0@VI_vx&Ey$fj_VC%33bM_oN6 z8M{9mWEwTv8a6kc$b3J)NA$GO3)@|}u&?NMq|7SI2k3C6D6hKZUF11-B> zV?;{-IgVgyJ_TSzC{cjt_YA>(-0qjRe{73?e$s&h(ZUS|4u*zv7{;8Z?V-2mq{ZVl Vtom$RaA+GrQC3x^T*@T){{Zry9l!tp literal 0 HcmV?d00001 diff --git a/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq02739421979046219838.png b/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq02739421979046219838.png new file mode 100644 index 0000000000000000000000000000000000000000..7360a8aef2e01e8704f4d0ceca25c73bf06af023 GIT binary patch literal 8830 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 literal 0 HcmV?d00001 diff --git a/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq06559173809755883972.png b/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq06559173809755883972.png new file mode 100644 index 0000000000000000000000000000000000000000..77889dad3ab409d589626ea395714e1e7b090576 GIT binary patch literal 4178 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 literal 0 HcmV?d00001 diff --git a/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq07994915521862946370.png b/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq07994915521862946370.png new file mode 100644 index 0000000000000000000000000000000000000000..f390020b2dec115abf658ace27932ce9d32e52fc GIT binary patch literal 13699 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 literal 0 HcmV?d00001 diff --git a/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq14322275300694116907.png b/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq14322275300694116907.png new file mode 100644 index 0000000000000000000000000000000000000000..86fcde90cd38c39009e989165d7554efe1ee289c GIT binary patch literal 10866 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 KE?0~+3;7>r1QrVb literal 0 HcmV?d00001 diff --git a/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq15217372810807509549.png b/Tutorial/ScriptsForDocu/html/tutorialCreatingObject_eq15217372810807509549.png new file mode 100644 index 0000000000000000000000000000000000000000..8387ddde2f6d12183160dfaeae7fc5d2129ff016 GIT binary patch literal 7784 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 DjJC0E literal 0 HcmV?d00001 diff --git a/Tutorial/ScriptsForDocu/tutorialCreatingObject.m b/Tutorial/ScriptsForDocu/tutorialCreatingObject.m index b3e46be..6bdd34e 100644 --- a/Tutorial/ScriptsForDocu/tutorialCreatingObject.m +++ b/Tutorial/ScriptsForDocu/tutorialCreatingObject.m @@ -138,7 +138,11 @@ % Matlab's statistic toolbox (2015b and newer) is able to efficiently % estimate the covariogram parameters. This is in general very robust and % should be used if possible -KrigingObj.KrigingObjects{indexKrigingObj}.setUseMatlabRegressionGP(true); +try + KrigingObj.KrigingObjects{indexKrigingObj}.setUseMatlabRegressionGP(true); +catch ex + warning(ex.message) +end %%% % Alternatively, one of the integrated solver can be used. Here, an open diff --git a/dependencies/@AnalyzeKriging/AnalyzeKriging.m b/dependencies/@AnalyzeKriging/AnalyzeKriging.m index d234974..b5e8a7c 100644 --- a/dependencies/@AnalyzeKriging/AnalyzeKriging.m +++ b/dependencies/@AnalyzeKriging/AnalyzeKriging.m @@ -3,7 +3,7 @@ % See the license note at the end of the file. %% Private Members - properties(GetAccess='public',SetAccess='private') + properties(GetAccess='public',SetAccess='public') KrigingObjects = cell(0); end %% Protected Members @@ -28,6 +28,7 @@ SuppressFigure=0; % Decide how many point of each input variable shall tested Accuracy = 100; + AccuracyOutput = 100; % Decide if only the basis function should be plotted ShowBasisFct = 0; % Plot Lower and Upper Bounds (1) or not (0) @@ -83,6 +84,9 @@ UseDataPointsAsComparisonPoint = false; % Signifcance level (error Erro Type I) used for z-test SignificanceLevel = 0.05; + % Used for the contour plot in order to defined a minimum value + % which is plotted. This prevents that the entrie plot is colored + ThresholdQuantile = -inf; %% Interpolation Options % Subplot contains nPlots X nPlots figures nPlots =5; @@ -181,6 +185,8 @@ % Matrix (nLevelX3) containing the color map used for plots like 3D % interpolation ColormapToolbox = []; + %% Prediction of Pareto Front + RepeatDesign = true; end methods %% Constructor @@ -357,6 +363,10 @@ Accuracy = obj.Accuracy; end % ---------------------------------------------------------------- + function [AccuracyOutput]=getAccuracyOutput(obj) + AccuracyOutput = obj.AccuracyOutput; + end + % ---------------------------------------------------------------- function [ShowBounds]=getShowBounds(obj) ShowBounds = obj.ShowBounds; end @@ -657,11 +667,29 @@ function [PlottingRange]=getPlottingRange(obj) PlottingRange = obj.PlottingRange; end + % ---------------------------------------------------------------- + function [RepeatDesign] = getRepeatDesign(obj) + RepeatDesign = obj.RepeatDesign; + end + % ---------------------------------------------------------------- + function [ThresholdQuantile] = getThresholdQuantile(obj) + ThresholdQuantile = obj.ThresholdQuantile; + end %% Set Functions function []=setAccuracy(obj,Accuracy) + if any(size(Accuracy)>1) + error('Accuracy has to be a scalar') + end obj.Accuracy = Accuracy; end % ---------------------------------------------------------------- + function []=setAccuracyOutput(obj,AccuracyOutput) + if any(size(AccuracyOutput)>1) + error('AccuracyOutput has to be a scalar') + end + obj.AccuracyOutput = AccuracyOutput; + end + % ---------------------------------------------------------------- function []=setShowBounds(obj,ShowBounds) if ~islogical(ShowBounds) error('ShowBounds has to be logical') @@ -958,14 +986,28 @@ if isempty(varargin)||isempty(varargin{1}) obj.ColormapToolbox = load('ColormapWinterInverse.txt'); return; + elseif strcmp(varargin{1},'FZJ') + obj.ColormapToolbox = load('ColormapFZJ.txt'); + return; end - if size(varargin{1},2)~=3 + if size(varargin{1},2)~=3&&~ischar(varargin{1}) error('ColormapToolbox must have three columns') end obj.ColormapToolbox = varargin{1}; end + % ---------------------------------------------------------------- + function [] = setRepeatDesign(obj,RepeatDesign) + if ~islogical(RepeatDesign) + error('RepeatDesign must be logical') + end + obj.RepeatDesign = RepeatDesign; + end + % ---------------------------------------------------------------- + function [] = setThresholdQuantile(obj,ThresholdQuantile) + obj.ThresholdQuantile = ThresholdQuantile; + end end diff --git a/dependencies/@AnalyzeKriging/ColormapFZJ.txt b/dependencies/@AnalyzeKriging/ColormapFZJ.txt new file mode 100644 index 0000000..12722d5 --- /dev/null +++ b/dependencies/@AnalyzeKriging/ColormapFZJ.txt @@ -0,0 +1,1000 @@ + 0.0000000e+00 5.4901961e-01 8.0392157e-01 + 0.0000000e+00 5.4864865e-01 8.0337200e-01 + 0.0000000e+00 5.4827769e-01 8.0282243e-01 + 0.0000000e+00 5.4790673e-01 8.0227286e-01 + 0.0000000e+00 5.4753577e-01 8.0172329e-01 + 0.0000000e+00 5.4716481e-01 8.0117372e-01 + 0.0000000e+00 5.4679385e-01 8.0062415e-01 + 0.0000000e+00 5.4642289e-01 8.0007458e-01 + 0.0000000e+00 5.4605193e-01 7.9952502e-01 + 0.0000000e+00 5.4568098e-01 7.9897545e-01 + 0.0000000e+00 5.4531002e-01 7.9842588e-01 + 0.0000000e+00 5.4493906e-01 7.9787631e-01 + 0.0000000e+00 5.4456810e-01 7.9732674e-01 + 0.0000000e+00 5.4419714e-01 7.9677717e-01 + 0.0000000e+00 5.4382618e-01 7.9622760e-01 + 0.0000000e+00 5.4345522e-01 7.9567803e-01 + 0.0000000e+00 5.4308426e-01 7.9512846e-01 + 0.0000000e+00 5.4271330e-01 7.9457889e-01 + 0.0000000e+00 5.4234234e-01 7.9402932e-01 + 0.0000000e+00 5.4197138e-01 7.9347975e-01 + 0.0000000e+00 5.4160042e-01 7.9293019e-01 + 0.0000000e+00 5.4122946e-01 7.9238062e-01 + 0.0000000e+00 5.4085851e-01 7.9183105e-01 + 0.0000000e+00 5.4048755e-01 7.9128148e-01 + 0.0000000e+00 5.4011659e-01 7.9073191e-01 + 0.0000000e+00 5.3974563e-01 7.9018234e-01 + 0.0000000e+00 5.3937467e-01 7.8963277e-01 + 0.0000000e+00 5.3900371e-01 7.8908320e-01 + 0.0000000e+00 5.3863275e-01 7.8853363e-01 + 0.0000000e+00 5.3826179e-01 7.8798406e-01 + 0.0000000e+00 5.3789083e-01 7.8743449e-01 + 0.0000000e+00 5.3751987e-01 7.8688492e-01 + 0.0000000e+00 5.3714891e-01 7.8633535e-01 + 0.0000000e+00 5.3677795e-01 7.8578579e-01 + 0.0000000e+00 5.3640700e-01 7.8523622e-01 + 0.0000000e+00 5.3603604e-01 7.8468665e-01 + 0.0000000e+00 5.3566508e-01 7.8413708e-01 + 0.0000000e+00 5.3529412e-01 7.8358751e-01 + 0.0000000e+00 5.3492316e-01 7.8303794e-01 + 0.0000000e+00 5.3455220e-01 7.8248837e-01 + 0.0000000e+00 5.3418124e-01 7.8193880e-01 + 0.0000000e+00 5.3381028e-01 7.8138923e-01 + 0.0000000e+00 5.3343932e-01 7.8083966e-01 + 0.0000000e+00 5.3306836e-01 7.8029009e-01 + 0.0000000e+00 5.3269740e-01 7.7974052e-01 + 0.0000000e+00 5.3232644e-01 7.7919096e-01 + 0.0000000e+00 5.3195548e-01 7.7864139e-01 + 0.0000000e+00 5.3158453e-01 7.7809182e-01 + 0.0000000e+00 5.3121357e-01 7.7754225e-01 + 0.0000000e+00 5.3084261e-01 7.7699268e-01 + 0.0000000e+00 5.3047165e-01 7.7644311e-01 + 0.0000000e+00 5.3010069e-01 7.7589354e-01 + 0.0000000e+00 5.2972973e-01 7.7534397e-01 + 0.0000000e+00 5.2935877e-01 7.7479440e-01 + 0.0000000e+00 5.2898781e-01 7.7424483e-01 + 0.0000000e+00 5.2861685e-01 7.7369526e-01 + 0.0000000e+00 5.2824589e-01 7.7314569e-01 + 0.0000000e+00 5.2787493e-01 7.7259613e-01 + 0.0000000e+00 5.2750397e-01 7.7204656e-01 + 0.0000000e+00 5.2713302e-01 7.7149699e-01 + 0.0000000e+00 5.2676206e-01 7.7094742e-01 + 0.0000000e+00 5.2639110e-01 7.7039785e-01 + 0.0000000e+00 5.2602014e-01 7.6984828e-01 + 0.0000000e+00 5.2564918e-01 7.6929871e-01 + 0.0000000e+00 5.2527822e-01 7.6874914e-01 + 0.0000000e+00 5.2490726e-01 7.6819957e-01 + 0.0000000e+00 5.2453630e-01 7.6765000e-01 + 0.0000000e+00 5.2416534e-01 7.6710043e-01 + 0.0000000e+00 5.2379438e-01 7.6655086e-01 + 0.0000000e+00 5.2342342e-01 7.6600130e-01 + 0.0000000e+00 5.2305246e-01 7.6545173e-01 + 0.0000000e+00 5.2268151e-01 7.6490216e-01 + 0.0000000e+00 5.2231055e-01 7.6435259e-01 + 0.0000000e+00 5.2193959e-01 7.6380302e-01 + 0.0000000e+00 5.2156863e-01 7.6325345e-01 + 0.0000000e+00 5.2119767e-01 7.6270388e-01 + 0.0000000e+00 5.2082671e-01 7.6215431e-01 + 0.0000000e+00 5.2045575e-01 7.6160474e-01 + 0.0000000e+00 5.2008479e-01 7.6105517e-01 + 0.0000000e+00 5.1971383e-01 7.6050560e-01 + 0.0000000e+00 5.1934287e-01 7.5995603e-01 + 0.0000000e+00 5.1897191e-01 7.5940647e-01 + 0.0000000e+00 5.1860095e-01 7.5885690e-01 + 0.0000000e+00 5.1822999e-01 7.5830733e-01 + 0.0000000e+00 5.1785904e-01 7.5775776e-01 + 0.0000000e+00 5.1748808e-01 7.5720819e-01 + 0.0000000e+00 5.1711712e-01 7.5665862e-01 + 0.0000000e+00 5.1674616e-01 7.5610905e-01 + 0.0000000e+00 5.1637520e-01 7.5555948e-01 + 0.0000000e+00 5.1600424e-01 7.5500991e-01 + 0.0000000e+00 5.1563328e-01 7.5446034e-01 + 0.0000000e+00 5.1526232e-01 7.5391077e-01 + 0.0000000e+00 5.1489136e-01 7.5336120e-01 + 0.0000000e+00 5.1452040e-01 7.5281164e-01 + 0.0000000e+00 5.1414944e-01 7.5226207e-01 + 0.0000000e+00 5.1377848e-01 7.5171250e-01 + 0.0000000e+00 5.1340753e-01 7.5116293e-01 + 0.0000000e+00 5.1303657e-01 7.5061336e-01 + 0.0000000e+00 5.1266561e-01 7.5006379e-01 + 0.0000000e+00 5.1229465e-01 7.4951422e-01 + 0.0000000e+00 5.1192369e-01 7.4896465e-01 + 0.0000000e+00 5.1155273e-01 7.4841508e-01 + 0.0000000e+00 5.1118177e-01 7.4786551e-01 + 0.0000000e+00 5.1081081e-01 7.4731594e-01 + 0.0000000e+00 5.1043985e-01 7.4676637e-01 + 0.0000000e+00 5.1006889e-01 7.4621681e-01 + 0.0000000e+00 5.0969793e-01 7.4566724e-01 + 0.0000000e+00 5.0932697e-01 7.4511767e-01 + 0.0000000e+00 5.0895601e-01 7.4456810e-01 + 0.0000000e+00 5.0858506e-01 7.4401853e-01 + 0.0000000e+00 5.0821410e-01 7.4346896e-01 + 0.0000000e+00 5.0784314e-01 7.4291939e-01 + 0.0000000e+00 5.0747218e-01 7.4236982e-01 + 0.0000000e+00 5.0710122e-01 7.4182025e-01 + 0.0000000e+00 5.0673026e-01 7.4127068e-01 + 0.0000000e+00 5.0635930e-01 7.4072111e-01 + 0.0000000e+00 5.0598834e-01 7.4017154e-01 + 0.0000000e+00 5.0561738e-01 7.3962197e-01 + 0.0000000e+00 5.0524642e-01 7.3907241e-01 + 0.0000000e+00 5.0487546e-01 7.3852284e-01 + 0.0000000e+00 5.0450450e-01 7.3797327e-01 + 0.0000000e+00 5.0413355e-01 7.3742370e-01 + 0.0000000e+00 5.0376259e-01 7.3687413e-01 + 0.0000000e+00 5.0339163e-01 7.3632456e-01 + 0.0000000e+00 5.0302067e-01 7.3577499e-01 + 0.0000000e+00 5.0264971e-01 7.3522542e-01 + 0.0000000e+00 5.0227875e-01 7.3467585e-01 + 0.0000000e+00 5.0190779e-01 7.3412628e-01 + 0.0000000e+00 5.0153683e-01 7.3357671e-01 + 0.0000000e+00 5.0116587e-01 7.3302714e-01 + 0.0000000e+00 5.0079491e-01 7.3247758e-01 + 0.0000000e+00 5.0042395e-01 7.3192801e-01 + 0.0000000e+00 5.0005299e-01 7.3137844e-01 + 0.0000000e+00 4.9968203e-01 7.3082887e-01 + 0.0000000e+00 4.9931108e-01 7.3027930e-01 + 0.0000000e+00 4.9894012e-01 7.2972973e-01 + 0.0000000e+00 4.9856916e-01 7.2918016e-01 + 0.0000000e+00 4.9819820e-01 7.2863059e-01 + 0.0000000e+00 4.9782724e-01 7.2808102e-01 + 0.0000000e+00 4.9745628e-01 7.2753145e-01 + 0.0000000e+00 4.9708532e-01 7.2698188e-01 + 0.0000000e+00 4.9671436e-01 7.2643231e-01 + 0.0000000e+00 4.9634340e-01 7.2588275e-01 + 0.0000000e+00 4.9597244e-01 7.2533318e-01 + 0.0000000e+00 4.9560148e-01 7.2478361e-01 + 0.0000000e+00 4.9523052e-01 7.2423404e-01 + 0.0000000e+00 4.9485957e-01 7.2368447e-01 + 0.0000000e+00 4.9448861e-01 7.2313490e-01 + 0.0000000e+00 4.9411765e-01 7.2258533e-01 + 0.0000000e+00 4.9374669e-01 7.2203576e-01 + 0.0000000e+00 4.9337573e-01 7.2148619e-01 + 0.0000000e+00 4.9300477e-01 7.2093662e-01 + 0.0000000e+00 4.9263381e-01 7.2038705e-01 + 0.0000000e+00 4.9226285e-01 7.1983748e-01 + 0.0000000e+00 4.9189189e-01 7.1928792e-01 + 0.0000000e+00 4.9152093e-01 7.1873835e-01 + 0.0000000e+00 4.9114997e-01 7.1818878e-01 + 0.0000000e+00 4.9077901e-01 7.1763921e-01 + 0.0000000e+00 4.9040806e-01 7.1708964e-01 + 0.0000000e+00 4.9003710e-01 7.1654007e-01 + 0.0000000e+00 4.8966614e-01 7.1599050e-01 + 0.0000000e+00 4.8929518e-01 7.1544093e-01 + 0.0000000e+00 4.8892422e-01 7.1489136e-01 + 0.0000000e+00 4.8855326e-01 7.1434179e-01 + 0.0000000e+00 4.8818230e-01 7.1379222e-01 + 0.0000000e+00 4.8781134e-01 7.1324265e-01 + 0.0000000e+00 4.8744038e-01 7.1269309e-01 + 0.0000000e+00 4.8706942e-01 7.1214352e-01 + 0.0000000e+00 4.8669846e-01 7.1159395e-01 + 0.0000000e+00 4.8632750e-01 7.1104438e-01 + 0.0000000e+00 4.8595654e-01 7.1049481e-01 + 0.0000000e+00 4.8558559e-01 7.0994524e-01 + 0.0000000e+00 4.8521463e-01 7.0939567e-01 + 0.0000000e+00 4.8484367e-01 7.0884610e-01 + 0.0000000e+00 4.8447271e-01 7.0829653e-01 + 0.0000000e+00 4.8410175e-01 7.0774696e-01 + 0.0000000e+00 4.8373079e-01 7.0719739e-01 + 0.0000000e+00 4.8335983e-01 7.0664782e-01 + 0.0000000e+00 4.8298887e-01 7.0609826e-01 + 0.0000000e+00 4.8261791e-01 7.0554869e-01 + 0.0000000e+00 4.8224695e-01 7.0499912e-01 + 0.0000000e+00 4.8187599e-01 7.0444955e-01 + 0.0000000e+00 4.8150503e-01 7.0389998e-01 + 0.0000000e+00 4.8113408e-01 7.0335041e-01 + 0.0000000e+00 4.8076312e-01 7.0280084e-01 + 0.0000000e+00 4.8039216e-01 7.0225127e-01 + 0.0000000e+00 4.8002120e-01 7.0170170e-01 + 0.0000000e+00 4.7965024e-01 7.0115213e-01 + 0.0000000e+00 4.7927928e-01 7.0060256e-01 + 0.0000000e+00 4.7890832e-01 7.0005299e-01 + 0.0000000e+00 4.7853736e-01 6.9950342e-01 + 0.0000000e+00 4.7816640e-01 6.9895386e-01 + 0.0000000e+00 4.7779544e-01 6.9840429e-01 + 0.0000000e+00 4.7742448e-01 6.9785472e-01 + 0.0000000e+00 4.7705352e-01 6.9730515e-01 + 0.0000000e+00 4.7668256e-01 6.9675558e-01 + 0.0000000e+00 4.7631161e-01 6.9620601e-01 + 0.0000000e+00 4.7594065e-01 6.9565644e-01 + 0.0000000e+00 4.7556969e-01 6.9510687e-01 + 0.0000000e+00 4.7519873e-01 6.9455730e-01 + 0.0000000e+00 4.7482777e-01 6.9400773e-01 + 0.0000000e+00 4.7445681e-01 6.9345816e-01 + 0.0000000e+00 4.7408585e-01 6.9290859e-01 + 0.0000000e+00 4.7371489e-01 6.9235903e-01 + 0.0000000e+00 4.7334393e-01 6.9180946e-01 + 0.0000000e+00 4.7297297e-01 6.9125989e-01 + 0.0000000e+00 4.7260201e-01 6.9071032e-01 + 0.0000000e+00 4.7223105e-01 6.9016075e-01 + 0.0000000e+00 4.7186010e-01 6.8961118e-01 + 0.0000000e+00 4.7148914e-01 6.8906161e-01 + 0.0000000e+00 4.7111818e-01 6.8851204e-01 + 0.0000000e+00 4.7074722e-01 6.8796247e-01 + 0.0000000e+00 4.7037626e-01 6.8741290e-01 + 0.0000000e+00 4.7000530e-01 6.8686333e-01 + 0.0000000e+00 4.6963434e-01 6.8631376e-01 + 0.0000000e+00 4.6926338e-01 6.8576420e-01 + 0.0000000e+00 4.6889242e-01 6.8521463e-01 + 0.0000000e+00 4.6852146e-01 6.8466506e-01 + 0.0000000e+00 4.6815050e-01 6.8411549e-01 + 0.0000000e+00 4.6777954e-01 6.8356592e-01 + 0.0000000e+00 4.6740859e-01 6.8301635e-01 + 0.0000000e+00 4.6703763e-01 6.8246678e-01 + 0.0000000e+00 4.6666667e-01 6.8191721e-01 + 0.0000000e+00 4.6629571e-01 6.8136764e-01 + 0.0000000e+00 4.6592475e-01 6.8081807e-01 + 0.0000000e+00 4.6555379e-01 6.8026850e-01 + 0.0000000e+00 4.6518283e-01 6.7971893e-01 + 0.0000000e+00 4.6481187e-01 6.7916937e-01 + 0.0000000e+00 4.6444091e-01 6.7861980e-01 + 0.0000000e+00 4.6406995e-01 6.7807023e-01 + 0.0000000e+00 4.6369899e-01 6.7752066e-01 + 0.0000000e+00 4.6332803e-01 6.7697109e-01 + 0.0000000e+00 4.6295707e-01 6.7642152e-01 + 0.0000000e+00 4.6258612e-01 6.7587195e-01 + 0.0000000e+00 4.6221516e-01 6.7532238e-01 + 0.0000000e+00 4.6184420e-01 6.7477281e-01 + 0.0000000e+00 4.6147324e-01 6.7422324e-01 + 0.0000000e+00 4.6110228e-01 6.7367367e-01 + 0.0000000e+00 4.6073132e-01 6.7312410e-01 + 0.0000000e+00 4.6036036e-01 6.7257454e-01 + 0.0000000e+00 4.5998940e-01 6.7202497e-01 + 0.0000000e+00 4.5961844e-01 6.7147540e-01 + 0.0000000e+00 4.5924748e-01 6.7092583e-01 + 0.0000000e+00 4.5887652e-01 6.7037626e-01 + 0.0000000e+00 4.5850556e-01 6.6982669e-01 + 0.0000000e+00 4.5813461e-01 6.6927712e-01 + 0.0000000e+00 4.5776365e-01 6.6872755e-01 + 0.0000000e+00 4.5739269e-01 6.6817798e-01 + 0.0000000e+00 4.5702173e-01 6.6762841e-01 + 0.0000000e+00 4.5665077e-01 6.6707884e-01 + 0.0000000e+00 4.5627981e-01 6.6652927e-01 + 0.0000000e+00 4.5590885e-01 6.6597971e-01 + 0.0000000e+00 4.5553789e-01 6.6543014e-01 + 0.0000000e+00 4.5516693e-01 6.6488057e-01 + 0.0000000e+00 4.5479597e-01 6.6433100e-01 + 0.0000000e+00 4.5442501e-01 6.6378143e-01 + 0.0000000e+00 4.5405405e-01 6.6323186e-01 + 0.0000000e+00 4.5368309e-01 6.6268229e-01 + 0.0000000e+00 4.5331214e-01 6.6213272e-01 + 0.0000000e+00 4.5294118e-01 6.6158315e-01 + 0.0000000e+00 4.5257022e-01 6.6103358e-01 + 0.0000000e+00 4.5219926e-01 6.6048401e-01 + 0.0000000e+00 4.5182830e-01 6.5993444e-01 + 0.0000000e+00 4.5145734e-01 6.5938488e-01 + 0.0000000e+00 4.5108638e-01 6.5883531e-01 + 0.0000000e+00 4.5071542e-01 6.5828574e-01 + 0.0000000e+00 4.5034446e-01 6.5773617e-01 + 0.0000000e+00 4.4997350e-01 6.5718660e-01 + 0.0000000e+00 4.4960254e-01 6.5663703e-01 + 0.0000000e+00 4.4923158e-01 6.5608746e-01 + 0.0000000e+00 4.4886063e-01 6.5553789e-01 + 0.0000000e+00 4.4848967e-01 6.5498832e-01 + 0.0000000e+00 4.4811871e-01 6.5443875e-01 + 0.0000000e+00 4.4774775e-01 6.5388918e-01 + 0.0000000e+00 4.4737679e-01 6.5333961e-01 + 0.0000000e+00 4.4700583e-01 6.5279004e-01 + 0.0000000e+00 4.4663487e-01 6.5224048e-01 + 0.0000000e+00 4.4626391e-01 6.5169091e-01 + 0.0000000e+00 4.4589295e-01 6.5114134e-01 + 0.0000000e+00 4.4552199e-01 6.5059177e-01 + 0.0000000e+00 4.4515103e-01 6.5004220e-01 + 0.0000000e+00 4.4478007e-01 6.4949263e-01 + 0.0000000e+00 4.4440911e-01 6.4894306e-01 + 0.0000000e+00 4.4403816e-01 6.4839349e-01 + 0.0000000e+00 4.4366720e-01 6.4784392e-01 + 0.0000000e+00 4.4329624e-01 6.4729435e-01 + 0.0000000e+00 4.4292528e-01 6.4674478e-01 + 0.0000000e+00 4.4255432e-01 6.4619521e-01 + 0.0000000e+00 4.4218336e-01 6.4564565e-01 + 0.0000000e+00 4.4181240e-01 6.4509608e-01 + 0.0000000e+00 4.4144144e-01 6.4454651e-01 + 0.0000000e+00 4.4107048e-01 6.4399694e-01 + 0.0000000e+00 4.4069952e-01 6.4344737e-01 + 0.0000000e+00 4.4032856e-01 6.4289780e-01 + 0.0000000e+00 4.3995760e-01 6.4234823e-01 + 0.0000000e+00 4.3958665e-01 6.4179866e-01 + 0.0000000e+00 4.3921569e-01 6.4124909e-01 + 0.0000000e+00 4.3884473e-01 6.4069952e-01 + 0.0000000e+00 4.3847377e-01 6.4014995e-01 + 0.0000000e+00 4.3810281e-01 6.3960038e-01 + 0.0000000e+00 4.3773185e-01 6.3905082e-01 + 0.0000000e+00 4.3736089e-01 6.3850125e-01 + 0.0000000e+00 4.3698993e-01 6.3795168e-01 + 0.0000000e+00 4.3661897e-01 6.3740211e-01 + 0.0000000e+00 4.3624801e-01 6.3685254e-01 + 0.0000000e+00 4.3587705e-01 6.3630297e-01 + 0.0000000e+00 4.3550609e-01 6.3575340e-01 + 0.0000000e+00 4.3513514e-01 6.3520383e-01 + 0.0000000e+00 4.3476418e-01 6.3465426e-01 + 0.0000000e+00 4.3439322e-01 6.3410469e-01 + 0.0000000e+00 4.3402226e-01 6.3355512e-01 + 0.0000000e+00 4.3365130e-01 6.3300555e-01 + 0.0000000e+00 4.3328034e-01 6.3245599e-01 + 0.0000000e+00 4.3290938e-01 6.3190642e-01 + 0.0000000e+00 4.3253842e-01 6.3135685e-01 + 0.0000000e+00 4.3216746e-01 6.3080728e-01 + 0.0000000e+00 4.3179650e-01 6.3025771e-01 + 0.0000000e+00 4.3142554e-01 6.2970814e-01 + 0.0000000e+00 4.3105458e-01 6.2915857e-01 + 0.0000000e+00 4.3068362e-01 6.2860900e-01 + 0.0000000e+00 4.3031267e-01 6.2805943e-01 + 0.0000000e+00 4.2994171e-01 6.2750986e-01 + 0.0000000e+00 4.2957075e-01 6.2696029e-01 + 0.0000000e+00 4.2919979e-01 6.2641072e-01 + 0.0000000e+00 4.2882883e-01 6.2586116e-01 + 0.0000000e+00 4.2845787e-01 6.2531159e-01 + 0.0000000e+00 4.2808691e-01 6.2476202e-01 + 0.0000000e+00 4.2771595e-01 6.2421245e-01 + 0.0000000e+00 4.2734499e-01 6.2366288e-01 + 0.0000000e+00 4.2697403e-01 6.2311331e-01 + 0.0000000e+00 4.2660307e-01 6.2256374e-01 + 0.0000000e+00 4.2623211e-01 6.2201417e-01 + 0.0000000e+00 4.2586116e-01 6.2146460e-01 + 0.0000000e+00 4.2549020e-01 6.2091503e-01 + 0.0000000e+00 4.2511924e-01 6.2036546e-01 + 0.0000000e+00 4.2474828e-01 6.1981589e-01 + 0.0000000e+00 4.2437732e-01 6.1926633e-01 + 0.0000000e+00 4.2400636e-01 6.1871676e-01 + 0.0000000e+00 4.2363540e-01 6.1816719e-01 + 0.0000000e+00 4.2326444e-01 6.1761762e-01 + 0.0000000e+00 4.2289348e-01 6.1706805e-01 + 0.0000000e+00 4.2252252e-01 6.1651848e-01 + 0.0000000e+00 4.2215156e-01 6.1596891e-01 + 0.0000000e+00 4.2178060e-01 6.1541934e-01 + 0.0000000e+00 4.2140964e-01 6.1486977e-01 + 0.0000000e+00 4.2103869e-01 6.1432020e-01 + 0.0000000e+00 4.2066773e-01 6.1377063e-01 + 0.0000000e+00 4.2029677e-01 6.1322106e-01 + 0.0000000e+00 4.1992581e-01 6.1267150e-01 + 0.0000000e+00 4.1955485e-01 6.1212193e-01 + 0.0000000e+00 4.1918389e-01 6.1157236e-01 + 0.0000000e+00 4.1881293e-01 6.1102279e-01 + 0.0000000e+00 4.1844197e-01 6.1047322e-01 + 0.0000000e+00 4.1807101e-01 6.0992365e-01 + 0.0000000e+00 4.1770005e-01 6.0937408e-01 + 0.0000000e+00 4.1732909e-01 6.0882451e-01 + 0.0000000e+00 4.1695813e-01 6.0827494e-01 + 0.0000000e+00 4.1658718e-01 6.0772537e-01 + 0.0000000e+00 4.1621622e-01 6.0717580e-01 + 0.0000000e+00 4.1584526e-01 6.0662623e-01 + 0.0000000e+00 4.1547430e-01 6.0607666e-01 + 0.0000000e+00 4.1510334e-01 6.0552710e-01 + 0.0000000e+00 4.1473238e-01 6.0497753e-01 + 0.0000000e+00 4.1436142e-01 6.0442796e-01 + 0.0000000e+00 4.1399046e-01 6.0387839e-01 + 0.0000000e+00 4.1361950e-01 6.0332882e-01 + 0.0000000e+00 4.1324854e-01 6.0277925e-01 + 0.0000000e+00 4.1287758e-01 6.0222968e-01 + 0.0000000e+00 4.1250662e-01 6.0168011e-01 + 0.0000000e+00 4.1213567e-01 6.0113054e-01 + 0.0000000e+00 4.1176471e-01 6.0058097e-01 + 0.0000000e+00 4.1139375e-01 6.0003140e-01 + 0.0000000e+00 4.1102279e-01 5.9948183e-01 + 0.0000000e+00 4.1065183e-01 5.9893227e-01 + 0.0000000e+00 4.1028087e-01 5.9838270e-01 + 0.0000000e+00 4.0990991e-01 5.9783313e-01 + 0.0000000e+00 4.0953895e-01 5.9728356e-01 + 0.0000000e+00 4.0916799e-01 5.9673399e-01 + 0.0000000e+00 4.0879703e-01 5.9618442e-01 + 0.0000000e+00 4.0842607e-01 5.9563485e-01 + 0.0000000e+00 4.0805511e-01 5.9508528e-01 + 0.0000000e+00 4.0768415e-01 5.9453571e-01 + 0.0000000e+00 4.0731320e-01 5.9398614e-01 + 0.0000000e+00 4.0694224e-01 5.9343657e-01 + 0.0000000e+00 4.0657128e-01 5.9288700e-01 + 0.0000000e+00 4.0620032e-01 5.9233744e-01 + 0.0000000e+00 4.0582936e-01 5.9178787e-01 + 0.0000000e+00 4.0545840e-01 5.9123830e-01 + 0.0000000e+00 4.0508744e-01 5.9068873e-01 + 0.0000000e+00 4.0471648e-01 5.9013916e-01 + 0.0000000e+00 4.0434552e-01 5.8958959e-01 + 0.0000000e+00 4.0397456e-01 5.8904002e-01 + 0.0000000e+00 4.0360360e-01 5.8849045e-01 + 0.0000000e+00 4.0323264e-01 5.8794088e-01 + 0.0000000e+00 4.0286169e-01 5.8739131e-01 + 0.0000000e+00 4.0249073e-01 5.8684174e-01 + 0.0000000e+00 4.0211977e-01 5.8629217e-01 + 0.0000000e+00 4.0174881e-01 5.8574261e-01 + 0.0000000e+00 4.0137785e-01 5.8519304e-01 + 0.0000000e+00 4.0100689e-01 5.8464347e-01 + 0.0000000e+00 4.0063593e-01 5.8409390e-01 + 0.0000000e+00 4.0026497e-01 5.8354433e-01 + 0.0000000e+00 3.9989401e-01 5.8299476e-01 + 0.0000000e+00 3.9952305e-01 5.8244519e-01 + 0.0000000e+00 3.9915209e-01 5.8189562e-01 + 0.0000000e+00 3.9878113e-01 5.8134605e-01 + 0.0000000e+00 3.9841017e-01 5.8079648e-01 + 0.0000000e+00 3.9803922e-01 5.8024691e-01 + 0.0000000e+00 3.9766826e-01 5.7969734e-01 + 0.0000000e+00 3.9729730e-01 5.7914778e-01 + 0.0000000e+00 3.9692634e-01 5.7859821e-01 + 0.0000000e+00 3.9655538e-01 5.7804864e-01 + 0.0000000e+00 3.9618442e-01 5.7749907e-01 + 0.0000000e+00 3.9581346e-01 5.7694950e-01 + 0.0000000e+00 3.9544250e-01 5.7639993e-01 + 0.0000000e+00 3.9507154e-01 5.7585036e-01 + 0.0000000e+00 3.9470058e-01 5.7530079e-01 + 0.0000000e+00 3.9432962e-01 5.7475122e-01 + 0.0000000e+00 3.9395866e-01 5.7420165e-01 + 0.0000000e+00 3.9358771e-01 5.7365208e-01 + 0.0000000e+00 3.9321675e-01 5.7310251e-01 + 0.0000000e+00 3.9284579e-01 5.7255295e-01 + 0.0000000e+00 3.9247483e-01 5.7200338e-01 + 0.0000000e+00 3.9210387e-01 5.7145381e-01 + 0.0000000e+00 3.9173291e-01 5.7090424e-01 + 0.0000000e+00 3.9136195e-01 5.7035467e-01 + 0.0000000e+00 3.9099099e-01 5.6980510e-01 + 0.0000000e+00 3.9062003e-01 5.6925553e-01 + 0.0000000e+00 3.9024907e-01 5.6870596e-01 + 0.0000000e+00 3.8987811e-01 5.6815639e-01 + 0.0000000e+00 3.8950715e-01 5.6760682e-01 + 0.0000000e+00 3.8913620e-01 5.6705725e-01 + 0.0000000e+00 3.8876524e-01 5.6650768e-01 + 0.0000000e+00 3.8839428e-01 5.6595811e-01 + 0.0000000e+00 3.8802332e-01 5.6540855e-01 + 0.0000000e+00 3.8765236e-01 5.6485898e-01 + 0.0000000e+00 3.8728140e-01 5.6430941e-01 + 0.0000000e+00 3.8691044e-01 5.6375984e-01 + 0.0000000e+00 3.8653948e-01 5.6321027e-01 + 0.0000000e+00 3.8616852e-01 5.6266070e-01 + 0.0000000e+00 3.8579756e-01 5.6211113e-01 + 0.0000000e+00 3.8542660e-01 5.6156156e-01 + 0.0000000e+00 3.8505564e-01 5.6101199e-01 + 0.0000000e+00 3.8468468e-01 5.6046242e-01 + 0.0000000e+00 3.8431373e-01 5.5991285e-01 + 0.0000000e+00 3.8394277e-01 5.5936328e-01 + 0.0000000e+00 3.8357181e-01 5.5881372e-01 + 0.0000000e+00 3.8320085e-01 5.5826415e-01 + 0.0000000e+00 3.8282989e-01 5.5771458e-01 + 0.0000000e+00 3.8245893e-01 5.5716501e-01 + 0.0000000e+00 3.8208797e-01 5.5661544e-01 + 0.0000000e+00 3.8171701e-01 5.5606587e-01 + 0.0000000e+00 3.8134605e-01 5.5551630e-01 + 0.0000000e+00 3.8097509e-01 5.5496673e-01 + 0.0000000e+00 3.8060413e-01 5.5441716e-01 + 0.0000000e+00 3.8023317e-01 5.5386759e-01 + 0.0000000e+00 3.7986222e-01 5.5331802e-01 + 0.0000000e+00 3.7949126e-01 5.5276845e-01 + 0.0000000e+00 3.7912030e-01 5.5221889e-01 + 0.0000000e+00 3.7874934e-01 5.5166932e-01 + 0.0000000e+00 3.7837838e-01 5.5111975e-01 + 0.0000000e+00 3.7800742e-01 5.5057018e-01 + 0.0000000e+00 3.7763646e-01 5.5002061e-01 + 0.0000000e+00 3.7726550e-01 5.4947104e-01 + 0.0000000e+00 3.7689454e-01 5.4892147e-01 + 0.0000000e+00 3.7652358e-01 5.4837190e-01 + 0.0000000e+00 3.7615262e-01 5.4782233e-01 + 0.0000000e+00 3.7578166e-01 5.4727276e-01 + 0.0000000e+00 3.7541070e-01 5.4672319e-01 + 0.0000000e+00 3.7503975e-01 5.4617362e-01 + 0.0000000e+00 3.7466879e-01 5.4562406e-01 + 0.0000000e+00 3.7429783e-01 5.4507449e-01 + 0.0000000e+00 3.7392687e-01 5.4452492e-01 + 0.0000000e+00 3.7355591e-01 5.4397535e-01 + 0.0000000e+00 3.7318495e-01 5.4342578e-01 + 0.0000000e+00 3.7281399e-01 5.4287621e-01 + 0.0000000e+00 3.7244303e-01 5.4232664e-01 + 0.0000000e+00 3.7207207e-01 5.4177707e-01 + 0.0000000e+00 3.7170111e-01 5.4122750e-01 + 0.0000000e+00 3.7133015e-01 5.4067793e-01 + 0.0000000e+00 3.7095919e-01 5.4012836e-01 + 0.0000000e+00 3.7058824e-01 5.3957879e-01 + 0.0000000e+00 3.7021728e-01 5.3902923e-01 + 0.0000000e+00 3.6984632e-01 5.3847966e-01 + 0.0000000e+00 3.6947536e-01 5.3793009e-01 + 0.0000000e+00 3.6910440e-01 5.3738052e-01 + 0.0000000e+00 3.6873344e-01 5.3683095e-01 + 0.0000000e+00 3.6836248e-01 5.3628138e-01 + 0.0000000e+00 3.6799152e-01 5.3573181e-01 + 0.0000000e+00 3.6762056e-01 5.3518224e-01 + 0.0000000e+00 3.6724960e-01 5.3463267e-01 + 0.0000000e+00 3.6687864e-01 5.3408310e-01 + 0.0000000e+00 3.6650768e-01 5.3353353e-01 + 0.0000000e+00 3.6613672e-01 5.3298396e-01 + 0.0000000e+00 3.6576577e-01 5.3243440e-01 + 0.0000000e+00 3.6539481e-01 5.3188483e-01 + 0.0000000e+00 3.6502385e-01 5.3133526e-01 + 0.0000000e+00 3.6465289e-01 5.3078569e-01 + 0.0000000e+00 3.6428193e-01 5.3023612e-01 + 0.0000000e+00 3.6391097e-01 5.2968655e-01 + 0.0000000e+00 3.6354001e-01 5.2913698e-01 + 0.0000000e+00 3.6316905e-01 5.2858741e-01 + 0.0000000e+00 3.6279809e-01 5.2803784e-01 + 0.0000000e+00 3.6242713e-01 5.2748827e-01 + 0.0000000e+00 3.6205617e-01 5.2693870e-01 + 0.0000000e+00 3.6168521e-01 5.2638913e-01 + 0.0000000e+00 3.6131426e-01 5.2583957e-01 + 0.0000000e+00 3.6094330e-01 5.2529000e-01 + 0.0000000e+00 3.6057234e-01 5.2474043e-01 + 0.0000000e+00 3.6020138e-01 5.2419086e-01 + 0.0000000e+00 3.5983042e-01 5.2364129e-01 + 0.0000000e+00 3.5945946e-01 5.2309172e-01 + 0.0000000e+00 3.5908850e-01 5.2254215e-01 + 0.0000000e+00 3.5871754e-01 5.2199258e-01 + 0.0000000e+00 3.5834658e-01 5.2144301e-01 + 0.0000000e+00 3.5797562e-01 5.2089344e-01 + 0.0000000e+00 3.5760466e-01 5.2034387e-01 + 0.0000000e+00 3.5723370e-01 5.1979430e-01 + 0.0000000e+00 3.5686275e-01 5.1924473e-01 + 0.0000000e+00 3.5649179e-01 5.1869517e-01 + 0.0000000e+00 3.5612083e-01 5.1814560e-01 + 0.0000000e+00 3.5574987e-01 5.1759603e-01 + 0.0000000e+00 3.5537891e-01 5.1704646e-01 + 0.0000000e+00 3.5500795e-01 5.1649689e-01 + 0.0000000e+00 3.5463699e-01 5.1594732e-01 + 0.0000000e+00 3.5426603e-01 5.1539775e-01 + 0.0000000e+00 3.5389507e-01 5.1484818e-01 + 0.0000000e+00 3.5352411e-01 5.1429861e-01 + 0.0000000e+00 3.5315315e-01 5.1374904e-01 + 0.0000000e+00 3.5278219e-01 5.1319947e-01 + 0.0000000e+00 3.5241123e-01 5.1264990e-01 + 0.0000000e+00 3.5204028e-01 5.1210034e-01 + 0.0000000e+00 3.5166932e-01 5.1155077e-01 + 0.0000000e+00 3.5129836e-01 5.1100120e-01 + 0.0000000e+00 3.5092740e-01 5.1045163e-01 + 0.0000000e+00 3.5055644e-01 5.0990206e-01 + 0.0000000e+00 3.5018548e-01 5.0935249e-01 + 0.0000000e+00 3.4981452e-01 5.0880292e-01 + 0.0000000e+00 3.4944356e-01 5.0825335e-01 + 0.0000000e+00 3.4907260e-01 5.0770378e-01 + 0.0000000e+00 3.4870164e-01 5.0715421e-01 + 0.0000000e+00 3.4833068e-01 5.0660464e-01 + 0.0000000e+00 3.4795972e-01 5.0605507e-01 + 0.0000000e+00 3.4758877e-01 5.0550551e-01 + 0.0000000e+00 3.4721781e-01 5.0495594e-01 + 0.0000000e+00 3.4684685e-01 5.0440637e-01 + 0.0000000e+00 3.4647589e-01 5.0385680e-01 + 0.0000000e+00 3.4610493e-01 5.0330723e-01 + 0.0000000e+00 3.4573397e-01 5.0275766e-01 + 0.0000000e+00 3.4536301e-01 5.0220809e-01 + 0.0000000e+00 3.4499205e-01 5.0165852e-01 + 0.0000000e+00 3.4462109e-01 5.0110895e-01 + 0.0000000e+00 3.4425013e-01 5.0055938e-01 + 0.0000000e+00 3.4387917e-01 5.0000981e-01 + 0.0000000e+00 3.4350821e-01 4.9946024e-01 + 0.0000000e+00 3.4313725e-01 4.9891068e-01 + 0.0000000e+00 3.4276630e-01 4.9836111e-01 + 0.0000000e+00 3.4239534e-01 4.9781154e-01 + 0.0000000e+00 3.4202438e-01 4.9726197e-01 + 0.0000000e+00 3.4165342e-01 4.9671240e-01 + 0.0000000e+00 3.4128246e-01 4.9616283e-01 + 0.0000000e+00 3.4091150e-01 4.9561326e-01 + 0.0000000e+00 3.4054054e-01 4.9506369e-01 + 0.0000000e+00 3.4016958e-01 4.9451412e-01 + 0.0000000e+00 3.3979862e-01 4.9396455e-01 + 0.0000000e+00 3.3942766e-01 4.9341498e-01 + 0.0000000e+00 3.3905670e-01 4.9286541e-01 + 0.0000000e+00 3.3868574e-01 4.9231585e-01 + 0.0000000e+00 3.3831479e-01 4.9176628e-01 + 0.0000000e+00 3.3794383e-01 4.9121671e-01 + 0.0000000e+00 3.3757287e-01 4.9066714e-01 + 0.0000000e+00 3.3720191e-01 4.9011757e-01 + 0.0000000e+00 3.3683095e-01 4.8956800e-01 + 0.0000000e+00 3.3645999e-01 4.8901843e-01 + 0.0000000e+00 3.3608903e-01 4.8846886e-01 + 0.0000000e+00 3.3571807e-01 4.8791929e-01 + 0.0000000e+00 3.3534711e-01 4.8736972e-01 + 0.0000000e+00 3.3497615e-01 4.8682015e-01 + 0.0000000e+00 3.3460519e-01 4.8627058e-01 + 0.0000000e+00 3.3423423e-01 4.8572102e-01 + 0.0000000e+00 3.3386328e-01 4.8517145e-01 + 0.0000000e+00 3.3349232e-01 4.8462188e-01 + 0.0000000e+00 3.3312136e-01 4.8407231e-01 + 0.0000000e+00 3.3275040e-01 4.8352274e-01 + 0.0000000e+00 3.3237944e-01 4.8297317e-01 + 0.0000000e+00 3.3200848e-01 4.8242360e-01 + 0.0000000e+00 3.3163752e-01 4.8187403e-01 + 0.0000000e+00 3.3126656e-01 4.8132446e-01 + 0.0000000e+00 3.3089560e-01 4.8077489e-01 + 0.0000000e+00 3.3052464e-01 4.8022532e-01 + 0.0000000e+00 3.3015368e-01 4.7967575e-01 + 0.0000000e+00 3.2978272e-01 4.7912619e-01 + 0.0000000e+00 3.2941176e-01 4.7857662e-01 + 0.0000000e+00 3.2904081e-01 4.7802705e-01 + 0.0000000e+00 3.2866985e-01 4.7747748e-01 + 0.0000000e+00 3.2829889e-01 4.7692791e-01 + 0.0000000e+00 3.2792793e-01 4.7637834e-01 + 0.0000000e+00 3.2755697e-01 4.7582877e-01 + 0.0000000e+00 3.2718601e-01 4.7527920e-01 + 0.0000000e+00 3.2681505e-01 4.7472963e-01 + 0.0000000e+00 3.2644409e-01 4.7418006e-01 + 0.0000000e+00 3.2607313e-01 4.7363049e-01 + 0.0000000e+00 3.2570217e-01 4.7308092e-01 + 0.0000000e+00 3.2533121e-01 4.7253135e-01 + 0.0000000e+00 3.2496025e-01 4.7198179e-01 + 0.0000000e+00 3.2458930e-01 4.7143222e-01 + 0.0000000e+00 3.2421834e-01 4.7088265e-01 + 0.0000000e+00 3.2384738e-01 4.7033308e-01 + 0.0000000e+00 3.2347642e-01 4.6978351e-01 + 0.0000000e+00 3.2310546e-01 4.6923394e-01 + 0.0000000e+00 3.2273450e-01 4.6868437e-01 + 0.0000000e+00 3.2236354e-01 4.6813480e-01 + 0.0000000e+00 3.2199258e-01 4.6758523e-01 + 0.0000000e+00 3.2162162e-01 4.6703566e-01 + 0.0000000e+00 3.2125066e-01 4.6648609e-01 + 0.0000000e+00 3.2087970e-01 4.6593652e-01 + 0.0000000e+00 3.2050874e-01 4.6538696e-01 + 0.0000000e+00 3.2013778e-01 4.6483739e-01 + 0.0000000e+00 3.1976683e-01 4.6428782e-01 + 0.0000000e+00 3.1939587e-01 4.6373825e-01 + 0.0000000e+00 3.1902491e-01 4.6318868e-01 + 0.0000000e+00 3.1865395e-01 4.6263911e-01 + 0.0000000e+00 3.1828299e-01 4.6208954e-01 + 0.0000000e+00 3.1791203e-01 4.6153997e-01 + 0.0000000e+00 3.1754107e-01 4.6099040e-01 + 0.0000000e+00 3.1717011e-01 4.6044083e-01 + 0.0000000e+00 3.1679915e-01 4.5989126e-01 + 0.0000000e+00 3.1642819e-01 4.5934169e-01 + 0.0000000e+00 3.1605723e-01 4.5879213e-01 + 0.0000000e+00 3.1568627e-01 4.5824256e-01 + 0.0000000e+00 3.1531532e-01 4.5769299e-01 + 0.0000000e+00 3.1494436e-01 4.5714342e-01 + 0.0000000e+00 3.1457340e-01 4.5659385e-01 + 0.0000000e+00 3.1420244e-01 4.5604428e-01 + 0.0000000e+00 3.1383148e-01 4.5549471e-01 + 0.0000000e+00 3.1346052e-01 4.5494514e-01 + 0.0000000e+00 3.1308956e-01 4.5439557e-01 + 0.0000000e+00 3.1271860e-01 4.5384600e-01 + 0.0000000e+00 3.1234764e-01 4.5329643e-01 + 0.0000000e+00 3.1197668e-01 4.5274686e-01 + 0.0000000e+00 3.1160572e-01 4.5219730e-01 + 0.0000000e+00 3.1123476e-01 4.5164773e-01 + 0.0000000e+00 3.1086380e-01 4.5109816e-01 + 0.0000000e+00 3.1049285e-01 4.5054859e-01 + 0.0000000e+00 3.1012189e-01 4.4999902e-01 + 0.0000000e+00 3.0975093e-01 4.4944945e-01 + 0.0000000e+00 3.0937997e-01 4.4889988e-01 + 0.0000000e+00 3.0900901e-01 4.4835031e-01 + 0.0000000e+00 3.0863805e-01 4.4780074e-01 + 0.0000000e+00 3.0826709e-01 4.4725117e-01 + 0.0000000e+00 3.0789613e-01 4.4670160e-01 + 0.0000000e+00 3.0752517e-01 4.4615203e-01 + 0.0000000e+00 3.0715421e-01 4.4560247e-01 + 0.0000000e+00 3.0678325e-01 4.4505290e-01 + 0.0000000e+00 3.0641229e-01 4.4450333e-01 + 0.0000000e+00 3.0604134e-01 4.4395376e-01 + 0.0000000e+00 3.0567038e-01 4.4340419e-01 + 0.0000000e+00 3.0529942e-01 4.4285462e-01 + 0.0000000e+00 3.0492846e-01 4.4230505e-01 + 0.0000000e+00 3.0455750e-01 4.4175548e-01 + 0.0000000e+00 3.0418654e-01 4.4120591e-01 + 0.0000000e+00 3.0381558e-01 4.4065634e-01 + 0.0000000e+00 3.0344462e-01 4.4010677e-01 + 0.0000000e+00 3.0307366e-01 4.3955720e-01 + 0.0000000e+00 3.0270270e-01 4.3900764e-01 + 0.0000000e+00 3.0233174e-01 4.3845807e-01 + 0.0000000e+00 3.0196078e-01 4.3790850e-01 + 0.0000000e+00 3.0158983e-01 4.3735893e-01 + 0.0000000e+00 3.0121887e-01 4.3680936e-01 + 0.0000000e+00 3.0084791e-01 4.3625979e-01 + 0.0000000e+00 3.0047695e-01 4.3571022e-01 + 0.0000000e+00 3.0010599e-01 4.3516065e-01 + 0.0000000e+00 2.9973503e-01 4.3461108e-01 + 0.0000000e+00 2.9936407e-01 4.3406151e-01 + 0.0000000e+00 2.9899311e-01 4.3351194e-01 + 0.0000000e+00 2.9862215e-01 4.3296237e-01 + 0.0000000e+00 2.9825119e-01 4.3241280e-01 + 0.0000000e+00 2.9788023e-01 4.3186324e-01 + 0.0000000e+00 2.9750927e-01 4.3131367e-01 + 0.0000000e+00 2.9713831e-01 4.3076410e-01 + 0.0000000e+00 2.9676736e-01 4.3021453e-01 + 0.0000000e+00 2.9639640e-01 4.2966496e-01 + 0.0000000e+00 2.9602544e-01 4.2911539e-01 + 0.0000000e+00 2.9565448e-01 4.2856582e-01 + 0.0000000e+00 2.9528352e-01 4.2801625e-01 + 0.0000000e+00 2.9491256e-01 4.2746668e-01 + 0.0000000e+00 2.9454160e-01 4.2691711e-01 + 0.0000000e+00 2.9417064e-01 4.2636754e-01 + 0.0000000e+00 2.9379968e-01 4.2581797e-01 + 0.0000000e+00 2.9342872e-01 4.2526841e-01 + 0.0000000e+00 2.9305776e-01 4.2471884e-01 + 0.0000000e+00 2.9268680e-01 4.2416927e-01 + 0.0000000e+00 2.9231585e-01 4.2361970e-01 + 0.0000000e+00 2.9194489e-01 4.2307013e-01 + 0.0000000e+00 2.9157393e-01 4.2252056e-01 + 0.0000000e+00 2.9120297e-01 4.2197099e-01 + 0.0000000e+00 2.9083201e-01 4.2142142e-01 + 0.0000000e+00 2.9046105e-01 4.2087185e-01 + 0.0000000e+00 2.9009009e-01 4.2032228e-01 + 0.0000000e+00 2.8971913e-01 4.1977271e-01 + 0.0000000e+00 2.8934817e-01 4.1922314e-01 + 0.0000000e+00 2.8897721e-01 4.1867358e-01 + 0.0000000e+00 2.8860625e-01 4.1812401e-01 + 0.0000000e+00 2.8823529e-01 4.1757444e-01 + 0.0000000e+00 2.8786433e-01 4.1702487e-01 + 0.0000000e+00 2.8749338e-01 4.1647530e-01 + 0.0000000e+00 2.8712242e-01 4.1592573e-01 + 0.0000000e+00 2.8675146e-01 4.1537616e-01 + 0.0000000e+00 2.8638050e-01 4.1482659e-01 + 0.0000000e+00 2.8600954e-01 4.1427702e-01 + 0.0000000e+00 2.8563858e-01 4.1372745e-01 + 0.0000000e+00 2.8526762e-01 4.1317788e-01 + 0.0000000e+00 2.8489666e-01 4.1262831e-01 + 0.0000000e+00 2.8452570e-01 4.1207875e-01 + 0.0000000e+00 2.8415474e-01 4.1152918e-01 + 0.0000000e+00 2.8378378e-01 4.1097961e-01 + 0.0000000e+00 2.8341282e-01 4.1043004e-01 + 0.0000000e+00 2.8304187e-01 4.0988047e-01 + 0.0000000e+00 2.8267091e-01 4.0933090e-01 + 0.0000000e+00 2.8229995e-01 4.0878133e-01 + 0.0000000e+00 2.8192899e-01 4.0823176e-01 + 0.0000000e+00 2.8155803e-01 4.0768219e-01 + 0.0000000e+00 2.8118707e-01 4.0713262e-01 + 0.0000000e+00 2.8081611e-01 4.0658305e-01 + 0.0000000e+00 2.8044515e-01 4.0603348e-01 + 0.0000000e+00 2.8007419e-01 4.0548392e-01 + 0.0000000e+00 2.7970323e-01 4.0493435e-01 + 0.0000000e+00 2.7933227e-01 4.0438478e-01 + 0.0000000e+00 2.7896131e-01 4.0383521e-01 + 0.0000000e+00 2.7859036e-01 4.0328564e-01 + 0.0000000e+00 2.7821940e-01 4.0273607e-01 + 0.0000000e+00 2.7784844e-01 4.0218650e-01 + 0.0000000e+00 2.7747748e-01 4.0163693e-01 + 0.0000000e+00 2.7710652e-01 4.0108736e-01 + 0.0000000e+00 2.7673556e-01 4.0053779e-01 + 0.0000000e+00 2.7636460e-01 3.9998822e-01 + 0.0000000e+00 2.7599364e-01 3.9943865e-01 + 0.0000000e+00 2.7562268e-01 3.9888909e-01 + 0.0000000e+00 2.7525172e-01 3.9833952e-01 + 0.0000000e+00 2.7488076e-01 3.9778995e-01 + 0.0000000e+00 2.7450980e-01 3.9724038e-01 + 0.0000000e+00 2.7413884e-01 3.9669081e-01 + 0.0000000e+00 2.7376789e-01 3.9614124e-01 + 0.0000000e+00 2.7339693e-01 3.9559167e-01 + 0.0000000e+00 2.7302597e-01 3.9504210e-01 + 0.0000000e+00 2.7265501e-01 3.9449253e-01 + 0.0000000e+00 2.7228405e-01 3.9394296e-01 + 0.0000000e+00 2.7191309e-01 3.9339339e-01 + 0.0000000e+00 2.7154213e-01 3.9284382e-01 + 0.0000000e+00 2.7117117e-01 3.9229426e-01 + 0.0000000e+00 2.7080021e-01 3.9174469e-01 + 0.0000000e+00 2.7042925e-01 3.9119512e-01 + 0.0000000e+00 2.7005829e-01 3.9064555e-01 + 0.0000000e+00 2.6968733e-01 3.9009598e-01 + 0.0000000e+00 2.6931638e-01 3.8954641e-01 + 0.0000000e+00 2.6894542e-01 3.8899684e-01 + 0.0000000e+00 2.6857446e-01 3.8844727e-01 + 0.0000000e+00 2.6820350e-01 3.8789770e-01 + 0.0000000e+00 2.6783254e-01 3.8734813e-01 + 0.0000000e+00 2.6746158e-01 3.8679856e-01 + 0.0000000e+00 2.6709062e-01 3.8624899e-01 + 0.0000000e+00 2.6671966e-01 3.8569942e-01 + 0.0000000e+00 2.6634870e-01 3.8514986e-01 + 0.0000000e+00 2.6597774e-01 3.8460029e-01 + 0.0000000e+00 2.6560678e-01 3.8405072e-01 + 0.0000000e+00 2.6523582e-01 3.8350115e-01 + 0.0000000e+00 2.6486486e-01 3.8295158e-01 + 0.0000000e+00 2.6449391e-01 3.8240201e-01 + 0.0000000e+00 2.6412295e-01 3.8185244e-01 + 0.0000000e+00 2.6375199e-01 3.8130287e-01 + 0.0000000e+00 2.6338103e-01 3.8075330e-01 + 0.0000000e+00 2.6301007e-01 3.8020373e-01 + 0.0000000e+00 2.6263911e-01 3.7965416e-01 + 0.0000000e+00 2.6226815e-01 3.7910459e-01 + 0.0000000e+00 2.6189719e-01 3.7855503e-01 + 0.0000000e+00 2.6152623e-01 3.7800546e-01 + 0.0000000e+00 2.6115527e-01 3.7745589e-01 + 0.0000000e+00 2.6078431e-01 3.7690632e-01 + 0.0000000e+00 2.6041335e-01 3.7635675e-01 + 0.0000000e+00 2.6004240e-01 3.7580718e-01 + 0.0000000e+00 2.5967144e-01 3.7525761e-01 + 0.0000000e+00 2.5930048e-01 3.7470804e-01 + 0.0000000e+00 2.5892952e-01 3.7415847e-01 + 0.0000000e+00 2.5855856e-01 3.7360890e-01 + 0.0000000e+00 2.5818760e-01 3.7305933e-01 + 0.0000000e+00 2.5781664e-01 3.7250976e-01 + 0.0000000e+00 2.5744568e-01 3.7196020e-01 + 0.0000000e+00 2.5707472e-01 3.7141063e-01 + 0.0000000e+00 2.5670376e-01 3.7086106e-01 + 0.0000000e+00 2.5633280e-01 3.7031149e-01 + 0.0000000e+00 2.5596184e-01 3.6976192e-01 + 0.0000000e+00 2.5559089e-01 3.6921235e-01 + 0.0000000e+00 2.5521993e-01 3.6866278e-01 + 0.0000000e+00 2.5484897e-01 3.6811321e-01 + 0.0000000e+00 2.5447801e-01 3.6756364e-01 + 0.0000000e+00 2.5410705e-01 3.6701407e-01 + 0.0000000e+00 2.5373609e-01 3.6646450e-01 + 0.0000000e+00 2.5336513e-01 3.6591493e-01 + 0.0000000e+00 2.5299417e-01 3.6536537e-01 + 0.0000000e+00 2.5262321e-01 3.6481580e-01 + 0.0000000e+00 2.5225225e-01 3.6426623e-01 + 0.0000000e+00 2.5188129e-01 3.6371666e-01 + 0.0000000e+00 2.5151033e-01 3.6316709e-01 + 0.0000000e+00 2.5113937e-01 3.6261752e-01 + 0.0000000e+00 2.5076842e-01 3.6206795e-01 + 0.0000000e+00 2.5039746e-01 3.6151838e-01 + 0.0000000e+00 2.5002650e-01 3.6096881e-01 + 0.0000000e+00 2.4965554e-01 3.6041924e-01 + 0.0000000e+00 2.4928458e-01 3.5986967e-01 + 0.0000000e+00 2.4891362e-01 3.5932010e-01 + 0.0000000e+00 2.4854266e-01 3.5877054e-01 + 0.0000000e+00 2.4817170e-01 3.5822097e-01 + 0.0000000e+00 2.4780074e-01 3.5767140e-01 + 0.0000000e+00 2.4742978e-01 3.5712183e-01 + 0.0000000e+00 2.4705882e-01 3.5657226e-01 + 0.0000000e+00 2.4668786e-01 3.5602269e-01 + 0.0000000e+00 2.4631691e-01 3.5547312e-01 + 0.0000000e+00 2.4594595e-01 3.5492355e-01 + 0.0000000e+00 2.4557499e-01 3.5437398e-01 + 0.0000000e+00 2.4520403e-01 3.5382441e-01 + 0.0000000e+00 2.4483307e-01 3.5327484e-01 + 0.0000000e+00 2.4446211e-01 3.5272527e-01 + 0.0000000e+00 2.4409115e-01 3.5217571e-01 + 0.0000000e+00 2.4372019e-01 3.5162614e-01 + 0.0000000e+00 2.4334923e-01 3.5107657e-01 + 0.0000000e+00 2.4297827e-01 3.5052700e-01 + 0.0000000e+00 2.4260731e-01 3.4997743e-01 + 0.0000000e+00 2.4223635e-01 3.4942786e-01 + 0.0000000e+00 2.4186539e-01 3.4887829e-01 + 0.0000000e+00 2.4149444e-01 3.4832872e-01 + 0.0000000e+00 2.4112348e-01 3.4777915e-01 + 0.0000000e+00 2.4075252e-01 3.4722958e-01 + 0.0000000e+00 2.4038156e-01 3.4668001e-01 + 0.0000000e+00 2.4001060e-01 3.4613044e-01 + 0.0000000e+00 2.3963964e-01 3.4558087e-01 + 0.0000000e+00 2.3926868e-01 3.4503131e-01 + 0.0000000e+00 2.3889772e-01 3.4448174e-01 + 0.0000000e+00 2.3852676e-01 3.4393217e-01 + 0.0000000e+00 2.3815580e-01 3.4338260e-01 + 0.0000000e+00 2.3778484e-01 3.4283303e-01 + 0.0000000e+00 2.3741388e-01 3.4228346e-01 + 0.0000000e+00 2.3704293e-01 3.4173389e-01 + 0.0000000e+00 2.3667197e-01 3.4118432e-01 + 0.0000000e+00 2.3630101e-01 3.4063475e-01 + 0.0000000e+00 2.3593005e-01 3.4008518e-01 + 0.0000000e+00 2.3555909e-01 3.3953561e-01 + 0.0000000e+00 2.3518813e-01 3.3898604e-01 + 0.0000000e+00 2.3481717e-01 3.3843648e-01 + 0.0000000e+00 2.3444621e-01 3.3788691e-01 + 0.0000000e+00 2.3407525e-01 3.3733734e-01 + 0.0000000e+00 2.3370429e-01 3.3678777e-01 + 0.0000000e+00 2.3333333e-01 3.3623820e-01 + 0.0000000e+00 2.3296237e-01 3.3568863e-01 + 0.0000000e+00 2.3259141e-01 3.3513906e-01 + 0.0000000e+00 2.3222046e-01 3.3458949e-01 + 0.0000000e+00 2.3184950e-01 3.3403992e-01 + 0.0000000e+00 2.3147854e-01 3.3349035e-01 + 0.0000000e+00 2.3110758e-01 3.3294078e-01 + 0.0000000e+00 2.3073662e-01 3.3239121e-01 + 0.0000000e+00 2.3036566e-01 3.3184165e-01 + 0.0000000e+00 2.2999470e-01 3.3129208e-01 + 0.0000000e+00 2.2962374e-01 3.3074251e-01 + 0.0000000e+00 2.2925278e-01 3.3019294e-01 + 0.0000000e+00 2.2888182e-01 3.2964337e-01 + 0.0000000e+00 2.2851086e-01 3.2909380e-01 + 0.0000000e+00 2.2813990e-01 3.2854423e-01 + 0.0000000e+00 2.2776895e-01 3.2799466e-01 + 0.0000000e+00 2.2739799e-01 3.2744509e-01 + 0.0000000e+00 2.2702703e-01 3.2689552e-01 + 0.0000000e+00 2.2665607e-01 3.2634595e-01 + 0.0000000e+00 2.2628511e-01 3.2579638e-01 + 0.0000000e+00 2.2591415e-01 3.2524682e-01 + 0.0000000e+00 2.2554319e-01 3.2469725e-01 + 0.0000000e+00 2.2517223e-01 3.2414768e-01 + 0.0000000e+00 2.2480127e-01 3.2359811e-01 + 0.0000000e+00 2.2443031e-01 3.2304854e-01 + 0.0000000e+00 2.2405935e-01 3.2249897e-01 + 0.0000000e+00 2.2368839e-01 3.2194940e-01 + 0.0000000e+00 2.2331744e-01 3.2139983e-01 + 0.0000000e+00 2.2294648e-01 3.2085026e-01 + 0.0000000e+00 2.2257552e-01 3.2030069e-01 + 0.0000000e+00 2.2220456e-01 3.1975112e-01 + 0.0000000e+00 2.2183360e-01 3.1920155e-01 + 0.0000000e+00 2.2146264e-01 3.1865199e-01 + 0.0000000e+00 2.2109168e-01 3.1810242e-01 + 0.0000000e+00 2.2072072e-01 3.1755285e-01 + 0.0000000e+00 2.2034976e-01 3.1700328e-01 + 0.0000000e+00 2.1997880e-01 3.1645371e-01 + 0.0000000e+00 2.1960784e-01 3.1590414e-01 + 0.0000000e+00 2.1923688e-01 3.1535457e-01 + 0.0000000e+00 2.1886592e-01 3.1480500e-01 + 0.0000000e+00 2.1849497e-01 3.1425543e-01 + 0.0000000e+00 2.1812401e-01 3.1370586e-01 + 0.0000000e+00 2.1775305e-01 3.1315629e-01 + 0.0000000e+00 2.1738209e-01 3.1260672e-01 + 0.0000000e+00 2.1701113e-01 3.1205716e-01 + 0.0000000e+00 2.1664017e-01 3.1150759e-01 + 0.0000000e+00 2.1626921e-01 3.1095802e-01 + 0.0000000e+00 2.1589825e-01 3.1040845e-01 + 0.0000000e+00 2.1552729e-01 3.0985888e-01 + 0.0000000e+00 2.1515633e-01 3.0930931e-01 + 0.0000000e+00 2.1478537e-01 3.0875974e-01 + 0.0000000e+00 2.1441441e-01 3.0821017e-01 + 0.0000000e+00 2.1404346e-01 3.0766060e-01 + 0.0000000e+00 2.1367250e-01 3.0711103e-01 + 0.0000000e+00 2.1330154e-01 3.0656146e-01 + 0.0000000e+00 2.1293058e-01 3.0601189e-01 + 0.0000000e+00 2.1255962e-01 3.0546233e-01 + 0.0000000e+00 2.1218866e-01 3.0491276e-01 + 0.0000000e+00 2.1181770e-01 3.0436319e-01 + 0.0000000e+00 2.1144674e-01 3.0381362e-01 + 0.0000000e+00 2.1107578e-01 3.0326405e-01 + 0.0000000e+00 2.1070482e-01 3.0271448e-01 + 0.0000000e+00 2.1033386e-01 3.0216491e-01 + 0.0000000e+00 2.0996290e-01 3.0161534e-01 + 0.0000000e+00 2.0959194e-01 3.0106577e-01 + 0.0000000e+00 2.0922099e-01 3.0051620e-01 + 0.0000000e+00 2.0885003e-01 2.9996663e-01 + 0.0000000e+00 2.0847907e-01 2.9941706e-01 + 0.0000000e+00 2.0810811e-01 2.9886749e-01 + 0.0000000e+00 2.0773715e-01 2.9831793e-01 + 0.0000000e+00 2.0736619e-01 2.9776836e-01 + 0.0000000e+00 2.0699523e-01 2.9721879e-01 + 0.0000000e+00 2.0662427e-01 2.9666922e-01 + 0.0000000e+00 2.0625331e-01 2.9611965e-01 + 0.0000000e+00 2.0588235e-01 2.9557008e-01 + 0.0000000e+00 2.0551139e-01 2.9502051e-01 + 0.0000000e+00 2.0514043e-01 2.9447094e-01 + 0.0000000e+00 2.0476948e-01 2.9392137e-01 + 0.0000000e+00 2.0439852e-01 2.9337180e-01 + 0.0000000e+00 2.0402756e-01 2.9282223e-01 + 0.0000000e+00 2.0365660e-01 2.9227266e-01 + 0.0000000e+00 2.0328564e-01 2.9172310e-01 + 0.0000000e+00 2.0291468e-01 2.9117353e-01 + 0.0000000e+00 2.0254372e-01 2.9062396e-01 + 0.0000000e+00 2.0217276e-01 2.9007439e-01 + 0.0000000e+00 2.0180180e-01 2.8952482e-01 + 0.0000000e+00 2.0143084e-01 2.8897525e-01 + 0.0000000e+00 2.0105988e-01 2.8842568e-01 + 0.0000000e+00 2.0068892e-01 2.8787611e-01 + 0.0000000e+00 2.0031797e-01 2.8732654e-01 + 0.0000000e+00 1.9994701e-01 2.8677697e-01 + 0.0000000e+00 1.9957605e-01 2.8622740e-01 + 0.0000000e+00 1.9920509e-01 2.8567783e-01 + 0.0000000e+00 1.9883413e-01 2.8512827e-01 + 0.0000000e+00 1.9846317e-01 2.8457870e-01 + 0.0000000e+00 1.9809221e-01 2.8402913e-01 + 0.0000000e+00 1.9772125e-01 2.8347956e-01 + 0.0000000e+00 1.9735029e-01 2.8292999e-01 + 0.0000000e+00 1.9697933e-01 2.8238042e-01 + 0.0000000e+00 1.9660837e-01 2.8183085e-01 + 0.0000000e+00 1.9623741e-01 2.8128128e-01 + 0.0000000e+00 1.9586645e-01 2.8073171e-01 + 0.0000000e+00 1.9549550e-01 2.8018214e-01 + 0.0000000e+00 1.9512454e-01 2.7963257e-01 + 0.0000000e+00 1.9475358e-01 2.7908300e-01 + 0.0000000e+00 1.9438262e-01 2.7853344e-01 + 0.0000000e+00 1.9401166e-01 2.7798387e-01 + 0.0000000e+00 1.9364070e-01 2.7743430e-01 + 0.0000000e+00 1.9326974e-01 2.7688473e-01 + 0.0000000e+00 1.9289878e-01 2.7633516e-01 + 0.0000000e+00 1.9252782e-01 2.7578559e-01 + 0.0000000e+00 1.9215686e-01 2.7523602e-01 + 0.0000000e+00 1.9178590e-01 2.7468645e-01 + 0.0000000e+00 1.9141494e-01 2.7413688e-01 + 0.0000000e+00 1.9104399e-01 2.7358731e-01 + 0.0000000e+00 1.9067303e-01 2.7303774e-01 + 0.0000000e+00 1.9030207e-01 2.7248817e-01 + 0.0000000e+00 1.8993111e-01 2.7193861e-01 + 0.0000000e+00 1.8956015e-01 2.7138904e-01 + 0.0000000e+00 1.8918919e-01 2.7083947e-01 + 0.0000000e+00 1.8881823e-01 2.7028990e-01 + 0.0000000e+00 1.8844727e-01 2.6974033e-01 + 0.0000000e+00 1.8807631e-01 2.6919076e-01 + 0.0000000e+00 1.8770535e-01 2.6864119e-01 + 0.0000000e+00 1.8733439e-01 2.6809162e-01 + 0.0000000e+00 1.8696343e-01 2.6754205e-01 + 0.0000000e+00 1.8659247e-01 2.6699248e-01 + 0.0000000e+00 1.8622152e-01 2.6644291e-01 + 0.0000000e+00 1.8585056e-01 2.6589334e-01 + 0.0000000e+00 1.8547960e-01 2.6534378e-01 + 0.0000000e+00 1.8510864e-01 2.6479421e-01 + 0.0000000e+00 1.8473768e-01 2.6424464e-01 + 0.0000000e+00 1.8436672e-01 2.6369507e-01 + 0.0000000e+00 1.8399576e-01 2.6314550e-01 + 0.0000000e+00 1.8362480e-01 2.6259593e-01 + 0.0000000e+00 1.8325384e-01 2.6204636e-01 + 0.0000000e+00 1.8288288e-01 2.6149679e-01 + 0.0000000e+00 1.8251192e-01 2.6094722e-01 + 0.0000000e+00 1.8214096e-01 2.6039765e-01 + 0.0000000e+00 1.8177001e-01 2.5984808e-01 + 0.0000000e+00 1.8139905e-01 2.5929851e-01 + 0.0000000e+00 1.8102809e-01 2.5874895e-01 + 0.0000000e+00 1.8065713e-01 2.5819938e-01 + 0.0000000e+00 1.8028617e-01 2.5764981e-01 + 0.0000000e+00 1.7991521e-01 2.5710024e-01 + 0.0000000e+00 1.7954425e-01 2.5655067e-01 + 0.0000000e+00 1.7917329e-01 2.5600110e-01 + 0.0000000e+00 1.7880233e-01 2.5545153e-01 + 0.0000000e+00 1.7843137e-01 2.5490196e-01 diff --git a/dependencies/@AnalyzeKriging/calcExpectedImprovement.m b/dependencies/@AnalyzeKriging/calcExpectedImprovement.m index 133456e..6066290 100644 --- a/dependencies/@AnalyzeKriging/calcExpectedImprovement.m +++ b/dependencies/@AnalyzeKriging/calcExpectedImprovement.m @@ -19,6 +19,15 @@ % For further optional settings and more details about the calculation of % expected improvement see "calcExpectedImprovementMainPart()" % +% Note: For more information about how to introduces fuzzy inequality +% constraints for the output see documentation for +% "modExpImprByOutputConstr". For fuzzy constraints the probability is +% calculated that these constraints hold. If fuzzy constraints are +% available than the modified expected improvement value is a compormise +% between achieving high improvement and not violating the constraints. +% This should be prefered for Markov Chain Monte Charlo Design of +% Experiment instead of hard constraints. +% % Copyright 2014-2016: Lars Freier, Eric von Lieres % See the license note at the end of the file. @@ -56,6 +65,13 @@ ExpectedImprovement = ExpectedImprovement'; end +% Include Inequality constraint distribution into final expected +% improvement +if isprop(obj,'InequalityConstraintOutputDistribution')&&~isempty(obj.getInequalityConstraintOutputDistribution) + predictionProto = -obj.MinMax(KrigingObjectIndex)*prediction(:,1); + ExpectedImprovement = obj.modExpImprByOutputConstr(ExpectedImprovement,predictionProto,prediction(:,2)); +end + end % ============================================================================= % KriKit - Kriging toolKit diff --git a/dependencies/@AnalyzeKriging/calcExpectedImprovementFromPredictions.m b/dependencies/@AnalyzeKriging/calcExpectedImprovementFromPredictions.m deleted file mode 100644 index bd89bac..0000000 --- a/dependencies/@AnalyzeKriging/calcExpectedImprovementFromPredictions.m +++ /dev/null @@ -1,66 +0,0 @@ -function [ExpectedImprovement]=calcExpectedImprovementFromPredictions(obj,varargin) -% [ExpectedImprovement]=calcExpectedImprovement(obj,KrigingObjectIndex,predictions) -% KrigingObjectIndex ... indicates the which Kriging Objective -% is considered -% prediction ... nPoints X 1 matrix containing Kriging predictions -% -% Copyright 2014-2016: Lars Freier, Eric von Lieres -% See the license note at the end of the file. - - KrigingObjectIndex = varargin{1}; - if length(KrigingObjectIndex)~=1 - error('KrigingObjectIndex must be a scalar') - end - - % Make Prediction - prediction = varargin{2}; - prediction(:,1) = -obj.MinMax(1)*prediction(:,1); - - % Calculate the expected improvements at the particular sample - % locations - % Best Measurement so far - % minOutput = min(obj.MinMax(1)*obj.KrigingObjects{KrigingObjectIndex}.getOutputData); - outputData = -obj.MinMax(KrigingObjectIndex)*obj.KrigingObjects{KrigingObjectIndex}.getOutputData; - [~,indexMin] = min(outputData); - bestOutput = outputData(indexMin); - % Argument for cumulative distribution function - u = (bestOutput - prediction(:,1))./prediction(:,2); - % Calculate expected improvement - % if statistic toolbox is installed, the following command can be used: - % ExpectedImprovement = (minOutput - prediction(:,1)).*normcdf(u,0,1) + prediction(:,2).*normpdf(u,0,1); - % ExpectedImprovement = (minOutput - prediction(:,1)).*(1/2+1/2*erf(u/sqrt(2)))+... - % prediction(:,2)./sqrt(2*pi).*exp(-u.^2/2); - switch obj.DegreeOfExpectedImprovement - case 0 - ExpectedImprovement = Phi(u); - case 1 - ExpectedImprovement = prediction(:,2).*(u.*Phi(u)+phi(u)); - case 2 - ExpectedImprovement = prediction(:,2).^2.*((u.^2+1).*Phi(u) +u.*phi(u)); - case 3 - ExpectedImprovement = prediction(:,2).^3.*((u.^3+3*u).*Phi(u) + (2+u.^2).*phi(u)); - otherwise - [ExpectedImprovement] = calcFinalExpImprovement(obj,prediction,u); - end - - %% Nested Function - function [cumProb]=Phi(x) - cumProb = (1/2+1/2*erf(x/sqrt(2))); - end - function [prob]=phi(x) - prob = 1./sqrt(2*pi).*exp(-x.^2/2); - end - -end -% ============================================================================= -% KriKit - Kriging toolKit -% -% Copyright 2014-2016: Lars Freier(1), Eric von Lieres(1) -% -% (1)Forschungszentrum Juelich GmbH, IBG-1, Juelich, Germany. -% -% All rights reserved. This program and the accompanying materials -% are made available under the terms of the GNU Public License v3.0 (or, at -% your option, any later version) which accompanies this distribution, and -% is available at http://www.gnu.org/licenses/gpl.html -% ============================================================================= diff --git a/dependencies/@AnalyzeKriging/calcExpectedImprovement_MO.m b/dependencies/@AnalyzeKriging/calcExpectedImprovement_MO.m index faa5b4a..da01e84 100644 --- a/dependencies/@AnalyzeKriging/calcExpectedImprovement_MO.m +++ b/dependencies/@AnalyzeKriging/calcExpectedImprovement_MO.m @@ -22,13 +22,13 @@ % [boolConstraintHolds]=inequalityConstraintOutput(estimationMean,estimationSD) % With % estimationMean ... kriging prediction at the point of interest -% given in "estimationPoints" [nPointsX1] +% given in "estimationPoints" [nPointsXnObj] % estimationSD ... kriging prediction error at the point of % interest, given in "estimationPoints" % [nPointsX1] % boolConstraintHolds ... boolean output vector containing true % if the point hold the constraint -% [nPointsX1] +% [nPointsXnObj] % % - DegreeOfExpectedImprovement ... exploration factor for adjusting the % trade-off between exploitation and exploration. @@ -42,7 +42,17 @@ % You can get: % % Note: Before Running "calcExpectedImprovement_MO" you should calculate -% the run "determineParetoSet()" +% the run "determineParetoSet()". +% +% Note: For more information about how to introduces fuzzy inequality +% constraints for the output see documentation for +% "modExpImprByOutputConstr". For fuzzy constraints the probability is +% calculated that these constraints hold. If fuzzy constraints are +% available than the modified expected improvement value is a compormise +% between achieving high improvement and not violating the constraints. +% This should be prefered for Markov Chain Monte Charlo Design of +% Experiment instead of hard constraints (like +% "InequalityConstraintOutputHandle" ) % % Copyright 2014-2016: Lars Freier, Eric von Lieres % See the license note at the end of the file. @@ -138,6 +148,12 @@ end end +% Include Inequality constraint distribution into final expected +% improvement +if isprop(obj,'InequalityConstraintOutputDistribution')&&~isempty(obj.getInequalityConstraintOutputDistribution) + estimationMeanProto = bsxfun(@times,estimationMean,-obj.MinMax(objectiveIndices)); + ExpectedImprovement = obj.modExpImprByOutputConstr(ExpectedImprovement,estimationMeanProto,estimationSD); +end end diff --git a/dependencies/@AnalyzeKriging/calcMutualInterpolation_23D.m b/dependencies/@AnalyzeKriging/calcMutualInterpolation_23D.m index c20df0b..659efe7 100644 --- a/dependencies/@AnalyzeKriging/calcMutualInterpolation_23D.m +++ b/dependencies/@AnalyzeKriging/calcMutualInterpolation_23D.m @@ -106,9 +106,11 @@ RemainingIndices = varargin{3}; RemainingValues = varargin{4}; if length(unique([varargin{2},RemainingIndices]))~=nInputData + errorCheck(); error('Entries in "[InputVar1,InputVar2]" and "RemainingIndices" must be unique') end if (size(RemainingValues,1)*size(RemainingValues,2))~=nInputData-(dimensionInterpolation-1) + errorCheck(); error('RemainingValues must be a vector with length %i',nInputData-(dimensionInterpolation-1)) end diff --git a/dependencies/@AnalyzeKriging/checkInputInterpolation.m b/dependencies/@AnalyzeKriging/checkInputInterpolation.m index 3ce4ab1..4cad6b9 100644 --- a/dependencies/@AnalyzeKriging/checkInputInterpolation.m +++ b/dependencies/@AnalyzeKriging/checkInputInterpolation.m @@ -58,9 +58,11 @@ RemainingIndices = varargin{3}; RemainingValues = varargin{4}; if length(unique([varargin{2},RemainingIndices]))~=obj.KrigingObjects{KrigingObjectIndex(1)}.getnInputVar + errorCheck(); error('Entries in "[InputVar1,InputVar2]" and "RemainingIndices" must be unique') end if dimensionInterpolation>2&&(size(RemainingValues,1)*size(RemainingValues,2))~=obj.KrigingObjects{KrigingObjectIndex(1)}.getnInputVar-2 + errorCheck(); error('RemainingValues must be a vector with length %i',obj.KrigingObjects{KrigingObjectIndex(1)}.getnInputVar-2) end diff --git a/dependencies/@AnalyzeKriging/defineBoundOfInputVar.m b/dependencies/@AnalyzeKriging/defineBoundOfInputVar.m index 17c1158..cd45d0c 100644 --- a/dependencies/@AnalyzeKriging/defineBoundOfInputVar.m +++ b/dependencies/@AnalyzeKriging/defineBoundOfInputVar.m @@ -19,9 +19,9 @@ obj.UBInputVarInterpolation{KrigingObjectIndex(iKriging)} = max(obj.KrigingObjects{KrigingObjectIndex(iKriging)}.getInputData); end - if sum(obj.LBInputVarInterpolation{KrigingObjectIndex(iKriging)}>=obj.UBInputVarInterpolation{KrigingObjectIndex(iKriging)})>=1 - error('One of the upper bounds is smaller or equal to the associated lower bound. ') - end +% if sum(obj.LBInputVarInterpolation{KrigingObjectIndex(iKriging)}>=obj.UBInputVarInterpolation{KrigingObjectIndex(iKriging)})>=1 +% error('One of the upper bounds is smaller or equal to the associated lower bound. ') +% end end end % ============================================================================= diff --git a/dependencies/@AnalyzeKriging/errorCheck.p b/dependencies/@AnalyzeKriging/errorCheck.p new file mode 100644 index 0000000000000000000000000000000000000000..b9631ecda54b334ca02bd457a3def6736df217d6 GIT binary patch literal 1420 zcmV;71#|j#FflGLFm^C7E-)|v1&|!2Pd~8$04}xw00nFS07m91_+^WRBFvs#O(6nB zvf=CaQfn9G#v$Xn9@ht^pb(N)^NJQD@eSx*uFT%eV#RU#|ExQDs84!rnVOLFe88of z6V;mfu>v#m=E8QfvxY|&c=&`vPb-I?W9bt6qH%Czr#>7ghbeVQU%@D1WY?T;VusqJ zjT3$X1*vfahrC|+;Y(7uao#Z-M_~Jj+crsI0K^a9Ex-@nGuwj1O%9VqH=q(G>^{@) zDu)Y-=*wmGbzs?pYQq%sRRyt4X7C@y7!Duq>Q;wh)hp zYS$i?`)g`-&F*;QIJ*Or#OH2m%rraXV~Bsd%U;#XjTw0fcbPYaeKDA4kD zEd_m%B=fPqH(qFN62E7Jttyi*%lqCmV_kkpEzawNf1yXRKSBs!GUv4S>=z^-H!SH*l~0kAsPr^2?gi8z7b+P%?Tou5hdsJ@Kq{+(^UjUaa+H#y@X zMFtphzf_Pw$e&|pdNag5`%ui-6ggObfue6bK`!;~^}>|XE2V=r1~m4UTJ zP-Om3Ez^|!(}DMD_sV6#&)Cd;nkEObq!;G<;erI_ORmmG=kUUt6gc0V_NB|>{uqNQ zP{Kn2uVAiYdHusm9its!e#kRFX!L_qTs&fU1S&rMMDVZ{O{cQBe?$Tp;;x z@Yemo?u~jf+6XA;uEa(}%YBj<@axEEzUCgR9mU0rxZpxASJY+F)G*pO5_c&-3Y z_liDlK$KsnE9ruz?)4+?B$F?RrsB)EKec6vtpyU|xPD~X0BIiW#zN)UvLuS|aQc>Y z7kbH{P1c@dV>R}`QT*H(%!cP_}Z8UYDcBQ*(Najv6shrE?Ngk#{a z*#p6x&Kmwu9uESoJ3N^Jd$*S}@eD$lQ0$9rJ^+JogjEF-m-HAX|CF%fE^7Ufqv0I1wtRrilSTRIHu?Oh(;v*HJ)B#>u$norgLLMYjO)NjEn5 z3P9OO((yv#Xh3u}37R-#udOcm=}>`hqr`%tu|0iAc718-pzx+GoN1JloV?RLP;1do z2UX=j$MY~{c$A$A*(5qbFDJbuhT0dtWAcG1?i)W5saw>nPVy0%zv|Tx@2=K`IDI0WjgeE zTpF5s?HOs!jc$;+E$)38Sl+CgT|SKiSP5DG*@{I8XL0PQi@4xBEq#MMmY)Ex=p)j( aZfb?l<;p5R9eo5hd%pndEM=>O+!^&Yxy9B1 literal 0 HcmV?d00001 diff --git a/dependencies/@AnalyzeKriging/plotInterpolation_23D.m b/dependencies/@AnalyzeKriging/plotInterpolation_23D.m index 729edb4..3c6a0d5 100644 --- a/dependencies/@AnalyzeKriging/plotInterpolation_23D.m +++ b/dependencies/@AnalyzeKriging/plotInterpolation_23D.m @@ -98,7 +98,7 @@ % Set Colormap colormap(gcf,obj.ColormapToolbox); - +grid on %% Nested Functions % ------------------------------------------------------------------------- @@ -173,7 +173,7 @@ unique(obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,2}(:,inputIndices(2))),... reshape(output,AccuracyTemp,AccuracyTemp)') else - mesh(unique(obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,2}(:,inputIndices(1))),... + surf(unique(obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,2}(:,inputIndices(1))),... unique(obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,2}(:,inputIndices(2))),... reshape(output,AccuracyTemp,AccuracyTemp)') end @@ -196,12 +196,12 @@ UB,'-.','Color',[0.3 0.3 0.3]); case 3 % LB - mesh(unique(obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,2}(:,obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,3}(1))),... + surf(unique(obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,2}(:,obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,3}(1))),... unique(obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,2}(:,obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,3}(2))),... reshape(LB,AccuracyTemp,AccuracyTemp)') % UB - mesh(unique(obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,2}(:,obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,3}(1))),... + surf(unique(obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,2}(:,obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,3}(1))),... unique(obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,2}(:,obj.KrigingPrediction_Interpolation3D{KrigingObjectIndex,3}(2))),... reshape(UB,AccuracyTemp,AccuracyTemp)') otherwise diff --git a/dependencies/@AnalyzeKriging/plotParetoFront.m b/dependencies/@AnalyzeKriging/plotParetoFront.m index 19d390d..bdcb315 100644 --- a/dependencies/@AnalyzeKriging/plotParetoFront.m +++ b/dependencies/@AnalyzeKriging/plotParetoFront.m @@ -1,5 +1,7 @@ function [] = plotParetoFront(obj,varargin) % [] = plotParetoFront(krigingObjVector,expectedParetoCurve,deviationParetoCurve,pCover,gridOriginal); +% This function plots the results produced by "predictParetoCurve" +% % Input: % - krigingObjVector(1XnObjectives): contains indices of kriging objects % - expectedParetoCurve(nParetoPointsXnObjectives): matrix contains @@ -44,21 +46,29 @@ gridOriginal = varargin{5}; nObj = length(krigingObjVector); - nGridPointsOutput = round(size(gridOriginal,1)^(1/nObj)); +% nGridPointsOutput = round(size(gridOriginal,1)^(1/nObj)); % Determine Unique Grid uniqueGridMatrix = calcUniqueGridMatrix(); % Find Quantiles in order to define the confidence tube - [gridToLow,gridToBig]=determinConfidenceBounds; + if obj.getShowBounds + [gridToLow,gridToBig]=determinConfidenceBounds; + end switch nObj case 2 + levelVec = unique(deviationParetoCurve(deviationParetoCurve>obj.getThresholdQuantile)); + figure() hold on - contourf(uniqueGridMatrix(:,1),uniqueGridMatrix(:,2),reshape(deviationParetoCurve,nGridPointsOutput,nGridPointsOutput)'); - hExpected = plot(expectedParetoCurve(:,1),expectedParetoCurve(:,2),'k.','MarkerSize',15); - + contourf(uniqueGridMatrix{1},... + uniqueGridMatrix{2},... + reshape(deviationParetoCurve,length(uniqueGridMatrix{1}),length(uniqueGridMatrix{2}))',... + levelVec); + [expectedParetoCurveXSort,idx] = sort(expectedParetoCurve(:,1)); + hExpected = plot(expectedParetoCurveXSort,expectedParetoCurve(idx,2),'k-','LineWidth',2); + if obj.getShowBounds % sort in ascend w.r.t to the first objective but descend % order w.r.t to the second objective @@ -149,14 +159,14 @@ %% Nested function [uniqueGridMatrix] = calcUniqueGridMatrix() - uniqueGridMatrix = zeros(nGridPointsOutput,nObj); + uniqueGridMatrix = cell(nObj,1); % Bring Data Set in correct order for iObjNested=1:nObj krigingIndexNested = krigingObjVector(iObjNested); if obj.getMinMax(krigingIndexNested)==1 - uniqueGridMatrix(:,iObjNested)=sort(unique(gridOriginal(1:end,krigingIndexNested)),'ascend'); + uniqueGridMatrix{iObjNested}=sort(unique(gridOriginal(1:end,krigingIndexNested)),'ascend'); else - uniqueGridMatrix(:,iObjNested)=sort(unique(gridOriginal(1:end,krigingIndexNested)),'descend'); + uniqueGridMatrix{iObjNested}=sort(unique(gridOriginal(1:end,krigingIndexNested)),'descend'); end end end @@ -170,8 +180,11 @@ % Choose all points outside off and at the broder off desired % confidence region - qToLow = pCover<=quantileValueLB; - qToBig = pCover>=quantileValueUB; + qToLow = pCover(end:-1:1)<=quantileValueLB; + qToBig = pCover(end:-1:1)>=quantileValueUB; + if ~any(qToLow)||~any(qToBig) + error('No point in the solution space fits the quantile contraints. This can be solved by adjusting number of simulations or by adjusting the outputConstraint for the "predictParetoCurve" function. You can also deactivate "ShowBounds"') + end % Define confidence borders gridToLow = determineParetoSet_Mex(bsxfun(@times,gridOriginal(qToLow,:),obj.MinMax(krigingObjVector))); diff --git a/dependencies/@AnalyzeKriging/predictParetoCurve.m b/dependencies/@AnalyzeKriging/predictParetoCurve.m index 5baa953..76b0420 100644 --- a/dependencies/@AnalyzeKriging/predictParetoCurve.m +++ b/dependencies/@AnalyzeKriging/predictParetoCurve.m @@ -1,5 +1,5 @@ function [expectedParetoCurve,deviationParetoCurve,pCover,gridOutput] = predictParetoCurve(obj,varargin) -% [expectedParetoCurve,deviationParetoCurve,pCover,gridOutput] = predictParetoCurve(krigingObjVector,nRealizations,nSampleLocations,nGridPointEachDirection,inEqualityCellArray) +% [expectedParetoCurve,deviationParetoCurve,pCover,gridOutput] = predictParetoCurve(krigingObjVector,nRealizations,nSampleLocations,nGridPointEachDirection,inEqualityCellArray,OutputConstraints) % % This function estimated the expected pareto curve pareto based on % conditional simulation results. Theory is described in detail in is @@ -57,6 +57,9 @@ % out a (nSamplePointsX1)-boolean vector. Where % each entry indicates if the associated sample % point is valid (true) or not (false). +% - OutputConstraints ... a matrix (nKrigingObjectsX2) containing the +% feasible lower and upperbound for the output +% space which shall be investigated % Output: % - expectedParetoCurve ... objective matrix containing the Pareto points % (nParetoPointsXnKrigingObjects) @@ -69,9 +72,13 @@ % You can set: % - setShowData ... Scan solution space also w.r.t. to the given output % data. This might needed if you want to plot the expected Pareto Curve -% together with the data +% together with the data. Caution: This might lead to a ncombinatorical +% explosion! % - LB(UB)InputVarInterpolation ... restict the input space for the % conditional simulation +% - RepeatDesign ... If "false" than a different lattin hypercube design +% is used for each realization (more roust but more +% expensive) % % You can get: - % @@ -96,11 +103,19 @@ nGridPointEachDirection = 1e6^(1/nObjects); inequalityConstraintInput = {}; end -if length(varargin)>5&&~isempty(varargin{6}) - inEqualityCellArray = varargin{6}; +if length(varargin)>4&&~isempty(varargin{5}) + inEqualityCellArray = varargin{5}; else inEqualityCellArray = {}; end +if length(varargin)>5&&~isempty(varargin{6}) + OutputConstraints = varargin{6}; +else + OutputConstraints = ones(nObjects,2); + OutputConstraints(:,1) = -inf; + OutputConstraints(:,2) = inf; +end + % If inequalityConstraintInput is given, nSampleLocations might change defineBoundOfInputVar(obj,krigingObjVector(krigingObjVector(1))); @@ -146,7 +161,7 @@ paretoSets{iRealization} = determineParetoSet_Mex(... bsxfun(@times,realizationCurveMaxtrix(:,indexSet),-obj.MinMax(krigingObjVector)) ); - + % Save Pareto Set in Matrix totalParetoSet = [totalParetoSet;paretoSets{iRealization}]; nMemberPratoCurve(iRealization) = size(paretoSets{iRealization},1); @@ -161,7 +176,12 @@ [rangeToCheck] = determineRangeForGrid; % Create Grid -gridX = createNDGRID(rangeToCheck(:,1),rangeToCheck(:,2),nGridPointEachDirection); +if obj.ShowData + gridX = createNDGRID(rangeToCheck(:,1),rangeToCheck(:,2),nGridPointEachDirection,totalParetoSet); +else + gridX = createNDGRID(rangeToCheck(:,1),rangeToCheck(:,2),nGridPointEachDirection); +end + nGridPoints = size(gridX,1); % Actual Calculation @@ -217,7 +237,8 @@ expectedParetoCurve,... pCover); deviationParetoCurve(1:end) = deviationParetoCurve(end:-1:1); - + pCover(1:end) = pCover(end:-1:1); + %% #### Convert everything back to the original space #### expectedParetoCurve = bsxfun(@times,expectedParetoCurve,-obj.MinMax(krigingObjVector)); gridOutput = bsxfun(@times,gridX,-obj.MinMax(krigingObjVector)); @@ -229,7 +250,7 @@ function [rangeToCheck] = determineRangeForGrid() % Initialization - rangeToCheck = []; + rangeToCheck = nan(nObjects,2); % Check provided sample points if obj.getShowData @@ -247,11 +268,17 @@ rangeToCheck(iKrigingObj,:) = [min(paretoSets{iRealizationNested}(:,iKrigingObj)),... max(paretoSets{iRealizationNested}(:,iKrigingObj))]; else - rangeToCheck(iKrigingObj,:) = [min([rangeToCheck(iKrigingObj,1),rangeToCheck(iKrigingObj,2),min(paretoSets{iRealizationNested}(:,iKrigingObj))]),... - max([rangeToCheck(iKrigingObj,1),rangeToCheck(iKrigingObj,2),min(paretoSets{iRealizationNested}(:,iKrigingObj))])]; + + pointsToCheck = [rangeToCheck(iKrigingObj,1),... + rangeToCheck(iKrigingObj,2),... + (paretoSets{iRealizationNested}(:,iKrigingObj))']; + rangeToCheck(iKrigingObj,:) = ... + [min(pointsToCheck),... + max(pointsToCheck)]; end end end + % Check if scale of data prediction are similar if obj.getShowData @@ -267,6 +294,16 @@ end end + if ~isempty(OutputConstraints) + if ~all(size(rangeToCheck)==size(OutputConstraints)) + error('OutputConstraints should be of Size nKrigingObjectsX2') + end + rangeToCheckProto = bsxfun(@times,(-obj.MinMax(krigingObjVector)'),OutputConstraints); + rangeToCheckProto = sort(rangeToCheckProto,2); % Guaranty that LBis first column + + rangeToCheck(~isinf(rangeToCheckProto)) = rangeToCheckProto(~isinf(rangeToCheckProto)); + + end end % ---------------------------------------------------------- @@ -274,16 +311,46 @@ epsilon = 1e-10; lowerLevel = 0; upperLevel = 1; + deltaNew = inf; + deltaOld = inf; + HV_QuantileOld = inf; + upperLevelOld = upperLevel; + lowerLevelOld = lowerLevel; + + firstTime = true; while upperLevel-lowerLevel>epsilon + if ~firstTime + deltaOld = deltaNew; + HV_QuantileOld = HV_Quantile; + end + pointsSelected = pCover>=(upperLevel+lowerLevel)/2; - HV_Quantile = Hypervolume_MEX(gridX(pointsSelected,:),bsxfun(@times,obj.ReferencePointHyperVolume(krigingObjVector),-obj.MinMax(krigingObjVector))); - - if HV_Quantileobj.getnKrigingObjects + error('KrigingObjectIndex must be a scalar between 1 and %i',obj.getnKrigingObjects) + end + % A row vector is needed if size(LBUBInputVarInterpolation,1)==obj.KrigingObjects{KrigingObjectIndex}.getnInputVar&&size(LBUBInputVarInterpolation,2)==1 LBUBInputVarInterpolation = LBUBInputVarInterpolation'; @@ -20,17 +25,17 @@ error('LB/UBInputVarInterpolation has to be of dimension 1x%i',obj.KrigingObjects{KrigingObjectIndex}.getnInputVar) end - % Check Input - if length(KrigingObjectIndex)~=1||KrigingObjectIndex<1||KrigingObjectIndex>obj.getnKrigingObjects - error('KrigingObjectIndex must be a scalar between 1 and %i',obj.getnKrigingObjects) - end + switch LBorUB case -1 obj.LBInputVarInterpolation{KrigingObjectIndex} = LBUBInputVarInterpolation; case 1 - if sum(obj.LBInputVarInterpolation{KrigingObjectIndex}>=LBUBInputVarInterpolation)>=1 - error('One of the upper bounds is smaller or equal to the associated lower bound. Please define the lower bound first') + if any(obj.LBInputVarInterpolation{KrigingObjectIndex}>LBUBInputVarInterpolation) + error('One of the upper bounds is smaller than the associated lower bound. Please define the lower bound first') + end + if all(obj.LBInputVarInterpolation{KrigingObjectIndex}==LBUBInputVarInterpolation) + error('All upper bounds is smaller or equal to the associated lower bound. Please define the lower bound first') end obj.UBInputVarInterpolation{KrigingObjectIndex} = LBUBInputVarInterpolation; otherwise diff --git a/dependencies/@AnalyzeMixture/AnalyzeMixture.m b/dependencies/@AnalyzeMixture/AnalyzeMixture.m index c4238d0..0cbd679 100644 --- a/dependencies/@AnalyzeMixture/AnalyzeMixture.m +++ b/dependencies/@AnalyzeMixture/AnalyzeMixture.m @@ -14,7 +14,7 @@ %% Private Members properties(GetAccess='private',SetAccess='private') - + PartOfMixture = []; end %% Protected Members @@ -25,6 +25,7 @@ %% Constructor function obj = AnalyzeMixture() obj@AnalyzeKriging(); + end %% Copy Operator for a shallow copy % ---------------------------------------------------------------- @@ -176,6 +177,35 @@ [] = labelPlots_23D(obj,varargin); % ---------------------------------------------------------------- [] = plotInterpolation_23D(obj,varargin) + + + + + + %% Get + % ---------------------------------------------------------------- + function [PartOfMixture] = getPartOfMixture(obj) + PartOfMixture = obj.PartOfMixture; + end + + %% Set + % ---------------------------------------------------------------- + function [] = setPartOfMixture(obj,varargin) + PartOfMixture = varargin{1}; + idxObj = varargin{2}; + if mod(idxObj,1)~=0 || length(idxObj)~=1 || idxObj>obj.getnKrigingObjects + error('Second input (idxObj) has to be an integer') + end + if length(PartOfMixture)~=obj.KrigingObjects{idxObj}.getnInputVar || ... + (size(PartOfMixture,1)*size(PartOfMixture,2))~=obj.KrigingObjects{idxObj}.getnInputVar + error('PartOfMixture has to be a vector of 1XninputVar') + end + if ~islogical(PartOfMixture) + error('PartOfMixture must contain only logical entries') + end + obj.PartOfMixture = PartOfMixture; + end +% PartOfMixture end end diff --git a/dependencies/@AnalyzeMixture/calcInterpolation.m b/dependencies/@AnalyzeMixture/calcInterpolation.m index 54e3c13..055bc33 100644 --- a/dependencies/@AnalyzeMixture/calcInterpolation.m +++ b/dependencies/@AnalyzeMixture/calcInterpolation.m @@ -47,7 +47,7 @@ nUnique = size(uniqueRows,1); iIndex = 0; for iUnique = 1:nUnique - concVec = linspace(0,1-sum(uniqueRows(iUnique,:),2),obj.getAccuracy); + concVec = linspace(0,1-sum(uniqueRows(iUnique,obj.PartOfMixture),2),obj.getAccuracy); for iAccuary=1:obj.getAccuracy indexStart = iIndex+(iAccuary-1)*obj.getAccuracy^(2-iComponent) + 1; indexEnd = iIndex+(iAccuary)*obj.getAccuracy^(2-iComponent); @@ -56,9 +56,12 @@ iIndex = iIndex+obj.getAccuracy^(iComponent-1); end end +% Input = createNDGRID([0,0],[1,1],obj.getAccuracy); % Use definition of mixtrue: Sum of input variables has to be 100% -indicesOthers = setdiff(1:obj.KrigingObjects{KrigingObjectIndex}.getnInputVar,inputVarIndices(3)); +idxAll = 1:obj.KrigingObjects{KrigingObjectIndex}.getnInputVar; +idxDoNotMod = [inputVarIndices(3),idxAll(~obj.PartOfMixture)]; +indicesOthers = setdiff(1:obj.KrigingObjects{KrigingObjectIndex}.getnInputVar,idxDoNotMod); Input(:,inputVarIndices(3)) = 1- sum(Input(:,indicesOthers),2); Input = unique(Input,'rows'); diff --git a/dependencies/@AnalyzeMixture/calcInterpolation_nD.m b/dependencies/@AnalyzeMixture/calcInterpolation_nD.m index 187a001..b51566e 100644 --- a/dependencies/@AnalyzeMixture/calcInterpolation_nD.m +++ b/dependencies/@AnalyzeMixture/calcInterpolation_nD.m @@ -140,16 +140,20 @@ nUnique = size(uniqueRows,1); iIndex = 0; for iUnique = 1:nUnique - concVec = linspace(0,1-sum(uniqueRows(iUnique,:),2),obj.getAccuracy); + concVec = linspace(0,1-sum(uniqueRows(iUnique,obj.PartOfMixture),2),obj.getAccuracy); for iAccuary=1:obj.getAccuracy - InputMatrix(iIndex+(iAccuary-1)*obj.getAccuracy^(nInputVarConti-1-iComponent)+startIndex + 1:iIndex+(iAccuary)*obj.getAccuracy^(nInputVarConti-1-iComponent)+startIndex,inputVarIndices(iComponent)) = concVec(iAccuary); + InputMatrix(iIndex+(iAccuary-1)*obj.getAccuracy^(nInputVarConti-1-iComponent)+startIndex + 1:iIndex+(iAccuary)*obj.getAccuracy^(nInputVarConti-1-iComponent)+startIndex,inputVarIndices(iComponent)) = ... + concVec(iAccuary); end iIndex = iIndex+obj.getAccuracy^(iComponent-1); end end % Use definition of mixtrue: Sum of input variables has to be 100% - remainintVar = setdiff(1:obj.KrigingObjects{KrigingObjectIndex}.getnInputVar,inputVarIndices(3)); + + idxAll = 1:obj.KrigingObjects{KrigingObjectIndex}.getnInputVar; + idxDoNotMod = [inputVarIndices(3),idxAll(~obj.PartOfMixture)]; + remainintVar = setdiff(1:obj.KrigingObjects{KrigingObjectIndex}.getnInputVar,idxDoNotMod); InputMatrix(startIndex+1:endIndex,inputVarIndices(3)) = 1- sum(InputMatrix(startIndex+1:endIndex,remainintVar),2); threshold = [1-1e-10,1+1e-10]; diff --git a/dependencies/@AnalyzeMixture/plotInterpolation_nD.m b/dependencies/@AnalyzeMixture/plotInterpolation_nD.m index 6af04d1..0fb760c 100644 --- a/dependencies/@AnalyzeMixture/plotInterpolation_nD.m +++ b/dependencies/@AnalyzeMixture/plotInterpolation_nD.m @@ -44,7 +44,7 @@ % variables InputMatrixProto = obj.KrigingPrediction_InterpolationnD{KrigingObjectIndex,4}; nRows = size(InputMatrixProto,2); - +nCol = obj.getnPlots+obj.getShowColorBar; %% Actual Plotting figure(); hold on @@ -53,7 +53,8 @@ for iPlots1=1:nRows for iPlots2=1:obj.getnPlots createContourPlot(iPlots1,iPlots2); - set(gca,'PlotBoxAspectRatio',[1,1,1]) + set(gca,'PlotBoxAspectRatio',[1,1,1],'XTick',[],'YTick',[],'Visible','off') + end end @@ -66,15 +67,19 @@ end % Title -subplot(nRows,obj.getnPlots+1,ceil(obj.getnPlots/2)) -title(obj.getKrigingObjectNames{KrigingObjectIndex},'FontSize',20) +subplot(nRows,nCol,ceil(obj.getnPlots/2)) +title(sprintf('%s\n',obj.getKrigingObjectNames{KrigingObjectIndex}),'FontSize',20) % Colorbar -subplot(obj.getnPlots,obj.getnPlots+1,obj.getnPlots+1:obj.getnPlots+1:obj.getnPlots*(obj.getnPlots+1)) + +if obj.getShowColorBar + subplot(obj.getnPlots,obj.getnPlots+1,obj.getnPlots+1:obj.getnPlots+1:obj.getnPlots*(obj.getnPlots+1)) +end if obj.getNormColors==1 caxis([minEstimation,maxEstimation]) end if obj.getShowColorBar==1&&obj.getNormColors==1 + colorbar end @@ -95,7 +100,7 @@ indexSubPlot = (iRow-1)*(obj.getnPlots+1)+iPlots2; % Plot - subplot(nRows,obj.getnPlots+1,indexSubPlot); + subplot(nRows,nCol,indexSubPlot); hold on [uniqueRow,indexRows]=unique(InputMatrix(validIndicesSub,:),'rows'); ternpcolor(uniqueRow(:,inputVarIndices(iRow,1)),... @@ -110,7 +115,7 @@ else stringInputVar = obj.getInputVarNames(KrigingObjectIndex(1)); xString = sprintf('\n\n\n%s=%g\n',stringInputVar{inputVarIndices(iRow,1)},max(uniqueRow(:,inputVarIndices(iRow,1))) ); - yString = sprintf('%s=%g',stringInputVar{inputVarIndices(iRow,2)},max(uniqueRow(:,inputVarIndices(iRow,2))) ); + yString = sprintf('%s=%g\n\n',stringInputVar{inputVarIndices(iRow,2)},max(uniqueRow(:,inputVarIndices(iRow,2))) ); zString = sprintf('\n\n\n\t\t %s=%g\t\t ',stringInputVar{inputVarIndices(iRow,3)},max(uniqueRow(:,inputVarIndices(iRow,3))) ); end ternlabel(zString,yString,xString); @@ -128,7 +133,12 @@ plotSamples(Data,iRow,iPlots2) end end - + +% ternpcolor(uniqueRow(:,inputVarIndices(iRow,1)),... +% uniqueRow(:,inputVarIndices(iRow,2)),... +% uniqueRow(:,inputVarIndices(iRow,3)),... +% Estimation(validIndicesSub(indexRows))) + end % ------------------------------------------------------------- function []=plotSamples(Data,iRow,iPlots2) @@ -160,12 +170,14 @@ Data(r,obj.KrigingPrediction_InterpolationnD{KrigingObjectIndex,3}(iRow,2)),... Data(r,obj.KrigingPrediction_InterpolationnD{KrigingObjectIndex,3}(iRow,3)),... 'ko','MarkerFaceColor',[255/255 102/255 0/255]); + lineObj = findobj(gca,'type','line'); + lineObj.ZData=(ones(1,size(lineObj.XData,2))*max(Estimation)); end % ------------------------------------------------------------- function []=labelPlotxAxis(iRow,iPlots2) % subplot(obj.getnPlots,obj.getnPlots+1,(obj.getnPlots-1)*(obj.getnPlots+1)+iPlots1) indexSubPlot = (iRow-1)*(obj.getnPlots+1)+iPlots2; - subplot(nRows,obj.getnPlots+1,indexSubPlot) + subplot(nRows,nCol,indexSubPlot) % Use default names of input variables when user did not provide any if isempty(obj.getInputVarNames(KrigingObjectIndex)) diff --git a/dependencies/@BayesianOptimization/BayesianOptimization.m b/dependencies/@BayesianOptimizationClass/BayesianOptimizationClass.m similarity index 75% rename from dependencies/@BayesianOptimization/BayesianOptimization.m rename to dependencies/@BayesianOptimizationClass/BayesianOptimizationClass.m index 237a5a1..b2054e9 100644 --- a/dependencies/@BayesianOptimization/BayesianOptimization.m +++ b/dependencies/@BayesianOptimizationClass/BayesianOptimizationClass.m @@ -1,4 +1,4 @@ -classdef BayesianOptimization2015b and Statistic Toolbox) UseMatlabRegressionGP = false; GPR_Model = []; - + %% Noise Modeling + KriKitObjNoise = []; + ThresholdSolver = 1e-6; end methods @@ -317,6 +321,10 @@ solveLeastSquareCovariogramGA2(obj); % Generate RGP model for further Kriging estimation generateRegressionGPModel(obj); + %-------------------------------------- + % Estimates a model for heterodestatic noise + generateNoiseModel(obj,varargin) + %-------------------------------------- % gaCreationUniformFeasible function[Population]=gaCreationUniformFeasible(obj,GenomeLength,FitnessFcn,options) Population = bsxfun(@times,rand(sum(options.PopulationSize),GenomeLength),(obj.getUBBasisFctParameters - obj.getLBBasisFctParameters)); @@ -373,6 +381,10 @@ % ---------------------------------------------------------------- [realizationCurve,nonNormSampleLocations] = doConditionalSimulation_ResAlgInEq(obj,varargin) % ---------------------------------------------------------------- + [realizationCurve,nonNormSampleLocations] = doConditionalSimulation_Decomposition(obj,varargin) + % ---------------------------------------------------------------- + [realizationCurve,nonNormSampleLocations] = doConditionalSimulation_ResAlgInEqTest(obj,varargin) + % ---------------------------------------------------------------- function [] = checkIfNumberOfParameterValuesIsCorrect(obj,varargin) if(length(varargin{1})>obj.nCovariogramParameters) error('Covariogram needs only %i parameter but %i are defined!',obj.nCovariogramParameters,length(varargin{1})); @@ -743,7 +755,18 @@ function [CovariogramUsesAbsoluteDistance]=getCovariogramUsesAbsoluteDistance(obj) CovariogramUsesAbsoluteDistance = obj.CovariogramUsesAbsoluteDistance; end - + %------------------------------------------------------------------ + function [heterogeneousNoise]=getHeterogeneousNoise(obj) + heterogeneousNoise = obj.HeterogeneousNoise; + end + %------------------------------------------------------------------ + function [KriKitObjNoise]=getKriKitObjNoise(obj) + KriKitObjNoise = obj.KriKitObjNoise; + end + %------------------------------------------------------------------ + function [ThresholdSolver]=getThresholdSolver(obj) + ThresholdSolver = obj.ThresholdSolver; + end %% Set Functions function [] = setInputData(obj,Input) % Define the InputVariables the number of rows should be equal @@ -771,6 +794,7 @@ obj.InputData_True = Input; obj.nExperiments = size(Input,1); obj.nInputVar = size(Input,2); + obj.HeterogeneousNoise = []; if(obj.nInputVar>obj.nExperiments) warning('InputData: More Input variables as Experiments'); end @@ -884,17 +908,8 @@ switch obj.CovariogramModelChoice case 1 -% if(length(varargin{1})>2) -% warning('The exponential model needs only 2 parameter but %i are defined!',length(varargin{1})); -% end -% if(length(varargin{1})<2) -% error('The exponential model needs 2 parameter but only %i are defined!',length(varargin{1})); -% end obj.theta = varargin{1}(1); obj.sigma = varargin{1}(2); - -% obj.CovariogramUsesEuclideanDistance = true; -% obj.p = varargin{1}(3); case {2,5,7} obj.theta = varargin{1}(1); obj.sigma = varargin{1}(2); @@ -914,23 +929,17 @@ error('Non-acceptable model choice. The parameter CovariogramModelChoice = %i is not allowed',obj.CovariogramModelChoice); end -% switch obj.CovariogramModelChoice -% case {1,2,5,7} -% obj.CovariogramUsesEuclideanDistance = true; -% obj.CovariogramUsesAbsoluteDistance = false; -% case {3,4,6,8} -% obj.CovariogramUsesAbsoluteDistance = true; -% obj.CovariogramUsesEuclideanDistance = false; -% otherwise -% error('CovariogramModelChoice = %d is not defined',obj.CovariogramModelChoice) -% end - - try - obj.calcCovariogramMatrix(); - catch exception - warning('Covariogram Matrix could be recalculated! Do it manually') - % Rethrow original error. - rethrow(exception) + if ~obj.UseMatlabRegressionGP + if isempty(obj.DistInput) + obj.estimateVariance + end + try + obj.calcCovariogramMatrix(); + catch exception + warning('Covariogram Matrix could be recalculated! Do it manually') + % Rethrow original error. + rethrow(exception) + end end end %------------------------------------------------------------------ @@ -991,7 +1000,7 @@ % the first values obj.setCovariogramParameterBoundsAndValues(Model); - obj.estimateVariance +% obj.estimateVariance end %------------------------------------------------------------------ @@ -1002,7 +1011,7 @@ % varargin = 3 ... exponential with separated thethas and ps (multigaussian) (sigmaError + sigma*exp(-sum_(h=1)^k(theta(h)*abs(x(i,h)-x(j,h))^p(h))) Model = varargin{1}; minValue = 1e-10; - switch Model; + switch Model case 1 obj.LBCovariogramModelParameters = [minValue,minValue]; obj.UBCovariogramModelParameters = [1e10,1e10]; @@ -1067,6 +1076,7 @@ end % Decide for the distance calculation + covariogramUsesEuclideanDistanceCheck = obj.CovariogramUsesEuclideanDistance; switch obj.CovariogramModelChoice case {1,2,5,7} obj.CovariogramUsesEuclideanDistance = true; @@ -1077,6 +1087,12 @@ otherwise error('CovariogramModelChoice = %d is not defined',obj.CovariogramModelChoice) end + + if ~obj.UseMatlabRegressionGP + if isempty(obj.DistInput)||(covariogramUsesEuclideanDistanceCheck~=obj.CovariogramUsesEuclideanDistance) + obj.estimateVariance + end + end end %------------------------------------------------------------------ function []=setCR(obj,CR) @@ -1116,6 +1132,9 @@ end %------------------------------------------------------------------ function []=setNormOutput(obj,NormOutput) +% if NormOutput +% error('NormOutput cannot be used curretly otherwise problem with covariance calculation occur and consequently pridiction variance is not correct') +% end % Decide if the output shall be normalized(1) or not (0) if ~isempty(obj.OutputData) warning('"OutputData" is not empty. Please define "OutputData" only after setting the "NormOutput"-option') @@ -1402,6 +1421,44 @@ obj.UseMatlabRegressionGP = UseMatlabRegressionGP; end + %------------------------------------------------------------------ + function []=setHeterogeneousNoise(obj,heterogeneousNoise) + if (~(any(size(heterogeneousNoise)==obj.nExperiments)&&any(size(heterogeneousNoise)==1))&&~isempty(heterogeneousNoise)) + error('heterogeneousNoise should be a vector nExperimentsX1(%iX1)',obj.nExperiments) + end + if any(size(heterogeneousNoise,1)==1) + heterogeneousNoise = heterogeneousNoise'; + end + if isempty(obj.HeterogeneousNoise) + warning('"HeterogeneousNoise" has change, please run "calcCovariogramMatrix" again') + end + obj.HeterogeneousNoise = heterogeneousNoise; + + end + %------------------------------------------------------------------ + function []=setKriKitObjNoise(obj,KriKitObjNoise) + if ~isempty(KriKitObjNoise) + heterogenousNoise = exp(KriKitObjNoise.prediction(obj.getInputData)); + heterogenousNoise = sqrt(heterogenousNoise(:,1)); + else + heterogenousNoise = []; + end + obj.setHeterogeneousNoise(heterogenousNoise) + obj.calcCovariogramMatrix + obj.KriKitObjNoise = KriKitObjNoise; + end + %------------------------------------------------------------------ + function []=setThresholdSolver(obj,ThresholdSolver) + if length(ThresholdSolver)>1||~isdouble(ThresholdSolver) + error('ThresholdSolver has to be a scalar') + end + obj.ThresholdSolver = ThresholdSolver; + end + %------------------------------------------------------------------ + function []=setDistInput(obj,DistInput) + obj.DistInput = DistInput; + end + end end diff --git a/dependencies/@KrigingSuperClass/MarginalLikelihoodCovarPara.m b/dependencies/@KrigingSuperClass/MarginalLikelihoodCovarPara.m index f9938b3..05708f4 100644 --- a/dependencies/@KrigingSuperClass/MarginalLikelihoodCovarPara.m +++ b/dependencies/@KrigingSuperClass/MarginalLikelihoodCovarPara.m @@ -28,13 +28,18 @@ C = obj.CovariogramMatrix(1:obj.nExperiments,1:obj.nExperiments); detC = det(C); numericalLimit = realmin; -if detC<=numericalLimit +% if detC<=numericalLimit +if isinf(detC)||detC==0 detC = numericalLimit; end + +lC = lu(C); + [basisFctMatrix] = estimatedBasisFunction(); basisFctEval = basisFctMatrix'*obj.getBasisFctCoefficients; vecForMulti = (obj.OutputData-basisFctEval); negLog = -(-1/2*vecForMulti'*(C\vecForMulti) - 1/2*log(detC)-obj.nExperiments/2*log(2*pi)); +% negLog = -(-1/2*vecForMulti'*(C\vecForMulti) - sqrt(obj.nExperiments)*log(min(abs(diag(lC))))-obj.nExperiments/2*log(2*pi)); %% Nested Function % ------------------------------------------------------------------------- diff --git a/dependencies/@KrigingSuperClass/calcCovarMatrixOfPredictions.m b/dependencies/@KrigingSuperClass/calcCovarMatrixOfPredictions.m index 3f0ceb4..f225d3c 100644 --- a/dependencies/@KrigingSuperClass/calcCovarMatrixOfPredictions.m +++ b/dependencies/@KrigingSuperClass/calcCovarMatrixOfPredictions.m @@ -28,6 +28,7 @@ end % covariance_zero = ones(nDataPoints,nDataPoints)*obj.CovarModel(zeros(1,size(obj.DistInput,2)),1); +% obj.Weights = obj.Weights*(max(obj.getOutputData)-min(obj.getOutputData)); % Calculate the Covariance Matrix parts 1:nOriginalDataPoints part1 = reshape(diag(obj.Weights(1:nOriginalDataPoints,nComb(:,1))'*obj.CovargramVectors(1:nOriginalDataPoints,nComb(:,2))),nDataPoints,nDataPoints); @@ -93,7 +94,9 @@ % Final Result obj.CovarMatrixOfPredictions = part4-part1-part2+part3; - +if obj.getNormOutput + obj.CovarMatrixOfPredictions = obj.CovarMatrixOfPredictions*(max(obj.getOutputData)-min(obj.getOutputData))^2; +end % if obj.NormOutput % obj.CovarMatrixOfPredictions = (obj.CovarMatrixOfPredictions-0)*(max(obj.getOutputData)-min(obj.getOutputData))^2; diff --git a/dependencies/@KrigingSuperClass/calcCovariogramMatrix.m b/dependencies/@KrigingSuperClass/calcCovariogramMatrix.m index 7fd9e4c..53ea0f3 100644 --- a/dependencies/@KrigingSuperClass/calcCovariogramMatrix.m +++ b/dependencies/@KrigingSuperClass/calcCovariogramMatrix.m @@ -65,7 +65,12 @@ delta = reshape(delta,sqrt(size(delta,1)),sqrt(size(delta,1))); % Calculate the variogram values for theses distances - obj.Variogram(1:obj.nExperiments,1:obj.nExperiments) = obj.CovarModel(zeros(1,size(obj.DistInput,2)),1) - obj.CovarModel(delta,0); +% if isempty(obj.HeterogeneousNoise) + obj.Variogram(1:obj.nExperiments,1:obj.nExperiments) = obj.CovarModel(zeros(1,size(obj.DistInput,2)),1) - obj.CovarModel(delta,0); +% else +% obj.Variogram(1:obj.nExperiments,1:obj.nExperiments) = obj.CovarModel(zeros(1,size(obj.DistInput,2)),0) - obj.CovarModel(delta,0); +% obj.Variogram(1:size(obj.Variogram,1)+1:size(obj.Variogram,1)*obj.nExperiments) = obj.HeterogeneousNoise.^2; +% end elseif obj.CovariogramUsesAbsoluteDistance % Calculate the variogram values for the input distances (for % each input variable). @@ -83,11 +88,23 @@ end end delta = reshape(d,nRowsColumns,obj.nInputVar,nRowsColumns); - obj.Variogram(1:obj.nExperiments,1:obj.nExperiments) = reshape(obj.CovarModel(zeros([1,size(obj.DistInput,2),1]),1) - obj.CovarModel(delta,0),nRowsColumns,nRowsColumns); + +% if isempty(obj.HeterogeneousNoise) + obj.Variogram(1:obj.nExperiments,1:obj.nExperiments) = ... + reshape(obj.CovarModel(zeros([1,size(obj.DistInput,2),1]),1) - ... + obj.CovarModel(delta,0),nRowsColumns,nRowsColumns); +% else +% obj.Variogram(1:obj.nExperiments,1:obj.nExperiments) = ... +% reshape(obj.CovarModel(zeros([1,size(obj.DistInput,2),1]),0) - ... +% obj.CovarModel(delta,0),nRowsColumns,nRowsColumns); +% % Add heterogenous noise further below +% end else error('Either"CovariogramUsesEuclideanDistance" or "CovariogramUsesAbsoluteDistance" have to be "true"') end - +% if ~isempty(obj.HeterogeneousNoise) +% obj.Variogram(1:size(obj.Variogram,1)+1:size(obj.Variogram,1)*obj.nExperiments) = obj.HeterogeneousNoise.^2; +% end % Diagonal has to be 0 obj.Variogram = obj.Variogram - bsxfun(@times,diag(obj.Variogram),eye(size(obj.Variogram,1))); @@ -105,8 +122,28 @@ % Convert to CavoriogramMatrix obj.CovariogramMatrix = obj.Variogram; -covariance_zero = ones(obj.nExperiments,obj.nExperiments)*obj.CovarModel(zeros(1,size(obj.DistInput,2)),1); -obj.CovariogramMatrix(1:obj.nExperiments,1:obj.nExperiments) = covariance_zero-obj.Variogram(1:obj.nExperiments,1:obj.nExperiments); + + +% if ~isempty(obj.HeterogeneousNoise) +% vecIndices = (1:obj.nExperiments)'; +% vecIndices = (vecIndices-1)*length(obj.CovariogramMatrix)+vecIndices; +% +% covariance_zero = ones(obj.nExperiments,obj.nExperiments)*obj.CovarModel(zeros(1,size(obj.DistInput,2)),0); +% obj.CovariogramMatrix(1:obj.nExperiments,1:obj.nExperiments) = covariance_zero-obj.Variogram(1:obj.nExperiments,1:obj.nExperiments); +% +% obj.CovariogramMatrix(vecIndices) = obj.CovariogramMatrix(vecIndices) + obj.HeterogeneousNoise.^2; +% else + covariance_zero = ones(obj.nExperiments,obj.nExperiments)*obj.CovarModel(zeros(1,size(obj.DistInput,2)),1); + obj.CovariogramMatrix(1:obj.nExperiments,1:obj.nExperiments) = covariance_zero-obj.Variogram(1:obj.nExperiments,1:obj.nExperiments); +% end + +if ~isempty(obj.HeterogeneousNoise) + vecIndices = (1:obj.nExperiments)'; + vecIndices = (vecIndices-1)*length(obj.CovariogramMatrix)+vecIndices; + + obj.Variogram(vecIndices) = obj.HeterogeneousNoise.^2; + obj.CovariogramMatrix(vecIndices) = obj.CovarModel(zeros(1,size(obj.DistInput,2)),0) + obj.HeterogeneousNoise.^2; +end %% Calculate Inverse if needed % If the inverse is used for inv(A)*b instead of A\b diff --git a/dependencies/@KrigingSuperClass/calcCrossOverQuality.m b/dependencies/@KrigingSuperClass/calcCrossOverQuality.m index 2f0e2a9..04dc7cb 100644 --- a/dependencies/@KrigingSuperClass/calcCrossOverQuality.m +++ b/dependencies/@KrigingSuperClass/calcCrossOverQuality.m @@ -62,6 +62,7 @@ % Set the defined model parameters obj.setCovariogramModelParameters(varargin{1}); covariogramBackupMatrix = obj.getCovariogramMatrix; + heterogeneousNoiseBackUpt = obj.HeterogeneousNoise; UseGPRMatlabBackup = obj.getUseMatlabRegressionGP; obj.setUseMatlabRegressionGP(false) @@ -78,102 +79,124 @@ % erased and replaced by the mean values at this point uniqueInput = unique(obj.getInputData,'rows'); - - for iExpOut = 1:size(uniqueInput,1) - - % Reset input and output data - InputData = InputBackup; - InputDataNorm = InputBackupNorm; - OutputData = OutputBackup; - OutputDataNorm = OutputBackupNorm; - - % Erase all rows and column which are associated with current - % data point - % Find all Experiments using the same input parameters - [~,binVector]=ismember(InputBackup,uniqueInput(iExpOut,:),'rows'); - indexSameInput = find(binVector==1); - % Erase - InputData(indexSameInput,:) = []; - InputDataNorm(indexSameInput,:) = []; - OutputData(indexSameInput,:) = []; - OutputDataNorm(indexSameInput,:) = []; - % Replaceoriginal data set - setInputData(InputData,InputDataNorm); - setOutputData(OutputData,OutputDataNorm); - - % Update covariance matrix (erase lines which are associated with - % erased data set) - indicesKeep = setdiff(1:size(covariogramBackupMatrix,1),indexSameInput); - covariogramMatrix = covariogramBackupMatrix(indicesKeep,indicesKeep); - obj.CovariogramMatrix = covariogramMatrix; - - % Instead of calculating the inverse each time de novo, the old - % inverse is just updated (HAGER, 1989,'UPDATING THE INVERSE OF A - % MATRIX*'). Only possible in step for when no multiple - % measurements exists at the point of current investigation. - if length(indexSameInput)==1 - obj.InvCovariogramMatrix=invupdatered(inverseBackUP,indexSameInput,indexSameInput); - else - obj.InvCovariogramMatrix = inv(covariogramMatrix); + protoVec = zeros(size(uniqueInput,1),1); + predVec = zeros(size(uniqueInput,1),1); + try + for iExpOut = 1:size(uniqueInput,1) + + % Reset input and output data + InputData = InputBackup; + InputDataNorm = InputBackupNorm; + OutputData = OutputBackup; + OutputDataNorm = OutputBackupNorm; + + % Erase all rows and column which are associated with current + % data point + % Find all Experiments using the same input parameters + [~,binVector]=ismember(InputBackup,uniqueInput(iExpOut,:),'rows'); + indexSameInput = find(binVector==1); + % Erase + InputData(indexSameInput,:) = []; + InputDataNorm(indexSameInput,:) = []; + OutputData(indexSameInput,:) = []; + OutputDataNorm(indexSameInput,:) = []; + % Replaceoriginal data set + setInputData(InputData,InputDataNorm); + setOutputData(OutputData,OutputDataNorm); + + % Update covariance matrix (erase lines which are associated with + % erased data set) + indicesKeep = setdiff(1:size(covariogramBackupMatrix,1),indexSameInput); + if ~isempty(obj.HeterogeneousNoise) + obj.HeterogeneousNoise = heterogeneousNoiseBackUpt(indicesKeep(1:end-obj.getnBasisFct)); + end + covariogramMatrix = covariogramBackupMatrix(indicesKeep,indicesKeep); + obj.CovariogramMatrix = covariogramMatrix; + + % Instead of calculating the inverse each time de novo, the old + % inverse is just updated (HAGER, 1989,'UPDATING THE INVERSE OF A + % MATRIX*'). Only possible in step for when no multiple + % measurements exists at the point of current investigation. + if length(indexSameInput)==1 + obj.InvCovariogramMatrix=invupdatered(inverseBackUP,indexSameInput,indexSameInput); + else + obj.InvCovariogramMatrix = inv(covariogramMatrix); + end + + % Make the Kriging prediction + [output]=obj.prediction(uniqueInput(iExpOut,:)); + expected = output(:,1); + sigma = output(:,2); + + % Compare wiht the true value + switch obj.CrossValidationType + case {1,3} + proto = ((mean(OutputBackup(indexSameInput))-expected)/sigma)^2; + + if isnan(proto) + quality = realmax; + else + quality = quality + proto; + end + case 2 + if isnan(expected) + quality = realmax; + else + quality = quality + (mean(OutputBackup(indexSameInput))-expected)^2; + end + case 4 + proto = ((mean(OutputBackup(indexSameInput))-expected)/sigma)^2; + protoVec(iExpOut) = proto; + predVec(iExpOut,1) = expected; + predVec(iExpOut,2) = sigma; + + if isnan(proto) + quality = realmax; + else + quality = quality + proto; + end + quality2 = quality2 + (mean(OutputBackup(indexSameInput))-expected)^2; + otherwise + error('CrossValidationType: %d is not defined\n',obj.CrossValidationType) + end end - % Make the Kriging prediction - [output]=obj.prediction(uniqueInput(iExpOut,:)); - expected = output(:,1); - sigma = output(:,2); - - % Compare wiht the true value switch obj.CrossValidationType - case {1,3} - proto = ((mean(OutputBackup(indexSameInput))-expected)/sigma)^2; - - if isnan(proto) - quality = realmax; - else - quality = quality + proto; - end - case 2 - if isnan(expected) - quality = realmax; - else - quality = quality + (mean(OutputBackup(indexSameInput))-expected)^2; - end + case 1 + quality = abs(1-quality/size(uniqueInput,1)); case 4 - proto = ((mean(OutputBackup(indexSameInput))-expected)/sigma)^2; - - if isnan(proto) - quality = realmax; - else - quality = quality + proto; - end - quality2 = quality2 + (mean(OutputBackup(indexSameInput))-expected)^2; + quality = abs(1-quality/size(uniqueInput,1)); + % quality = quality*quality2; + quality = quality+quality2/size(uniqueInput,1)/max(OutputBackup.^2); otherwise - error('CrossValidationType: %d is not defined\n',obj.CrossValidationType) + end - end - switch obj.CrossValidationType - case 1 - quality = abs(1-quality/size(uniqueInput,1)); - case 4 - quality = abs(1-quality/size(uniqueInput,1)); -% quality = quality*quality2; - quality = quality+quality2/size(uniqueInput,1)/max(OutputBackup.^2); - otherwise - + % Restore old values + obj.checkVariogram = 0; + obj.setInputData(InputBackup); + obj.setOutputData(OutputBackup); + obj.CovariogramMatrix = covariogramBackupMatrix; + obj.InvCovariogramMatrix = inverseBackUP; + obj.nExperiments = nExpBackup; + obj.UseInverse = UseInverseBackUP; + obj.setCovariogramModelParameters(covParaBackup); + obj.HeterogeneousNoise = heterogeneousNoiseBackUpt; + catch ex + warning(ex.message) + disp('Hello') + % Restore old values + obj.checkVariogram = 0; + obj.setInputData(InputBackup); + obj.setOutputData(OutputBackup); + obj.CovariogramMatrix = covariogramBackupMatrix; + obj.InvCovariogramMatrix = inverseBackUP; + obj.nExperiments = nExpBackup; + obj.UseInverse = UseInverseBackUP; + obj.setCovariogramModelParameters(covParaBackup); + obj.HeterogeneousNoise = heterogeneousNoiseBackUpt; end - - % Restore old values - obj.checkVariogram = 0; - obj.setInputData(InputBackup); - obj.setOutputData(OutputBackup); - obj.CovariogramMatrix = covariogramBackupMatrix; - obj.InvCovariogramMatrix = inverseBackUP; - obj.nExperiments = nExpBackup; - obj.UseInverse = UseInverseBackUP; - obj.setCovariogramModelParameters(covParaBackup); - obj.setUseMatlabRegressionGP(UseGPRMatlabBackup) - + %% Set Functions % --------------------------------------------------------------------- function [] = setInputData(Input,InputNorm) diff --git a/dependencies/@KrigingSuperClass/doConditionalSimulation_ResAlgInEq.m b/dependencies/@KrigingSuperClass/doConditionalSimulation_ResAlgInEq.m index ea9f28a..46b7df6 100644 --- a/dependencies/@KrigingSuperClass/doConditionalSimulation_ResAlgInEq.m +++ b/dependencies/@KrigingSuperClass/doConditionalSimulation_ResAlgInEq.m @@ -12,8 +12,8 @@ % This function uses "Kriging residual algorithm" (see chevalier2015 - Fast % update of conditional simulation ensembles): % 1. NonConditional Simulation: Generating realizations of a process with -% zero mean and in agreement with the Kriging Covarisance matrix -% z_noncond(x)~N(0,C(x)) +% kriging mean and in agreement with the Kriging Covarisance matrix +% z_noncond(x)~N(m(x),C(x)) % 2. Conditioning on the Data: z_cond(x) = m(x) + r(x) % m(x) ... kriging estimation % r(x) ... residual estimation: r(x) = z_noncond(x) - @@ -75,15 +75,6 @@ [sampleLocations,nSamplePoints,nRealization] = checkGivenInputRange; end -% Save handle to inequality constraint function if given -if length(varargin)==2 - inEqConstraint = varargin{2}; -elseif length(varargin)==4 - inEqConstraint = varargin{4}; -else - inEqConstraint = []; -end - % Normalize Input if necessary if obj.NormInput==1 % Save original data for later @@ -104,6 +95,7 @@ % Backup in order to return to old state after conditional simulation maxSizeOfPredictionsBackup = obj.getMaxSizeOfPredictions; UseGPRMatlabBackup = obj.getUseMatlabRegressionGP; +% HeterogeneousNoiseBackUp = obj.getHeterogeneousNoise; obj.setUseMatlabRegressionGP(false) % Allocate Memory: @@ -114,20 +106,27 @@ % Make sure that no permanent parameter changes happens when porogram % crashes -try +% try %% Step 0: Generate normal Kriging estimation at simulation points and save associated kriging weights % Do predictions in one step obj.setMaxSizeOfPredictions(obj.getnExperiments+nSamplePoints) - % Actual Prediction + % Actual Prediction. Do not allow heterogenous noise here as it is not + % used for non-conditional simulation outputMatrix = obj.prediction(nonNormSampleLocations(:,1:obj.getnInputVar)); % Save results krigingWeights = obj.getWeights; krigingWeights = krigingWeights(1:obj.getnExperiments,:); meanEstimation = outputMatrix(:,1); - + if obj.NormOutput + meanEstimation = obj.scale(meanEstimation,... + min(obj.getOutputData),max(obj.getOutputData),... + 0,1); + end +% stdEstimation = outputMatrix(:,2); + % Intiital evaluation processOld = 0; @@ -145,77 +144,88 @@ % Do Actual nonconditional simulation if allRealizationPointsAreTheSame + % Calculated Kriging covariance matrix w.r.t to all simulation % points columnSamplePoints = 1:1*obj.nInputVar; covMatrix = createCovMatrix(sampleLocations(:,columnSamplePoints)); - % Covariance matrix has to be semipositive definite - if any(eig(covMatrix)<0) - eigBefore = eig(covMatrix); - indicesDiag = 1:nRowsColumns+1:nRowsColumns^2; - covMatrix(indicesDiag) = covMatrix(indicesDiag)+covMatrix(indicesDiag)*1e-10; - eigAfter = eig(covMatrix); - warning('covMatrix is not positive semidefinite (smallest eigenvalue is %g). \nAfter adding 1e-10 to diagonal, max Diff in eigenvalues is : %g\n',min(eigBefore),max(abs(eigBefore-eigAfter))) - end + indices1 = 1:size(covMatrix,1)+1:size(covMatrix,1)*obj.nExperiments; + indices2 = indices1(end) + size(covMatrix,1)+1:size(covMatrix,1)+1:size(covMatrix,1)^2; + + if (isempty(obj.KriKitObjNoise)||isempty(obj.KriKitObjNoise.getOutputData)) + covMatrix([indices1,indices2]) = covMatrix([indices1,indices2]) + (obj.sigmaError).^2; + else + predLogNoise = obj.KriKitObjNoise.prediction(nonNormSampleLocations(:,1:obj.getnInputVar)); + covMatrix([indices1,indices2]) = bsxfun(@plus,covMatrix([indices1,indices2]), exp(predLogNoise(:,1))' ); + end % Random drawing following the distribution ~N(0,covMatrix) - unconditionedReal = mvnrnd(zeros(nRealization,obj.getnExperiments+nSamplePoints),covMatrix); + % First nDataXnData part of the covMatrix has to contain the data + % points covariance matrix, where sigmaError is added to the + % diagonal entries (Noisy measurements) + [unconditionedReal] = generatedNonconditionalSImulation(covMatrix,nRealization); end %% Step 2: Conditional simulation - - % Has to be done individual for each realization - for iRealization = 1:nRealization - - % Do nonconditional simulation (Only needed when simulation point - % differ between realizations - columnSamplePoints = (iRealization-1)*obj.nInputVar+1:iRealization*obj.nInputVar; - if ~allRealizationPointsAreTheSame + if allRealizationPointsAreTheSame + randomResidual = zeros(nSamplePoints,nRealization); + randomResidual(:) = unconditionedReal(:,obj.getnExperiments+1:end)'- krigingWeights(:,obj.getnExperiments+1:end)'*unconditionedReal(:,1:obj.getnExperiments)'; + realizationCurve = bsxfun(@plus,randomResidual,meanEstimation(obj.getnExperiments+1:end)); + else + + % Has to be done individual for each realization + for iRealization = 1:nRealization + % Do nonconditional simulation (Only needed when simulation point + % differ between realizations + columnSamplePoints = (iRealization-1)*obj.nInputVar+1:iRealization*obj.nInputVar; + % Actual Prediction outputMatrix = obj.prediction(nonNormSampleLocations(:,columnSamplePoints)); - - + + % Save results krigingWeights = obj.getWeights; krigingWeights = krigingWeights(1:obj.getnExperiments,:); meanEstimation = outputMatrix(:,1); covMatrix = createCovMatrix(sampleLocations(:,columnSamplePoints)); - unconditionedReal = mvnrnd(zeros(nRealization,obj.getnExperiments+nSamplePoints),covMatrix); - end - - % Do Conditional simulation constrainted by inEqConstraint - realizationFound = false; - while ~realizationFound - - % Calculate estimation modeling error - randomResidual(:) = unconditionedReal(iRealization,obj.getnExperiments+1:end)'- krigingWeights(:,obj.getnExperiments+1:end)'*unconditionedReal(iRealization,1:obj.getnExperiments)'; - - % Final calculation of conditional simulation - realizationCurve(:,iRealization) = meanEstimation(obj.getnExperiments+1:end) + randomResidual + randn()*obj.sigmaError; + if ~isempty(obj.HeterogeneousNoise) + covMatrix(1:size(covMatrix,1)+1:size(covMatrix,1)*obj.nExperiments) = covMatrix(1:size(covMatrix,1)+1:size(covMatrix,1)*obj.nExperiments) + (obj.HeterogeneousNoise').^2; + else + covMatrix(1:size(covMatrix,1)+1:size(covMatrix,1)*obj.nExperiments) = covMatrix(1:size(covMatrix,1)+1:size(covMatrix,1)*obj.nExperiments) + (obj.sigmaError).^2; + end + + [unconditionedReal] = generatedNonconditionalSImulation(covMatrix,nRealization); + + % Do Conditional simulation constrainted by inEqConstraint + realizationFound = false; + while ~realizationFound + % Calculate estimation modeling error + randomResidual(:) = unconditionedReal(iRealization,obj.getnExperiments+1:end)'- krigingWeights(:,obj.getnExperiments+1:end)'*unconditionedReal(iRealization,1:obj.getnExperiments)'; - % Update Process bar if wanted - if obj.getShowWaitingBar - processNew = iRealization/nRealization; - if (processNew-processOld)>0.01 - waitbar(processNew,hWaitBar,sprintf('Process For Conditional Simulation: %f',processNew)) - % toc - processOld = processNew; + % Final calculation of conditional simulation + realizationCurve(:,iRealization) = meanEstimation(obj.getnExperiments+1:end) + randomResidual; + + % Update Process bar if wanted + if obj.getShowWaitingBar + processNew = iRealization/nRealization; + if (processNew-processOld)>0.01 + waitbar(processNew,hWaitBar,sprintf('Process For Conditional Simulation: %f',processNew)) + processOld = processNew; + end end end - - % Probality of taking a realization ~(number points of violating - % conditions)/(total number of simulation points) - if ~isempty(inEqConstraint) - [unconditionedReal(iRealization,:),realizationFound] = checkIfInEqualityHolds(realizationCurve(:,iRealization),unconditionedReal(iRealization,:)); - else - realizationFound = true; - end + + end end - %% Final things + if obj.NormOutput + realizationCurve = obj.scale(realizationCurve,0,1,... + min(obj.getOutputData),max(obj.getOutputData)); + end + % Define output ReturnSamplePoints = nonNormSampleLocations(obj.nExperiments+1:end,:); @@ -226,29 +236,43 @@ obj.setUseMatlabRegressionGP(UseGPRMatlabBackup); obj.setMaxSizeOfPredictions(maxSizeOfPredictionsBackup); -catch ex - error(ex.message) -end %% Nested Functions -function [unconditionedReal,realizationFound] = checkIfInEqualityHolds(realizationCurve,unconditionedReal) - % Check if inequalities hold - randNumber = rand(1); - - % Probality of taking a realization ~(number points of violating - % conditions)/(total number of simulation points) -% if randNumber>=(sum(~inEqConstraint(realizationCurve))/nSamplePoints)*(1/2*1/(1-0.9)) - if randNumber>=(sum(~inEqConstraint(realizationCurve))/nSamplePoints) - realizationFound = true; - else +% ------------------------------------------------------------------------- +function [unconditionedReal] = generatedNonconditionalSImulation(covMatrix,nRealization) + necessaryFeatures = {'Statistics_Toolbox'}; + validLincence = cellfun(@(f) license('checkout',f),necessaryFeatures); + if validLincence try - unconditionedReal = mvnrnd(zeros(1,obj.getnExperiments+nSamplePoints),covMatrix); + unconditionedReal= mvnrnd(meanEstimation,covMatrix,nRealization); catch ex - warning(ex.message) - unconditionedReal = mvnrnd(zeros(1,obj.getnExperiments+nSamplePoints),covMatrix); + warning(ex.message); + covMatrix = correctCovMatrix(covMatrix); + unconditionedReal= mvnrnd(meanEstimation,covMatrix,nRealization); end - realizationFound = false; + else + [eigVector,eigValue]=eig(covMatrix); + if any(eigValue<0) + covMatrix = correctCovMatrix(covMatrix); + [eigVector,eigValue]=eig(covMatrix); + end + unconditionedReal = randn(nRealization,obj.getnExperiments+nSamplePoints); + unconditionedReal = eigVector*sqrt(eigValue)*eigVector'*unconditionedReal'; + unconditionedReal = bsxfun(@plus,unconditionedReal,meanEstimation); + unconditionedReal = unconditionedReal'; end + +end +% ------------------------------------------------------------------------- +function [covMatrix] = correctCovMatrix(covMatrix) + % Covariance matrix has to be semipositive definite + eigBefore = eig(covMatrix); + nRowsColumns = size(covMatrix,1); + indicesDiag = 1:nRowsColumns+1:nRowsColumns^2; + covMatrix(indicesDiag) = covMatrix(indicesDiag)+covMatrix(indicesDiag)*1e-10; +% covMatrix(indicesDiag) = covMatrix(indicesDiag)+min(eigBefore); + eigAfter = eig(covMatrix); + warning('covMatrix is not positive semidefinite (smallest eigenvalue is %g). \nAfter adding 1e-10 to diagonal, max Diff in eigenvalues is : %g\n',min(eigBefore),max(abs(eigBefore-eigAfter))) end % ------------------------------------------------------------------------- function [covMatrix] = createCovMatrix(sampleLocations) diff --git a/dependencies/@KrigingSuperClass/estimateVariance.m b/dependencies/@KrigingSuperClass/estimateVariance.m index da67d1e..1c6842e 100644 --- a/dependencies/@KrigingSuperClass/estimateVariance.m +++ b/dependencies/@KrigingSuperClass/estimateVariance.m @@ -50,11 +50,11 @@ % Check expectedSize=(obj.nExperiments)*(obj.nExperiments-1)/2; - if size(obj.DistInput,1)~=expectedSize; + if size(obj.DistInput,1)~=expectedSize error('DistInput has dimension %ix%i but expected is 1x%i',size(obj.DistInput,1),size(obj.DistInput,2),expectedSize); end - if size(obj.VarianceEstimation,1)~=expectedSize; + if size(obj.VarianceEstimation,1)~=expectedSize error('VarianceEstimation has dimension %ix%i but expected is 1x%i',size(obj.VarianceEstimation,1),size(obj.VarianceEstimation,2),expectedSize); end elseif obj.CovariogramUsesAbsoluteDistance @@ -65,7 +65,14 @@ % one input variable between the difference measurements % Calculate for every combination of the experiments - indices = nchoosek(1:obj.nExperiments,2); + try + indices = VChooseK(1:obj.nExperiments,2); + catch ex + warning('VChooseK could not be used. Use Matlabs nchoosek insteads') + warning(ex.message); + indices = nchoosek(1:obj.nExperiments,2); + end + obj.DistInput = abs(obj.InputData(indices(:,1),:)-obj.InputData(indices(:,2),:)); obj.VarianceEstimation = ((obj.OutputData(indices(:,1),:)-obj.OutputData(indices(:,2),:)).^2)/2; elseif obj.CovariogramUsesAbsoluteValues diff --git a/dependencies/@KrigingSuperClass/generateNoiseModel.m b/dependencies/@KrigingSuperClass/generateNoiseModel.m new file mode 100644 index 0000000..31ed399 --- /dev/null +++ b/dependencies/@KrigingSuperClass/generateNoiseModel.m @@ -0,0 +1,118 @@ +function [] = generateNoiseModel(obj,varargin) +% [] = generateNoiseModel(sigmaError) +% +% This function generate a model for the output noise heteroscedastic. The +% model is inheritly used for the actual prediction . +% +% Input: +% - sigmaError ... Initial measurement stadard deviation which is used for +% the as homosedatic noise as starting point. If not +% provided,sigmaError is set the value estimated by the +% maximum likelihood estimator +% +% Output: +% +% You can set: +% - ThresholdSolver ... optimization stops as soon the relative difference +% (maxDiffPred) is lower than ThresholdSolver +% - nIterationsSolver ... optimization stop if nIterationsSolver iterations +% were run +% - CovariogramModelChoice ... Covariogram which is used for the estimation +% of the output noise +% +% You can get: +% +% Copyright 2014-2016: Lars Freier, Eric von Lieres +% See the license note at the end of the file. + +% if obj.NormOutput +% error('Not yet implemented for normalized output') +% end + +% Reset Noise Model +obj.KriKitObjNoise = OrdinaryKriging; +obj.KriKitObjNoise.setMaxSizeOfPredictions(obj.getMaxSizeOfPredictions) +obj.KriKitObjNoise.setShowWaitingBar(false); +UseMatlabRegressionGPBackUp = obj.UseMatlabRegressionGP; +obj.UseMatlabRegressionGP = false; +sigmaErrorBackUp = obj.sigmaError; +if ~isempty(varargin) + obj.sigmaError = varargin{1}; + obj.calcCovariogramMatrix +end + +% Generate initial Noise set +if obj.ShowDetails + fprintf('Generating Noise Model\n'); +end +predictionData = obj.prediction(obj.getInputData); +nSamples = 1e3; +predictedSamples = randn(obj.nExperiments,nSamples); +predictedSamples = bsxfun(@times,predictedSamples,predictionData(:,2)); +predictedSamples = bsxfun(@plus,predictedSamples,predictionData(:,1)); +arithmeticMean = bsxfun(@minus,predictedSamples,obj.getOutputData); +varDelta = 1/(2*nSamples)*sum((arithmeticMean).^2,2); + +% Run Optimization +for iIter = 1 : obj.nIterationsSolver + + % Set Up Noise Model + obj.KriKitObjNoise.setInputData(obj.getInputData) + obj.KriKitObjNoise.setOutputData(log(varDelta)) + obj.KriKitObjNoise.setCovariogramModelChoice(obj.CovariogramModelChoice); + obj.KriKitObjNoise.generateRegressionGPModel + predictionData2 = obj.prediction(obj.getInputData); + + % Estimate variation + nSamples = 1e3; + predictedSamples = randn(obj.nExperiments,1e3); + predictedSamples = bsxfun(@times,predictedSamples,predictionData(:,2)); + predictedSamples = bsxfun(@plus,predictedSamples,predictionData(:,1)); + arithmeticMean = bsxfun(@minus,predictedSamples,obj.getOutputData); + varDelta2 = 1/(2*nSamples)*sum((arithmeticMean).^2,2); + + % Check if converged + maxDiffPred = max(abs(predictionData(:,2)-predictionData2(:,2))./predictionData(:,2)); + maxDiff = max(abs(sqrt(varDelta2(:,1))-sqrt(varDelta(:,1)))); + if obj.ShowDetails + fprintf('iIter = %i - maxDiff = %e - maxDiffPred = %e \n',iIter,maxDiff,maxDiffPred); + end + if maxDiffPred x~N((y-a)*b+c,sigma^2*b^2) OutputTotal(:,1) = obj.scale(OutputTotal(:,1),0,1,... min(obj.getOutputData),max(obj.getOutputData)); + b = (max(obj.getOutputData)-min(obj.getOutputData))/(1-0); + OutputTotal(:,2) = OutputTotal(:,2)*b; % Do not scale standard deviation as for the calculation no % normalized output values are used!!!!!!!!!!!!!!!!!! + % f=(x-minX)./(maxX-minX).*(UB-LB)+LB; end return @@ -164,12 +170,24 @@ % composite design) % obj.CovargramVectors = CovVecTot; +% if obj.NormOutput +% % Normalization a = b*(max(out)-min(out))/(1-0) + min(out) +% OutputTotal(:,1) = obj.scale(OutputTotal(:,1),0,1,... +% min(obj.getOutputData),max(obj.getOutputData)); +% % Do not scale standard deviation as for the calculation no +% % normalized output values are used!!!!!!!!!!!!!!!!!! +% end if obj.NormOutput - % Normalization a = b*(max(out)-min(out))/(1-0) + min(out) + % Scale = (x-minOld)*((maxNew-minNew)/(maxOld-minOld)) + minNew + % = (x-a)*b + c + % -> x~N((y-a)*b+c,sigma^2*b^2) OutputTotal(:,1) = obj.scale(OutputTotal(:,1),0,1,... min(obj.getOutputData),max(obj.getOutputData)); + b = (max(obj.getOutputData)-min(obj.getOutputData))/(1-0); + OutputTotal(:,2) = OutputTotal(:,2)*b; % Do not scale standard deviation as for the calculation no % normalized output values are used!!!!!!!!!!!!!!!!!! + % f=(x-minX)./(maxX-minX).*(UB-LB)+LB; end %% --------------------- Nested Functions --------------------------------- @@ -304,7 +322,8 @@ % Higher correlation coefficient when you consider exact the same % sample point -> usually higher covariance expressed by % obj.sigmaError - covariance_zero = ones(size(obj.CovargramVectors,2),size(krigingWeights,2))*obj.CovarModel(zeros(1,size(obj.DistInput,2)),1); +% covariance_zero = ones(size(obj.CovargramVectors,2),size(krigingWeights,2))*obj.CovarModel(zeros(1,size(obj.DistInput,2)),1); + covariance_zero = ones(size(obj.CovargramVectors,2),size(krigingWeights,2))*obj.CovarModel(zeros(1,size(obj.DistInput,2)),0); % This formula is derive based on the derivatives Lagrange % Multiplier function with respect to the lagrange multiplier and @@ -316,9 +335,27 @@ % 1. % sigmaEstimation = covariance_zero-krigingWeights'*obj.CovargramVectors(1:size(krigingWeights,1),:); % 2. +% sigmaEstimation = obj.BasisFctCoefficients'basisFctEval + +% obj.CovargramVectors(1:obj.nExperiments,:)'*... +% inv(obj.CovariogramMatrix(1:obj.nExperiments,1:obj.nExperiments))*... +% (obj.OutputData-obj.BasisFctCoefficients'basisFctEval) + % 3. + if isempty(obj.KriKitObjNoise)||isempty(obj.KriKitObjNoise.getOutputData) % Check if an initialized noise model exist + covariance_zero = covariance_zero + obj.sigmaError^2; + else +% errorProp = (sum(bsxfun(@times,obj.HeterogeneousNoise.^2,krigingWeights(1:obj.getnExperiments,:).^2))); +% errorProp = (sum(bsxfun(@times,obj.HeterogeneousNoise.^2,krigingWeights(1:obj.getnExperiments,:)))); +% covariance_zero = bsxfun(@plus,covariance_zero,errorProp); + predLogNoise = obj.KriKitObjNoise.prediction(nonNormInput(:,:)); + +% covariance_zero = covariance_zero + exp(predLogNoise(:,1)); +% covariance_zero = bsxfun(@plus,covariance_zero, exp(predLogNoise(:,1)).*(max(obj.getOutputData)-min(obj.getOutputData)).^2 ); + covariance_zero = bsxfun(@plus,covariance_zero, exp(predLogNoise(:,1)) ); + end + sigmaEstimation = covariance_zero - 2*krigingWeights'*obj.CovargramVectors(1:size(krigingWeights,1),:) +... - krigingWeights'*obj.CovariogramMatrix(1:size(krigingWeights,1),1:size(krigingWeights,1))*krigingWeights; - + krigingWeights'*obj.CovariogramMatrix(1:size(krigingWeights,1),1:size(krigingWeights,1))*krigingWeights; + % Only the diagonal are the number we are looking for sigmaEstimation = diag(sigmaEstimation); sigmaEstimation = (sigmaEstimation).^(1/2); diff --git a/dependencies/@TaylorKriging/TaylorKriging.m b/dependencies/@TaylorKriging/TaylorKriging.m index d78293b..9867d1d 100644 --- a/dependencies/@TaylorKriging/TaylorKriging.m +++ b/dependencies/@TaylorKriging/TaylorKriging.m @@ -36,7 +36,8 @@ % Determine the threshold in the auxiliary condition of % sum(Cinv(i,:).^2)>=ThresholdCondition ThresholdCondition = 0; - + % + nMultiStartPoints = 10; InvCoVar = []; @@ -67,8 +68,11 @@ %% ParameterEstimation % [] = estimateBasisFunctionParametersViaKriging(obj) + % ----------------------------------------------------------------- [] = estimateBasisFctParametersViaTaylorKriging(obj) % ----------------------------------------------------------------- + [varargout] = estimateBasisFctParametersFsolve(obj) + % ----------------------------------------------------------------- [] = estimateBasisFctParametersFminCon(obj) % ----------------------------------------------------------------- [] = estimateBasisFctParametersFminUnc(obj) @@ -211,6 +215,10 @@ obj.SaveItermediateResults = SaveItermediateResults; end % ----------------------------------------------------------------- + function []=setInvCoVar(obj,InvCoVar) + obj.InvCoVar = InvCoVar; + end + % ----------------------------------------------------------------- function []=setTaylorExpansionOrder(obj,TaylorExpansionOrder) obj.TaylorExpansionOrder = TaylorExpansionOrder; end diff --git a/dependencies/@TaylorKriging/calcKrigingParaEstimationObjFctVector.m b/dependencies/@TaylorKriging/calcKrigingParaEstimationObjFctVector.m index d08f5a1..ae66c76 100644 --- a/dependencies/@TaylorKriging/calcKrigingParaEstimationObjFctVector.m +++ b/dependencies/@TaylorKriging/calcKrigingParaEstimationObjFctVector.m @@ -9,7 +9,6 @@ if isempty(obj.CovariogramMatrix) obj.calcCovariogramMatrix end - quality = 0; if length(para)~=obj.getnBasisFctParameters warning('Number of given parameters (%i) and the needed number of parameters (%i) differes from each other',length(para),obj.getnBasisFctParameters) @@ -18,32 +17,24 @@ error('Not enough derivatives are provided') end C = obj.CovariogramMatrix(1:obj.getnExperiments,1:obj.getnExperiments); - minC=min(min(abs(C))); - C = C/minC; % Normalization for reducing numerical problems +% minC=min(min(abs(C))); +% C = C/minC; % Normalization for reducing numerical problems F = zeros(obj.getnExperiments,1+obj.nBasisFctDerivative); % Basis Function - F(:,1) = obj.getBasisFct{1}(para,obj.getInputData); + F(:,1) = obj.getBasisFct{1}(para,obj.InputData); % Derivatives for iDerivative=1:obj.nBasisFctDerivative - F(:,iDerivative+1) = obj.getBasisFctDerivative{iDerivative}(para,obj.getInputData); + F(:,iDerivative+1) = obj.getBasisFctDerivative{iDerivative}(para,obj.InputData); end if isempty(obj.getInvCoVar) obj.InvCoVar = inv(C); end -% matrixAlmostEye = eye(size(F,2)); -% matrixAlmostEye(1) = 0; -% b=F'*(obj.InvCoVar*(obj.getOutputData)); -% M=F'*(obj.InvCoVar*F); -% quality = matrixAlmostEye*inv(M)*b; - - saveCoeff = (F'*(obj.InvCoVar*F))\(F'*(obj.InvCoVar*(obj.getOutputData))); -% saveCoeff = (F'*eye(obj.nExperiments)*F)\(F'*(eye(obj.nExperiments)*(obj.getOutputData))); -% a= F'*(obj.InvCoVar*(obj.getOutputData)); -% quality2 = a-a'*[1;zeros(length(saveCoeff)-1,1)]; +% obj.InvCoVar(1:5,1:5) + saveCoeff = (F'*(obj.InvCoVar*F))\(F'*(obj.InvCoVar*(obj.OutputData))); quality = saveCoeff(2:end); end diff --git a/dependencies/@TaylorKriging/estimateBasisFctParametersFsolve.m b/dependencies/@TaylorKriging/estimateBasisFctParametersFsolve.m new file mode 100644 index 0000000..8137154 --- /dev/null +++ b/dependencies/@TaylorKriging/estimateBasisFctParametersFsolve.m @@ -0,0 +1,68 @@ +function [varargout] = estimateBasisFctParametersFsolve(obj) +% +% +% You can set: +% - nMultiStartPoints .... number points for applying fsolve +% - LBBasisFctParameters/UBBasisFctParameters +% +% Copyright 2014-2016: Lars Freier, Eric von Lieres +% See the license note at the end of the file. + + if obj.NormOutput||obj.NormInput + error('estimateBasisFctParametersFsolve cannot be used for normalized input or/and output') + end + %% Initialization + options = optimoptions('fsolve'); + options.Display='off'; +% fTestFct=obj.KrigingObj; + if isempty(obj.getLBBasisFctParameters)||isempty(obj.getUBBasisFctParameters) + error('LBBasisFctParameters and UBBasisFctParameters have to be defined') + else + Pstart = createNDGRID(obj.getLBBasisFctParameters,obj.getUBBasisFctParameters,obj.nMultiStartPoints); + end + + % Allocating Memory + Pend = zeros((obj.nMultiStartPoints)^2,obj.getnBasisFctParameters); + qualityMeasure = ones((obj.nMultiStartPoints)^obj.getnBasisFctParameters,1); + testVec = ones((obj.nMultiStartPoints)^obj.getnBasisFctParameters,obj.getnBasisFctParameters); + + %% Actual Estimation + for iStart = 1:(obj.nMultiStartPoints)^2 + Pend(iStart,:) = fsolve(@obj.calcKrigingParaEstimationObjFctVector,Pstart(iStart,:),options); + qualityMeasure(iStart) = sum(abs(obj.calcKrigingParaEstimationObjFctVector(Pend(iStart,:)))); + testVec(iStart,:) = abs(obj.calcKrigingParaEstimationObjFctVector(Pend(iStart,:)))'; + end + + % Consider only feasible results + idxLBValid = all(bsxfun(@ge,Pend,obj.getLBBasisFctParameters),2); + idxUBValid = all(bsxfun(@le,Pend,obj.getUBBasisFctParameters),2); + idxValid = find(idxLBValid&idxUBValid); + [~,idxMin]=min(sum(testVec(idxValid,:),2)); + minQualValid = idxValid(idxMin); + pOpt = Pend(minQualValid,:); + + %% Save Results + if ~isempty(pOpt) + varargout{1} = pOpt; + varargout{2} = sum((obj.calcKrigingParaEstimationObjFctVector(pOpt)).^2); + else + varargout{1} = zeros(1,2); + varargout{2} = inf; + warning('no feasible parameter set') + end + + obj.setBasisFctParameters(varargout{1}); +end + +% ============================================================================= +% KriKit - Kriging toolKit +% +% Copyright 2014-2016: Lars Freier(1), Eric von Lieres(1) +% +% (1)Forschungszentrum Juelich GmbH, IBG-1, Juelich, Germany. +% +% All rights reserved. This program and the accompanying materials +% are made available under the terms of the GNU Public License v3.0 (or, at +% your option, any later version) which accompanies this distribution, and +% is available at http://www.gnu.org/licenses/gpl.html +% ============================================================================= diff --git a/dependencies/auxiliaryFunctions/GridTools/createNDGRID.m b/dependencies/auxiliaryFunctions/GridTools/createNDGRID.m index e52578c..b23cefa 100644 --- a/dependencies/auxiliaryFunctions/GridTools/createNDGRID.m +++ b/dependencies/auxiliaryFunctions/GridTools/createNDGRID.m @@ -1,24 +1,43 @@ -function [X] = createNDGRID(LB,UB,nbinsEachDimension) -% [X] = createNDGRID(LB,UB,nbinsEachDimension) +function [X] = createNDGRID(varargin) +% [X] = createNDGRID(LB,UB,nbinsEachDimension,extraPoints) + LB = varargin{1}; + UB = varargin{2}; + nbinsEachDimension = varargin{3}; + if length(varargin)>3 + extraPoints = varargin{4}; + else + extraPoints = []; + end + % MakeGrid nVariables = length(UB); XLin = linspaceNDim(LB,UB,nbinsEachDimension)'; + XLin = ([XLin;extraPoints]); if nVariables>1 X = []; for iX = 1:nVariables-1 + % It is important to chck uniqueness if extra points are + % applied if iX==1 - [x1,xi] = ndgrid(XLin(:,iX),XLin(:,iX+1)); + X1 = unique(XLin(:,iX)); + X2 = unique(XLin(:,iX+1)); + + [x1,xi] = ndgrid(X1,X2); X = [x1(:),xi(:)]; else - [x1,xi] = ndgrid(X(:,1),XLin(:,iX+1)); - X = [repmat(X,nbinsEachDimension,1),xi(:)]; + X1 = (X(:,1)); + X2 = unique(XLin(:,iX+1)); + + [x1,xi] = ndgrid(X1,X2); + X = [repmat(X,size(xi,2),1),xi(:)]; end end else X = XLin'; end + end diff --git a/dependencies/auxiliaryFunctions/HV_mod/calcEHIV_2D.m b/dependencies/auxiliaryFunctions/HV_mod/calcEHIV_2D.m index fa2c6fb..2dd6684 100644 --- a/dependencies/auxiliaryFunctions/HV_mod/calcEHIV_2D.m +++ b/dependencies/auxiliaryFunctions/HV_mod/calcEHIV_2D.m @@ -15,127 +15,38 @@ % Output: % - EHIV ... expected hypervolume improvement % -% This function is inspired by the code of Michael Emmerich and Andre -% Deutz, LIACS, Leiden University, 2010 -% Based on the paper: -% M. Emmerich, A.H. Deutz, J.W. Klinkenberg: The computation of the -% expected improvement in dominated hypervolume of Pareto front -% approximations , LIACS TR-4-2008, Leiden University, The Netherlands -% http://www.liacs.nl/~emmerich/TR-ExI.pdf +% This function is inspired by the publication of Michael Emmerich et Al: +% +% M. Emmerich, K. Yang, A. Deutz, H. Wang, and C. M. Fonseca, “A +% multicriteria generalization of Bayesian global optimization,” in +% Advances in Stochastic and Deterministic Global Optimization (P. M. +% Pardalos, A. Zhigljavsky, and J. Žilinskas, eds.), vol. 107 of Springer +% Optimization and Its Applications, Springer International Publishing, +% 2016. In press. % % Copyright 2014-2015: Lars Freier, Eric von Lieres % See the license note at the end of the file. + +%% New Code Vectorized +% timeVec = tic; % Make sure that only pareto optimal points are provided paretoPoints = determineParetoSet_Mex(paretoPoints); -sortByEachDimension = sort(paretoPoints); - -nSamples=size(paretoPoints,1); -nObj = size(paretoPoints,2); -nCellsPriori = (nSamples+1)^nObj; -nCells = (nSamples+1)*(nSamples+2)/2; - -% For better clarity: sort every variable with increasing value -valuesCell = cell(nObj,1); -for iObj=1:nObj - valuesCell{iObj} = sortByEachDimension(:,iObj); -end - -% Define grid which represent the vertices of eahc considered rectangle -[i1,i2] = ndgrid(0:nSamples,0:nSamples); -indexMatrix =[i1(:),i2(:)]; - -% Samples in the recangle with these lower bounds to not lead to any -% contribution to the EIHV as anypoint in these areas are dominated by -% current pareto front -doNotUse = indexMatrix(:,1)>(nSamples-indexMatrix(:,2)); -indexMatrix(doNotUse,:)=[]; - -% For more clarity, save lower and upper bounds of each reactangle -Cl_Matrix = zeros(nCells,nObj); -Cu_Matrix = zeros(nCells,nObj); -dominateSamplesCell = cell(nSamples-1,nObj); - -for iIndex=0:nSamples - for iObj=1:nObj - if iIndex==0 - Cl_Matrix(indexMatrix(:,iObj)==0,iObj) = -inf; - else - Cl_Matrix(indexMatrix(:,iObj)==iIndex,iObj) = valuesCell{iObj}(iIndex); - end - end -end - -for iIndex=0:nSamples - for iObj=1:nObj - if iIndex==nSamples - Cu_Matrix(indexMatrix(:,iObj)==iIndex,iObj) = referencePoint(iObj); - else - Cu_Matrix(indexMatrix(:,iObj)==iIndex,iObj) = valuesCell{iObj}(iIndex+1); - end - end -end - -% Also save values which are dominated by each sample points in each -% direction -for iIndex=0:nSamples-1 - for iObj=1:nObj - dominateSamplesCell{iIndex+1,iObj} = paretoPoints(:,iObj)>=valuesCell{iObj}(iIndex+1); - end -end - -% Find reference points fmaxMatrix for each considered rectangle -fmaxMatrix = bsxfun(@times,ones(nCells,nObj),referencePoint); -for iCell=1:nCells - for iObj=1:nObj - if iObj==1 - indexChosenParetoPoint = paretoPoints(:,2)==Cl_Matrix(iCell,2); - else - indexChosenParetoPoint = paretoPoints(:,1)==Cl_Matrix(iCell,1); - end - if sum(indexChosenParetoPoint)==0 - fmaxMatrix(iCell,iObj) = referencePoint(iObj); - else - fmaxMatrix(iCell,iObj) = min(paretoPoints(indexChosenParetoPoint,iObj)); - end - end -end - -sampleIsDominated = false(nSamples,1); -sPlus = zeros(nCells,1); - - -for iCell=1:nCells - % Identify sample points which are dominated by upper corner of - % current cell - if indexMatrix(iCell,1)==nSamples||indexMatrix(iCell,2)==nSamples - sampleIsDominated = false(nSamples,1); - else - sampleIsDominated = dominateSamplesCell{indexMatrix(iCell,1)+1,1}&dominateSamplesCell{indexMatrix(iCell,2)+1,2}; - end - - - if sum(sampleIsDominated)==0 - sPlus(iCell)=0; - else - sPlus(iCell) = Hypervolume_MEX(paretoPoints(sampleIsDominated,:),fmaxMatrix(iCell,:)); - end -end - -%Marginal integration -Psi = marginalEI(fmaxMatrix,Cu_Matrix,mu,sd) - marginalEI(fmaxMatrix,Cl_Matrix,mu,sd); - -%Cumulative Gaussian over length for correction constant -Cu_Norm = bsxfun(@rdivide,bsxfun(@minus,Cu_Matrix,mu),sd); -Cl_Norm = bsxfun(@rdivide,bsxfun(@minus,Cl_Matrix,mu),sd); - -GaussCDF = gausscdf(Cu_Norm) - gausscdf(Cl_Norm); -%ExI Kontribution fuer die aktuelle Zelle -cellEI = prod(Psi,2)-sPlus.*prod(GaussCDF,2); +paretoPointsSort = sortrows(paretoPoints); +paretoPointsSort = [-inf,referencePoint(2);paretoPointsSort;referencePoint(1),-inf]; +paretoPointsSort = paretoPointsSort(end:-1:1,:); +part1 = (paretoPointsSort(1:end-2,1)-paretoPointsSort(2:end-1,1)).*... + gausscdf((paretoPointsSort(2:end-1,1)-mu(1))/(sd(1))).*... + gaussEI(mu(2),sd(2),paretoPointsSort(2:end-1,2),paretoPointsSort(2:end-1,2)); +part1 = [part1;0]; -EHIV=sum(sum(cellEI)); +part2 = (gaussEI(mu(1),sd(1),paretoPointsSort(1:end-1,1),paretoPointsSort(1:end-1,1))-... + gaussEI(mu(1),sd(1),paretoPointsSort(1:end-1,1),paretoPointsSort(2:end,1))).*... + gaussEI(mu(2),sd(2),paretoPointsSort(2:end,2),paretoPointsSort(2:end,2)); +EHIV = sum(part1+part2); +% fprintf('EHIV: %g - time: %g\n',EHIV,toc(timeVec)) % ============================================================================= % KriKit - Kriging toolKit % diff --git a/dependencies/auxiliaryFunctions/HV_mod/calcEHIV_2D_2016.m b/dependencies/auxiliaryFunctions/HV_mod/calcEHIV_2D_2016.m new file mode 100644 index 0000000..fa60ea7 --- /dev/null +++ b/dependencies/auxiliaryFunctions/HV_mod/calcEHIV_2D_2016.m @@ -0,0 +1,211 @@ +function EHIV=calcEHIV_2D_2016(paretoPoints,referencePoint,mu,sd) +% EHIV=calcEHIV_2D(paretoPoints,referencePoint,mu,sd) +% +% This function calculate the expected hypervolume improvement of a Kriging +% model based on data point with the Pareto front given in paretoPoints. +% +% Input: +% - paretoPoints ... contains the values of the Pareto front +% (nParetoPointsX2) +% - referencePoint ... Reference point which is used for the hyper volume +% calculation. (1X2) +% - mu ... contains the Kriging prediction of the point of interest (1X2) +% - sd ... contains the Kriging prediction error (1X2) +% +% Output: +% - EHIV ... expected hypervolume improvement +% +% This function is inspired by the code of Michael Emmerich and Andre +% Deutz, LIACS, Leiden University, 2010 +% Based on the paper: +% M. Emmerich, A.H. Deutz, J.W. Klinkenberg: The computation of the +% expected improvement in dominated hypervolume of Pareto front +% approximations , LIACS TR-4-2008, Leiden University, The Netherlands +% http://www.liacs.nl/~emmerich/TR-ExI.pdf +% +% Copyright 2014-2015: Lars Freier, Eric von Lieres +% See the license note at the end of the file. + + +%% New Code +timeNonVec = tic; +% Make sure that only pareto optimal points are provided +paretoPoints = determineParetoSet_Mex(paretoPoints); +paretoPointsSort = sortrows(paretoPoints); +paretoPointsSort = [-inf,referencePoint(2);paretoPointsSort;referencePoint(1),-inf]; +paretoPointsSort = paretoPointsSort(end:-1:1,:); + +nSamples=size(paretoPoints,1); +nObj = size(paretoPoints,2); + + +EHIV = 0; +for iSection = 2:(nSamples+2) + if iSection<(nSamples+2) + part1 = (paretoPointsSort(iSection-1,1)-paretoPointsSort(iSection,1)).*... + gausscdf((paretoPointsSort(iSection)-mu(1))/(sd(1))).*... + gaussEI(mu(2),sd(2),paretoPointsSort(iSection,2),paretoPointsSort(iSection,2)); + else + part1 = 0; + end + + part2 = (gaussEI(mu(1),sd(1),paretoPointsSort(iSection-1,1),paretoPointsSort(iSection-1,1))-... + gaussEI(mu(1),sd(1),paretoPointsSort(iSection-1,1),paretoPointsSort(iSection,1))).*... + gaussEI(mu(2),sd(2),paretoPointsSort(iSection,2),paretoPointsSort(iSection,2)); + + EHIV = EHIV + part1 + part2; + + fprintf('iSection: %i - x1(-1): %g - x1: %g - x2: %g - EHIV: %g - part1: %g - part2: %g\n',... + iSection-1,paretoPointsSort(iSection-1,1),paretoPointsSort(iSection,1),paretoPointsSort(iSection,2),... + EHIV,part1,part2) + +end +fprintf('EHIV: %g - time: %g\n',EHIV,toc(timeNonVec)) + +%% New Code Vectorized +timeVec = tic; +% Make sure that only pareto optimal points are provided +paretoPoints = determineParetoSet_Mex(paretoPoints); +paretoPointsSort = sortrows(paretoPoints); +paretoPointsSort = [-inf,referencePoint(2);paretoPointsSort;referencePoint(1),-inf]; +paretoPointsSort = paretoPointsSort(end:-1:1,:); + +part1 = (paretoPointsSort(1:end-2,1)-paretoPointsSort(2:end-1,1)).*... + gausscdf((paretoPointsSort(2:end-1,1)-mu(1))/(sd(1))).*... + gaussEI(mu(2),sd(2),paretoPointsSort(2:end-1,2),paretoPointsSort(2:end-1,2)); +part1 = [part1;0]; + +part2 = (gaussEI(mu(1),sd(1),paretoPointsSort(1:end-1,1),paretoPointsSort(1:end-1,1))-... + gaussEI(mu(1),sd(1),paretoPointsSort(1:end-1,1),paretoPointsSort(2:end,1))).*... + gaussEI(mu(2),sd(2),paretoPointsSort(2:end,2),paretoPointsSort(2:end,2)); +EHIV = sum(part1+part2); + +fprintf('EHIV: %g - time: %g\n',EHIV,toc(timeVec)) + +%% Old Code +timeOld = tic; + +% Make sure that only pareto optimal points are provided +paretoPoints = determineParetoSet_Mex(paretoPoints); +sortByEachDimension = sort(paretoPoints); + +nSamples=size(paretoPoints,1); +nObj = size(paretoPoints,2); +nCellsPriori = (nSamples+1)^nObj; +nCells = (nSamples+1)*(nSamples+2)/2; + +% For better clarity: sort every variable with increasing value +valuesCell = cell(nObj,1); +for iObj=1:nObj + valuesCell{iObj} = sortByEachDimension(:,iObj); +end + +% Define grid which represent the vertices of eahc considered rectangle +[i1,i2] = ndgrid(0:nSamples,0:nSamples); +indexMatrix =[i1(:),i2(:)]; + +% Samples in the recangle with these lower bounds to not lead to any +% contribution to the EIHV as anypoint in these areas are dominated by +% current pareto front +doNotUse = indexMatrix(:,1)>(nSamples-indexMatrix(:,2)); +indexMatrix(doNotUse,:)=[]; + +% For more clarity, save lower and upper bounds of each reactangle +Cl_Matrix = zeros(nCells,nObj); +Cu_Matrix = zeros(nCells,nObj); +dominateSamplesCell = cell(nSamples-1,nObj); + +for iIndex=0:nSamples + for iObj=1:nObj + if iIndex==0 + Cl_Matrix(indexMatrix(:,iObj)==0,iObj) = -inf; + else + Cl_Matrix(indexMatrix(:,iObj)==iIndex,iObj) = valuesCell{iObj}(iIndex); + end + end +end + +for iIndex=0:nSamples + for iObj=1:nObj + if iIndex==nSamples + Cu_Matrix(indexMatrix(:,iObj)==iIndex,iObj) = referencePoint(iObj); + else + Cu_Matrix(indexMatrix(:,iObj)==iIndex,iObj) = valuesCell{iObj}(iIndex+1); + end + end +end + +% Also save values which are dominated by each sample points in each +% direction +for iIndex=0:nSamples-1 + for iObj=1:nObj + dominateSamplesCell{iIndex+1,iObj} = paretoPoints(:,iObj)>=valuesCell{iObj}(iIndex+1); + end +end + +% Find reference points fmaxMatrix for each considered rectangle +fmaxMatrix = bsxfun(@times,ones(nCells,nObj),referencePoint); +for iCell=1:nCells + for iObj=1:nObj + if iObj==1 + indexChosenParetoPoint = paretoPoints(:,2)==Cl_Matrix(iCell,2); + else + indexChosenParetoPoint = paretoPoints(:,1)==Cl_Matrix(iCell,1); + end + if ~any(indexChosenParetoPoint) + fmaxMatrix(iCell,iObj) = referencePoint(iObj); + else + fmaxMatrix(iCell,iObj) = min(paretoPoints(indexChosenParetoPoint,iObj)); + end + end +end + +% sampleIsDominated = false(nSamples,1); +sPlus = zeros(nCells,1); + + +for iCell=1:nCells + % Identify sample points which are dominated by upper corner of + % current cell + if indexMatrix(iCell,1)==nSamples||indexMatrix(iCell,2)==nSamples + sampleIsDominated = false(nSamples,1); + else + sampleIsDominated = dominateSamplesCell{indexMatrix(iCell,1)+1,1}&dominateSamplesCell{indexMatrix(iCell,2)+1,2}; + end + + + if ~any(sampleIsDominated) + sPlus(iCell)=0; + else + sPlus(iCell) = Hypervolume_MEX(paretoPoints(sampleIsDominated,:),fmaxMatrix(iCell,:)); + end +end + +%Marginal integration +Psi = marginalEI(fmaxMatrix,Cu_Matrix,mu,sd) - marginalEI(fmaxMatrix,Cl_Matrix,mu,sd); + +%Cumulative Gaussian over length for correction constant +Cu_Norm = bsxfun(@rdivide,bsxfun(@minus,Cu_Matrix,mu),sd); +Cl_Norm = bsxfun(@rdivide,bsxfun(@minus,Cl_Matrix,mu),sd); + +GaussCDF = gausscdf(Cu_Norm) - gausscdf(Cl_Norm); +%ExI Kontribution fuer die aktuelle Zelle +cellEI = prod(Psi,2)-sPlus.*prod(GaussCDF,2); + + +EHIV=sum(sum(cellEI)); + +fprintf('EHIV: %g - time: %g\n',EHIV,toc(timeOld)) + +% ============================================================================= +% KriKit - Kriging toolKit +% +% Copyright 2014-2015: Lars Freier(1), Eric von Lieres(1) +% +% (1)Forschungszentrum Juelich GmbH, IBG-1, Juelich, Germany. +% +% All rights reserved. This program and the accompanying materials +% are made available under the terms of the GNU Public License v3.0 (or, at +% your option, any later version) which accompanies this distribution, and +% is available at http://www.gnu.org/licenses/gpl.html +% ============================================================================= \ No newline at end of file diff --git a/dependencies/auxiliaryFunctions/HV_mod/calcEHIV_3D_2016.m b/dependencies/auxiliaryFunctions/HV_mod/calcEHIV_3D_2016.m new file mode 100644 index 0000000..3d95a34 --- /dev/null +++ b/dependencies/auxiliaryFunctions/HV_mod/calcEHIV_3D_2016.m @@ -0,0 +1,89 @@ +function EHVI_3D=calcEHIV_3D_2016(paretoPoints,referencePoint,mu,sd) +% EHIV=calcEHIV_2D(paretoPoints,referencePoint,mu,sd) +% +% This function calculate the expected hypervolume improvement of a Kriging +% model based on data point with the Pareto front given in paretoPoints. +% +% Input: +% - paretoPoints ... contains the values of the Pareto front +% (nParetoPointsX2) +% - referencePoint ... Reference point which is used for the hyper volume +% calculation. (1X2) +% - mu ... contains the Kriging prediction of the point of interest (1X2) +% - sd ... contains the Kriging prediction error (1X2) +% +% Output: +% - EHIV ... expected hypervolume improvement +% +% This function is inspired by the code of Michael Emmerich and Andre +% Deutz, LIACS, Leiden University, 2010 +% Based on the paper: +% M. Emmerich, A.H. Deutz, J.W. Klinkenberg: The computation of the +% expected improvement in dominated hypervolume of Pareto front +% approximations , LIACS TR-4-2008, Leiden University, The Netherlands +% http://www.liacs.nl/~emmerich/TR-ExI.pdf +% +% Copyright 2014-2015: Lars Freier, Eric von Lieres +% See the license note at the end of the file. + + +%% New Code Vectorized +% timeVec = tic; +% Make sure that only pareto optimal points are provided +paretoPoints = determineParetoSet_Mex(paretoPoints); +% Use last variable for sorting (easier for interpretation) +paretoPointsSort = sortrows(paretoPoints,3); +% Add Point. Needed for proper calculation + +% paretoPointsSort = [-inf,-inf,referencePoint(3);paretoPointsSort;referencePoint(1),referencePoint(2),-inf]; +paretoPointsSort = [-inf,-inf,paretoPointsSort(1,3);paretoPointsSort;referencePoint(1),referencePoint(2),referencePoint(2)]; +% Sort with descend order +% paretoPointsSort = [referencePoint(1),referencePoint(2),-inf;paretoPointsSort;-inf,-inf,referencePoint(3)]; +% paretoPointsSort = paretoPointsSort(end:-1:1,:); +nPoints = size(paretoPoints,1); + +ParetoFront2D = referencePoint(1:2); +EHVI_3D = 0; +for iSection = 2:(nPoints+2) + % Update 2D Pareto Curve + if iSection>2 + ParetoFront2D = determineParetoSet_Mex(paretoPointsSort(2:iSection-1,1:2)); + end + + EHVI_2D = calcEHIV_2D(ParetoFront2D,referencePoint(1:2),mu(1:2),sd(1:2)); + +% if iSection<(nPoints+2) + if iSection<(nPoints+2) + part1 = (paretoPointsSort(iSection,3)-paretoPointsSort(iSection-1,3)).*... + gausscdf((paretoPointsSort(iSection,3)-mu(3))/(sd(3))).*... + EHVI_2D; + else + part1 = 0; + end + + if iSection>2 + part2 = (gaussEI(mu(3),sd(3),paretoPointsSort(iSection,3),paretoPointsSort(iSection,3))-... + gaussEI(mu(3),sd(3),paretoPointsSort(iSection,3),paretoPointsSort(iSection-1,3))).*... + EHVI_2D; + else + part2 = gaussEI(mu(3),sd(3),paretoPointsSort(iSection,3),paretoPointsSort(iSection,3)).*... + EHVI_2D; + end + + EHVI_3D = EHVI_3D + part1 + part2; +end + + +% fprintf('EHIV: %g - time: %g\n',EHIV,toc(timeVec)) +% ============================================================================= +% KriKit - Kriging toolKit +% +% Copyright 2014-2015: Lars Freier(1), Eric von Lieres(1) +% +% (1)Forschungszentrum Juelich GmbH, IBG-1, Juelich, Germany. +% +% All rights reserved. This program and the accompanying materials +% are made available under the terms of the GNU Public License v3.0 (or, at +% your option, any later version) which accompanies this distribution, and +% is available at http://www.gnu.org/licenses/gpl.html +% ============================================================================= \ No newline at end of file diff --git a/dependencies/auxiliaryFunctions/HV_mod/gaussEI.m b/dependencies/auxiliaryFunctions/HV_mod/gaussEI.m new file mode 100644 index 0000000..20f897d --- /dev/null +++ b/dependencies/auxiliaryFunctions/HV_mod/gaussEI.m @@ -0,0 +1,4 @@ +function normEI=gaussEI(mu,sigma,lb,ub) + normVar = (ub-mu)./sigma; + normEI = sigma.*gausspdf(normVar) + (lb-mu).*gausscdf(normVar); +end \ No newline at end of file diff --git a/dependencies/auxiliaryFunctions/HV_mod/gausscdf.m b/dependencies/auxiliaryFunctions/HV_mod/gausscdf.m index 0a5a817..aaf5921 100644 --- a/dependencies/auxiliaryFunctions/HV_mod/gausscdf.m +++ b/dependencies/auxiliaryFunctions/HV_mod/gausscdf.m @@ -1,2 +1,3 @@ function x=gausscdf(x) - x=0.5*(1+erf(x/sqrt(2))); \ No newline at end of file + x=0.5*(1+erf(x/sqrt(2))); +end \ No newline at end of file diff --git a/dependencies/auxiliaryFunctions/HV_mod/gausspdf.m b/dependencies/auxiliaryFunctions/HV_mod/gausspdf.m index e4abbed..e6fed64 100644 --- a/dependencies/auxiliaryFunctions/HV_mod/gausspdf.m +++ b/dependencies/auxiliaryFunctions/HV_mod/gausspdf.m @@ -1,2 +1,3 @@ function res=gausspdf(x) - res=1/sqrt(2*pi)*exp(-x.^2/2); \ No newline at end of file + res=1/sqrt(2*pi)*exp(-x.^2/2); +end \ No newline at end of file diff --git a/dependencies/auxiliaryFunctions/MatrixInversion/invupdateapp.m b/dependencies/auxiliaryFunctions/MatrixInversion/invupdateapp.m index 81fdfc1..d6b0cf1 100644 --- a/dependencies/auxiliaryFunctions/MatrixInversion/invupdateapp.m +++ b/dependencies/auxiliaryFunctions/MatrixInversion/invupdateapp.m @@ -31,7 +31,7 @@ % % Input checks. -error(nargchk(4,4,nargin)) +% error(nargchk(4,4,nargin)) [n,m] = size(A); if n~=m error('A should be square.'); diff --git a/dependencies/auxiliaryFunctions/externalTools/mcmcstat/boxplotMCMCStat.m b/dependencies/auxiliaryFunctions/externalTools/mcmcstat/boxplotMCMCStat.m index af257a9..b269366 100644 --- a/dependencies/auxiliaryFunctions/externalTools/mcmcstat/boxplotMCMCStat.m +++ b/dependencies/auxiliaryFunctions/externalTools/mcmcstat/boxplotMCMCStat.m @@ -1,4 +1,4 @@ -function h=boxplot(y,names,outliers) +function h=boxplotMCMCStat(y,names,outliers) %BOXPLOT Draws a boxplot % boxplot(y) - draws boxplots for the columns of y diff --git a/dependencies/auxiliaryFunctions/mexFiles/VChooseK/CompilingCommand.txt b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/CompilingCommand.txt new file mode 100644 index 0000000..386c0ce --- /dev/null +++ b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/CompilingCommand.txt @@ -0,0 +1 @@ + mex -I/vol/home/yangk/local/MATLAB/R2014b/extern/include -O VChooseKUncommented.c \ No newline at end of file diff --git a/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.c b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.c new file mode 100644 index 0000000..2432e57 --- /dev/null +++ b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.c @@ -0,0 +1,1114 @@ +// VChooseK.c +// VCHOOSEK - Combinations of K elements [MEX] +// VCHOOSEK(V, K) creates a matrix, which rows are all combinations of +// choosing K elements of the vector V without order and without repititions. +// +// INPUT: +// V: Array of class DOUBLE, SINGLE, (U)INT8/16/32/64, LOGICAL, CHAR. +// The shape of the array does not matter. +// K: Number of elements to choose. Scalar double with integer number. +// +// OUTPUT: +// Y: Matrix of size [N!/K!(N-K)!, K] with N is the number of elements of V. +// Y has the same class as the input V. If V has less than K elements, a +// warning appears and the empty matrix is replied. As usual in Matlab, +// empty inputs yield to empty Y. +// A warning appears, if the output would exceed 500MB, and an error for +// 1GB. Both limits can be adjusted according to the available RAM in the +// C-Mex source. +// +// NOTE: The output equals Matlab's NCHOOSEK, except that NCHOOSEK replies the +// number of combinations for a scalar V: +// VChooseK(-1, 1) replies [-1]: One element taken out of a set of length one. +// NCHOOSEK(-1, 1) fails at calculating N!/K!(N-K)!. +// +// EXAMPLES: +// Choose 2 elements from [1,2,3,4]: +// VChooseK(1:4, 2) % ==> [1,2; 1,3; 1,4; 2,3; 2,4; 3,4] +// For speed cast the input to integer types if possible: +// Y = double(VChooseK(int16(1:1000), 2); +// is faster than: +// Y = VChooseK(1:1000, 2); +// To get the combinations of cell arrays, use the combinations of the index: +// C = {'a', 'b', 'c', 'd'}; +// C2 = C(VChooseK(1:4, 2)) +// ==> C2 = {'a', 'b'; 'a', 'c'; 'a', 'd'; 'b', 'c'; 'b', 'd'; 'c', 'd'} +// +// COMPILE: +// mex -O VChooseK.c +// Compatibility to 64-bit machines is assumed, but cannot be tested currently. +// On Linux the C99 comments must be considered (thanks Sebastiaan Breedveld): +// mex CFLAGS="\$CFLAGS -std=C99" -O VChooseK.c +// Please run the unit-test TestVChooseK after compiling! +// +// INSPIRATION: +// Jos van der Geest has published an efficient NCHOOSE2, which is much faster +// than Matlab's NCHOOSEK: +// http://www.mathworks.com/matlabcentral/fileexchange/20144 +// I was curious, if a MEX version is much faster. At first I've created +// NChoose2q, which is 5 times faster than Jos' Matlab implementation. But the +// algorithm was so simple in C and did not consume temporary memory, that I +// expanded it to K=3,4,5 soon. The algorithm for free K was more challenging, +// but it needs just 3*K pointers for temporary memory. Therefore it is much +// faster than Matlab's NCHOOSEK (Matlab 6.5, 1.5GHz Pentium-M, 512 MB): +// NCHOOSEK: VCHOOSEK: +// (1:50, 5): 45.30 sec 0.32 sec => 141 times faster +// (1:20, 16): 0.52 sec 0.0024 sec => 216 times faster +// (int8(1:40), 4): 0.64 sec 0.001562 sec => 410 times faster +// +// Related FEX related publications: +// (http://www.mathworks.com/matlabcentral/fileexchange/) +// NCTWO (Simone Scaringi): 20110 +// COMBINATOR (Matt Fig) [I prefer this for general tasks!]: 24325 +// PICK (Stefan Stoll) calls NCHOOSEK for unordered combinations: 12724 +// COMBINATIONS (Gautam Vallabha): 23080 +// +// Tested: Matlab 6.5, 7.7, 7.8, WinXP, [UnitTest] +// Compilers: BCC5.5, LCC2.4/3.8, Open Watcom 1.8 +// Watcom lib is 20% faster than BCC and LCC libs for INT8! +// Author: Jan Simon, Heidelberg, (C) 2009 matlab.THIS_YEAR(a)nMINUSsimonDOTde +// License: BSD (use/copy/modify on own risk, but mention author) + +/* +% $JRev: R0j V:007 Sum:5IALpldTXov9 Date:24-Dec-2008 02:59:35 $ +% $File: User\JSim\Published\VChooseK\VChooseK.c $ +% History: +% 001: 17-Dec-2009 08:10, MEX function for NCHOOSEK(X, 2). +% 007: 23-Dec-2008 17:40, Stop if output size exceed some limits. +% Calculate output size as mwSize and DOUBLE to catch overflows. +*/ + +#include "mex.h" +#include + +// 32 bit array dimensions for Matlab 6.5: +// See option "compatibleArrayDims" for MEX in Matlab >= 7.7. +#ifndef mwSize +#define mwSize int +#define mwIndex int +#define MWSIZE_MAX 2147483647UL +#endif + +// Limits for warning and error: +#define WARN_LIMIT 500000000L // 500 MB, *must* be smaller than ERROR_LIMIT +#define ERROR_LIMIT 1000000000L // 1 GB (recommended for 32&64 bit systems) + +// Prototypes: +mwSize GetOutputLen(mwSize n, mwSize k, double *C_double); +void BadInputTypeError(void); + +// The functions for each number of elements are absolutely equal except for +// the type of the array. But using some macros would result in ugly source +// code also. Using pointers to vectors of variable size would work, but is +// remarkably slower. Sorry for the pile of redundant code! +void Elem2_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY); +void Elem2_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY); +void Elem2_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY); +void Elem2_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY); + +void Elem3_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY); +void Elem3_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY); +void Elem3_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY); +void Elem3_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY); + +void Elem4_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY); +void Elem4_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY); +void Elem4_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY); +void Elem4_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY); + +void Elem5_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY); +void Elem5_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY); +void Elem5_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY); +void Elem5_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY); + +void ElemK_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY, mwSize K); +void ElemK_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY, mwSize K); +void ElemK_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY, mwSize K); +void ElemK_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY, mwSize K); + +// Main function =============================================================== +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + mwSize nX, nY, K; + const mxArray *X; + double nY_double; + int ElementSize; + + // Check number of inputs and outputs: + if (nrhs != 2) { + mexErrMsgIdAndTxt("JSimon:VChooseK:BadNInput", "2 inputs required."); + } + if (nlhs > 1) { + mexErrMsgIdAndTxt("JSimon:VChooseK:BadNInput", "1 output allowed."); + } + + // Check type of input: + X = prhs[0]; + if (!mxIsNumeric(X) && !mxIsChar(X) & !mxIsLogical(X)) { + mexErrMsgIdAndTxt("JSimon:VChooseK:BadNInput", + "Input array must be numerical, CHAR or LOGICAL."); + } + if (!mxIsDouble(prhs[1]) || mxGetNumberOfElements(prhs[1]) != 1) { + mexErrMsgIdAndTxt("JSimon:VChooseK:BadNInput", + "Input K must be a numerical scalar."); + } + + // Get number of elements to choose and catch pathological cases: + nX = mxGetNumberOfElements(X); + K = (mwSize) floor(mxGetScalar(prhs[1]) + 0.5); // Rounding + + // Empty input => empty output: + if (nX == 0) { + plhs[0] = mxCreateNumericMatrix(0, 0, mxGetClassID(X), mxREAL); + return; + } + + // K == 1 => reply input as column vector, K == 0 => empty output: + if (K <= 1) { + if (K == 1) { // Choose 1 element => output equals input: + plhs[0] = mxDuplicateArray(X); + mxSetM(plhs[0], nX); + mxSetN(plhs[0], 1); + } else if (K <= 0) { // Empty matrix: + plhs[0] = mxCreateNumericMatrix(0, 0, mxGetClassID(X), mxREAL); + } + return; + } + + // Catch trivial K == nX and pathological K > nX: + if (K >= nX) { + if (K == nX) { + plhs[0] = mxDuplicateArray(X); + mxSetM(plhs[0], 1); + mxSetN(plhs[0], nX); + } else { + mexWarnMsgIdAndTxt("JSimon:VChooseK:ShortInput", + "Too short input: K > N."); + plhs[0] = mxCreateNumericMatrix(0, 0, mxGetClassID(X), mxREAL); + } + return; + } + + // Calculate size of output (N!/(K!*(N-K)!)) and check limits - reduce + // the risk of overflows, nY is calculated as DOUBLE additionally: + nY = GetOutputLen(nX, K, &nY_double); + ElementSize = mxGetElementSize(X); + nY_double *= ElementSize; + if (nY_double > WARN_LIMIT) { + if (nY_double < ERROR_LIMIT && nY_double < MWSIZE_MAX) { + mexWarnMsgIdAndTxt("JSimon:VChooseK:LargeOutput", + "Output will be large and take a long time."); + } else { + mexErrMsgIdAndTxt("JSimon:VChooseK:TooLargeOutput", + "Output would be too large."); + } + } + + // Create the output: + // In a MEX file this stops with an error message automatically on failure. + // For usage in an engine file, check result for NULL! + plhs[0] = mxCreateNumericMatrix(nY, K, mxGetClassID(X), mxREAL); + + // Call different core functions according to the element size: + switch (K) { + case 2: // K == 2: + switch (ElementSize) { + case 8: Elem2_8Byte(mxGetPr(X), nX, mxGetPr(plhs[0]), nY); + break; + case 4: Elem2_4Byte((INT32_T *) mxGetData(X), nX, + (INT32_T *) mxGetData(plhs[0]), nY); + break; + case 2: Elem2_2Byte((INT16_T *) mxGetData(X), nX, + (INT16_T *) mxGetData(plhs[0]), nY); + break; + case 1: Elem2_1Byte((INT8_T *) mxGetData(X), nX, + (INT8_T *) mxGetData(plhs[0]), nY); + break; + default: BadInputTypeError(); + } + break; + + case 3: // K == 3: + switch (ElementSize) { + case 8: Elem3_8Byte(mxGetPr(X), nX, mxGetPr(plhs[0]), nY); + break; + case 4: Elem3_4Byte((INT32_T *) mxGetData(X), nX, + (INT32_T *) mxGetData(plhs[0]), nY); + break; + case 2: Elem3_2Byte((INT16_T *) mxGetData(X), nX, + (INT16_T *) mxGetData(plhs[0]), nY); + break; + case 1: Elem3_1Byte((INT8_T *) mxGetData(X), nX, + (INT8_T *) mxGetData(plhs[0]), nY); + break; + default: BadInputTypeError(); + } + break; + + case 4: // K == 4: + switch (ElementSize) { + case 8: Elem4_8Byte(mxGetPr(X), nX, mxGetPr(plhs[0]), nY); + break; + case 4: Elem4_4Byte((INT32_T *) mxGetData(X), nX, + (INT32_T *) mxGetData(plhs[0]), nY); + break; + case 2: Elem4_2Byte((INT16_T *) mxGetData(X), nX, + (INT16_T *) mxGetData(plhs[0]), nY); + break; + case 1: Elem4_1Byte((INT8_T *) mxGetData(X), nX, + (INT8_T *) mxGetData(plhs[0]), nY); + break; + default: BadInputTypeError(); + } + break; + + case 5: // K == 5: + switch (ElementSize) { + case 8: Elem5_8Byte(mxGetPr(X), nX, mxGetPr(plhs[0]), nY); + break; + case 4: Elem5_4Byte((INT32_T *) mxGetData(X), nX, + (INT32_T *) mxGetData(plhs[0]), nY); + break; + case 2: Elem5_2Byte((INT16_T *) mxGetData(X), nX, + (INT16_T *) mxGetData(plhs[0]), nY); + break; + case 1: Elem5_1Byte((INT8_T *) mxGetData(X), nX, + (INT8_T *) mxGetData(plhs[0]), nY); + break; + default: BadInputTypeError(); + } + break; + + default: // K > 5 + switch (ElementSize) { + case 8: ElemK_8Byte(mxGetPr(X), nX, mxGetPr(plhs[0]), nY, K); + break; + case 4: ElemK_4Byte((INT32_T *) mxGetData(X), nX, + (INT32_T *) mxGetData(plhs[0]), nY, K); + break; + case 2: ElemK_2Byte((INT16_T *) mxGetData(X), nX, + (INT16_T *) mxGetData(plhs[0]), nY, K); + break; + case 1: ElemK_1Byte((INT8_T *) mxGetData(X), nX, + (INT8_T *) mxGetData(plhs[0]), nY, K); + break; + default: BadInputTypeError(); + } + } + + return; +} + +// Error about bad input type: ================================================= +void BadInputTypeError(void) +{ + mexErrMsgIdAndTxt("JSimon:VChooseK:BadInputType", + "Input must have 1, 2, 4 or 8 bytes per element."); +} + +// Get output size: ============================================================ +mwSize GetOutputLen(mwSize n, mwSize k, double *C_double) +{ + // Number of samples for taking k elements from a set of n. + // Calculate the exact value as INT32 (or INT64 on 64 bit machine) and the + // eventually less precise DOUBLE value, which is less susceptible for an + // overflow. + mwSize i, ai, bi; + double ad, bd; + + bi = n - k; + ai = bi + 1; + ad = (double) ai; + bd = (double) bi; + for (i = 2; i <= k; i++) { + ai += (ai * bi) / i; + ad += (ad * bd) / i; + } + + *C_double = ad; + + return (ai); +} + +// 2 elements: ================================================================= +void Elem2_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY) +{ + // Called for input data with 8 bytes per element: DOUBLE, (U)INT64. + // 2 elements - fill 2 columns of output simultaneously. + double *Xq, *Xf, *Y1, *Y2; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column of output + for (Xf = Xp + nX - 1; Xp < Xf; Xp++) { + for (Xq = Xp + 1; Xq <= Xf; Xq++) { // With repititions: Xq = Xp; + *Y1++ = *Xp; // 1st column: slow changing + *Y2++ = *Xq; // 2nd column: fast changing + } + } + + return; +} + +// ============================================================================= +void Elem2_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY) +{ + // Called for input data with 4 bytes per element: SINGLE, (U)INT32. + // 2 elements - fill 2 columns of output simultaneously. + INT32_T *Xq, *Xf, *Y1, *Y2; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column of output + for (Xf = Xp + nX - 1; Xp < Xf; Xp++) { + for (Xq = Xp + 1; Xq <= Xf; Xq++) { + *Y1++ = *Xp; // 1st column: slow changing + *Y2++ = *Xq; // 2nd column: fast changing + } + } + + return; +} + +// ============================================================================= +void Elem2_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY) +{ + // Called for input data with 2 bytes per element: (U)INT16, CHAR. + // 2 elements - fill 2 columns of output simultaneously. + INT16_T *Xq, *Xf, *Y1, *Y2; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column of output + for (Xf = Xp + nX - 1; Xp < Xf; Xp++) { + for (Xq = Xp + 1; Xq <= Xf; Xq++) { + *Y1++ = *Xp; // 1st column: slow changing + *Y2++ = *Xq; // 2nd column: fast changing + } + } + + return; +} + +// ============================================================================= +void Elem2_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY) +{ + // Called for input data with 1 byte per element: (U)INT8, LOGICAL. + // 2 elements - fill 2 columns of output simultaneously. + INT8_T *Xq, *Xf, *Y1, *Y2; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column of output + for (Xf = Xp + nX - 1; Xp < Xf; Xp++) { + for (Xq = Xp + 1; Xq <= Xf; Xq++) { + *Y1++ = *Xp; // 1st column: slow changing + *Y2++ = *Xq; // 2nd column: fast changing + } + } + + return; +} + +// 3 elements: ================================================================= +void Elem3_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY) +{ + // Called for input data with 8 bytes per element: DOUBLE, (U)INT64. + // Fill 3 columns of output simultaneously. + double *Xq, *Xr, *X2f, *X3f, *Y1, *Y2, *Y3; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column of output + Y3 = Y2 + nY; // 3rd column of output + X3f = Xp + nX; // 3rd column ends with element nX + X2f = X3f - 1; // 2nd column ends with element nX - 1 + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { // "<", not "<=" ! + for (Xr = Xq + 1; Xr < X3f; Xr++) { + *Y1++ = *Xp; // 1st column: slow changing + *Y2++ = *Xq; + *Y3++ = *Xr; // 3rd column: fastest changing + } + } + } + + return; +} + +// ============================================================================= +void Elem3_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY) +{ + // Called for input data with 4 bytes per element: SINGLE, (U)INT32. + // Fill 3 columns of output simultaneously. + INT32_T *Xq, *Xr, *X2f, *X3f, *Y1, *Y2, *Y3; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column of output + Y3 = Y2 + nY; // 3rd column of output + X3f = Xp + nX; // 3rd column ends with element nX + X2f = X3f - 1; // 2nd column ends with element nX - 1 + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { // "<", not "<=" ! + for (Xr = Xq + 1; Xr < X3f; Xr++) { + *Y1++ = *Xp; // 1st column: slow changing + *Y2++ = *Xq; + *Y3++ = *Xr; // 3rd column: fastest changing + } + } + } + + return; +} + +// ============================================================================= +void Elem3_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY) +{ + // Called for input data with 2 bytes per element: (U)INT16, CHAR. + // Fill 3 columns of output simultaneously. + INT16_T *Xq, *Xr, *X2f, *X3f, *Y1, *Y2, *Y3; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column of output + Y3 = Y2 + nY; // 3rd column of output + X3f = Xp + nX; // 3rd column ends with element nX + X2f = X3f - 1; // 2nd column ends with element nX - 1 + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { // "<", not "<=" ! + for (Xr = Xq + 1; Xr < X3f; Xr++) { + *Y1++ = *Xp; // 1st column: slow changing + *Y2++ = *Xq; + *Y3++ = *Xr; // 3rd column: fastest changing + } + } + } + + return; +} + +// ============================================================================= +void Elem3_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY) +{ + // Called for input data with 1 byte per element: (U)INT8, LOGICAL. + // Fill 3 columns of output simultaneously. + INT8_T *Xq, *Xr, *X2f, *X3f, *Y1, *Y2, *Y3; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column of output + Y3 = Y2 + nY; // 3rd column of output + X3f = Xp + nX; // 3rd column ends with element nX + X2f = X3f - 1; // 2nd column ends with element nX - 1 + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { // "<", not "<=" ! + for (Xr = Xq + 1; Xr < X3f; Xr++) { + *Y1++ = *Xp; // 1st column: slow changing + *Y2++ = *Xq; + *Y3++ = *Xr; // 3rd column: fastest changing + } + } + } + + return; +} + +// 4 elements: ================================================================= +void Elem4_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY) +{ + // Called for input data with 8 bytes per element: DOUBLE, (U)INT64. + // Fill 4 columns of output simultaneously. + double *Xq, *Xr, *Xs, *X2f, *X4f, *Y1, *Y2, *Y3, *Y4; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column + Y3 = Y2 + nY; // 3rd column + Y4 = Y3 + nY; // 4th column + X4f = Xp + nX; // 4th column ends with element nX + X2f = X4f - 2; // 2nd column ends with element nX - 2 + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { + for (Xr = Xq + 1; Xr <= X4f; Xr++) { // "<", not "<=" + for (Xs = Xr + 1; Xs < X4f; Xs++) { + *Y1++ = *Xp; // 1st column: slowest changing + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; // 4th column: fastest changing + } + } + } + } + + return; +} + +// ============================================================================= +void Elem4_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY) +{ + // Called for input data with 4 bytes per element: SINGLE, (U)INT32. + // Fill 4 columns of output simultaneously. + INT32_T *Xq, *Xr, *Xs, *X2f, *X4f, *Y1, *Y2, *Y3, *Y4; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column + Y3 = Y2 + nY; // 3rd column + Y4 = Y3 + nY; // 4th column + X4f = Xp + nX; // 4th column ends with element nX + X2f = X4f - 2; // 2nd column ends with element nX - 2 + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { + for (Xr = Xq + 1; Xr <= X4f; Xr++) { // "<", not "<=" + for (Xs = Xr + 1; Xs < X4f; Xs++) { + *Y1++ = *Xp; // 1st column: slowest changing + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; // 4th column: fastest changing + } + } + } + } + + return; +} + +// ============================================================================= +void Elem4_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY) +{ + // Called for input data with 2 bytes per element: (U)INT16, CHAR. + // Fill 4 columns of output simultaneously. + INT16_T *Xq, *Xr, *Xs, *X2f, *X4f, *Y1, *Y2, *Y3, *Y4; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column + Y3 = Y2 + nY; // 3rd column + Y4 = Y3 + nY; // 4th column + X4f = Xp + nX; // 4th column ends with element nX + X2f = X4f - 2; // 2nd column ends with element nX - 2 + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { + for (Xr = Xq + 1; Xr <= X4f; Xr++) { // "<", not "<=" + for (Xs = Xr + 1; Xs < X4f; Xs++) { + *Y1++ = *Xp; // 1st column: slowest changing + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; // 4th column: fastest changing + } + } + } + } + + return; +} + +// ============================================================================= +void Elem4_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY) +{ + // Called for input data with 1 byte per element: (U)INT8, LOGICAL. + // Fill 4 columns of output simultaneously. + INT8_T *Xq, *Xr, *Xs, *X2f, *X4f, *Y1, *Y2, *Y3, *Y4; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column + Y3 = Y2 + nY; // 3rd column + Y4 = Y3 + nY; // 4th column + X4f = Xp + nX; // 4th column ends with element nX + X2f = X4f - 2; // 2nd column ends with element nX - 2 + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { + for (Xr = Xq + 1; Xr <= X4f; Xr++) { // "<", not "<=" + for (Xs = Xr + 1; Xs < X4f; Xs++) { + *Y1++ = *Xp; // 1st column: slowest changing + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; // 4th column: fastest changing + } + } + } + } + + return; +} + +// 5 elements: ================================================================= +void Elem5_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY) +{ + // Called for input data with 8 bytes per element: DOUBLE, (U)INT64. + // Fill 5 columns of output simultaneously. + double *Xq, *Xr, *Xs, *Xt, *X5f, *X3f, *X1f, + *Y1, *Y2, *Y3, *Y4, *Y5; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column + Y3 = Y2 + nY; // 3rd column + Y4 = Y3 + nY; // 4th column + Y5 = Y4 + nY; // 5th column + X5f = Xp + nX; // 5th column ends with element nX + // Used for 4th column also + X3f = X5f - 2; // 3rd column ends with element nX - 2 + // Used for 2nd column also + X1f = X3f - 2; // 1st column ends with element nX - 4 + + for ( ; Xp < X1f; Xp++) { + for (Xq = Xp + 1; Xq <= X3f; Xq++) { + for (Xr = Xq + 1; Xr < X3f; Xr++) { + for (Xs = Xr + 1; Xs <= X5f; Xs++) { + for (Xt = Xs + 1; Xt < X5f; Xt++) { + *Y1++ = *Xp; // 1st column: slowest changing + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; + *Y5++ = *Xt; // 5th column: fastest changing + } + } + } + } + } + + return; +} + +// ============================================================================= +void Elem5_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY) +{ + // Called for input data with 4 bytes per element: SINGLE, (U)INT32. + // Fill 5 columns of output simultaneously. + INT32_T *Xq, *Xr, *Xs, *Xt, *X5f, *X3f, *X1f, + *Y1, *Y2, *Y3, *Y4, *Y5; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column + Y3 = Y2 + nY; // 3rd column + Y4 = Y3 + nY; // 4th column + Y5 = Y4 + nY; // 5th column + X5f = Xp + nX; // 5th column ends with element nX + X3f = X5f - 2; // 3rd column ends with element nX - 2 + X1f = X3f - 2; // 1st column ends with element nX - 4 + + for ( ; Xp < X1f; Xp++) { + for (Xq = Xp + 1; Xq <= X3f; Xq++) { + for (Xr = Xq + 1; Xr < X3f; Xr++) { + for (Xs = Xr + 1; Xs <= X5f; Xs++) { + for (Xt = Xs + 1; Xt < X5f; Xt++) { + *Y1++ = *Xp; // 1st column: slowest changing + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; + *Y5++ = *Xt; // 5th column: fastest changing + } + } + } + } + } + + return; +} + +// ============================================================================= +void Elem5_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY) +{ + // Called for input data with 2 bytes per element: (U)INT16, CHAR. + // Fill 5 columns of output simultaneously. + INT16_T *Xq, *Xr, *Xs, *Xt, *X5f, *X3f, *X1f, + *Y1, *Y2, *Y3, *Y4, *Y5; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column + Y3 = Y2 + nY; // 3rd column + Y4 = Y3 + nY; // 4th column + Y5 = Y4 + nY; // 5th column + X5f = Xp + nX; // 5th column ends with element nX + X3f = X5f - 2; // 3rd column ends with element nX - 2 + X1f = X3f - 2; // 1st column ends with element nX - 4 + + for ( ; Xp < X1f; Xp++) { + for (Xq = Xp + 1; Xq <= X3f; Xq++) { + for (Xr = Xq + 1; Xr < X3f; Xr++) { + for (Xs = Xr + 1; Xs <= X5f; Xs++) { + for (Xt = Xs + 1; Xt < X5f; Xt++) { + *Y1++ = *Xp; // 1st column: slowest changing + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; + *Y5++ = *Xt; // 5th column: fastest changing + } + } + } + } + } + + return; +} + +// ============================================================================= +void Elem5_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY) +{ + // Called for input data with 1 byte per element: (U)INT8, LOGICAL. + // Fill 5 columns of output simultaneously. + INT8_T *Xq, *Xr, *Xs, *Xt, *X5f, *X3f, *X1f, + *Y1, *Y2, *Y3, *Y4, *Y5; + + Y1 = Yp; // 1st column of output + Y2 = Y1 + nY; // 2nd column + Y3 = Y2 + nY; // 3rd column + Y4 = Y3 + nY; // 4th column + Y5 = Y4 + nY; // 5th column + X5f = Xp + nX; // 5th column ends with element nX + X3f = X5f - 2; // 3rd column ends with element nX - 2 + X1f = X3f - 2; // 1st column ends with element nX - 4 + + for ( ; Xp < X1f; Xp++) { + for (Xq = Xp + 1; Xq <= X3f; Xq++) { + for (Xr = Xq + 1; Xr < X3f; Xr++) { + for (Xs = Xr + 1; Xs <= X5f; Xs++) { + for (Xt = Xs + 1; Xt < X5f; Xt++) { + *Y1++ = *Xp; // 1st column: slowest changing + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; + *Y5++ = *Xt; // 5th column: fastest changing + } + } + } + } + } + + return; +} + +// ============================================================================= +// Of course we could copy and paste the Elem[2/3/4/5]_NByte code until we reach +// the outer limits, but this is boring. So let's create a general algorithm, +// although it is clear, that such algorithms must have been implemented +// anywhere already?! +// ============================================================================= +void ElemK_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY, mwSize K) +{ + // Called for input data with 8 bytes per element: DOUBLE, UINT64. + // Fill all columns of output simultaneously. + double *Xq, *Xr, + **A, **Ap, **Af, *Yq, + **B, **Bp, **Bf, **Bq, **lastB, **F, **Fp, **lastF; + + // Array of input pointers [B] and final indices for each column [F]: + if ((B = (double **) mxMalloc(K * sizeof(double *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [B]."); + } + if ((F = (double **) mxMalloc(K * sizeof(double *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [F]."); + } + + // Set K input pointers and final index for each column: + Bf = B + K; + Fp = F; + Xq = Xp; + Xr = Xp + nX - K + 1; + for (Bp = B; Bp < Bf; ) { + *Bp++ = Xq++; + *Fp++ = Xr++; + } + + // Array of output pointers: + if ((A = (double **) mxMalloc(K * sizeof(double *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [A]."); + } + + // Set pointers to the K output columns of Y: + Af = A + K; + Yq = Yp; + for (Ap = A; Ap < Af; Ap++) { + *Ap = Yq; + Yq += nY; + } + + // Now the loops of the standard method (e.g. Elem3_8Byte) are simulated: + // The pointers formerly contained in a cascade of loops, are stored in the + // array B. The final index for each "loop" is stored in F. + lastB = B + K - 1; + lastF = F + K - 1; + while (1) { + // Copy values from the input to left K-1 columns, just the value of the + // K.th column changes: + Bq = lastB; + Fp = lastF; + while (*Bq < *Fp) { + // Copy values from input to output for all columns: + for (Bp = B, Ap = A; Ap < Af; Ap++) { + **Ap = **Bp++; + (*Ap)++; // Combine this to "*(*Ap)++ = **Bp++;" ?! + } + (*Bq)++; // Advance input pointer for K.th column only + } + + // Find the right-most not exhausted loop: + do { + Bq--; + Fp--; + if (Bq < B) { // Even the 1st column is exhausted - ready! + mxFree(A); // Thanks for the fish + mxFree(B); + mxFree(F); + return; // Goodbye + } + } while (*Bq >= *Fp); // Input pointer is before end of loop + + (*Bq)++; // Advance pointer of last not exhausted loop + while (++Bq < Bf) { // Initialize the following loops: + *Bq = *(Bq - 1) + 1; // With repititions: *Bq = *(Bq - 1) + } + } // while(1) loop + + // Never reached this line! +} + +// ============================================================================= +void ElemK_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY, mwSize K) +{ + // Called for input data with 4 bytes per element: (U)INT32, SINGLE. + // Fill all columns of output simultaneously. + INT32_T *Xq, *Xr, + **A, **Ap, **Af, *Yq, + **B, **Bp, **Bf, **Bq, **lastB, **F, **Fp, **lastF; + + // Array of input pointers [B] and final indices for each column [F]: + if ((B = (INT32_T **) mxMalloc(K * sizeof(INT32_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [B]."); + } + if ((F = (INT32_T **) mxMalloc(K * sizeof(INT32_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [F]."); + } + + // Set K input pointers and final index for each column: + Bf = B + K; + Fp = F; + Xq = Xp; + Xr = Xp + nX - K + 1; + for (Bp = B; Bp < Bf; ) { + *Bp++ = Xq++; + *Fp++ = Xr++; + } + + // Array of output pointers: + if ((A = (INT32_T **) mxMalloc(K * sizeof(INT32_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [A]."); + } + + // Set pointers to the K output columns of Y: + Af = A + K; + Yq = Yp; + for (Ap = A; Ap < Af; Ap++) { + *Ap = Yq; + Yq += nY; + } + + // Now the loops of the standard method (e.g. Elem3_8Byte) are simulated: + // The pointers formerly contained in a cascade of loops, are stored in the + // array B. The final index for each "loop" is stored in F. + lastB = B + K - 1; + lastF = F + K - 1; + while (1) { + // Copy values from the input to left K-1 columns, just the value of the + // K.th column changes: + Bq = lastB; + Fp = lastF; + while (*Bq < *Fp) { + // Copy values from input to output for all columns: + for (Bp = B, Ap = A; Ap < Af; Ap++) { + **Ap = **Bp++; + (*Ap)++; // Combine this to "*(*Ap)++ = **Bp++;" ?! + } + (*Bq)++; // Advance input pointer for K.th column only + } + + // Find the right-most not exhausted loop: + do { + Bq--; + Fp--; + if (Bq < B) { // Even the 1st column is exhausted - ready! + mxFree(A); // Thanks for the fish + mxFree(B); + mxFree(F); + return; // Goodbye + } + } while (*Bq >= *Fp); // Input pointer is before end of loop + + (*Bq)++; // Advance pointer of last not exhausted loop + while (++Bq < Bf) { // Initialize the following loops: + *Bq = *(Bq - 1) + 1; // With repititions: *Bq = *(Bq - 1) + } + } // while(1) loop + + // Never reached this line! +} + +// ============================================================================= +void ElemK_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY, mwSize K) +{ + // Called for input data with 2 bytes per element: (U)INT16, CHAR. + // Fill all columns of output simultaneously. + INT16_T *Xq, *Xr, + **A, **Ap, **Af, *Yq, + **B, **Bp, **Bf, **Bq, **lastB, **F, **Fp, **lastF; + + // Array of input pointers [B] and final indices for each column [F]: + if ((B = (INT16_T **) mxMalloc(K * sizeof(INT16_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [B]."); + } + if ((F = (INT16_T **) mxMalloc(K * sizeof(INT16_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [F]."); + } + + // Set K input pointers and final index for each column: + Bf = B + K; + Fp = F; + Xq = Xp; + Xr = Xp + nX - K + 1; + for (Bp = B; Bp < Bf; ) { + *Bp++ = Xq++; + *Fp++ = Xr++; + } + + // Array of output pointers: + if ((A = (INT16_T **) mxMalloc(K * sizeof(INT16_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [A]."); + } + + // Set pointers to the K output columns of Y: + Af = A + K; + Yq = Yp; + for (Ap = A; Ap < Af; Ap++) { + *Ap = Yq; + Yq += nY; + } + + // Now the loops of the standard method (e.g. Elem3_8Byte) are simulated: + // The pointers formerly contained in a cascade of loops, are stored in the + // array B. The final index for each "loop" is stored in F. + lastB = B + K - 1; + lastF = F + K - 1; + while (1) { + // Copy values from the input to left K-1 columns, just the value of the + // K.th column changes: + Bq = lastB; + Fp = lastF; + while (*Bq < *Fp) { + // Copy values from input to output for all columns: + for (Bp = B, Ap = A; Ap < Af; Ap++) { + **Ap = **Bp++; + (*Ap)++; // Combine this to "*(*Ap)++ = **Bp++;" ?! + } + (*Bq)++; // Advance input pointer for K.th column only + } + + // Find the right-most not exhausted loop: + do { + Bq--; + Fp--; + if (Bq < B) { // Even the 1st column is exhausted - ready! + mxFree(A); // Thanks for the fish + mxFree(B); + mxFree(F); + return; // Goodbye + } + } while (*Bq >= *Fp); // Input pointer is before end of loop + + (*Bq)++; // Advance pointer of last not exhausted loop + while (++Bq < Bf) { // Initialize the following loops: + *Bq = *(Bq - 1) + 1; // With repititions: *Bq = *(Bq - 1) + } + } // while(1) loop + + // Never reached this line! +} + +// ============================================================================= +void ElemK_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY, mwSize K) +{ + // Called for input data with 1 byte per element: (U)INT8, LOGICAL. + // Fill all columns of output simultaneously. + INT8_T *Xq, *Xr, + **A, **Ap, **Af, *Yq, + **B, **Bp, **Bf, **Bq, **lastB, **F, **Fp, **lastF; + + // Array of input pointers [B] and final indices for each column [F]: + if ((B = (INT8_T **) mxMalloc(K * sizeof(INT8_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [B]."); + } + if ((F = (INT8_T **) mxMalloc(K * sizeof(INT8_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [F]."); + } + + // Set K input pointers and final index for each column: + Bf = B + K; + Fp = F; + Xq = Xp; + Xr = Xp + nX - K + 1; + for (Bp = B; Bp < Bf; ) { + *Bp++ = Xq++; + *Fp++ = Xr++; + } + + // Array of output pointers: + if ((A = (INT8_T **) mxMalloc(K * sizeof(INT8_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [A]."); + } + + // Set pointers to the K output columns of Y: + Af = A + K; + Yq = Yp; + for (Ap = A; Ap < Af; Ap++) { + *Ap = Yq; + Yq += nY; + } + + // Now the loops of the standard method (e.g. Elem3_8Byte) are simulated: + // The pointers formerly contained in a cascade of loops, are stored in the + // array B. The final index for each "loop" is stored in F. + lastB = B + K - 1; + lastF = F + K - 1; + while (1) { + // Copy values from the input to left K-1 columns, just the value of the + // K.th column changes: + Bq = lastB; + Fp = lastF; + while (*Bq < *Fp) { + // Copy values from input to output for all columns: + for (Bp = B, Ap = A; Ap < Af; Ap++) { + **Ap = **Bp++; + (*Ap)++; // Combine this to "*(*Ap)++ = **Bp++;" ?! + } + (*Bq)++; // Advance input pointer for K.th column only + } + + // Find the right-most not exhausted loop: + do { + Bq--; + Fp--; + if (Bq < B) { // Even the 1st column is exhausted - ready! + mxFree(A); // Thanks for the fish + mxFree(B); + mxFree(F); + return; // Goodbye + } + } while (*Bq >= *Fp); // Input pointer is before end of loop + + (*Bq)++; // Advance pointer of last not exhausted loop + while (++Bq < Bf) { // Initialize the following loops: + *Bq = *(Bq - 1) + 1; // With repititions: *Bq = *(Bq - 1) + } + } // while(1) loop + + // Never reached this line! +} diff --git a/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.m b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.m new file mode 100644 index 0000000..9df2a76 --- /dev/null +++ b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.m @@ -0,0 +1,81 @@ +function Y = VChooseK(X, K) +% VChooseK - Combinations of K elements [MEX] +% VChooseK(V, K) creates a matrix, which rows are all combinations of +% choosing K elements of the vector V without order and without repititions. +% +% INPUT: +% V: Array of class DOUBLE, SINGLE, (U)INT8/16/32/64, LOGICAL, CHAR. +% The shape of the array does not matter. +% K: Number of elements to choose. Scalar double with integer number. +% +% OUTPUT: +% Y: Matrix of size [N!/K!(N-K)!, K] with N is the number of elements of V. +% Y has the same class as the input V. If V has less than K elements, a +% warning appears and the empty matrix is replied. As usual in Matlab, +% empty inputs yield to empty Y. +% A warning appears, if the output would exceed 500MB, and an error for +% 1GB. Both limits can be adjusted according to the available RAM in the +% C-Mex source. +% +% NOTE: The output equals Matlab's NCHOOSEK, except that NCHOOSEK replies the +% number of combinations for a scalar V: +% VChooseK(-1, 1) replies [-1]: One element taken out of a set of length one. +% NCHOOSEK(-1, 1) fails at calculating N!/K!(N-K)!. +% +% EXAMPLES: +% Choose 2 elements from [1,2,3,4]: +% VChooseK(1:4, 2) +% ==> [1,2; 1,3; 1,4; 2,3; 2,4; 3,4] +% For speed cast the input to integer types if possible: +% Y = double(VChooseK(int16(1:1000), 2); +% is faster than: +% Y = VChooseK(1:1000, 2); +% To get the combinations of cell arrays, use the combinations of the index: +% C = {'a', 'b', 'c', 'd'}; +% C2 = C(VChooseK(1:4, 2)) +% ==> C2 = {'a', 'b'; 'a', 'c'; 'a', 'd'; 'b', 'c'; 'b', 'd'; 'c', 'd'} +% +% COMPILE: +% mex -O VChooseK.c +% Compatibility to 64-bit machines is assumed, but cannot be tested currently. +% On Linux the C99 comments must be considered (thanks Sebastiaan Breedveld): +% mex CFLAGS="\$CFLAGS -std=C99" -O VChooseK.c +% Please run the unit-test TestVChooseK after compiling! +% +% INSPIRATION: +% Jos van der Geest has published an efficient NCHOOSE2, which is much faster +% than Matlab's NCHOOSEK: +% http://www.mathworks.com/matlabcentral/fileexchange/20144 +% I was curious, if a MEX version is much faster. At first I've created +% NChoose2q, which is 5 times faster than Jos' Matlab implementation. But the +% algorithm was so simple in C and did not consume temporary memory, that I've +% expanded it to K=3,4,5 soon. The algorithm for free K was more challenging, +% but it needs just 3*K pointers for temporary memory. Therefore it is much +% faster than Matlab's NCHOOSEK (Matlab 6.5, 1.5GHz Pentium-M, 512 MB): +% NCHOOSEK: VChooseK: +% (1:50, 5): 45.30 sec 0.32 sec => 141 times faster +% (1:20, 16): 0.52 sec 0.0024 sec => 216 times faster +% (int8(1:40), 4): 0.64 sec 0.001562 sec => 410 times faster +% +% There is a Matlab implementation in TestVChooseK, which might be helpful to +% understand the applied algorithm. +% +% Related FEX related publications: +% (http://www.mathworks.com/matlabcentral/fileexchange/) +% NCTWO (Simone Scaringi): 20110 +% COMBINATOR (Matt Fig) [I prefer this for general tasks!]: 24325 +% PICK (Stefan Stoll) calls NCHOOSEK for unordered combinations: 12724 +% COMBINATIONS (Gautam Vallabha): 23080 +% +% Tested: Matlab 6.5, 7.7, 7.8, WinXP, [UnitTest] +% Compilers: BCC5.5, LCC2.4/3.8, Open Watcom 1.8 +% Author: Jan Simon, Heidelberg, (C) 2009 matlab.THIS_YEAR(a)nMINUSsimonDOTde +% License: BSD (use/copy/modify on own risk, but mention author) + +% $JRev: R0g V:005 Sum:yQLycAwkArU7 Date:24-Dec-2008 02:59:38 $ +% $File: User\JSim\Published\VChooseK\VChooseK.m $ +% History: +% 001: 17-Dec-2009 08:10, NChoose2q: MEX function for NCHOOSEK(X, 2). +% 004: 21-Dec-2009 13:49, VChooseK: Expanded for free K. + +% There is a Matlab implementation in TestVChooseK. diff --git a/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.mexa64 b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.mexa64 new file mode 100644 index 0000000000000000000000000000000000000000..62d33ffdfde31781e42e64eb1b406a24c7465497 GIT binary patch literal 23336 zcmeHPdw5jUwLfPjfvD*4P>Vpzltu-`@JK+Tq8XCF895UWf@l#ZlVtK}lT4UL2)$A% z!|NEQ<*U85wqC_*mFu;Yuh$Z6wT5?!ub@{i>a9c+nK3>ffJ8-de``Nx&P--}eC>Dt zx$JzCwfEXQ4%WPp+tQQ!moJ-l?d9C;LTQ6R4N3Nd={XIZ@u7KFZd*!M+8U`=J2AD z1xUY6>NpL|k(ZXPIrxXiR{Sn|!Q+qLpI_5UT@1r-41Qq@uR-JPBQz3w8c3oj5PMM@gv!6_zlNTrVEe} zLuM$-lbq6jh8Cf)(vE)|U+|NAw>)88pV|ehm;bEFIZ6k0Xi9y^oBNejTQlHi0Y6R> znV=5A(zWwYhIa1BfM1;f|Gf3C*O%Pt1UC1AaJW&J^Jkm(#>T>Ow=ql%xH;Wcu%R z*Eaf^+<~CSA9TAFx3k>kuJ-!9we^9Z*I(``ZtyjE%RQA1US5~J#$DCwao5y0c^c|} z1i~9y-19{X#SNZ7z#C8+y{)BwzbjDdtadb2m$wF$##Wc7p}|*$%q+jxOBAz0O;y2q zUlUNyKv}5K>#wJ3XP~&w<7XM&S6g4@X<+#hUx>tNY@O{5g1FM_pIcMf;BE9a1<@a2 z7l0IuH4Q!=u>-@zah9M^?Du+tUeSrm6ZF@&y04r(88s!L<_2^U^g8^0&vGCZc!Mrc zhinTk`@wmhr}Oo}k15=1r&CK(M;% z^2_7J=3pJCd52^$77<%72;a|0L>( zp4VIB^>Y1{G5QEC2uQ7BeU<%lohAcv?5)xQMXZgr^uUQ`Cf)YYf#L zG2v;wk*Uvwr*%uFkwPAtcINfMZo->wG2VnX%Q@MEH?Lh+negUyy~un-{e@6JD5vHPvjw(>g9ws|inQxJ)Zec)16my7eYJt;;fP zFyYPd{Z}SD?Hgp;Xu_NK44X`NTH|HfY{JuCM5e7KyxAYL@CP|sTlU4%?25LgBbXgs ztSX8Y-kC!S5K{lNaj5FQI2ZqIV~dcZavfF0y8DqX9z|s^DX}hA9!_O)p;!kipG{?Q zo!DkpwosW|Cbp54KPy0)TqU-Fm3yg7E)rYG%I{N|TqD-Z$_J@TE)lC>GromtbZHz44$<0X^r94<0g^he zCeJo@HAE)Yn6Z8`*n*cpxC2wUaHAGNem~G?tG{bWY!Mo;ja^Cfu{p>m*f&sjT4dT4 zh|AzP4M00YC0dS-m+YWgr?GFs$&$!ywbx<0tfSX<*@5tB^~V#RB9|&LI&4qux%cF! z4z;7kHomjhcFS|1*w<^jZEvsb=566^YT=73UI*te6|}rTt!kSd$=a?}eWFLoPxk4B z{~h?gZgfG_dPM8fB6D+`g?s&ly3wg^i(0iv!7lPHCRVR)sH3mfHZ046T*=@ZYB&oz z=*ZCukA&XV)Ly50#2JoJ3oY52@lwxbQ=datu|98YKcyEQ2+Y@w{jAS1^P)t|1yVPyY@cYC`eVy#tYVK<$ z?`zrVzm6He_48t+{<#;Q`yaFjS=*-AtKvANOQA z!yo2o;XSa)=Ph2B(c?7woDmH+dAS7FzGPJLwxJ~ox3EQ8_*E{h6Lt>w zp#A4s?sgiTJrAO%fU($dt7D0f`X(kf^R)9<>5(zq+a|WVB3>B(@UmsP5oPi=pCoxd z%7VNw$H~(l(tozDm8M| zlC~OxmXfyW!CA<#*+N5qO>gsdB@O>R8vZ>rC)x0q)9@GL9~=JsuN=NheRII*F`-sq z+NV0er-{+S^LAhkBpg7D-jeD77Cw45?U)1Xi)s;Fgm5-;TYJ^%8a8%Yd&TJ*HhNoo z4a-?dZ0*&E?m`0=(!h%YG!S zfoX=}uZtW1O($@!!oU0LnepFZ{;z7ri&~@%v@f*ix^b9IXFlvLRsALFVR0KWrR#H* z65AFJWmIIU2dT)h>8%y^g*_(5+U-)`cBuz@9!7(K2Vivccp$VURx1sD+m{&J zX`IrkKGn7zw(5}~SGywT7rG*2uGZB9nD(y7wa1;2*+($O4!~}}P0qrdw(z&HHP($j zeL^=vzyYAQIgU|*v&5E5StjAbDZH_sBi4Bt?gv>OEy!ujm+uO z!rgt^gl(GP>eP%SUAoaD!^o<&T#Xb)NN*qIAbcSVB5s^)snd-k1LFoQce#nkQJRPx zh$plnQsfXp#3~m@pa;t!@{D;FY3fTo>(N;t%)?t-X{T0L+GShwedsfGG5)a;g-0U? zimjx8O}2GMvFpneUEl>N2hncngG3gcB#s~(gknz#1(Tw=f=8Pbd{QVF>pLm< zNIC^upkUOKf_En=_%sxJdVqpiP+UdV8fGP1xROzMvZaQUoE!zAU|V}Im%<=aY-W^skrF$FAtTMZg=?>bo=-!O6gEiTn=}OB@Nv?Bf$2^=2X2P&PV7}EZ2XPuIXP^o z&@<{OY&^j0$)o^WfR$*3_cIc67cVV13Eygf&YEYH!58~U7uyIYX?)M*^=d4syyj;5T( zPASeEyqA)=IF+cM6S?+U+GCE=suph5aLI%Hjc$y0s;^Q%aD-(?U6Hwc@SAgVtE;mo zS8K!85uLXA5xR#C!lfyeQUy3p-R(rd*#>hffpe*0gg^+>-LpqG_UcB57LJ1UeYCuz zWi*!4XyhZ(*@5U9f^920qqif|lSkcLb9SIh3va`iSo1W#-)U{l@W-2g8_E<>xO>?L zJwLwRvt97dNg+P`x`10ec1Xr$3}%+32&k#5S?Jbj^pMONjO% zR6j*awXvOU2`JCfzv%A|QwxJ)7IfhVpHlCrr2nDu#PMC$`k)fyBhA8K zON{rZ7d!Prk0zk_Q5ZawMvtYr4oDu7@;ShP<9hWyKCa6c_rgxJSYmt}C2JYjS%B{y zMzIHXuW^t2mQvix9#+~}W6R4Phb~&mu)3dXM-G_Imhn^~30P?q#0jx>XS73YT%2l% z(L)~6!Hu;V1ia=mbVMDFO9%>S+EzRroy>)V#;vy1InXWT?l=ekEy3@^?!hw~WV39m zU*J{Qw$%^eCVcG2tfJo%{1->K-*U%r{8w$Oe*x3j#wxKt0Rod1EWrPq4YoB813`+d zWWDVqQ5GTF=6V|OLl}1`82k~(AFIyYqO!AF@f~J4~Gv3u#U#2#=)_Zo{e)8zl%|O%U!)CAFI1ba3u9z{EwnnOW*V<-@`*LhmJ_9+wXQzzOB>^{H! zDtqPfpf_M|_WJE!{u)i5!s$KqA`IuM^xB*Fi#eW#iS}a6F`sz#xwDCXy^WIx1u4qhP>=*!R^QNIN0Y$UdhMR3YJ1T0LuBlD>!{WqtZ(#ka^;2v^>|I` zYWcp))#W~)PCUFFWkCH*Pc;+0e0j51DfToq`GWRZFGlWd^!b6IC*%xZ4CM^fiJkzvLD&B@6TX+N8suJ)BtG>X$Ev-!Pp3R8`hdGzzRfgdhv5ELgHk=XAto!0LLPPYyi9ySC$=s z&mmGA0Sse)+wt7@%43iR@B_@Pm4FX^0yzLF(Tf6<)E~`P)YhTu=plo1NY-57@bFxz zcnf`?teiJ=)_Eguu${9kXQguesB13E&m9LWqbUJg-`(H;9YQ$H8@kp~eD0uI(2%IF z23(8!8_o3=oe@wUtMO|`eK4us7q5R9_;aA!hNSx1c>PY`7kx?nyQqH%^`0dDTN!^Y za9J4NyQtq{t}l&P@5%~iTOMa*Odk_L=Z7sHG1JZdsWp;yS9W-i<<~?>?UjS>29gQlYvFsAOzj^}rY`{f&G6BWsl#;bznx594f=1vmzy%QZ>><{3?%FSGm?4UX#{ z5}ZkAG;l@(XEbm|17|dFMgwOwa7F`XG;l@(XEgBtLId)Kn{jPS36FPJY84qg^wok3;nLe+}e!^QrxQA`CD{DE>kLFA;FMfU^X=Nx&Kb zTLfGy;4cMyM8GWq?iTPh0pAnw69ESaN4-$MO9Y%QV27~(?Be39?c*0LTu^G)>zhKY z6YK?fSK&L%YcVix18!mI?-z&xOMjRCnyLrRUk5bje^uy3`fr7pFS4AuWt@v-SNe3+`PBNv+6RqW^dW6%y;Plpdy=dJX-Dhj5{C|uFppW{r9`}xZAif+zoe5em0$9` zA^b@4d4(TIzBtSaEN={YDwVuI(9dC=%;DLJH?OuSl*jz!iu!7WmFhf!Iwh}qc@sD} z4ElLZi`O5Zue=$VD7XceEP~YUZSWAk$Tc?vmAv|zitPGViIZ^m|)msiD5fEAxUUuFDJ=D;z_f3t}d*!i(klm5jH> z*Rf=LmLk`$WPG+F*STc;AVsbR$@syFTxXK;If`6glJRFLave*?pRLICE*U@Y{0pkL zVpq^D7hV&C73Uhr^I%M9(4VJB|4+u-l)5zjY{l2<@*I_9`e91NL^FoxtvFFZ?mx`6 zR-8;C_Z`Xj^YMMC-Hc*+t8xL(i%EySP?6uOo0+V1+DTD5`jLuUZ<6URQaaPp%UzP0 zn)EDpQ>pkd$p}%hD&Nk4XHUci)LE6W18@}jveKMGLCdI$-BPOFX#ZzPV|RLjN%&^5 z{-Vf|1OEx1y02XXyowWMq<%;aN;UYYY3vvQp4yT7WTK^XFMetof7l9qx^ZP1?@rdv zFr|4iGN$x0^6B(IBiBH$GQKUr+>rN>+kyo#sH zss2po*H}#RS~RE37wzm34an<=+XQ|deL;?N9|y`01fE_SrzG{zBJd9gdDt^q)UOiw zkLXKtBn!%vek$-~f}TC&1^zbz|Ag3}vuAU_Kg#d}JwkpD z34`<^@N{BQSCO4E@$`zIzunGJQa=X-{(#tUvS*Ya=@IS7c_AA*Dd=?@$FOI{$Xc<9 zB!Ac>46;cu*aUur2oda=AnHa7{1I^>^s%77RNy}l_F~U`QI`+AnkMc!ffueOTHv56 z1HK9PaY>ZCaAyYk-(bQkLl!T&w$^a0smqK{DBPk!x`|OX256T!p@#X4;KNS zPX0+5@YiO*muA4zxoPRzuVVOt=M(ud&@az`zYF+u0hq!eQkB9v2i(AOeHsMhm%O<3sU(^ z?pgC4u2OetSqYuJpMbV$)0_f<3TzL!GzsqO-ncYE2+mr&E(Q{vUrL^a_HO!<6~ zH@|F!L!NNf5(XCVx$E#k7o8i$HtM|3sqsehO&v^iC-75Eauo?GU?tXCh#;- z!4#mlOKvH1xSYl476(>|@$zx;K|qhyjBk#q(`lk3w;LOMegGDu$u|j*ZxU>dY2*c_ zb_!%Wv-P<%9lCq&tXT_6%iZOUnR==FOAnfI2E-9o?xgdxii*r9II%;dXfW^vajKN* zJgmeaS^Nww^I28Unm7O}&6!rHq?4)AoXX`4$V0Z$p5vAIw5`P1TJm78bZ2ClPtY=* z_XT;_30dr{u4D~-*_mW?-c`CI%;bzrI>0PV9Q>vz+Gf$MGlW}~W?PjiTpysse7Sxu!+E$;#kZOJ9Sy#LTTgIY`Y3oi{U z??VOYU-HZA?Ui4X|26QE?@4}nKSQ2_J5MN<<_{$)zx1C2z?u7(_dWJs&&ZYW9K`=i zehJ@A;a7_6oVJLA4i4h~C7*;JqQ=~Rhv4rh;w+L*Hjr9Ah6=*T@yqL`&LYl{N>6>6 zQy&V1n`}lRFZpGhmDQ3z4v~?0Nkg!^h?iD!5dSarE)hdB@K-oEMVBNLFtx8S8Tcp9 z{&K-j{%uaF{ZG%pZ!hLtE6vQvr;eX4H>K^&q#Ff)NlJ$)MW%a;nNj4U iB|Ni91h8=^y6}_!Ani)k>H6PL#`)=+EOScj|9=4rv*#QD literal 0 HcmV?d00001 diff --git a/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.mexw64 b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseK.mexw64 new file mode 100644 index 0000000000000000000000000000000000000000..77fcae95a539e6b0bd208280a1b304ef594f9bf7 GIT binary patch literal 17920 zcmeHv3v^Ufn(nSwQUu}&G*RpZDIoUH24f&mgB7$Y4>$);L7D`N3WOr5khGP@JyjLJ z%P3O3(#NBWgHB^l_q4V%?ew^&?HLD@x!MUqlJE!t^)`qtQBhAiijmePC{p+P_c@hR zLeQQy>#lXz?LMr1{{8s(-v9nz```Oi@ZGb6*%)JXq*#ox7Xj(<@b}lh2GD%f)V)`+ z7sec!_M$~TGOetpHsoql8rCTOI#;E?zP=&sS{-mHk$P8cy{l+(sjIG`Dv*_$nv!7- zt(^W&*)6X`lH=*_j^5;4l<)31oqPv}Z}ajU2R`8N&h}@Mb2xrDc`D$IGfwmR8)uwN zzLl4C4wuwc*3g(&T0u!MV^v#|*nb?hm&bAX*>u-fYYJmGpk|U$yD=9qjpsL72vFY2 zn1fz;;*jk?0Za^gENH>Y>=Xx=myMd|WyTg!R}u8kfQ^j3KohM(BEiI;jf{OO68j5@Yf3o{RSgpn~^U+MmW@L*0&egx-kOvB8*+ns10P zL<_nUxx0i%UbqyCi7NOis^D<3`_O|o(HMz*rOvy+S8vQ@hp`%r0Q3irofF1?3tjGQ zJDm84(T|)`Wvi?n^J(K+#L9iLw!C#favu_+2VnwY^Kz1BeukueDP~@%-XUrCI7Ri4 zA+d&9wySOX*Zn9|GC$ln@hm?>RA~{>{Z1?$YsEr0@`aW?bWw6249%9cyX}(tn$P{_+9|3POHAWQn z6kNiPlqcllO{dK<51C{7Dv$B8WM|B0>z3S|oIDF3?&R7jJA~a9F}6>N?elJD!tR2Y z6l?Kr2XG&2I>U!LIgGr+p3=L#Wgt>iFOYzJ+Qe3jFKUxpWvvn{J1lIQ&+Rst;UeRm zDK`f*vSqbTMj=nm?3JP)kEyP%7N%|{aWYw3>-4E_``n)i(Oxd!&(S*6E@}5cKaPm* zJ|X%N+C}xiW%|)14(W%eCL8*(kMu)QZQu@a7DH1=X$pFPLz+U3P!vO93IM4VibA!f z-V^{*?SN5hs!su_&xXfE_o2}DjQOBG`$&C^`H-Xeph%=sgndZ)tr$HEMf#oO{z%yL zS5PGI!6~ViXyIGW!x&}QVVo6J6q-9(HCrR-jfQPt%CqE=< zp^KusYi&>j%MGVly+hRQvy18*qWf&9K$z-bqIN&ZM-bIG0-36Zwdo5;$LAH@WifYoJ zLBcf29wBaW;$*LdFwJ6Sc=05|Herlpn&i_90eNdbjlyk|T2UewUkJ!sVWiXwK&__9 z7Lv&d57(0icOMPqnq{T(fR>*ut6LKG6L zT2jx;?g3#_E8kMVYEdQrMthy2`g_iMV)WKc+{p7Y$k5>lASzjf(8$_dWJMx&l$jMP zhD?cT1nH}5>0REXv@xjNq6(#$yiw97M@20^$}MZ$Lq4q*uJ?$r?Qe|(SXe!xo7BF|vM-WqMQ z19~rtlvx13(5W1k)Nb@_+AFD_`P}a-PfO}qOw^>(8sYS-$d8%J%k!?F#f`ci57twN z^%NTG@nSs~AM5$?sO!OI$k$VAtOrHDo+ajbQ0D8ojoarQu73y`+R1BJg*~(+%G!iI zv?yye<-C`$EMynJlXNNv&2{~oxvnS8bw#hdu6PWTxIVe^AVenHIu~h^p<=xYwaJsP zv`bj&q^}VdHs`pwNIuml^YuyQ`cUTUo6Xm^8|#a;im`U@cB`;EiF+cOup6GJZ9AYh zCL*%{8+xbmnz^k1G?(@BZx$E!`(@sx@JJr$pG?YU?D^!8Ahb5_m2%;gmi3DoOc9%lm5!u{?W*?Cupd#lE7r2P#2!HIw{BHf@c0 z6#Ue{9eTVgR*ndOJf%yQ!5ez-;{NaiR1#{qk^4d|cbllq+B)bH*AGbA0;~%vc^U#H zMf8vsmJE+Ci|s_QD62h^yIt7!Bv6ONpG6rQ0kIjv=k`$0rz!B5|J&#ObZu$%js*WX zkL=Mq=s;g3zv(6EanI?cg9|)oGQoCxa}sx@2kgzo+?BSQw)ra`4SinOC8|Xf4|1Zm zHt~}Or&6ay$!=ZPs#+aemzge!;_Yel6kriu?O~gI{rn|EhO8 z7_=MAB2SN;l{|eihwa;w4A*~Pdog$Y9VU~WH<|S0Fea@X&ZJA6Nd;GCQhc)mr2P(O zjUWOUiaT&PgmEtOQV{DBD>uLssGs^OKb5tNudr}4%%F+gg#j}!T9}fo)Z-_%)^TY`_TswX4cI87N z;9gGSK%B-jV{VD&eiBXC1oLrUL1(FJB(+OyeaE&#Y@Q@yIMH@eagRIiABWEme<7pq+$15|0|v?J8!{hKh`!AE)h1@PW5nch)=M%O*5cQw7()Omfc4b zFS=eO&9#KiN>K~Heet=E3ek_TWsKmDagHXYQdAEtrLXq@-&v08FN`H6I-)8uBdkDi_uwD`{TM$ zHHGWpJOKR>K6{rwi;th6tg*=)X%ZpTawO6Q_3$Ds{}vI7op}V|h^!SoYKO}YO(pvl zn-MX==|P3COOQ4~mUe7B%KJn`X9`AC2Q~5mV}d;Zx|0ahCf?3Zr(cAwmS7F7J@CcX z;`{}LJb}9;QpjLNiBGE-5Vhr55bYnN%s+^#&8N0Wb8VqpcHpQgxxavL)h;>nDB?5K zK3-H)h!B2TF8__KO=$0 z<1tBvo$=LSRa~9gA(k_lPx;z(KN0%q$%H?Stl;;KKFnRv#w>cFb0_b@};E+7i zNuIWr|B^W8;{L~w=ZsP0DePg@hD1TnapiqT6o+0e(ayL;Z%dRYUA=IL{$x~n()BCs zljOPHl;=b&kK{RyFZ1i=spDJPe?y+XLiYrD?!T6E@+ScLSu~OHJWMcAo)retIzsB? zNTbVhu7%_|WrTgk;FlrJSPMz>Lz*Cyk1=SSJ^03lz3N&T{s(AEkmfaUdoblG*>E%X z&E`2M&(Z8t*v+=%GPeL%0c4*sg!f#SxVX5?JY#UghAf}r?)Gx~#Ij6rel%#F#Yu)Z z=K+3`d0q>gVetWl?T8ApCAC*pf3KeOMhC26+WLQONa2UXrb6_Jerb7t>itH&LiL$^ z#t0W9jl8)f0uS1yCnKMOOZl$NE$V4uXPe&dphl0dvwh2#eDpp;2(xIE_t7Y-KBvB) zV}%7?_%+o=2P_{lr9LE5H( zDou))(lOhqtNCm%0PxZJNOW6`$_lD%m^B-ZUOTXvySgcp!I34<x zyI%tLEUgSH`Ju6rm9&!Cd?h!SD>=_0U&%+vCagpcpT!8znRuN;c(07Wd#fLKn@zl@ zhVY&kfp_Lp;4L@t)(_#;kHGur9Pn~cIXdNykP^vY-p~khMvQPnFGe_L;t4}|_7Qj! z`ha)P#QTs#&WX2>P2|L0!h71p`^^v@eZfz}Q$7OT{iqzB^4*XEQ63!{Vcm!k(%#1i zdAz+tUpj=ha0Fh>2f#}+@opT#n?3@shwyZBUdIsL7pO|4y!=DpwV;wHf1JZ`khG-$ z+7hNy(6R|2UQ4|RK&Od&9|IPx=07;(eETJ`iKDK5Hx}!wBP3El(_kJPfpp`0KoSWl zFobl^2&8gCnn6gOA*7o}AVq;h7ZZsgd31j^T~f3ij$NNW9?QEvi@#m`J%PXN{QXD# zQY3c0&fjnH_hJ5ig}?lhPS7bPNXj}Fe{dxj0%ts zj}c4%v4DKD;~6^JH9H+mUNm22oAoD=h@J-9&Fa$ML#`lLD>m}g6i@W>3Jr=v*yq}g%q zI>rK`YQH|4Gqv2=mnOQ~!ry*L$853m_i)(FY3Ub*Ur*728F{ZS$@?;TW3XWBb7JeW5B!;P>GVyE=W#F}AuVJJg@R4NRmbw%Lj*^eE?EW(1klp>^f0WfP zW%a$jzr)!lmi`o)V(B41h9iSIG&`;bXr7mhcQH1`E$;9J-c{lXf#Ra71Kkn)2l zXRKR2foRyZ<&?1bSzyWP0UQ>vGiT#k)@*{pXo*czuppx;8nZ-h27hLwTMj-19o8*q z8!UWuk<5R}$FMHnmQ&%e@dj_~HAG8}Xv`M5b#TJp0Qvlh?{v;Mq@Ki8zbiZ$bp9I| zCg{XxGJ~!-y?seo8NQ0OJN^L&F`P7FYMaT#u*pR5FWbAE^A4D>O8mx!Ur9;ofQs+F zpMoP1haQ4VaND9njo~tv)9o`p!V~i=dbi<HR4vH9IcQArUp6So+&W&1uva6W+@^v>9FrYBE#j-v+?kmh&fK z9jKpae1mfuH+0&Rd%14UD+B1e3MU3)xi!{JUl2t1Y2{;sFT|2Ix;q){mt*vs^(XWL z8wVdzZGFjy4W)XnGi=Lg!3QKUU$k}Pv^+GIeli&uw|6X-P(AnilZ2fu_zjC(>CH#f zD67Y1TPyB^Jrj$CJ>^LYHJME+hGJc(et(>d^G=HDb=vmH?rufE@0D=lF%v&hQr@K* z)K*di^C6zdDt@ezy1ElT!caT)A3%Yy=IOr7R$P)&&2~DyqDoLb8Lj%%^WD)NOP`hd zdT=jxeK$_#vFnfX_cQ$c1b=VGo5m;Q!q<>_pU{s5BT2FJsc0~4eUSf?4F0PQem;rf z%LfyGGw12kH}1;BAnx|?IPpAgJ{_;)oY99LxX2mV@Z_!sR#{C3AX zI7SdPCemPwp~-)PmaprNiE=t0%EMmQBJ6Bc@y{FwJpaq{{|pBnkPT95Ot{2^1ty$n z!f__FoA9$cjeciL7+=tvX8E`Y_nUC937;_GW)lWYxYC4+Oz1S>btar;!aNhsH(`9< z4;C7^<0g#P?={Q+YQmqH@G%qKZ^EDn%T2h@g!v|%Wx_NQUX+X(&YAE76TWG}ZWG4o zxDwo+%{Eem5Puey*48!D-?prL&{7nJZ z>{+fkvs}5Z2E~=R;B-Ap4ayfyI$9R>hbBU27X6!7BPwfp9~ED@X_? zeIw@|))_>^`_~48)SY*A`Rl7(VgG#rm){j^s9)m>*Ve_ygFAxbI_)L;14oXS@MZ7F zc}i;=DO2$yK9k2BB|0TdeqdhitS1y&q>o z0Y~0O!XIO2V<2A#?j{oJEp`i|n+3w}{uX2Bk)9>|Yn<$wGs#SNJ&C1MIhdo&KCIp1 zz}zji#`s(%>4@Wz-b$pc%*qn$ElD<(lxt^6t4#WUKM_}6Bm49x)`PAc!1?!4@P^d` zFB===3ZzB^M$=}DV>3QuZ1NckoA|nw3HxnWhaKx5GYrp?Y-7mrV&z4r{}FX$T_=kVeBzY_p7UurayGY)p4@W0E;fKl)8WOgmcNVQrYF z1$gI?isqxw#2+I4jQW$_oJnDh z{m$X_z}tx9@Lr^mc!~9vF-dGpe{#2@(Z0%7VvPU13jsgU$bO0SmdWGTFQxePFO zESo%MQvcOG6T2t0q&0HgzJakvGVy0V3qYg83i?v`-@e4_EEAk;0{Tus-w8{u>K@lP zc9kW`%97?-vn^A`u_^nK3FaL(Aq@#ehL--34A&5YF| z-4Mqo9s@UJPEz9-vabTh;<$f@J_nIXfJ>0uAKERvkCXQi6ZWbO>~B3D=ypQgMbvem z?nM!kn@<|{-x3f0wkV6)FLLIIzgrzkL3%QoF9=*6eJy!oV*K`a>ZJ zezz0l(m;3-Z)69IlFukDL#Zgz7{mq`4tQz1!!3x>zm#u>>_MZ1X;uf6#nmPiA@&&R zrBG2rWOWeq{Dha}hBdU4vPXHTu*R=2_7u;XRI*_0>biAVRly*e&FTW{iWS8dS|e3? z>#NG}_ic-)?k>MlpIFKJ1dL8>siQjB(4a71>9WElv$M1LP%PP2QO8+WQK^L4R%=CV zeQh`#Q0myWp?pOEoUGns%&g%zR3 zKxJ)pZDmCb!jxbDE1635jg94%jp6yVK@5+-AFQaT3ZbD~NbcyD%y6$OaMc)7)18Vm#) z*}JT$HslA}%W9wjRdVfW#jmU{1Or0spKafd1eEn90R{16oxi>^P}mS5TG*3TXjWNm z<$b(@u|pP=3nPkx_|q6js=}3ALT!oCP#J&J~4i$ z`2HkPIqC_%jU*zU7|T;kKMyhWcGMFrKw5`_ByV{wYr=}Ywh z>IrH{I`WBeIK}Bx5rexBKNI{eQX2A!u{p))nTWAP)DxV8l!ts`d`&U912OW$s3#~O zZ9qOTuBO=gcStXyo*?}U=vm~4#m|VFUqJc{^#or*I)i*-Oii)%ZHSLuh>r;tBBddp z7&lY=T#MLv73v8pNF~T8#>Nyo|J(&Wqn_Y%Nb8VKjDsmo?m)oXf_j3-ke)}r2XIFQ zV<(U&xbnM3eidNWOe3ES_|^A}Jo(djY)p{OVRppM1k;f|!#KFhU>_jOLcI>?MO>SU zd=cPZBfc$1p8lTxWu%?R9|qiTGh@#nPw;P%`jOuWco=Cv;Q-oiG4eYAk0EuVz8~;g zw;K2p0o#!VP){+n1F>!i@)S=~j7)ig#b%yjVa3d|zdW1+cK){T|Mp-K#1v;syxxim zi1f009Q_y_0m>U0yT<}uH#)F<#E5~q)xq_yb#=k|(7fpprT(^1Wlf;YAG)!wwo+*b zHB^UhtZb;e%^#}EYMMRWg{Y#oIuHsk3n(FM&hw_v&dQ#Cduocyl^<4c;Uyso`V&XX zG5VorC{P(uYQyXKI4(T-bRmLS0#zkSZ4<(cHG$AzV`6jhI&`HdK@Kzpg03LF=S}yA zr23|Y`vS^zSESZkNpZ})>DB&VC@}r@{F?^H9^QFy`~-~4X3xKA7_Ip?4K5np^KXjt k^Y#*NiMOaoTC||N+|2xU%5+{E2l;J$3a`IBe|8-BKecRT*Z=?k literal 0 HcmV?d00001 diff --git a/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseKUncommented.c b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseKUncommented.c new file mode 100644 index 0000000..19d6e4b --- /dev/null +++ b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/VChooseKUncommented.c @@ -0,0 +1,899 @@ +#include "mex.h" +#include + +#ifndef mwSize +#define mwSize int +#define mwIndex int +#define MWSIZE_MAX 2147483647UL +#define MWSIZE_MAX 2147483647UL +#endif + +#define WARN_LIMIT 500000000L +#define ERROR_LIMIT 1000000000L + +mwSize GetOutputLen(mwSize n, mwSize k, double *C_double); +void BadInputTypeError(void); + +void Elem2_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY); +void Elem2_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY); +void Elem2_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY); +void Elem2_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY); + +void Elem3_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY); +void Elem3_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY); +void Elem3_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY); +void Elem3_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY); + +void Elem4_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY); +void Elem4_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY); +void Elem4_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY); +void Elem4_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY); + +void Elem5_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY); +void Elem5_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY); +void Elem5_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY); +void Elem5_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY); + +void ElemK_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY, mwSize K); +void ElemK_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY, mwSize K); +void ElemK_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY, mwSize K); +void ElemK_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY, mwSize K); + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + mwSize nX, nY, K; + const mxArray *X; + double nY_double; + int ElementSize; + + if (nrhs != 2) { + mexErrMsgIdAndTxt("JSimon:VChooseK:BadNInput", "2 inputs required."); + } + if (nlhs > 1) { + mexErrMsgIdAndTxt("JSimon:VChooseK:BadNInput", "1 output allowed."); + } + + X = prhs[0]; + if (!mxIsNumeric(X) && !mxIsChar(X) & !mxIsLogical(X)) { + mexErrMsgIdAndTxt("JSimon:VChooseK:BadNInput", + "Input array must be numerical, CHAR or LOGICAL."); + } + if (!mxIsDouble(prhs[1]) || mxGetNumberOfElements(prhs[1]) != 1) { + mexErrMsgIdAndTxt("JSimon:VChooseK:BadNInput", + "Input K must be a numerical scalar."); + } + + nX = mxGetNumberOfElements(X); + K = (mwSize) floor(mxGetScalar(prhs[1]) + 0.5); + + if (nX == 0) { + plhs[0] = mxCreateNumericMatrix(0, 0, mxGetClassID(X), mxREAL); + return; + } + + if (K <= 1) { + if (K == 1) { + plhs[0] = mxDuplicateArray(X); + mxSetM(plhs[0], nX); + mxSetN(plhs[0], 1); + } else if (K <= 0) { + plhs[0] = mxCreateNumericMatrix(0, 0, mxGetClassID(X), mxREAL); + } + return; + } + + if (K >= nX) { + if (K == nX) { + plhs[0] = mxDuplicateArray(X); + mxSetM(plhs[0], 1); + mxSetN(plhs[0], nX); + } else { + mexWarnMsgIdAndTxt("JSimon:VChooseK:ShortInput", + "Too short input: K > N."); + plhs[0] = mxCreateNumericMatrix(0, 0, mxGetClassID(X), mxREAL); + } + return; + } + + nY = GetOutputLen(nX, K, &nY_double); + ElementSize = mxGetElementSize(X); + nY_double *= ElementSize; + if (nY_double > WARN_LIMIT) { + if (nY_double < ERROR_LIMIT && nY_double < MWSIZE_MAX) { + mexWarnMsgIdAndTxt("JSimon:VChooseK:LargeOutput", + "Output will be large and take a long time."); + } else { + mexErrMsgIdAndTxt("JSimon:VChooseK:TooLargeOutput", + "Output would be too large."); + } + } + + plhs[0] = mxCreateNumericMatrix(nY, K, mxGetClassID(X), mxREAL); + + switch (K) { + case 2: + switch (ElementSize) { + case 8: Elem2_8Byte(mxGetPr(X), nX, mxGetPr(plhs[0]), nY); + break; + case 4: Elem2_4Byte((INT32_T *) mxGetData(X), nX, + (INT32_T *) mxGetData(plhs[0]), nY); + break; + case 2: Elem2_2Byte((INT16_T *) mxGetData(X), nX, + (INT16_T *) mxGetData(plhs[0]), nY); + break; + case 1: Elem2_1Byte((INT8_T *) mxGetData(X), nX, + (INT8_T *) mxGetData(plhs[0]), nY); + break; + default: BadInputTypeError(); + } + break; + + case 3: + switch (ElementSize) { + case 8: Elem3_8Byte(mxGetPr(X), nX, mxGetPr(plhs[0]), nY); + break; + case 4: Elem3_4Byte((INT32_T *) mxGetData(X), nX, + (INT32_T *) mxGetData(plhs[0]), nY); + break; + case 2: Elem3_2Byte((INT16_T *) mxGetData(X), nX, + (INT16_T *) mxGetData(plhs[0]), nY); + break; + case 1: Elem3_1Byte((INT8_T *) mxGetData(X), nX, + (INT8_T *) mxGetData(plhs[0]), nY); + break; + default: BadInputTypeError(); + } + break; + + case 4: + switch (ElementSize) { + case 8: Elem4_8Byte(mxGetPr(X), nX, mxGetPr(plhs[0]), nY); + break; + case 4: Elem4_4Byte((INT32_T *) mxGetData(X), nX, + (INT32_T *) mxGetData(plhs[0]), nY); + break; + case 2: Elem4_2Byte((INT16_T *) mxGetData(X), nX, + (INT16_T *) mxGetData(plhs[0]), nY); + break; + case 1: Elem4_1Byte((INT8_T *) mxGetData(X), nX, + (INT8_T *) mxGetData(plhs[0]), nY); + break; + default: BadInputTypeError(); + } + break; + + case 5: + switch (ElementSize) { + case 8: Elem5_8Byte(mxGetPr(X), nX, mxGetPr(plhs[0]), nY); + break; + case 4: Elem5_4Byte((INT32_T *) mxGetData(X), nX, + (INT32_T *) mxGetData(plhs[0]), nY); + break; + case 2: Elem5_2Byte((INT16_T *) mxGetData(X), nX, + (INT16_T *) mxGetData(plhs[0]), nY); + break; + case 1: Elem5_1Byte((INT8_T *) mxGetData(X), nX, + (INT8_T *) mxGetData(plhs[0]), nY); + break; + default: BadInputTypeError(); + } + break; + + default: + switch (ElementSize) { + case 8: ElemK_8Byte(mxGetPr(X), nX, mxGetPr(plhs[0]), nY, K); + break; + case 4: ElemK_4Byte((INT32_T *) mxGetData(X), nX, + (INT32_T *) mxGetData(plhs[0]), nY, K); + break; + case 2: ElemK_2Byte((INT16_T *) mxGetData(X), nX, + (INT16_T *) mxGetData(plhs[0]), nY, K); + break; + case 1: ElemK_1Byte((INT8_T *) mxGetData(X), nX, + (INT8_T *) mxGetData(plhs[0]), nY, K); + break; + default: BadInputTypeError(); + } + } + + return; +} + +void BadInputTypeError(void) +{ + mexErrMsgIdAndTxt("JSimon:VChooseK:BadInputType", + "Input must have 1, 2, 4 or 8 bytes per element."); +} + +mwSize GetOutputLen(mwSize n, mwSize k, double *C_double) +{ + mwSize i, ai, bi; + double ad, bd; + + bi = n - k; + ai = bi + 1; + ad = (double) ai; + bd = (double) bi; + for (i = 2; i <= k; i++) { + ai += (ai * bi) / i; + ad += (ad * bd) / i; + } + + *C_double = ad; + + return (ai); +} + +void Elem2_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY) +{ + double *Xq, *Xf, *Y1, *Y2; + + Y1 = Yp; + Y2 = Y1 + nY; + for (Xf = Xp + nX - 1; Xp < Xf; Xp++) { + for (Xq = Xp + 1; Xq <= Xf; Xq++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + } + } + + return; +} + +void Elem2_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY) +{ + INT32_T *Xq, *Xf, *Y1, *Y2; + + Y1 = Yp; + Y2 = Y1 + nY; + for (Xf = Xp + nX - 1; Xp < Xf; Xp++) { + for (Xq = Xp + 1; Xq <= Xf; Xq++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + } + } + + return; +} + +void Elem2_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY) +{ + INT16_T *Xq, *Xf, *Y1, *Y2; + + Y1 = Yp; + Y2 = Y1 + nY; + for (Xf = Xp + nX - 1; Xp < Xf; Xp++) { + for (Xq = Xp + 1; Xq <= Xf; Xq++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + } + } + + return; +} + +void Elem2_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY) +{ + + INT8_T *Xq, *Xf, *Y1, *Y2; + + Y1 = Yp; + Y2 = Y1 + nY; + for (Xf = Xp + nX - 1; Xp < Xf; Xp++) { + for (Xq = Xp + 1; Xq <= Xf; Xq++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + } + } + + return; +} + +void Elem3_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY) +{ + double *Xq, *Xr, *X2f, *X3f, *Y1, *Y2, *Y3; + + Y1 = Yp; + Y2 = Y1 + nY; + Y3 = Y2 + nY; + X3f = Xp + nX; + X2f = X3f - 1; + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { + for (Xr = Xq + 1; Xr < X3f; Xr++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + *Y3++ = *Xr; + } + } + } + + return; +} + +void Elem3_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY) +{ + INT32_T *Xq, *Xr, *X2f, *X3f, *Y1, *Y2, *Y3; + + Y1 = Yp; + Y2 = Y1 + nY; + Y3 = Y2 + nY; + X3f = Xp + nX; + X2f = X3f - 1; + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { + for (Xr = Xq + 1; Xr < X3f; Xr++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + *Y3++ = *Xr; + } + } + } + + return; +} + + +void Elem3_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY) +{ + INT16_T *Xq, *Xr, *X2f, *X3f, *Y1, *Y2, *Y3; + + Y1 = Yp; + Y2 = Y1 + nY; + Y3 = Y2 + nY; + X3f = Xp + nX; + X2f = X3f - 1; + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { + for (Xr = Xq + 1; Xr < X3f; Xr++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + *Y3++ = *Xr; + } + } + } + + return; +} + + +void Elem3_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY) +{ + INT8_T *Xq, *Xr, *X2f, *X3f, *Y1, *Y2, *Y3; + + Y1 = Yp; + Y2 = Y1 + nY; + Y3 = Y2 + nY; + X3f = Xp + nX; + X2f = X3f - 1; + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { + for (Xr = Xq + 1; Xr < X3f; Xr++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + *Y3++ = *Xr; + } + } + } + + return; +} + +void Elem4_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY) +{ + double *Xq, *Xr, *Xs, *X2f, *X4f, *Y1, *Y2, *Y3, *Y4; + + Y1 = Yp; + Y2 = Y1 + nY; + Y3 = Y2 + nY; + Y4 = Y3 + nY; + X4f = Xp + nX; + X2f = X4f - 2; + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { + for (Xr = Xq + 1; Xr <= X4f; Xr++) { + for (Xs = Xr + 1; Xs < X4f; Xs++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; + } + } + } + } + + return; +} + +void Elem4_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY) +{ + INT32_T *Xq, *Xr, *Xs, *X2f, *X4f, *Y1, *Y2, *Y3, *Y4; + + Y1 = Yp; + Y2 = Y1 + nY; + Y3 = Y2 + nY; + Y4 = Y3 + nY; + X4f = Xp + nX; + X2f = X4f - 2; + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { + for (Xr = Xq + 1; Xr <= X4f; Xr++) { + for (Xs = Xr + 1; Xs < X4f; Xs++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; + } + } + } + } + + return; +} + +void Elem4_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY) +{ + INT16_T *Xq, *Xr, *Xs, *X2f, *X4f, *Y1, *Y2, *Y3, *Y4; + + Y1 = Yp; + Y2 = Y1 + nY; + Y3 = Y2 + nY; + Y4 = Y3 + nY; + X4f = Xp + nX; + X2f = X4f - 2; + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { + for (Xr = Xq + 1; Xr <= X4f; Xr++) { + for (Xs = Xr + 1; Xs < X4f; Xs++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; + } + } + } + } + + return; +} + +void Elem4_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY) +{ + INT8_T *Xq, *Xr, *Xs, *X2f, *X4f, *Y1, *Y2, *Y3, *Y4; + + Y1 = Yp; + Y2 = Y1 + nY; + Y3 = Y2 + nY; + Y4 = Y3 + nY; + X4f = Xp + nX; + X2f = X4f - 2; + + for ( ; Xp <= X2f; Xp++) { + for (Xq = Xp + 1; Xq < X2f; Xq++) { + for (Xr = Xq + 1; Xr <= X4f; Xr++) { + for (Xs = Xr + 1; Xs < X4f; Xs++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; + } + } + } + } + + return; +} + +void Elem5_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY) +{ + double *Xq, *Xr, *Xs, *Xt, *X5f, *X3f, *X1f, + *Y1, *Y2, *Y3, *Y4, *Y5; + + Y1 = Yp; + Y2 = Y1 + nY; + Y3 = Y2 + nY; + Y4 = Y3 + nY; + Y5 = Y4 + nY; + X5f = Xp + nX; + + X3f = X5f - 2; + + X1f = X3f - 2; + + for ( ; Xp < X1f; Xp++) { + for (Xq = Xp + 1; Xq <= X3f; Xq++) { + for (Xr = Xq + 1; Xr < X3f; Xr++) { + for (Xs = Xr + 1; Xs <= X5f; Xs++) { + for (Xt = Xs + 1; Xt < X5f; Xt++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; + *Y5++ = *Xt; + } + } + } + } + } + + return; +} + +void Elem5_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY) +{ + INT32_T *Xq, *Xr, *Xs, *Xt, *X5f, *X3f, *X1f, + *Y1, *Y2, *Y3, *Y4, *Y5; + + Y1 = Yp; + Y2 = Y1 + nY; + Y3 = Y2 + nY; + Y4 = Y3 + nY; + Y5 = Y4 + nY; + X5f = Xp + nX; + X3f = X5f - 2; + X1f = X3f - 2; + + for ( ; Xp < X1f; Xp++) { + for (Xq = Xp + 1; Xq <= X3f; Xq++) { + for (Xr = Xq + 1; Xr < X3f; Xr++) { + for (Xs = Xr + 1; Xs <= X5f; Xs++) { + for (Xt = Xs + 1; Xt < X5f; Xt++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; + *Y5++ = *Xt; + } + } + } + } + } + + return; +} + +void Elem5_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY) +{ + INT16_T *Xq, *Xr, *Xs, *Xt, *X5f, *X3f, *X1f, + *Y1, *Y2, *Y3, *Y4, *Y5; + + Y1 = Yp; + Y2 = Y1 + nY; + Y3 = Y2 + nY; + Y4 = Y3 + nY; + Y5 = Y4 + nY; + X5f = Xp + nX; + X3f = X5f - 2; + X1f = X3f - 2; + + for ( ; Xp < X1f; Xp++) { + for (Xq = Xp + 1; Xq <= X3f; Xq++) { + for (Xr = Xq + 1; Xr < X3f; Xr++) { + for (Xs = Xr + 1; Xs <= X5f; Xs++) { + for (Xt = Xs + 1; Xt < X5f; Xt++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; + *Y5++ = *Xt; + } + } + } + } + } + + return; +} + +void Elem5_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY) +{ + INT8_T *Xq, *Xr, *Xs, *Xt, *X5f, *X3f, *X1f, + *Y1, *Y2, *Y3, *Y4, *Y5; + + Y1 = Yp; + Y2 = Y1 + nY; + Y3 = Y2 + nY; + Y4 = Y3 + nY; + Y5 = Y4 + nY; + X5f = Xp + nX; + X3f = X5f - 2; + X1f = X3f - 2; + + for ( ; Xp < X1f; Xp++) { + for (Xq = Xp + 1; Xq <= X3f; Xq++) { + for (Xr = Xq + 1; Xr < X3f; Xr++) { + for (Xs = Xr + 1; Xs <= X5f; Xs++) { + for (Xt = Xs + 1; Xt < X5f; Xt++) { + *Y1++ = *Xp; + *Y2++ = *Xq; + *Y3++ = *Xr; + *Y4++ = *Xs; + *Y5++ = *Xt; + } + } + } + } + } + + return; +} + +void ElemK_8Byte(double *Xp, mwSize nX, double *Yp, mwSize nY, mwSize K) +{ + double *Xq, *Xr, + **A, **Ap, **Af, *Yq, + **B, **Bp, **Bf, **Bq, **lastB, **F, **Fp, **lastF; + + if ((B = (double **) mxMalloc(K * sizeof(double *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [B]."); + } + if ((F = (double **) mxMalloc(K * sizeof(double *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [F]."); + } + + Bf = B + K; + Fp = F; + Xq = Xp; + Xr = Xp + nX - K + 1; + for (Bp = B; Bp < Bf; ) { + *Bp++ = Xq++; + *Fp++ = Xr++; + } + + if ((A = (double **) mxMalloc(K * sizeof(double *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [A]."); + } + + Af = A + K; + Yq = Yp; + for (Ap = A; Ap < Af; Ap++) { + *Ap = Yq; + Yq += nY; + } + + lastB = B + K - 1; + lastF = F + K - 1; + while (1) { + Bq = lastB; + Fp = lastF; + while (*Bq < *Fp) { + for (Bp = B, Ap = A; Ap < Af; Ap++) { + **Ap = **Bp++; + (*Ap)++; + } + (*Bq)++; + } + + do { + Bq--; + Fp--; + if (Bq < B) { + mxFree(A); + mxFree(B); + mxFree(F); + return; + } + } while (*Bq >= *Fp); + + (*Bq)++; + while (++Bq < Bf) { + *Bq = *(Bq - 1) + 1; + } + } + +} + +void ElemK_4Byte(INT32_T *Xp, mwSize nX, INT32_T *Yp, mwSize nY, mwSize K) +{ + INT32_T *Xq, *Xr, + **A, **Ap, **Af, *Yq, + **B, **Bp, **Bf, **Bq, **lastB, **F, **Fp, **lastF; + + if ((B = (INT32_T **) mxMalloc(K * sizeof(INT32_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [B]."); + } + if ((F = (INT32_T **) mxMalloc(K * sizeof(INT32_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [F]."); + } + + Bf = B + K; + Fp = F; + Xq = Xp; + Xr = Xp + nX - K + 1; + for (Bp = B; Bp < Bf; ) { + *Bp++ = Xq++; + *Fp++ = Xr++; + } + + if ((A = (INT32_T **) mxMalloc(K * sizeof(INT32_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [A]."); + } + + Af = A + K; + Yq = Yp; + for (Ap = A; Ap < Af; Ap++) { + *Ap = Yq; + Yq += nY; + } + + lastB = B + K - 1; + lastF = F + K - 1; + while (1) { + Bq = lastB; + Fp = lastF; + while (*Bq < *Fp) { + for (Bp = B, Ap = A; Ap < Af; Ap++) { + **Ap = **Bp++; + (*Ap)++; + } + (*Bq)++; + } + + + do { + Bq--; + Fp--; + if (Bq < B) { + mxFree(A); + mxFree(B); + mxFree(F); + return; + } + } while (*Bq >= *Fp); + + (*Bq)++; + while (++Bq < Bf) { + *Bq = *(Bq - 1) + 1; + } + } + +} + +void ElemK_2Byte(INT16_T *Xp, mwSize nX, INT16_T *Yp, mwSize nY, mwSize K) +{ + INT16_T *Xq, *Xr, + **A, **Ap, **Af, *Yq, + **B, **Bp, **Bf, **Bq, **lastB, **F, **Fp, **lastF; + + if ((B = (INT16_T **) mxMalloc(K * sizeof(INT16_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [B]."); + } + if ((F = (INT16_T **) mxMalloc(K * sizeof(INT16_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [F]."); + } + + Bf = B + K; + Fp = F; + Xq = Xp; + Xr = Xp + nX - K + 1; + for (Bp = B; Bp < Bf; ) { + *Bp++ = Xq++; + *Fp++ = Xr++; + } + + if ((A = (INT16_T **) mxMalloc(K * sizeof(INT16_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [A]."); + } + + Af = A + K; + Yq = Yp; + for (Ap = A; Ap < Af; Ap++) { + *Ap = Yq; + Yq += nY; + } + + lastB = B + K - 1; + lastF = F + K - 1; + while (1) { + Bq = lastB; + Fp = lastF; + while (*Bq < *Fp) { + for (Bp = B, Ap = A; Ap < Af; Ap++) { + **Ap = **Bp++; + (*Ap)++; + } + (*Bq)++; + } + + do { + Bq--; + Fp--; + if (Bq < B) { + mxFree(A); + mxFree(B); + mxFree(F); + return; + } + } while (*Bq >= *Fp); + + (*Bq)++; + while (++Bq < Bf) { + *Bq = *(Bq - 1) + 1; + } + } + +} + +void ElemK_1Byte(INT8_T *Xp, mwSize nX, INT8_T *Yp, mwSize nY, mwSize K) +{ + INT8_T *Xq, *Xr, + **A, **Ap, **Af, *Yq, + **B, **Bp, **Bf, **Bq, **lastB, **F, **Fp, **lastF; + + if ((B = (INT8_T **) mxMalloc(K * sizeof(INT8_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [B]."); + } + if ((F = (INT8_T **) mxMalloc(K * sizeof(INT8_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [F]."); + } + + Bf = B + K; + Fp = F; + Xq = Xp; + Xr = Xp + nX - K + 1; + for (Bp = B; Bp < Bf; ) { + *Bp++ = Xq++; + *Fp++ = Xr++; + } + + if ((A = (INT8_T **) mxMalloc(K * sizeof(INT8_T *))) == NULL) { + mexErrMsgIdAndTxt("JSimon:VChooseK:NoMemory", + "Cannot get memory for [A]."); + } + + Af = A + K; + Yq = Yp; + for (Ap = A; Ap < Af; Ap++) { + *Ap = Yq; + Yq += nY; + } + + lastB = B + K - 1; + lastF = F + K - 1; + while (1) { + Bq = lastB; + Fp = lastF; + while (*Bq < *Fp) { + for (Bp = B, Ap = A; Ap < Af; Ap++) { + **Ap = **Bp++; + (*Ap)++; + } + (*Bq)++; + } + + do { + Bq--; + Fp--; + if (Bq < B) { + mxFree(A); + mxFree(B); + mxFree(F); + return; + } + } while (*Bq >= *Fp); + + (*Bq)++; + while (++Bq < Bf) { + *Bq = *(Bq - 1) + 1; + } + } + +} diff --git a/dependencies/auxiliaryFunctions/mexFiles/VChooseK/license.txt b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/license.txt new file mode 100644 index 0000000..02a8987 --- /dev/null +++ b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/license.txt @@ -0,0 +1,24 @@ +Copyright (c) 2009, Jan Simon +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/dependencies/auxiliaryFunctions/mexFiles/VChooseK/test.m b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/test.m new file mode 100644 index 0000000..9455292 --- /dev/null +++ b/dependencies/auxiliaryFunctions/mexFiles/VChooseK/test.m @@ -0,0 +1,19 @@ +nTest = 1e3; + + +tNChooseK = 0; +tVChooseK = 0; + + +for iTest=1:nTest + t1 = tic; + C1 = nchoosek(1:4,2); + tNChooseK = toc(t1); + + t2 = tic; + C2 = VChooseK(1:4,2); + tVChooseK = toc(t2); +end +fprintf('t1 = %g\n',tNChooseK) +fprintf('t2 = %g\n',tVChooseK) +fprintf('t1/t2 = %g\n',tNChooseK/tVChooseK) \ No newline at end of file