В моем приложении C# мне нужно запустить алгоритм математической оптимизации, где управляющие значения влияют на состояние системы. и косвенно изменяет измеренные (целевые) значения после обновления состояния. Например, может существовать 3 (или более) контрольных значения, изменение которых влияет на 3 (или более) целевых значения. Любое изменение даже одного контрольного значения может изменить значения всех трех целевых значений, и их взаимосвязь неизвестна.
Цель алгоритма — найти все минимумы, при которых элементы управления устанавливаются на значения (при этом оставаясь в установленных пределах), которые приносят целевые значения в пределах желаемой погрешности. Позже другой код сравнит их и определит глобальные минимумы. В других случаях, когда известно, что может существовать только 1 минимум, оптимизатор должен завершить работу, как только он обнаружит этот минимум (не искать дополнительные минимумы). Оптимизация должна выполняться за как можно меньшее количество циклов, поскольку изменение состояния системы и проведение измерений требуют очень больших вычислительных ресурсов.
Кроме того, мне нужен доступ к данным «угаданий» оптимизатора. , поэтому его можно повторно использовать для повторных вычислений, поскольку система может измениться очень незначительно, а повторное использование частично подходящих данных из предыдущих запусков может значительно ускорить процесс.
Проблема в том, что я не могу найти алгоритм непрерывной математической оптимизации или библиотеку C#, которую можно было бы адаптировать для использования таким образом.
Это скелетный код оптимизатора и тестер, демонстрирующий, как он предназначен для использования. Пустые функции оптимизатора — это то место, куда я хочу подключить алгоритм или библиотеку.
Код: Выделить всё
public class Optimizer
{
public List Controls { get; init; } = new();
public List Targets { get; init; } = new();
public List Minimas { get; init; } = new();
public OptimizerData Data { get; init; } = new();
public void Optimize()
{
//1. Make Controls values guess and assign OptimizedValue value for each object in Controls list
//2. Save Controls and Targets values combination to Data
//2. If a minima is found - add it to the list of Minimas
}
public bool AllMinimaFound()
{
//returns true when there are likely no more minima to be found - used for terminating the optimizer
}
public class Control
{
public string Name { get; init; }
public double OptimizedValue { get; set; }
public double MinBound { get; init; }
public double MaxBound { get; init; }
public Control(string name, double minBound, double maxBound)
{
Name = name;
MinBound = minBound;
MaxBound = maxBound;
}
}
public class Target
{
public string Name { get; init; }
public double MeasuredValue { get; set; }
public double TargetValue { get; init; }
public double ErrorMargin { get; init; }
public Target(string name, double target, double errorMargin)
{
Name = name;
TargetValue = target;
ErrorMargin = errorMargin;
}
public bool IsWithinMargin()
{
if (Math.Abs(MeasuredValue - TargetValue) < ErrorMargin) { return true; }
return false;
}
}
public class Minima
{
public Dictionary ControlNamesAndValues { get; init; } = new(); // Stores the name and value of each Control for this Minima
}
public class OptimizerData
{
private List DataPoints { get; init; } = new();
public void AddDataPoint(List controls, List targets)
{
DataPoints.Add(new(controls, targets));
}
public class OptimizerDataPoint
{
public Dictionary controlsNamesAndValues { get; init; } = new();
public Dictionary targetsNamesAndValues { get; init; } = new();
public OptimizerDataPoint(List controls, List targets)
{
foreach (Control control in controls) { controlsNamesAndValues.Add(control.Name, control.OptimizedValue); }
foreach (Target target in targets) { targetsNamesAndValues.Add(target.Name, target.MeasuredValue); }
}
}
}
}
public class OptimizerTester
{
public void OptimizeTest()
{
Optimizer optimizer = new();
optimizer.Controls.Add(new("Length", -5, 5));
optimizer.Controls.Add(new("Width", 10, 125));
optimizer.Controls.Add(new("Height", -7, 0));
optimizer.Targets.Add(new("Mass", 20, 0.01));
optimizer.Targets.Add(new("SurfaceArea", 32, 0.01));
optimizer.Targets.Add(new("BoundingBoxVolume", 150, 0.01));
//test 1 - find all minimas
while (!optimizer.AllMinimaFound())
{
optimizer.Optimize();
SetMeasuredTargetValues(optimizer.Targets);
}
//test2 - find first minima and terminate
while (optimizer.Minimas.Count < 1)
{
optimizer.Optimize();
SetMeasuredTargetValues(optimizer.Targets);
}
}
public void SetMeasuredTargetValues(List targets)
{
//external code - measures and sets MeasuredValue in each Target
}
}
Подробнее здесь: https://stackoverflow.com/questions/787 ... adaptation