Commit 39794ede authored by Dmitry Bagaev's avatar Dmitry Bagaev
Browse files

multiple parameters update support

parent a694e31f
set(SOURCE ${SOURCE}
${CMAKE_CURRENT_SOURCE_DIR}/static_sin.cpp
${CMAKE_CURRENT_SOURCE_DIR}/static_sin_r2.cpp
${CMAKE_CURRENT_SOURCE_DIR}/dynamic_x2.cpp)
set(HEADER ${HEADER}
${CMAKE_CURRENT_SOURCE_DIR}/dynamic_function.h
${CMAKE_CURRENT_SOURCE_DIR}/static_sin.h
${CMAKE_CURRENT_SOURCE_DIR}/static_sin_r2.h
${CMAKE_CURRENT_SOURCE_DIR}/dynamic_x2.h)
set(HEADER ${HEADER} PARENT_SCOPE)
......
......@@ -6,31 +6,37 @@
#include <cmath>
DynamicX2::DynamicX2() : distribution(-0.01, 0.01) {}
double DynamicX2::invoke(double x, double y, int iteration) const noexcept {
double xm = GetMinimumPoint(iteration).first;
double f = 0.0;
if (x <= xm) {
double a = 10.0 / (xm * xm);
double b = -20.0 / xm;
double c = 10.0;
return a * x * x + b * x + c;
f = a * x * x + b * x + c;
} else {
double a = 10.0 / (xm * xm - 8.0 * xm + 16);
double b = -2.0 * a * xm;
double c = b * b / (4.0 * a);
return a * x * x + b * x + c;
f = a * x * x + b * x + c;
}
return f + 1 + 2 * distribution(generator);
}
double DynamicX2::GetMinimumValue(int iteration) const noexcept {
return 0.0;
return 1.0;
}
std::pair<double, double> DynamicX2::GetMinimumPoint(int iteration) const noexcept {
return std::make_pair(2 + std::sin(iteration / 100.0), 0.0);
return std::make_pair(2 + std::sin(iteration / 250.0), 0.0);
}
std::pair<double, double> DynamicX2::GetXRange() const noexcept {
......
......@@ -5,11 +5,16 @@
#ifndef INMOST_DYNAMIC_X2_H
#define INMOST_DYNAMIC_X2_H
#include "dynamic_function.h"
#include <random>
class DynamicX2 : public DynamicFunction {
private:
mutable std::mt19937 generator;
mutable std::uniform_real_distribution<> distribution;
public:
DynamicX2();
double invoke(double x, double y, int iteration) const noexcept override;
double GetMinimumValue(int iteration) const noexcept override;
......
......@@ -3,3 +3,25 @@
//
#include "static_sin_r2.h"
#include <cmath>
double StaticSinR2::invoke(double x, double y, int iteration) const noexcept {
return -1.0 * std::sin(x) * std::cos(y) + 1.0;
}
double StaticSinR2::GetMinimumValue(int iteration) const noexcept {
return 0;
}
std::pair<double, double> StaticSinR2::GetMinimumPoint(int iteration) const noexcept {
return std::make_pair(M_PI / 2.0, 0);
}
std::pair<double, double> StaticSinR2::GetXRange() const noexcept {
return std::make_pair(0, M_PI);
}
std::pair<double, double> StaticSinR2::GetYRange() const noexcept {
return std::make_pair(-M_PI / 2.0, M_PI / 2.0);
}
......@@ -6,8 +6,19 @@
#define INMOST_STATIC_SIN_R2_H
class static_sin_r2 {
#include "dynamic_function.h"
class StaticSinR2 : public DynamicFunction {
public:
double invoke(double x, double y, int iteration) const noexcept override;
double GetMinimumValue(int iteration) const noexcept override;
std::pair<double, double> GetMinimumPoint(int iteration) const noexcept override;
std::pair<double, double> GetXRange() const noexcept override;
std::pair<double, double> GetYRange() const noexcept override;
};
......
......@@ -2,6 +2,7 @@
#include <iostream>
#include <dynamic_function.h>
#include <static_sin.h>
#include <static_sin_r2.h>
#include <dynamic_x2.h>
#include <inmost_ttsp.h>
......@@ -29,7 +30,7 @@ int main(int argc, char **argv) {
std::string optimizer_type = "noop";
std::string function_type = "sin1d";
std::string out_file = "";
std::string out_file = "";
//Parse argv parameters
if (argc == 1) goto help_message;
......@@ -111,11 +112,14 @@ int main(int argc, char **argv) {
DynamicFunction *f = nullptr;
if (function_type == "sin1d") {
f = new StaticSin();
} else if (function_type == "sin2d") {
f = new StaticSinR2();
} else if (function_type == "x21d") {
f = new DynamicX2();
} else {
std::cout << "Available function types:" << std::endl;
std::cout << " sin1d - Static sin with x parameter only" << std::endl;
std::cout << " sin2d - Static sin with x and y parameters" << std::endl;
std::cout << " x21d - Dynamic x2 with x parameter only" << std::endl;
return 0;
}
......
......@@ -172,13 +172,13 @@ int main(int argc, char **argv) {
if (rank == 0) std::cout << "Solving with " << solverName << std::endl;
TTSP::OptimizationParameter tau("tau", std::make_pair(-3, -0.1), 0.05, -2, TTSP::OptimizationParameterType::PARAMETER_TYPE_EXPONENT);
//TTSP::OptimizationParameter q("q", {0, 1, 2, 3, 4}, 2);
TTSP::OptimizationParameter q("q", {0, 1, 2, 3, 4}, 2);
//TTSP::OptimizationParameter eps("eps", {1e-7, 1e-6, 1e-5, 1e-4, 1e-3}, 1e-5);
TTSP::OptimizationParameterEntries entries;
//entries.emplace_back(std::make_pair(eps, eps.GetDefaultValue()));
entries.emplace_back(std::make_pair(tau, tau.GetDefaultValue()));
//entries.emplace_back(std::make_pair(q, q.GetDefaultValue()));
entries.emplace_back(std::make_pair(q, q.GetDefaultValue()));
TTSP::OptimizerProperties properties;
......
......@@ -33,6 +33,7 @@ namespace TTSP {
OptimizationParameterPoint(const std::string &name, double value, OptimizationParameterType type);
static void swap(OptimizationParameterPoint &left, OptimizationParameterPoint &right);
public:
OptimizationParameterPoint(const OptimizationParameterPoint &other);
......@@ -147,7 +148,30 @@ namespace TTSP {
/// @see OptimizationParametersEntry
typedef std::vector<OptimizationParametersEntry> OptimizationParameterEntries;
typedef std::pair<std::size_t, double> OptimizationAlgorithmSuggestion;
class SuggestionChangedParameter {
private:
std::size_t index;
double value;
static void swap(SuggestionChangedParameter &left, SuggestionChangedParameter &right);
public:
SuggestionChangedParameter(std::size_t index, double value);
SuggestionChangedParameter(const SuggestionChangedParameter &other);
SuggestionChangedParameter(SuggestionChangedParameter &&other);
SuggestionChangedParameter &operator=(const SuggestionChangedParameter &other);
std::size_t GetIndex() const noexcept;
double GetValue() const noexcept;
~SuggestionChangedParameter();
};
typedef std::vector<SuggestionChangedParameter> SuggestionChangedParameters;
/// This class is used to store a result of optimization iterations with suggested points and changed parameter
/// @see OptimizationParameter
......@@ -156,19 +180,16 @@ namespace TTSP {
/// @see OptimizationParameters
class OptimizationParametersSuggestion {
private:
std::size_t changed_index;
double changed_value;
SuggestionChangedParameters changed;
OptimizationParameterPoints before;
double metrics_before;
OptimizationParameterPoints after;
public:
OptimizationParametersSuggestion(std::size_t changed_index, double changed_value,
OptimizationParametersSuggestion(const SuggestionChangedParameters &changed,
const OptimizationParameterPoints &before, double metrics_before,
const OptimizationParameterPoints &after);
std::size_t GetChangedParameterIndex() const noexcept;
double GetChangedValue() const noexcept;
const SuggestionChangedParameters &GetChangedParameters() const noexcept;
const OptimizationParameterPoints &GetPointsBefore() const noexcept;
......@@ -225,7 +246,10 @@ namespace TTSP {
/// Getter for slice of parameters of this space with changed parameter
const OptimizationParameterPoints GetPointsWithChangedParameter(const OptimizationParameter &parameter, double value) const noexcept;
void Update(const std::vector<double> &update, double metrics);
/// Getter for slice of parameters of this space with many changed parameters
const OptimizationParameterPoints GetPointsWithChangedParameters(const SuggestionChangedParameters &changed) const noexcept;
void Update(const SuggestionChangedParameters &changed, double metrics);
void Update(std::size_t index, double value, double metrics);
};
......@@ -233,8 +257,7 @@ namespace TTSP {
/// This class is used to store timings result for some optimization parameter points
class OptimizationParameterResult {
private:
std::size_t changed_index; /// Changed optimization parameter index
double changed_value; /// New changed value for 'changed' parameter
SuggestionChangedParameters changed; /// Changed optimization parameters indices and values
OptimizationParameterPoints before; /// Optimization parameter points before changing
double metrics_before; /// Optimization metrics before changing
OptimizationParameterPoints after; /// Optimization parameter points after changing
......@@ -245,7 +268,7 @@ namespace TTSP {
public:
/// Default constructor to define an OptimizationParameterResult
OptimizationParameterResult(std::size_t changed_index, double changed_value,
OptimizationParameterResult(const SuggestionChangedParameters &changed,
const OptimizationParameterPoints &before, const OptimizationParameterPoints &after,
double metrics_before, double metrics_after, bool is_good);
......@@ -277,10 +300,7 @@ namespace TTSP {
bool IsGood() const noexcept;
/// Getter for changed parameter
std::size_t GetChangedParameterIndex() const noexcept;
/// Getter for new changed value
double GetChangedValue() const noexcept;
const SuggestionChangedParameters& GetChangedParameters() const noexcept;
};
/// This class is used to store last N solve results and used parameters on it
......@@ -378,9 +398,9 @@ namespace TTSP {
virtual bool UpdateSpaceWithLatestResults();
virtual OptimizationAlgorithmSuggestion AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const = 0;
virtual SuggestionChangedParameters AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const = 0;
public:
OptimizerInterface(const std::string &name, const OptimizationParameters &parameters, const OptimizerProperties &properties, std::size_t buffer_capacity) :
......@@ -397,11 +417,11 @@ namespace TTSP {
return std::make_pair(false, 0);
}, void *data = nullptr);
void SaveResult(std::size_t changed_index, double changed_value,
void SaveResult(const SuggestionChangedParameters &changed,
const OptimizationParameterPoints &before, double metrics_before,
const OptimizationParameterPoints &after, double metrics_after, bool is_good);
void SaveResult(std::size_t changed_index, double changed_value, const OptimizationParameterPoints &after, double metrics_after, bool is_good);
void SaveResult(const SuggestionChangedParameters &changed, const OptimizationParameterPoints &after, double metrics_after, bool is_good);
void SaveResult(const OptimizationParametersSuggestion &suggestion, double metrics, bool is_good);
......
......@@ -87,11 +87,11 @@ namespace TTSP {
});
}
OptimizationAlgorithmSuggestion AlternatingOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
SuggestionChangedParameters AlternatingOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
const AlternatingParameterHandler &handler = handlers.at(current_handler_index);
return std::make_pair(current_handler_index, handler.GetParameter().GetValues().at(handler.NextIndex()));
return std::vector<SuggestionChangedParameter>{SuggestionChangedParameter(current_handler_index, handler.GetParameter().GetValues().at(handler.NextIndex()))};
}
bool AlternatingOptimizer::UpdateSpaceWithLatestResults() {
......
......@@ -45,9 +45,9 @@ namespace TTSP {
protected:
bool UpdateSpaceWithLatestResults() override;
OptimizationAlgorithmSuggestion AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const override;
SuggestionChangedParameters AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const override;
public:
AlternatingOptimizer(const std::string &name, const OptimizationParameters &space, const OptimizerProperties &properties, std::size_t buffer_capacity);
......
......@@ -212,10 +212,10 @@ namespace TTSP {
});
}
OptimizationAlgorithmSuggestion AnnealingOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
return std::make_pair(current_handler_index, handlers.at(current_handler_index).GetNextValue());
SuggestionChangedParameters AnnealingOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
return std::vector<SuggestionChangedParameter>{SuggestionChangedParameter(current_handler_index, handlers.at(current_handler_index).GetNextValue())};
}
bool AnnealingOptimizer::UpdateSpaceWithLatestResults() {
......@@ -230,7 +230,7 @@ namespace TTSP {
bool is_updated = false;
if (last.IsGood() && (last.GetMetricsBefore() < 0.0 || ((delta_e < 0.0) || alpha < et))) {
double update_value = last.GetChangedValue();
double update_value = last.GetChangedParameters().at(0).GetValue();
h.SetValue(update_value);
parameters.Update(current_handler_index, update_value, last.GetMetricsAfter());
is_updated = true;
......
......@@ -80,9 +80,9 @@ namespace TTSP {
protected:
bool UpdateSpaceWithLatestResults() override;
OptimizationAlgorithmSuggestion AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const override;
SuggestionChangedParameters AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const override;
public:
AnnealingOptimizer(const std::string &name, const OptimizationParameters &space, const OptimizerProperties &properties, std::size_t buffer_capacity);
......
......@@ -91,39 +91,56 @@ namespace TTSP {
}
OptimizationAlgorithmSuggestion BayesianOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
SuggestionChangedParameters BayesianOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
auto unique = results.GetLastUniqueEntries(unique_points_max_count);
auto unique = results.GetLastUniqueEntries(unique_points_max_count);
auto entries = parameters.GetParameterEntries();
std::vector<SuggestionChangedParameter> changed_parameters;
if (unique.size() == 0) {
return std::make_pair(0, parameters.GetParameter(0).GetDefaultValue());
std::size_t index = 0;
std::for_each(entries.cbegin(), entries.cend(), [&index, &changed_parameters](const OptimizationParametersEntry &entry) {
changed_parameters.emplace_back(SuggestionChangedParameter(index++, entry.first.GetDefaultValue()));
});
return changed_parameters;
} else if (unique.size() < initial_iterations_count) {
// TODO Make for all
auto parameter = parameters.GetParameter(0);
std::size_t index = 0;
std::for_each(entries.cbegin(), entries.cend(), [&index, &changed_parameters, this](const OptimizationParametersEntry &entry) {
auto parameter = entry.first;
double min_bound = parameter.GetMinimalValue();
double max_bound = parameter.GetMaximumValue();
double min_bound = parameter.GetMinimalValue();
double max_bound = parameter.GetMaximumValue();
double r = (random.next() - 0.5) * (max_bound - min_bound) * initial_iterations_radius;
double r = (random.next() - 0.5) * (max_bound - min_bound) * initial_iterations_radius;
double next = parameters.GetParameterEntry(0).second + r;
double next = entry.second + r;
while (next < min_bound || next > max_bound) {
r = (random.next() - 0.5) * (max_bound - min_bound) * initial_iterations_radius;
next = parameters.GetParameterEntry(0).second + r;
}
while (next < min_bound || next > max_bound) {
r = (random.next() - 0.5) * (max_bound - min_bound) * initial_iterations_radius;
next = entry.second + r;
}
changed_parameters.emplace_back(SuggestionChangedParameter(index++, next));
});
return std::make_pair(0, parameters.GetParameterEntry(0).second + r);
return changed_parameters;
}
std::random_shuffle(unique.begin() + 1, unique.end(), random);
struct Params {
struct kernel : public limbo::defaults::kernel {
struct kernel {
BO_PARAM(double, noise, 0.02);
BO_PARAM(bool, optimize_noise, false);
};
struct kernel_squared_exp_ard : public limbo::defaults::kernel_squared_exp_ard {
};
struct opt_rprop : public limbo::defaults::opt_rprop {
......@@ -143,23 +160,10 @@ namespace TTSP {
using GP2_t = limbo::model::GP<Params, Kernel2_t, Mean_t, limbo::model::gp::KernelMeanLFOpt<Params>>;
GP2_t gp_ard;
// do not forget to call the optimization!
std::vector<Eigen::VectorXd> samples;
std::vector<Eigen::VectorXd> observations;
// std::cout << "Used: [ ";
// double min_unique = (*std::min_element(unique.cbegin(), unique.cbegin() + std::min(static_cast<std::size_t>(unique_points_random_count), unique.size()), []
// (const OptimizationParameterResult &l, const OptimizationParameterResult &r) {
// return l.GetMetricsAfter() < r.GetMetricsAfter();
// })).GetMetricsAfter();
//
// double max_unique = (*std::max_element(unique.cbegin(), unique.cbegin() + std::min(static_cast<std::size_t>(unique_points_random_count), unique.size()), []
// (const OptimizationParameterResult &l, const OptimizationParameterResult &r) {
// return l.GetMetricsAfter() < r.GetMetricsAfter();
// })).GetMetricsAfter();
std::for_each(unique.cbegin(), unique.cbegin() + std::min(static_cast<std::size_t>(unique_points_random_count), unique.size()), [this, &samples, &observations]
(const OptimizationParameterResult &result) {
Eigen::VectorXd sample(parameters.Size());
......@@ -175,8 +179,6 @@ namespace TTSP {
sample(i) = normalized;
// std::cout << sample(i) << " ";
i += 1;
});
......@@ -184,8 +186,6 @@ namespace TTSP {
observations.push_back(limbo::tools::make_vector(-1.0 * result.GetMetricsAfter()));
});
// std::cout << "]" << std::endl;
double min_observation = (*std::min_element(observations.cbegin(), observations.cend(), [](const Eigen::VectorXd &l, const Eigen::VectorXd &r) {
return l(0) < r(0);
}))(0);
......@@ -198,15 +198,6 @@ namespace TTSP {
return limbo::tools::make_vector((ob(0) - min_observation) / ((10.0 / 6.0) * (max_observation - min_observation)) + 0.2); // Normalize here to [ 0.2, 0.8 ]
});
// std::cout << "Obse: [ ";
//
// std::for_each(observations.cbegin(), observations.cend(), [](const Eigen::VectorXd &ob) {
// std::cout << ob(0) << " ";
// });
//
// std::cout << " ]" << std::endl;
gp_ard.compute(samples, observations);
gp_ard.optimize_hyperparams();
......@@ -247,10 +238,10 @@ namespace TTSP {
new_sample(k) = starting_point(k) + barrier * (new_sample(k) - starting_point(k));
}
new_sample(k) = (new_sample(k) * (max_bound - min_bound)) + min_bound;
changed_parameters.emplace_back(SuggestionChangedParameter(k, (new_sample(k) * (max_bound - min_bound)) + min_bound));
}
return std::make_pair(0, new_sample(0));
return changed_parameters;
}
BayesianOptimizer::~BayesianOptimizer() {}
......
......@@ -40,9 +40,9 @@ namespace TTSP {
mutable BayesianUniformDistribution random;
protected:
OptimizationAlgorithmSuggestion AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const override;
SuggestionChangedParameters AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const override;
public:
BayesianOptimizer(const std::string &name, const OptimizationParameters &space, const OptimizerProperties &properties, std::size_t buffer_capacity);
......
......@@ -10,9 +10,9 @@ namespace TTSP {
BruteforceOptimizer::BruteforceOptimizer(const std::string &name, const OptimizationParameters &space, const OptimizerProperties &properties, std::size_t buffer_capacity) :
OptimizerInterface(name, space, properties, buffer_capacity), current_index(0) {}
OptimizationAlgorithmSuggestion BruteforceOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
SuggestionChangedParameters BruteforceOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
const OptimizationParameterPoints &before = parameters.GetPoints();
const OptimizationParameter &parameter = parameters.GetParameter(current_index);
......@@ -37,7 +37,7 @@ namespace TTSP {
std::cout << "| Metrics = " << metrics << "\t" << is_solved << std::endl;
});
return std::make_pair(current_index, best_value);
return std::vector<SuggestionChangedParameter>{SuggestionChangedParameter(current_index, best_value)};
}
bool BruteforceOptimizer::UpdateSpaceWithLatestResults() {
......
......@@ -15,9 +15,9 @@ namespace TTSP {
protected:
bool UpdateSpaceWithLatestResults() override;
OptimizationAlgorithmSuggestion AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const override;
SuggestionChangedParameters AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const override;
public:
BruteforceOptimizer(const std::string &name, const OptimizationParameters &space, const OptimizerProperties &properties, std::size_t buffer_capacity);
......
......@@ -9,10 +9,10 @@ namespace TTSP {
NoopOptimizer::NoopOptimizer(const std::string &name, const OptimizationParameters &space, const OptimizerProperties &properties, std::size_t buffer_capacity) :
OptimizerInterface(name, space, properties, buffer_capacity) {}
OptimizationAlgorithmSuggestion NoopOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
return std::make_pair(0, parameters.GetParameter(0).GetDefaultValue());
SuggestionChangedParameters NoopOptimizer::AlgorithmMakeSuggestion(const std::function<OptimizationFunctionInvokeResult(const OptimizationParameterPoints &,
const OptimizationParameterPoints &,
void *)> &invoke, void *data) const {
return std::vector<SuggestionChangedParameter>{SuggestionChangedParameter(0, parameters.GetParameter(0).GetDefaultValue())};
}