/////////////////////////////////////////////////////////////////////////
//
// © University of Southampton IT Innovation Centre, 2011
//
// Copyright in this software belongs to University of Southampton
// IT Innovation Centre of 2 Venture Road, Chilworth Science Park, Southampton SO16 7NP, UK.
//
// This software may not be used, sold, licensed, transferred, copied
// or reproduced in whole or in part in any manner or form or in or
// on any media by any person other than in accordance with the terms
// of the Licence Agreement supplied with the software, or otherwise
// without the prior written consent of the copyright owners.
//
// This software is distributed WITHOUT ANY WARRANTY, without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE, except where stated in the Licence Agreement supplied with
// the software.
//
// Created By : Vegard Engen, Stuart E. Middleton
// Created Date : 13-Jan-2011
// Created for Project : IRMOS---BonFIRE
//
/////////////////////////////////////////////////////////////////////////
//
// Dependencies : none
//
/////////////////////////////////////////////////////////////////////////
package uk.ac.soton.itinnovation.pes.optimiser.test;
import uk.ac.soton.itinnovation.pes.optimiser.common.OptimiserUtil;
import uk.ac.soton.itinnovation.pes.optimiser.common.AObjectiveFunction;
import uk.ac.soton.itinnovation.pes.optimiser.common.IPenaltyCalculator;
import uk.ac.soton.itinnovation.pes.optimiser.common.IPriceCalculator;
import uk.ac.soton.itinnovation.pes.optimiser.common.AModel;
import uk.ac.soton.itinnovation.pes.data.dao.DAOFactory;
import uk.ac.soton.itinnovation.pes.data.model.AttributeType;
import uk.ac.soton.itinnovation.pes.data.model.BasicType;
import uk.ac.soton.itinnovation.pes.data.model.EstimationResult;
import uk.ac.soton.itinnovation.pes.data.model.MetricType;
import uk.ac.soton.itinnovation.pes.data.model.ModelExecutionResult;
import java.io.File;
import java.util.Map;
import org.apache.log4j.Logger;
import uk.ac.soton.itinnovation.pes.data.model.ObjectiveFunctionConfig;
import uk.ac.soton.itinnovation.pes.data.model.ObjectiveFunctionExecutionResult;
import uk.ac.soton.itinnovation.pes.data.model.Resource;
import uk.ac.soton.itinnovation.pes.data.model.ValueType;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import uk.ac.soton.itinnovation.pes.optimiser.common.IResourceMapper;
import uk.ac.soton.itinnovation.pes.optimiser.common.ObjectiveFunctionUtil;
/**
* A sample objective function implementation, which is hard coded and does not
* take in any ASLA parameters. For this, we use a hard coded requested reliability
* of 99%.
*
* INPUTS:
* - HW specs from optimisation algorithm
*
* OUTPUTS:
* - fitness
* - infrastructure_cost
* - customer_cost (infrastructure cost + 10%)
*
* The outputs are stored in a Set<AttributeType>, which is cached in the DB if
* this is enabled.
*/
public class SampleObjectiveFunction extends AObjectiveFunction
{
private ObjectiveFunctionConfig objFuncDB = null;
private EstimationResult estimationResult = null;
private DAOFactory daoFactory = null;
private AModel appModel = null;
private Map<String, List<AttributeType>> aslaParameters = null;
private IPriceCalculator priceCalculator = null;
private IResourceMapper resourceMapper = null;
private File workspace = null;
private double[] fitness = null;
private int numObjectives;
// PARAMETERS REQUIRED FOR CALCULATING INCOME & PENALTY
double requestedReliability = 95;
double markup = 1.1;
// UTILITY & LOGGING RELATED
private OptimiserUtil optUtil = OptimiserUtil.getInstance();
private ObjectiveFunctionUtil objFuncUtil = ObjectiveFunctionUtil.getInstance();
private Logger log = Logger.getLogger(getClass());
private boolean initialised, reInitialised;
private int iterationCounter = 0;
private final int numDecimalPlaces = 3; // the number of decimal places used to round doubles
/**
* constructor
*/
public SampleObjectiveFunction ()
{
this.iterationCounter = 0;
this.numObjectives = 1;
this.initialised = false;
this.reInitialised = false;
System.out.println("[ObjectiveFunction] created instance");
log.debug("Created ObjectiveFunction instance");
}
/**
* Initialisation method for the objective function, which MUST be called
* before the optimisation process can start.
* @param of The database object, which is required for performing database
* caching of results, but also to contains the configuration parameters
* defined in the XML file.
* @param m The application model wrapper for the model that should be
* executed as part of the fitness calculation.
* @param ws The workspace directory where any outputs may be saved to.
* @param res The EstimationResult object created by the Estimation Manager,
* which is required for performing database caching of execution
* results. This can be NULL in this sample class.
* @param daoFact The DAOFactory object, which is used to instantiate the
* required DAO for interacting with the database. This can
* be NULL in this sample class.
* @throws Exception if initialisation fails (e.g. expected parameter values not valid).
*/
@Override
public void init(ObjectiveFunctionConfig of, AModel m, String ws, EstimationResult res, DAOFactory daoFact) throws Exception
{
this.objFuncDB = of;
this.appModel = m;
this.workspace = new File (ws);
this.estimationResult = res;
this.daoFactory = daoFact;
this.iterationCounter = 0;
this.reInitialised = false;
this.fitness = new double[numObjectives];
log.debug("Initialising the ObjectiveFunction");
initialised = objFuncUtil.validateInitParams(of, m, workspace, res, daoFact);
if (!initialised)
throw new Exception("Failed to initialise the objective function. Refer to the error log for details.");
extractConfigParameters();
}
/**
* Initialisation method for the objective function, which MUST be called
* before the optimisation process can start.
* @param of The database object, which is required for performing database
* caching of results, but also to contains the configuration parameters.
* @param m The application model wrapper for the model that should be
* executed as part of the fitness calculation.
* @param aslaParams The ASLA parameters.
* @param ws The workspace directory where any outputs may be saved to.
* @param res The EstimationResult object created by the Estimation Manager,
* which is required for performing database caching of execution
* results.
* @param daoFact The DAOFactory object, which is used to instantiate the
* required DAO for interacting with the database.
* @throws Exception if initialisation fails.
*/
@Override
public void init(ObjectiveFunctionConfig of, AModel m,
Map<String, List<AttributeType>> params, String ws,
EstimationResult res, DAOFactory daoFact) throws Exception
{
this.objFuncDB = of;
this.appModel = m;
this.aslaParameters = params;
this.workspace = new File (ws);
this.estimationResult = res;
this.daoFactory = daoFact;
this.iterationCounter = 0;
this.reInitialised = false;
this.fitness = new double[numObjectives];
log.debug("Initialising the ObjectiveFunction");
initialised = objFuncUtil.validateInitParams(of, m, aslaParameters, workspace, res, daoFact);
if (!initialised)
throw new Exception("Failed to initialise the objective function. Refer to the error log for details.");
extractASLAParameters(aslaParameters);
extractConfigParameters();
}
/**
* Initialisation method for the objective function, which MUST be called
* before the optimisation process can start.
* @param of The database object, which is required for performing database
* caching of results, but also to contains the configuration parameters.
* @param m The application model wrapper for the model that should be
* executed as part of the fitness calculation.
* @param aslaParams The ASLA parameters.
* @param priceCalc The price calculator
* @param penaltyCalc The penalty calculator.
* @param ws The workspace directory where any outputs may be saved to.
* @param res The EstimationResult object created by the Estimation Manager,
* which is required for performing database caching of execution
* results.
* @param daoFact The DAOFactory object, which is used to instantiate the
* required DAO for interacting with the database.
* @throws Exception if initialisation fails.
*/
@Override
public void init(ObjectiveFunctionConfig of, AModel m,
Map<String, List<AttributeType>> params,
IPriceCalculator priceCalc, IPenaltyCalculator penaltyCalc,
String ws, EstimationResult res, DAOFactory daoFact) throws Exception
{
throw new UnsupportedOperationException("Overloaded init method for the objective function not implemented");
}
/**
* Extract the configuration parameters in the ObjectiveFunctionConfig object
* given in the init() method call.
*/
private void extractConfigParameters()
{
if (objFuncDB.getAttrs() != null && !objFuncDB.getAttrs().isEmpty())
{
for (AttributeType attrib : objFuncDB.getAttrs())
{
if (attrib.getName().equalsIgnoreCase("markup"))
{
try {
markup = Double.parseDouble(attrib.getExactValue().getVal());
System.out.println("[ObjectiveFunction] extracted the configuration parameter 'markup' with the value: " + markup);
} catch (Exception ex) {
log.debug("Found a config attribute with the name markup, but could not parse the value to a double: " + attrib.getExactValue().getVal());
}
}
}
}
}
/**
* Extract the ASLA parameters from the map. In this case, the method searches
* for an attribute with the name 'reliability'.
* @param parameters ASLA parameters.
*/
private void extractASLAParameters (Map<String, List<AttributeType>> parameters)
{
boolean found = false;
List<AttributeType> attribSet = null;
if ( (parameters == null) || parameters.isEmpty())
{
System.out.println("[ObjectiveFunction] no ASLA parameters given - using default values.");
log.debug("No ASLA parameters given - using default values.");
}
System.out.println("[ObjectiveFunction] extracting requested reliability from ASLA parameters");
log.debug("Extracting requested reliability from ASLA parameters");
found = false;
for (Entry<String, List<AttributeType>> entry : parameters.entrySet())
{
attribSet = entry.getValue();
for (AttributeType attribute : attribSet)
{
if (attribute.getName().equalsIgnoreCase("reliability"))
{
try {
requestedReliability = Double.parseDouble(attribute.getValues().get(0).getVal());
if (requestedReliability <= 1)
requestedReliability *= 100;
found = true;
break;
} catch (Exception e) {
log.error("Failed to extract the requested reliability from the ASLA parameters due to an exception: " + e.getMessage());
break;
}
}
}
}
if (found)
{
System.out.println("[ObjectiveFunction] requested reliability set to " + requestedReliability + "%");
log.debug("Requested reliability set to " + requestedReliability + "%");
}
else
{
System.out.println("[ObjectiveFunction] reliability not found - set to a default value of " + requestedReliability + "%");
log.debug("Reliability not found - set to a default value of " + requestedReliability + "%");
}
}
/**
* Resets the iteration counter and sets the re-initialisation flag to true.
*/
@Override
public void reInitialise()
{
iterationCounter = 0;
reInitialised = true;
}
/**
* Set the objective function config object.
* @param of ObjectiveFunctionConfig object.
*/
@Override
public void setObjectiveFunctionConfig (ObjectiveFunctionConfig of)
{
this.objFuncDB = of;
}
/**
* Set the application model wrapper, which should be called when the
* objective function is evaluated.
* @param model AModel wrapper.
*/
@Override
public void setApplicationModel (AModel model)
{
this.appModel = model;
}
/**
* Set the ASLA parameters. Will call a method to extract the required
* value for the requested reliability.
* @param params ASLA parameter map.
*/
@Override
public void setASLAParameters(Map<String, List<AttributeType>> params) throws Exception
{
this.aslaParameters = params;
extractASLAParameters(aslaParameters);
}
/**
* Get the ASLA parameter map.
* @return ASLA parameter map.
*/
@Override
public Map<String, List<AttributeType>> getASLAParameters ()
{
return this.aslaParameters;
}
/**
* Set the price calculator.
* @param calc A price calculator class extending the IPriceCalculator interface.
*/
@Override
public void setPriceCalculator(IPriceCalculator calc)
{
this.priceCalculator = calc;
}
/**
* NOT USED does nothing
*/
@Override
public void setPenaltyCalculator(IPenaltyCalculator calc){}
/**
* Set the resource mapper.
* @param resMap resource mapper instance.
*/
@Override
public void setResourceMapper(IResourceMapper resMap)
{
this.resourceMapper = resMap;
}
/**
* Set the work space directory where the objective function can perform file I/O.
* @param ws A String specifying the path to the workspace directory.
*/
@Override
public void setWorkspace(String ws)
{
this.workspace = new File (ws);
}
/**
* Get the application model wrapper.
* @return application model wrapper.
*/
@Override
public AModel getApplicationModel ()
{
return this.appModel;
}
/**
* Return the resource mapper instance.
* @return Resource mapper instance.
*/
@Override
public IResourceMapper getResourceMapper ()
{
return this.resourceMapper;
}
/**
* Return the price calculator instance.
* @return price calculator instance.
*/
@Override
public IPriceCalculator getPriceCalculator ()
{
return this.priceCalculator;
}
/**
* NOT USED always return null
* @return penalty calculator instance
*/
@Override
public IPenaltyCalculator getPenaltyCalculator ()
{
return null;
}
/**
* Return the objective function configuration instance.
* @return ObjectiveFunctionConfig instance.
*/
@Override
public ObjectiveFunctionConfig getObjectiveFunctionConfig()
{
return this.objFuncDB;
}
/**
* Return the workspace file path (absolute).
* @return workspace file path (null if not setup).
*/
@Override
public String getWorkspace()
{
if (workspace == null)
return null;
else
return this.workspace.getAbsolutePath();
}
/**
* Return the current number of objectives.
* @return The number of objectives.
*/
@Override
public int getNumObjectives ()
{
return this.numObjectives;
}
/**
* Return the current number of evaluations.
* @return number of evaluations.
*/
@Override
public int getNumFunctionEvaluations ()
{
return this.iterationCounter;
}
/**
* Checks that the objective function has been initialised and that the components
* called in this sample class are set: price calulator, resource mapper and
* application model wrapper. Also calls on the model wrapper's isValid() method.
* @return true if all valid. Otherwise, false.
*/
@Override
public boolean isValid()
{
boolean returnVal = true;
if (!initialised)
{
System.out.println("[ObjectiveFunction.isValid()] ERROR: not initialised!");
log.debug("[ObjectiveFunction.isValid()] ERROR: not initialised!");
returnVal = false;
}
if (priceCalculator == null)
{
System.out.println("[ObjectiveFunction.isValid()] ERROR: priceCalculator == NULL");
log.debug("[ObjectiveFunction.isValid()] ERROR: priceCalculator == NULL");
returnVal = false;
}
if (resourceMapper == null)
{
System.out.println("[ObjectiveFunction.isValid()] ERROR: resourceMapper == NULL");
log.debug("[ObjectiveFunction.isValid()] ERROR: resourceMapper == NULL");
returnVal = false;
}
if (!appModel.isValid())
{
System.out.println("[ObjectiveFunction.isValid()] ERROR: appModel.isValid() returned FALSE");
log.debug("[ObjectiveFunction.isValid()] ERROR: appModel.isValid() returned FALSE");
returnVal = false;
}
return returnVal;
}
/**
* Evaluate the parameter values chosen by an optimisation algorithm. Since
* these are numerical, the resource mapper should be used to get a resource
* map.
* @param params Numerical parameter values, corresponding to the chosen HW
* specifications defined in the resource mapper.
* @return The calculated fitness value(es) (corresponding to the number of objectives).
*/
@Override
public double[] evaluate(double[] params) throws Exception
{
System.out.println (" ObjFunc " + ++iterationCounter);
log.debug("\n\n*** ITERATION " + iterationCounter + " ***\n");
log.debug("Getting the resource map");
double [] roundedParams = optUtil.roundDoubleArray(params, numDecimalPlaces);
Map <String, Set<Resource>> resources = resourceMapper.getResourceMap(roundedParams);
return evaluate (resources);
}
/**
* Evaluate the parameter values chosen by an optimisation algorithm. Since
* these are numerical, the resource mapper should be used to get a resource
* map.
* @param params Numerical parameter values, corresponding to the chosen HW
* specifications defined in the resource mapper.
* @return The calculated fitness value(es) (corresponding to the number of objectives).
*/
@Override
public double[] evaluate(int[] params) throws Exception
{
System.out.println (" ObjFunc " + ++iterationCounter);
log.debug("\n\n*** ITERATION " + iterationCounter + " ***\n");
log.debug("Getting the resource map");
Map <String, Set<Resource>> resources = resourceMapper.getResourceMap(params);
return evaluate (resources);
}
/**
* This method performs the 'real' evaluation, which runs the
* application model, calculates infrastructure and customer cost, and, finally,
* the fitness that is returned to the optimisation algorithm.
* @param resources A map of HW resources.
* @return An array of doubles, corresponding to fitness values for each objective.
*/
@Override
public double[] evaluate (Map <String, Set<Resource>> resources) throws Exception
{
ObjectiveFunctionExecutionResult cachedResult = null;
double[] tmp = null;
ModelExecutionResult modelExecRes = null;
Double reliability, infrastructureCost, customerCost;
Set<AttributeType> outputs = null;
// check execution cache
if (!optUtil.disableDBCaching)
{
System.out.println(" Checking execution cache");
log.debug("Checking past objective function executions");
cachedResult = super.checkExecutionResult(objFuncDB, daoFactory, resources, null);
if (cachedResult != null)
{
log.debug("Past objective execution result found, start validating found execution cache ... ");
System.out.println(" Found a cached result, now validating it");
tmp = objFuncUtil.validateExecutionCache(cachedResult, numObjectives);
if(tmp != null)
{
fitness = tmp;
System.out.println(" Cached result valid, returning fitness to the optimisation algorithm");
System.out.println(" Fitness: " + fitness[0]);
log.debug("Cached result valid, returning fitness to the optimisation algorithm");
log.debug("Fitness = " + fitness[0]);
return fitness;
}
else
{
log.debug("Found execution result is not valid, starting executing model anyway ...");
System.out.println(" Unable to extract the fitness value(s) from the cached result object");
}
}
else
{
log.debug("No past objective execution result found");
System.out.println(" No cached result found");
}
log.debug ("Did not find any cached execution result - executing model instead");
System.out.println(" Will proceed to execute model and calculate fitness");
} // end if (!optUtil.disableDBCaching)
log.debug("Setting up an output directory where the model can save output files");
String outputDir = objFuncUtil.setUpOutputDir(workspace, iterationCounter);
log.debug("Outputdirectory for saving execution data in: " + outputDir);
System.out.println(" Executing application model");
try {
modelExecRes = appModel.execute(resources, outputDir);
}
catch (Exception ex) {
log.error("Application model failed to execute, an exception was caught: " + ex.getMessage());
System.out.println("Application model execution threw an exception: " + ex.getMessage());
throw ex;
}
log.debug("Model execution completed!");
if (modelExecRes == null)
{
log.error("model execution result is null, cannot calculate fitness!");
throw new RuntimeException("The ModelExecutionResult object returned from executing the application was NULL. Cannot calculate fitness.");
}
log.debug("Model execution result obtained, start calculating ISONI costs ... ");
// extract the reliability from the model execution result object
reliability = Double.NaN;
try {
reliability = getModelReliability(modelExecRes);
if (!reliability.isNaN() && !reliability.isInfinite())
reliability = optUtil.roundDouble(reliability, numDecimalPlaces);
}
catch (Throwable t) {
throw new RuntimeException("Unable to get reliability from model execution result", t);
}
System.out.println(" Reliability: " + reliability);
log.debug(" Reliability: " + reliability);
// calculate infrastructure cost
infrastructureCost = Double.NaN;
try {
infrastructureCost = optUtil.roundDouble(priceCalculator.getPrice(resources),numDecimalPlaces);//optUtil.calculateCost(priceCalculator, resources);
}
catch (Exception e) {
System.out.println("[ObjectiveFunction.evaluate()] ERROR: exception caught when calculating the ISONI HW cost");
log.debug("[ObjectiveFunction.evaluate()] ERROR: exception caught when calculating the ISONI HW cost");
throw new RuntimeException("Exception caught when calculating the ISONI HW cost in the objective function: " + e.getMessage(), e);
}
System.out.println(" Infrastructure cost: " + infrastructureCost);
log.debug(" Infrastructure cost: " + infrastructureCost);
// calculate customer cost
customerCost = optUtil.roundDouble(infrastructureCost*1.1,numDecimalPlaces);
System.out.println(" Customer cost: " + customerCost);
log.debug(" Customer cost: " + customerCost);
// calculate fitness value(s)
log.debug("Calculating fitness");
fitness[0] = infrastructureCost;
fitness[0] += ASLAFitnessCompensation(fitness[0], reliability, requestedReliability);
fitness[0] = optUtil.roundDouble(fitness[0], numDecimalPlaces);
System.out.println(" Fitness: " + fitness[0]);
log.debug(" Fitness: " + fitness[0]);
// cache objective function execution result
if (!optUtil.disableDBCaching)
{
log.debug("Caching the execution result");
System.out.println(" Caching the execution result");
outputs = createOutputSet(fitness, infrastructureCost, customerCost);
super.saveExecutionResult(objFuncDB, estimationResult, daoFactory, resources, null, outputs, modelExecRes);
}
// return fitness value
return fitness;
}
/**
* A method that can be called to retrieve an ObjectiveFunctionExecutionResult
* containing the outputs from the objective function as per the evaluate method.
* This method is called by the Optimisation Manager if database caching is
* not enabled, so that the output parameters from the objective function for
* the optimal point can be retrieved.
* @param resources A map of HW resources.
* @param outputDir The output directory where file I/O can be performed.
* @return An ObjectiveFunctionExecutionResult instance.
*/
@Override
public ObjectiveFunctionExecutionResult getExecutionResult(Map<String, Set<Resource>> resources, String outputDir) throws Exception
{
ObjectiveFunctionExecutionResult objFuncRes = null;
ModelExecutionResult modelExecRes = null;
Double reliability, infrastructureCost, customerCost;
Set<AttributeType> outputs = null;
// check execution cache
if (!optUtil.disableDBCaching)
{
log.debug("Checking past objective function executions");
objFuncRes = super.checkExecutionResult(objFuncDB, daoFactory, resources, null);
if (objFuncRes != null)
{
log.debug("Past objective execution result found");
return objFuncRes;
}
else
{
log.debug("No past objective execution result found. Need to execute model.");
System.out.println(" No cached result found");
}
} // end if (!optUtil.disableDBCaching)
try {
modelExecRes = appModel.execute(resources, outputDir);
} catch (Throwable t) {
log.error("Application model failed to execute, an exception was caught: " + t.getMessage());
System.out.println("Application model execution threw an exception: " + t.getMessage());
throw new RuntimeException("Application model execution threw an exception: " + t.getMessage(), t);
}
log.debug("Model execution completed!");
if (modelExecRes == null)
{
log.error("model execution result is null, cannot calculate fitness!");
throw new RuntimeException("The ModelExecutionResult object returned from executing the application was NULL. Cannot calculate fitness.");
}
log.debug("Model execution result obtained, start calculating ISONI costs ... ");
// extract the reliability from the model execution result object
reliability = Double.NaN;
try {
reliability = getModelReliability(modelExecRes);
if (!reliability.isNaN() && !reliability.isInfinite())
reliability = optUtil.roundDouble(reliability, numDecimalPlaces);
}
catch (Throwable t) {
throw new RuntimeException("Unable to get reliability from model execution result", t);
}
System.out.println(" Reliability: " + reliability);
log.debug(" Reliability: " + reliability);
// calculate infrastructure cost
infrastructureCost = Double.NaN;
try {
infrastructureCost = optUtil.roundDouble(priceCalculator.getPrice(resources),numDecimalPlaces);//optUtil.calculateCost(priceCalculator, resources);
} catch (Exception e) {
System.out.println("[ObjectiveFunction.getExecutionResult()] ERROR: exception caught when calculating the ISONI HW cost");
log.debug("[ObjectiveFunction.getExecutionResult()] ERROR: exception caught when calculating the ISONI HW cost");
throw new RuntimeException("Exception caught when calculating the ISONI HW cost in the objective function: " + e.getMessage(), e);
}
System.out.println(" Infrastructure cost: " + infrastructureCost);
log.debug(" Infrastructure cost: " + infrastructureCost);
// calculate customer cost
customerCost = optUtil.roundDouble(infrastructureCost*1.1,numDecimalPlaces);
System.out.println(" Customer cost: " + customerCost);
log.debug(" Customer cost: " + customerCost);
// calculate fitness value(s)
log.debug("Calculating fitness");
fitness[0] = infrastructureCost;
fitness[0] += ASLAFitnessCompensation(fitness[0], reliability, requestedReliability);
// round value for fitness[0]
fitness[0] = optUtil.roundDouble( fitness[0], numDecimalPlaces );
System.out.println(" Fitness: " + fitness[0]);
log.debug(" Fitness: " + fitness[0]);
// cache objective function execution result
if (!optUtil.disableDBCaching)
{
log.debug("Caching the execution result");
System.out.println(" Caching the execution result");
}
outputs = createOutputSet(fitness, infrastructureCost, customerCost);
objFuncRes = super.saveExecutionResult(objFuncDB, estimationResult, daoFactory, resources, null, outputs, modelExecRes);
if (objFuncRes == null)
{
log.error("Failed to save the execution result");
throw new RuntimeException("Failed to save objective function execution result. Refer to error log for details.");
}
return objFuncRes;
}
/**
* Extract the reliability from the model output.
* @throws RuntimeException if reliability is not found.
*/
private Double getModelReliability (ModelExecutionResult res) throws Exception
{
try {
for (AttributeType attrib: res.getOutputs())
{
if (attrib.getName().equalsIgnoreCase("reliability"))
{
return Double.parseDouble(attrib.getValues().get(0).getVal());
}
}
} catch (Throwable t) {
log.error("Unable to find reliability parameter in the outputs from the model execution result due to an exception/error: " + t.getMessage());
throw new RuntimeException("Unable to find reliability parameter in the outputs from the model execution result due to an exception/error: " + t.getMessage(), t);
}
log.error("Unable to find reliability parameter in the outputs from the model execution result");
throw new RuntimeException("Unable to find reliability parameter in the outputs from the model execution result");
}
/**
* If the requested reliability is not met, this method will penalise the
* fitness value proportionally.
* @param fitness The fitness value.
* @param reliability The calculated/simulated reliability.
* @param requestedReliability The requested reliability from the ASLA.
* @return A modified fitness value if the QoS is not met.
*/
public double ASLAFitnessCompensation (double fitness, double reliability, double requestedReliability)
{
if (reliability >= requestedReliability)
return 0;
return fitness * 10 * (requestedReliability - reliability) * 0.01;
}
/**
* Create a Set of AttributeTypes of the evaluation results (fitness, cost, penalty).
* @param fitness should not be null.
* @param infrastructureCost should be Double.NaN if not set.
* @param customerCost should be Double.NaN if not set.
* @return A Set of AttributeType objects, which is required to cache the result in the DB.
*/
public Set<AttributeType> createOutputSet(double[] fitness, Double infrastructureCost, Double customerCost)
{
Set<AttributeType> outputs = new HashSet<AttributeType>();
AttributeType fitnessAttr = null;
AttributeType isoniCostAttr = null;
AttributeType attr = null;
if (fitness != null)
{
fitnessAttr = new AttributeType();
fitnessAttr.setName("fitness");
fitnessAttr.setType(BasicType.convert("double"));
for (int i = 0; i < fitness.length; i++)
fitnessAttr.addAValue(new ValueType(String.valueOf(fitness[i]), MetricType.DEFAULT));
outputs.add(fitnessAttr);
}
if ((infrastructureCost != null) && !infrastructureCost.isNaN())
{
isoniCostAttr = new AttributeType();
isoniCostAttr.setName("infrastructure_cost");
isoniCostAttr.setType(BasicType.convert("double"));
isoniCostAttr.addAValue(new ValueType(String.valueOf(infrastructureCost), MetricType.DEFAULT));
outputs.add(isoniCostAttr);
}
if ((customerCost != null) && !customerCost.isNaN())
{
attr = new AttributeType();
attr.setName("customer_cost");
attr.setType(BasicType.convert("double"));
attr.addAValue(new ValueType(String.valueOf(customerCost), MetricType.DEFAULT));
outputs.add(attr);
}
return outputs;
}
} // SampleObjectiveFunction