Package uk.ac.soton.itinnovation.pes.optimiser.test

Source Code of uk.ac.soton.itinnovation.pes.optimiser.test.SampleObjectiveFunction

/////////////////////////////////////////////////////////////////////////
//
// © 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
TOP

Related Classes of uk.ac.soton.itinnovation.pes.optimiser.test.SampleObjectiveFunction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.