def initialize(self, externalSeeding=None, solutionExport=None): """ This function should be called every time a clean optimizer is needed. Called before takeAstep in <Step> @ In, externalSeeding, int, optional, external seed @ In, solutionExport, DataObject, optional, a PointSet to hold the solution @ Out, None """ AdaptiveSampler.initialize(self, externalSeeding=externalSeeding, solutionExport=solutionExport) # functional constraints for entry in self.assemblerDict.get('Constraint', []): self._constraintFunctions.append(entry[3]) for entry in self.assemblerDict.get('ImplicitConstraint', []): self._impConstraintFunctions.append(entry[3]) # sampler self._initializeInitSampler(externalSeeding) # seed if self._seed is not None: randomUtils.randomSeed(self._seed) # variable bounds self._variableBounds = {} for var in self.toBeSampled: dist = self.distDict[var] lower = dist.lowerBound if dist.lowerBound is not None else -np.inf upper = dist.upperBound if dist.upperBound is not None else np.inf self._variableBounds[var] = [lower, upper] self.raiseADebug('Set bounds for opt var "{}" to {}'.format(var, self._variableBounds[var])) # trajectory initialization for i, init in enumerate(self._initialValues): self._initialValues[i] = self.normalizeData(init) self.initializeTrajectory()
def __init__(self): """ Default Constructor that will initialize member variables with reasonable defaults or empty lists/dictionaries where applicable. @ In, None @ Out, None """ AdaptiveSampler.__init__(self) self._initialValues = { } # dict stores the user provided initial values, i.e. {var: val} self._updateValues = { } # dict stores input variables values for the current MCMC iteration, i.e. {var:val} self._proposal = { } # dict stores the proposal distributions for input variables, i.e. {var:dist} self._priorFuns = { } # dict stores the prior functions for input variables, i.e. {var:fun} self._burnIn = 0 # integers indicate how many samples will be discarded self._likelihood = None # stores the output from the likelihood self._logLikelihood = False # True if the user provided likelihood is in log format self._availProposal = { 'normal': Distributions.Normal(0.0, 1.0), 'uniform': Distributions.Uniform(-1.0, 1.0) } # available proposal distributions self._acceptDist = Distributions.Uniform( 0.0, 1.0) # uniform distribution for accept/rejection purpose self.toBeCalibrated = {} # parameters that will be calibrated # assembler objects self.addAssemblerObject('proposal', InputData.Quantity.zero_to_infinity) self.addAssemblerObject('probabilityFunction', InputData.Quantity.zero_to_infinity)
def __init__(self): """ Constructor. @ In, None @ Out, None """ AdaptiveSampler.__init__(self) ## Instance Variable Initialization # public # _protected self._seed = None # random seed to apply self._minMax = 'min' # maximization or minimization? self._activeTraj = [] # tracks live trajectories self._cancelledTraj = {} # tracks cancelled trajectories, and reasons self._convergedTraj = {} # tracks converged trajectories, and values obtained self._numRepeatSamples = 1 # number of times to repeat sampling (e.g. denoising) self._objectiveVar = None # objective variable for optimization self._initialValues = None # initial variable values (trajectory starting locations), list of dicts self._variableBounds = None # dictionary of upper/lower bounds for each variable (may be inf?) self._trajCounter = 0 # tracks numbers to assign to trajectories self._initSampler = None # sampler to use for picking initial seeds self._constraintFunctions = [] # list of constraint functions self._impConstraintFunctions = [] # list of implicit constraint functions # __private # additional methods self.addAssemblerObject('Constraint', '-1') # Explicit (input-based) constraints self.addAssemblerObject('ImplicitConstraint', '-1') # Implicit constraints self.addAssemblerObject('Sampler', '-1') # This Sampler can be used to initialize the optimization initial points (e.g. partially replace the <initial> blocks for some variables) # register adaptive sample identification criteria self.registerIdentifier('traj') # the trajectory of interest
def initialize(self, externalSeeding=None, solutionExport=None): """ This function should be called every time a clean MCMC is needed. Called before takeAstep in <Step> @ In, externalSeeding, int, optional, external seed @ In, solutionExport, DataObject, optional, a PointSet to hold the solution @ Out, None """ self._acceptDist.initializeDistribution() AdaptiveSampler.initialize(self, externalSeeding=externalSeeding, solutionExport=solutionExport) ## TODO: currently AdaptiveSampler is still using self.assemblerDict to retrieve the target evaluation. # We should change it to using the following method. # retrieve target evaluation # self._targetEvaluation = self.retrieveObjectFromAssemblerDict('TargetEvaluation', self._targetEvaluation) for var, priorFun in self._priorFuns.items(): self._priorFuns[var] = self.retrieveObjectFromAssemblerDict('probabilityFunction', priorFun) if "pdf" not in self._priorFuns[var].availableMethods(): self.raiseAnError(IOError,'Function', self._priorFuns[var], 'does not contain a method named "pdf". \ It must be present if this needs to be used in a MCMC Sampler!') if not self._initialValues[var]: self.raiseAnError(IOError, '"initial" is required when using "probabilityFunction", but not found \ for variable "{}"'.format(var)) # initialize the input variable values for var, dist in self.distDict.items(): distType = dist.getDistType() if distType != 'Continuous': self.raiseAnError(IOError, 'variable "{}" requires continuous distribution, but "{}" is provided!'.format(var, distType)) meta = ['LogPosterior', 'AcceptRate'] self.addMetaKeys(meta)
def localFinalizeActualSampling(self, jobObject, model, myInput): """ General function (available to all samplers) that finalizes the sampling calculation just ended. In this case, The function is aimed to check if all the batch calculations have been performed @ In, jobObject, instance, an instance of a JobHandler @ In, model, model instance, it is the instance of a RAVEN model @ In, myInput, list, the generating input @ Out, None """ AdaptiveSampler.localFinalizeActualSampling(self, jobObject, model, myInput)
def _localGenerateAssembler(self, initDict): """ It is used for sending to the instanciated class, which is implementing the method, the objects that have been requested through "whatDoINeed" method Overloads the base Sampler class since optimizer has different requirements @ In, initDict, dict, dictionary ({'mainClassName(e.g., Databases):{specializedObjectName(e.g.,DatabaseForSystemCodeNamedWolf):ObjectInstance}'}) @ Out, None """ AdaptiveSampler._localGenerateAssembler(self, initDict) # functions and distributions already collected self.assemblerDict['DataObjects'] = [] self.assemblerDict['Distributions'] = [] self.assemblerDict['Functions'] = [] for mainClass in ['DataObjects', 'Distributions', 'Functions']: for funct in initDict[mainClass]: self.assemblerDict[mainClass].append([mainClass, initDict[mainClass][funct].type, funct, initDict[mainClass][funct]])
def localStillReady(self, ready): """ Determines if sampler is prepared to provide another input. If not, and if jobHandler is finished, this will end sampling. @ In, ready, bool, a boolean representing whether the caller is prepared for another input. @ Out, ready, bool, a boolean representing whether the caller is prepared for another input. """ ready = AdaptiveSampler.localStillReady(self, ready) return ready
def _formatSolutionExportVariableNames(self, acceptable): """ Does magic formatting for variables, based on this class's needs. Extend in inheritors as needed. @ In, acceptable, set, set of acceptable entries for solution export for this entity @ Out, acceptable, set, modified set of acceptable variables with all formatting complete """ acceptable = AdaptiveSampler._formatSolutionExportVariableNames(self, acceptable) return acceptable
def _localWhatDoINeed(self): """ This method is a local mirror of the general whatDoINeed method. It is implemented by the optimizers that need to request special objects @ In, None @ Out, needDict, dict, list of objects needed """ needDict = AdaptiveSampler._localWhatDoINeed() needDict['Functions'] = [(None, 'all')] return needDict
def localFinalizeActualSampling(self, jobObject, model, myInput): """ General function (available to all samplers) that finalizes the sampling calculation just ended. In this case, The function is aimed to check if all the batch calculations have been performed @ In, jobObject, instance, an instance of a JobHandler @ In, model, model instance, it is the instance of a RAVEN model @ In, myInput, list, the generating input @ Out, None """ self._localReady = True AdaptiveSampler.localFinalizeActualSampling(self, jobObject, model, myInput) prefix = jobObject.getMetadata()['prefix'] full = self._targetEvaluation.realization(index=self.counter-1) rlz = dict((var, full[var]) for var in (list(self.toBeCalibrated.keys()) + [self._likelihood] + list(self.dependentSample.keys()))) rlz['traceID'] = self.counter rlz['LogPosterior'] = self.inputInfo['LogPosterior'] rlz['AcceptRate'] = self.inputInfo['AcceptRate'] if self.counter == 1: self._addToSolutionExport(rlz) self._currentRlz = rlz if self.counter > 1: alpha = self._useRealization(rlz, self._currentRlz) self.netLogPosterior = alpha self._accepted = self._checkAcceptance(alpha) if self._accepted: self._currentRlz = rlz self._addToSolutionExport(rlz) self._updateValues = dict((var, rlz[var]) for var in self._updateValues) else: self._currentRlz.update({'traceID':self.counter, 'LogPosterior': self.inputInfo['LogPosterior'], 'AcceptRate':self.inputInfo['AcceptRate']}) self._addToSolutionExport(self._currentRlz) self._updateValues = dict((var, self._currentRlz[var]) for var in self._updateValues) if self._tune: self._acceptInTune = self._acceptInTune + 1 if self._accepted else self._acceptInTune self._countsUntilTune -= 1 ## tune scaling parameter if not self._countsUntilTune and self._tune: ### tune self._scaling = self.tuneScalingParam(self._scaling, self._acceptInTune/float(self._tuneInterval)) ### reset counter self._countsUntilTune = self._tuneInterval self._acceptInTune = 0
def amIreadyToProvideAnInput(self): """ This is a method that should be called from any user of the optimizer before requiring the generation of a new input. This method act as a "traffic light" for generating a new input. Reason for not being ready could be for example: exceeding number of model evaluation, convergence criteria met, etc. @ In, None @ Out, ready, bool, indicating the readiness of the optimizer to generate a new input. """ # if any trajectories are still active, we're ready to provide an input ready = AdaptiveSampler.amIreadyToProvideAnInput(self) if not self._activeTraj: self.raiseADebug(' ... No active optimization trajectories.') ready = False return ready
def __init__(self): """ Default Constructor that will initialize member variables with reasonable defaults or empty lists/dictionaries where applicable. @ In, None @ Out, None """ AdaptiveSampler.__init__(self) self.onlySampleAfterCollecting = True self._initialValues = {} # dict stores the user provided initial values, i.e. {var: val} self._updateValues = {} # dict stores input variables values for the current MCMC iteration, i.e. {var:val} self._proposal = {} # dict stores the proposal distributions for input variables, i.e. {var:dist} self._proposalDist = {} # dist stores the input variables for each proposal distribution, i.e. {distName:[(var,dim)]} self._priorFuns = {} # dict stores the prior functions for input variables, i.e. {var:fun} self._burnIn = 0 # integers indicate how many samples will be discarded self._likelihood = None # stores the output from the likelihood self._logLikelihood = False # True if the user provided likelihood is in log format self._availProposal = {'normal': Distributions.Normal, 'multivariateNormal': Distributions.MultivariateNormal} # available proposal distributions self._acceptDist = Distributions.Uniform(0.0, 1.0) # uniform distribution for accept/rejection purpose self.toBeCalibrated = {} # parameters that will be calibrated self._correlated = False # True if input variables are correlated else False self.netLogPosterior = 0.0 # log-posterior vs iteration self._localReady = True # True if the submitted job finished self._currentRlz = None # dict stores the current realizations, i.e. {var: val} self._acceptRate = 1. # The accept rate for MCMC self._acceptCount = 1 # The total number of accepted samples self._tune = True # Tune the scaling parameter if True self._tuneInterval = 100 # the number of sample steps for each tuning of scaling parameter self._scaling = 1.0 # The initial scaling parameter self._countsUntilTune = self._tuneInterval # The remain number of sample steps until the next tuning self._acceptInTune = 0 # The accepted number of samples for given tune interval self._accepted = False # The indication of current samples, True if accepted otherwise False self._stdProposalDefault = 0.2 # the initial scaling of the std of proposal distribution (only apply to default) # assembler objects self.addAssemblerObject('proposal', InputData.Quantity.zero_to_infinity) self.addAssemblerObject('probabilityFunction', InputData.Quantity.zero_to_infinity)
def initialize(self, externalSeeding=None, solutionExport=None): """ This function should be called every time a clean MCMC is needed. Called before takeAstep in <Step> @ In, externalSeeding, int, optional, external seed @ In, solutionExport, DataObject, optional, a PointSet to hold the solution @ Out, None """ # TODO: currently, we only consider uncorrelated case # initialize distributions for _, dist in self._availProposal.items(): dist.initializeDistribution() self._acceptDist.initializeDistribution() for var in self._updateValues: if var in self._proposal: self._proposal[var] = self.retrieveObjectFromAssemblerDict( 'proposal', self._proposal[var]) distType = self._proposal[var].getDistType() if distType != 'Continuous': self.raiseAnError( IOError, 'variable "{}" requires continuous proposal distribution, but "{}" is provided!' .format(var, distType)) else: self._proposal[var] = self._availProposal['normal'] AdaptiveSampler.initialize(self, externalSeeding=externalSeeding, solutionExport=solutionExport) ## TODO: currently AdaptiveSampler is still using self.assemblerDict to retrieve the target evaluation. # We should change it to using the following method. # retrieve target evaluation # self._targetEvaluation = self.retrieveObjectFromAssemblerDict('TargetEvaluation', self._targetEvaluation) for var, priorFun in self._priorFuns.items(): self._priorFuns[var] = self.retrieveObjectFromAssemblerDict( 'probabilityFunction', priorFun) if "pdf" not in self._priorFuns[var].availableMethods(): self.raiseAnError( IOError, 'Function', self._priorFuns[var], 'does not contain a method named "pdf". \ It must be present if this needs to be used in a MCMC Sampler!') if not self._initialValues[var]: self.raiseAnError( IOError, '"initial" is required when using "probabilityFunction", but not found \ for variable "{}"'.format(var)) # initialize the input variable values for var, dist in self.distDict.items(): totDim = self.variables2distributionsMapping[var]['totDim'] distType = dist.getDistType() if distType != 'Continuous': self.raiseAnError( IOError, 'variable "{}" requires continuous distribution, but "{}" is provided!' .format(var, distType)) if totDim != 1: self.raiseAnError( IOError, "Total dimension for given distribution {} should be 1". format(dist.type)) if self._updateValues[var] is None: value = dist.rvs() self._updateValues[var] = value