#region Namespaces
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
#endregion
namespace ScriptCode
{
/// <summary>
/// Optimization algorithm scripts are used to select the script parameter values to be used in the next optimization runs.
/// </summary>
public partial class MyOptimizationAlgorithm : OptimizationAlgorithmScriptBase // NEVER CHANGE THE CLASS NAME
{
#region Variables
// The current pass number.
private int _currentPass;
// The number of times a group of optimization vectors are selected.
private int _numberOfPasses;
// The number of optimization vectors selected at each pass.
private int _numberOfRunsPerPass;
// The score of the best vector so far.
private double _bestVectorScore;
// The index of the best vector so far.
private int _bestVectorIndex;
// Use for a random number generator.
private Random _random;
#endregion
#region OnInitialize
/// <summary>
/// This function is used for accepting the script parameters and for initializing the script prior to all other function calls.
/// Once the script is assigned to a desktop, its parameter values can be specified by the user.
/// </summary>
/// --------------------------------------------------------------------------------------------------
/// PLEASE USE THE SCRIPT WIZARD (CTRL+W) TO ADD, EDIT AND REMOVE THE SCRIPT PARAMETERS
/// --------------------------------------------------------------------------------------------------
/// YOU MUST SET A PARAM TAG FOR EACH PARAMETER ACCEPTED BY THIS FUNCTION.
/// ALL PARAM TAGS SHOULD BE SET IN THE 'OnInitialize' REGION, RIGHT ABOVE THE 'OnInitialize' FUNCTION.
/// THE ORDER OF THE TAGS MUST MATCH THE ORDER OF THE ACTUAL PARAMETERS.
/// REQUIRED ATTRIBUTES:
/// (1) name: The exact parameter name.
/// (2) type: The type of data to collect from the user:
/// Set to "Integer" when the data type is 'int'
/// Set to "IntegerArray" when the data type is 'int[]'
/// Set to "DateTime" when the data type is 'long'
/// Set to "DateTimeArray" when the data type is 'long[]'
/// Set to "Boolean" when the data type is 'bool'
/// Set to "BooleanArray" when the data type is 'bool[]'
/// Set to "Double" when the data type is 'double'
/// Set to "DoubleArray" when the data type is 'double[]'
/// Set to "String" when the data type is 'string'
/// Set to "StringArray" when the data type is 'string[]'
/// OPTIONAL ATTRIBUTES:
/// (3) default: The default parameter value is only valid when the type is Integer, Boolean, Double, String or an API Type.
/// (4) min: The minimum parameter value is only valid when the type is Integer or Double.
/// (5) max: The maximum parameter value is only valid when the type is Integer or Double.
/// EXAMPLE: <param name="" type="" default="" min="" max="">Enter the parameter description here.</param>
/// --------------------------------------------------------------------------------------------------
/// <param name="numberOfPasses" type="Integer" default="10">The number of times a group of optimization vectors are selected.</param>
/// <param name="numberOfRunsPerPass" type="Integer" default="10">The number of optimization vectors selected at each pass.</param>
public void OnInitialize(
int numberOfPasses,
int numberOfRunsPerPass)
{
// Set the number of passes.
_numberOfPasses = numberOfPasses;
// Set the number of runs per pass.
_numberOfRunsPerPass = numberOfRunsPerPass;
// Create for generating random numbers.
_random = new Random();
// Calculate the current pass.
_currentPass = (int)(((double) OptimizationProcessedVectorsCount()) / numberOfRunsPerPass);
// Pick the best vector randomly.
_bestVectorIndex = _random.Next(0, OptimizationVectorCount());
// Set a really negative score for the random best vector.
_bestVectorScore = int.MinValue;
}
#endregion
#region OnSelectNextOptimizationVectors
/// <summary>
/// This function is called in order to select the next optimization vectors to be processed.
/// The function may be called multiple times in a row before the OnUpdateOptimizationVector function is called.
/// </summary>
/// <returns type="IntegerArray">The indexes of the next optimization vectors to process.</returns>
public override int[] OnSelectNextOptimizationVectors()
{
// Get the vector count.
int vectorCount = OptimizationVectorCount();
// Get the best vector so far.
double[] bestVectorValues = OptimizationVectorValues(_bestVectorIndex);
// Iterate over the optimization vectors while measuring their distance from the best vector so far.
for (int i = 0; i < vectorCount; i++) {
// Get the vector values for the current vector.
double[] currentValues = OptimizationVectorValues(i);
// The vector distance.
double distance = 0;
// Iterate over the best vector values.
for (int j = 0; j < bestVectorValues.Length; j++) {
// Calculate the distance between the two values in steps.
double delta = Math.Abs(currentValues[j] - bestVectorValues[j]) / OptimizationParameterStep(j);
// Increase the step distance.
distance += delta;
}
// Set the distance from the best vector.
OptimizationSetSortValue(i, distance);
}
// Get the vector indexes sorted by their distance from the best vector.
int[] sortedVectorIndexes = OptimizationSortVectors();
// Use for counting the number of attempts.
int maxAttempts = 0;
// Create for holding whether vectors already exists.
Dictionary<int, bool> exists = new Dictionary<int, bool>();
// Create for holding the vector for the current pass.
List<int> vectors = new List<int>();
// Calculate the max vector index from which to chose.
int maxVectorIndex = Math.Max(vectorCount - (int)(((double) vectorCount / _numberOfPasses) * _currentPass) - 1, 0);
// Iterate until enough vectors have been selected.
while (vectors.Count < _numberOfRunsPerPass && maxAttempts < _numberOfRunsPerPass * 10) {
// Get the random vector index.
int randomVectorIndex = _random.Next(0, maxVectorIndex + 1);
// Check whether the optimization vector hasn't been processed.
if (!OptimizationVectorIsProcessed(sortedVectorIndexes[randomVectorIndex]) && !exists.ContainsKey(randomVectorIndex)) {
// Set the vector to be run.
vectors.Add(sortedVectorIndexes[randomVectorIndex]);
// Set the vector index as already existing in the list.
exists.Add(randomVectorIndex, true);
}
// Increase the max attempts.
maxAttempts++;
}
// Iterate until enough vectors have been selected.
while (vectors.Count < _numberOfRunsPerPass && maxAttempts < _numberOfRunsPerPass * 50) {
// Select a vector from all of the vectors.
int randomVectorIndex = _random.Next(0, vectorCount);
// Check whether the optimization vector hasn't been processed.
if (!OptimizationVectorIsProcessed(sortedVectorIndexes[randomVectorIndex]) && !exists.ContainsKey(randomVectorIndex)) {
// Set the vector to be run.
vectors.Add(sortedVectorIndexes[randomVectorIndex]);
// Set the vector index as already existing in the list.
exists.Add(randomVectorIndex, true);
}
// Increase the max attempts.
maxAttempts++;
}
// Increase the current pass index.
_currentPass++;
return vectors.ToArray();
}
#endregion
#region OnGetMaxVectors
/// <summary>
/// This function is called to get the number of optimization vectors that the algorithm will
/// select and run if the optimization process runs to completion.
/// </summary>
/// <returns type="Integer">The maximum number of optimization vectors to be run.</returns>
public override int OnGetMaxVectors()
{
// Calculate the maximum number of vectors to calculate.
int maxVectors = _numberOfPasses * _numberOfRunsPerPass;
// Check whether the number of vectors to run is less than the number of existing vectors.
if (maxVectors <= OptimizationVectorCount())
return maxVectors;
else return OptimizationVectorCount();
}
#endregion
#region OnUpdateOptimizationVector
/// <summary>
/// This function is called to notify the optimization algorithm that a vector has been processed.
/// </summary>
/// <param name="vectorIndex" type="Integer">The vector index of the optimization vector that has been processed</param>
public override void OnUpdateOptimizationVector(int vectorIndex)
{
// Check whether the specified vector is better than the best vector so far.
if (OptimizationVectorScore(vectorIndex) > _bestVectorScore) {
// Keep the score of the best vector so far.
_bestVectorScore = OptimizationVectorScore(vectorIndex);
// Keep the index of th best vector so far.
_bestVectorIndex = vectorIndex;
}
}
#endregion
#region OnShutdown
/// <summary>
/// This function is called when the script is shutdown.
/// </summary>
public override void OnShutdown()
{
// OnShutdown Content
}
#endregion
}
}