Beispiel #1
0
    def __init__(self, inputsrom, outputsamples, outputgradients=None):
        '''
        Initialize SROM surrogate using the input SROM used to generate the
        output samples. Output gradients are also supplied for the case of
        the piecewise linear surrogate.

        output samples have the following convention:

        m = SROM size (superscript), do = dimension (subscript);

        outputsamples =  |  y^(1)_1, ..., y^(1)_do |
                         |  ...    , ..., ...      |
                         |  y^(m)_1, ..., y^(m)_do |

        output samples must match the order of inputsrom samples/probs!

        (m x d_i array)
        gradients = | dy(x^{(1)})/dx_1, ..., dy(x^{(1)})/dx_di |
                    | ...             , ...,    ...           |
                    | dy(x^{(m)})/dx_1, ..., dy(x^{(m)})/dx_di |

        do - dimension of output samples (doesn't need to equal di of input)

        '''

        if inputsrom._samples is None or inputsrom._probs is None:
            raise ValueError("Input SROM must be properly initialized")

        self._inputsrom = inputsrom

        #Handle 1 dimension case, adjust shape:
        if len(outputsamples.shape) == 1:
            outputsamples.shape = (len(outputsamples), 1)

        #Verify dimensions of samples/probs
        (size, dim) = outputsamples.shape

        if size != self._inputsrom._size:
            raise ValueError("Number of output samples must match input " +
                             " srom size!")

        self._outsamples = outputsamples
        self._dim = dim
        self._size = size

        #TODO - checks on outputgradients:
        if outputgradients is not None:
            (size__, dim__) = outputgradients.shape
            if size__ != self._inputsrom._size:
                raise ValueError("Incorrect # samples in gradient array!")
            if dim__ != self._inputsrom._dim:
                raise ValueError("Incorrect dimension in gradient array!")

        self._gradients = outputgradients

        #Make SROM for output?
        self._outputsrom = SROM(size, dim)
        self._outputsrom.set_params(outputsamples, inputsrom._probs)
Beispiel #2
0
import numpy as np

from postprocess import Postprocessor
from srom import SROM
from target import SampleRandomVector
'''
Generate SROM to model input distribution (samples)
'''

#Specify input/output files and SROM optimization parameters
dim = 3
srom_size = 20
samplesfile = "mc_data/input_samples_MC.txt"
outfile = "srom_data_tmp/srom_m" + str(srom_size) + ".txt"

#Define target random variable from samples
MCsamples = np.genfromtxt(samplesfile)
target = SampleRandomVector(MCsamples)

#Define SROM, determine optimal parameters, store parameters
srom = SROM(srom_size, dim)
srom.optimize(target, weights=[1, 1, 1], error="SSE")
#NOTE - commented out to not overwrite paper data files:
#srom.save_params(outfile)

#Check out the CDFs
pp = Postprocessor(srom, target)
pp.compare_CDFs(variablenames=[r'log$C$', r'$y_{0}$', r'$n$'])
Beispiel #3
0
    disp_samples[i] = model.get_max_disp(k_samples[i], m_samples[i])

#Get Monte carlo solution as a sample-based random variable:
mc_solution = SampleRandomVector(disp_samples)

#-------------SROM-----------------------

#generate SROM for random vector of stiffness & mass
sromsize = 25
dim = 2

#Assume we only have access to samples in this example and want SROM from them:
km_samples = np.array([k_samples, m_samples]).T
km_random_vector = SampleRandomVector(km_samples)

srom = SROM(sromsize, dim)
srom.optimize(km_random_vector)
(samples, probs) = srom.get_params()

#Run model to get max disp for each SROM stiffness sample
srom_disps = np.zeros(sromsize)
for i in range(sromsize):
    k = samples[i,0]
    m = samples[i,1]
    srom_disps[i] = model.get_max_disp(k, m)
 
#Form new SROM for the max displacement solution using samples from the model   
srom_solution = SROM(sromsize, 1)
srom_solution.set_params(srom_disps, probs)

#----------------------------------------
Beispiel #4
0
import numpy as np

from model import Model
from srom import SROM
'''
Run computational model for each input SROM sample - step 2
NOTE - this script will not run, "Model" class is not provided. But this 
script is representative of a common SROM workflow.
'''

dim = 3
srom_size = 20
sromfile = "srom_data/srom_m" + str(srom_size) + ".txt"
sromeolfile = "srom_data/srom_eol_m" + str(srom_size) + ".txt"

srom = SROM(srom_size, dim)
srom.load_params(sromfile)

srom_outputs = np.zeros(srom_size)
(srom_samples, srom_probs) = srom.get_params()
for i, input in enumerate(srom_samples):
    srom_outputs[i] = model.evaluate(input)

np.savetxt(sromeolfile, srom_outputs)
Beispiel #5
0
dim = 3
sromsize = 10

#Data files for EOL samples, EOL finite difference samples, and SROM inputs
srom_eol_file = "srom_data/srom_eol_m" + str(sromsize) + ".txt"
srom_fd_eol_file = "srom_data/srom_fd_eol_m" + str(sromsize) + ".txt"
srom_input_file = "srom_data/srom_m" + str(sromsize) + ".txt"

#Get MC input/EOL samples
MC_inputs = np.genfromtxt(mc_input_file)
MC_eols = np.genfromtxt(mc_eol_file)

#Get SROM EOL samples, FD samples and input SROM from file
srom_eols = np.genfromtxt(srom_eol_file)
srom_fd_eols = np.genfromtxt(srom_fd_eol_file)
input_srom  = SROM(sromsize, dim)
input_srom.load_params(srom_input_file)

#Get FD step sizes from file (the same for all samples, just pull the first)
#Step sizes chosen as approximately 2% of the median sample value of inputs
stepsizes = [0.083, 0.0065, 0.025]

#Calculate gradient from FiniteDifference class:
gradient = FD.compute_gradient(srom_eols, srom_fd_eols, stepsizes)

#Create SROM surrogate, sample, and create random variable solution
surrogate_PWL = SROMSurrogate(input_srom, srom_eols, gradient)
srom_eol_samples = surrogate_PWL.sample(MC_inputs)
solution_PWL = SampleRandomVector(srom_eol_samples)

#Store EOL samples for plotting later:
Beispiel #6
0
import numpy
from os import path
from postprocess import Postprocessor
from srom import SROM, SROMSurrogate
from target import SampleRandomVector

#Define target random vector from samples
monte_carlo_input_samples_filename = path.join("mc_data",
                                               "input_samples_MC.txt")
monte_carlo_input_samples = numpy.genfromtxt(
    monte_carlo_input_samples_filename)
target_vector = SampleRandomVector(monte_carlo_input_samples)

#Define SROM and determine optimal parameters
srom_size = 20
input_srom = SROM(size=srom_size, dim=3)
input_srom.optimize(target_vector)

#Compare the input CDFs (produces Figure 6)
post_processor = Postprocessor(input_srom, target_vector)
post_processor.compare_CDFs(variablenames=[r'log$C$', r'$y_{0}$', r'$n$'])

#Run the model for each input SROM sample:
srom_results = numpy.zeros(srom_size)
(srom_samples, srom_probs) = input_srom.get_params()

# TODO: define model here.
model = None

if model is None:
    raise ValueError("model has not been defined.")
Beispiel #7
0
from target import SampleRandomVector

'''
Ex3 - unimodal 3D
Script to generate PW constant SROM approximation to EOL and compare it with the
monte carlo solution (w/ surrogate model)
'''

mc_eol_file = "mc_data/eol_samples_MC.txt"

sromsize = 20

srom_eol_file = "srom_data/srom_eol_m" + str(sromsize) + ".txt"
srom_input_file = "srom_data/srom_m" + str(sromsize) + ".txt"

#Get MC EOL samples
MC_eols = np.genfromtxt(mc_eol_file)

#Get SROM EOL samples & probabilities from input srom
srom_eols = np.genfromtxt(srom_eol_file)
srom_probs = np.genfromtxt(srom_input_file)[:,-1]  #probs in last column

#Make MC random variable & SROM to compare
eol_srom = SROM(sromsize, dim=1)
eol_srom.set_params(srom_eols, srom_probs)
eol_mc = SampleRandomVector(MC_eols)

pp = Postprocessor(eol_srom, eol_mc)
pp.compare_CDFs(variablenames=["EOL"])

Beispiel #8
0
'''
Generate SROM to model input distribution (samples)
'''

#Specify input/output files and SROM optimization parameters
dim = 3
srom_size = 20
mc_input_file = "mc_data/input_samples_MC.txt"
mc_eol_file = "mc_data/eol_samples_MC.txt"

#Define target random variable from samples
MCsamples = np.genfromtxt(samplesfile)
target = SampleRandomVector(MCsamples)

#Define SROM, determine optimal parameters, store parameters
input_srom = SROM(srom_size, dim)
input_srom.optimize(target, weights=[1,1,1], error="SSE")

#Compare the CDFs
pp = Postprocessor(srom, target)
pp.compare_CDFs(saveFig=False)

#Run the model for each input SROM sample:
srom_eols = np.zeros(srom_size)
(srom_samples, srom_probs) = input_srom.get_params()
for i, sample in enumerate(srom_samples):
    srom_eols[i] = model.evaluate(sample)

#Generate SROM surrogate for the output
eol_srom = SROMSurrogate(input_srom, srom_eols)
Beispiel #9
0
#Load / initialize target random variable from samples:
samples = np.genfromtxt(targetsamples)
target = SampleRandomVector(samples)

#Set x limits for each variable based on target:
xlimits = []
for i in range(target._dim):
    lims = [np.min(samples[:, i]), np.max(samples[:, i])]
    xlimits.append(lims)

#Build up sromsize-to-SROM object map for plotting routine
sroms = OrderedDict()

for sromsize in sromsizes:

    #Generate SROM from file:
    srom = SROM(sromsize, target._dim)
    sromfile = "srom_m" + str(sromsize) + ".txt"
    sromfile = os.path.join(srom_dir, sromfile)
    srom.load_params(sromfile)
    sroms[sromsize] = srom

Postprocessor.compare_srom_CDFs(sroms,
                                target,
                                plotdir="plots",
                                plotsuffix=plot_suffix,
                                variablenames=varz,
                                xlimits=xlimits,
                                xticks=xticks,
                                cdfylabel=cdfylabel)
Beispiel #10
0
from postprocess import Postprocessor
from srom import SROM
from target import NormalRandomVariable

#Initialize Normal random variable object to be modeled by SROM:
normal = NormalRandomVariable(mean=3., std_dev=1.5)

#Initialize SROM & optimize to model the normal random variable:
srom = SROM(size=10, dim=1)
srom.optimize(normal)

#Compare the CDF of the SROM & target normal variable:
pp = Postprocessor(srom, normal)
pp.compare_CDFs()

Beispiel #11
0
class SROMSurrogate:
    """
    SROMPy class that provides a closed-form surrogate model for a model output
    that can be sampled as a means of efficiently propagating uncertainty.
    Enables both a piecewise-constant model and a piecewise-linear model, if
    gradient information is provided. 

    :param inputsrom: The input SROM that was used to generate the outputs.
    :type inputsrom: SROMPy SROM object.
    :param outputsamples: Output samples corresponding to each input SROM sample
    :type outputsamples: 2d Numpy Array
    :param outputgradients: Gradient of output with respect to input samples
    :type outputgradients: 2d Numpy Array
    
    Conventions:

    * m denotes the SROM size (superscripts). di denotes the dimension of the 
      SROM input (subscripts). do denotes dimension of SROM output (subscripts).
    * The output samples array has the following layout (m x d0):

        | [[ y^(1)_1,   y_2^(1), ..., y_do^(1)],
        | [y_1^(2), y_2^(2), ..., y_d0^(2)],
        | ...     ...   ...    ....  
        | [y_1^(m), y_2^(m),  ...  y_d0^(m)]]    
    
    * The gradients array has the following layout (m x di):

        | [[dy(x^{(1)})/dx_1, ..., dy(x^{(1)})/dx_di ],
        | ...             , ...,    ...           
        | [dy(x^{(m)})/dx_1, ..., dy(x^{(m)})/dx_di ]]

    Note

    * the order of the output samples array must match the order of the
      samples array from the input SROM!
    * If gradients array is provided, the piecewise-linear surrogate 
      model is implemented. Otherwise, the piecewise-constant surrogate is
      used.

    """

    def __init__(self, inputsrom, outputsamples, outputgradients=None):
        '''
        Initialize SROM surrogate using the input SROM used to generate the
        output samples. Output gradients are also supplied for the case of
        the piecewise linear surrogate.

        output samples have the following convention:

        m = SROM size (superscript), do = dimension (subscript);

        outputsamples =  |  y^(1)_1, ..., y^(1)_do |
                         |  ...    , ..., ...      |
                         |  y^(m)_1, ..., y^(m)_do |

        output samples must match the order of inputsrom samples/probs!

        (m x d_i array)
        gradients = | dy(x^{(1)})/dx_1, ..., dy(x^{(1)})/dx_di |
                    | ...             , ...,    ...           |
                    | dy(x^{(m)})/dx_1, ..., dy(x^{(m)})/dx_di |

        do - dimension of output samples (doesn't need to equal di of input)

        '''

        if inputsrom._samples is None or inputsrom._probs is None:
            raise ValueError("Input SROM must be properly initialized")

        self._inputsrom = inputsrom

        #Handle 1 dimension case, adjust shape:
        if len(outputsamples.shape) == 1:
            outputsamples.shape = (len(outputsamples), 1)

        #Verify dimensions of samples/probs
        (size, dim) = outputsamples.shape

        if size != self._inputsrom._size:
            raise ValueError("Number of output samples must match input " +
                             " srom size!")

        self._outsamples = outputsamples
        self._dim = dim
        self._size = size

        #TODO - checks on outputgradients:
        if outputgradients is not None:
            (size__, dim__) = outputgradients.shape
            if size__ != self._inputsrom._size:
                raise ValueError("Incorrect # samples in gradient array!")
            if dim__ != self._inputsrom._dim:
                raise ValueError("Incorrect dimension in gradient array!")

        self._gradients = outputgradients

        #Make SROM for output?
        self._outputsrom = SROM(size, dim)
        self._outputsrom.set_params(outputsamples, inputsrom._probs)


    #Do these change for linear surrogate?
    def compute_moments(self, max_order):
        """
        Calculates and returns SROM moments.

        :param max_order: Maximum order of moments to return
        :type max_order: int

        Returns (max_order x dim) size Numpy array with SROM moments for 
        each dimension.
        """

        return self._outputsrom.compute_moments(max_order)

    def compute_CDF(self, x_grid):
        """
        Computes the SROM marginal CDF values in each dimension.

        :param x_grid: Grid of points to compute CDF values on. If 1d array is
            provided, the same points are used to evaluate CDF in each 
            dimension. If 2d array is provided, calculates CDF values on
            different points, but must have same # points for each dimension. 
            Size is (# grid pts) x (dim) or (# grid pts) x (1).
        :type x_grid: Numpy array.

        Returns: Numpy array of CDF values at x_grid points. Size is (# grid 
        pts) x (dim).

        Note: 
            * Increasing the number of grid points can significantly slow 
              down the SROM optimization problem.
            * Providing a 2d array for x_grid can specify a different range
              of values for each dimension, but must use the same number of pts.
        """

        return self._outputsrom.compute_CDF(x_grid)

    def sample(self, inputsamples):
        '''
        Generates output samples from the SROM surrogate corresponding to
        the provided input samples.

        :param inputsamples: samples of inputs to draw output samples for
        :type inputsamples: 2d Numpy array.

        Returns: 2d Numpy array of output samples corresponding to input samples

        Convention:
            * N - number of samples. di - dimension of the input. do - dimension
              of the output. 
            * input samples array has following layout (N x di):


              | [[x^(1)_1, ..., x^(1)_di ],    
              |  ...    , ..., ...   
              | [x^(N)_1, ..., x^(N)_di ]]   
        
            * surrogate output samples has following layout (N x do):

              | [[y^(1)_1, ..., y^(1)_do ],    
              |  ...    , ..., ...      
              | [y^(N)_1, ..., y^(N)_do ]]   

        Note that the samples are drawn from a piecewise-linear SROM 
        surrogate when gradients are provided to the constructor of this class,
        and drawn from a piecewise-constant SROM surrogate if not.

        '''

        #Handle 1 dimension case, adjust shape:
        if len(inputsamples.shape) == 1:
            inputsamples.shape = (len(inputsamples), 1)

        #Verify dimensions of samples/probs
        (numsamples, dim) = inputsamples.shape

        if dim != self._inputsrom._dim:
            raise ValueError("Incorrect input sample dimension")

        #Evaluate piecewise constant or linear surrogate model to get samples:
        if self._gradients is None:
            surr_samples = self._sample_pwconstant_surrogate(inputsamples)
        else:
            surr_samples = self._sample_pwlinear_surrogate(inputsamples)

        return surr_samples

    def _sample_pwconstant_surrogate(self, inputsamples):
        '''
        Evaluate standard piecewise constant output surrogate model
        '''

        inputsamples_srom = self._inputsrom._samples

        #Generate surrogate samples:
        (numsamples, _) = inputsamples.shape

        #Generate surrogate samples:
        surr_samples = np.zeros((numsamples, self._dim))
        for i in range(numsamples):
            #Find which input SROM sample is closest to current sample
            sample_i = inputsamples[i, :]
            diff_norms = np.linalg.norm(sample_i - inputsamples_srom, axis=1)
            sromindex = np.argmin(diff_norms)
            surr_samples[i, :] = self._outsamples[sromindex, :]

        return surr_samples

    def _sample_pwlinear_surrogate(self, inputsamples): 
        '''
        Evaluate the linear output surrogate model using input SROM samples
        and gradients

        input:
        inputsamples =  |  x^(1)_1, ..., x^(1)_di |
                        |  ...    , ..., ...      |
                        |  x^(N)_1, ..., x^(N)_di |

        (mxd array)
        gradients = | dy(x^{(1)})/dx_1, ..., dy(x^{(1)})/dx_d |
                    | ...             , ...,    ...           |
                    | dy(x^{(m)})/dx_1, ..., dy(x^{(m)})/dx_d |

        '''

        inputsamples_srom = self._inputsrom._samples

        #Generate surrogate samples:
        (numsamples, _) = inputsamples.shape

        #Generate surrogate samples:
        surr_samples = np.zeros((numsamples, self._dim))
        for i in range(numsamples):
            #Find which input SROM sample is closest to current sample
            sample_i = inputsamples[i, :]
            diffs = sample_i - inputsamples_srom
            diff_norms = np.linalg.norm(diffs, axis=1)
            sromindex = np.argmin(diff_norms)

            #Calculate ouput sample value (eq 11b from emery paper)
            output_k = self._outsamples[sromindex, :]
            diffs_k = diffs[sromindex, :]
            grad_k = self._gradients[sromindex, :]

            out = output_k + np.dot(grad_k, diffs_k)
            surr_samples[i, :] = out

        return surr_samples
Beispiel #12
0
stiffness_samples = stiffness_rv.draw_random_sample(num_samples)

#Calculate maximum displacement samples using MC simulation
disp_samples = np.zeros(num_samples)
for i, stiff in enumerate(stiffness_samples):
    disp_samples[i] = model.get_max_disp(stiff)

#Get Monte carlo solution as a sample-based random variable:
mc_solution = SampleRandomVector(disp_samples)

#-------------SROM-----------------------

#generate SROM for random stiffness
sromsize = 10
dim = 1
input_srom = SROM(sromsize, dim)
input_srom.optimize(stiffness_rv)

#Compare SROM vs target stiffness distribution:
pp_input = Postprocessor(input_srom, stiffness_rv)
pp_input.compare_CDFs()

#Run model to get max disp for each SROM stiffness sample
srom_disps = np.zeros(sromsize)
(samples, probs) = input_srom.get_params()
for i, stiff in enumerate(samples):
    srom_disps[i] = model.get_max_disp(stiff)

#Form new SROM for the max disp. solution using samples from the model
output_srom = SROM(sromsize, dim)
output_srom.set_params(srom_disps, probs)