minimize method

List<double> minimize(
  1. List<double> start,
  2. double f(
    1. List<double> x
    )
)

Implementation

List<double> minimize(List<double> start, double Function(List<double>) f) {
  final n = start.length;
  // simpleks başlat
  final simplex = <List<double>>[List<double>.from(start)];
  final step = 0.1;
  for (int i = 0; i < n; i++) {
    final v = List<double>.from(start);
    v[i] += (v[i].abs() > 1e-6 ? 0.05 * v[i].abs() : step);
    simplex.add(v);
  }

  List<double> centroid(List<List<double>> s, int except) {
    final c = List<double>.filled(n, 0.0);
    for (int i = 0; i < s.length; i++) {
      if (i == except) continue;
      for (int j = 0; j < n; j++) c[j] += s[i][j];
    }
    final denom = (s.length - 1).toDouble();
    for (int j = 0; j < n; j++) c[j] /= denom;
    return c;
  }

  List<double> op(List<double> a, List<double> b, double alpha) {
    final r = List<double>.filled(n, 0.0);
    for (int i = 0; i < n; i++) r[i] = a[i] + alpha * (b[i] - a[i]);
    return r;
  }

  var s = simplex;
  var vals = s.map(f).toList();

  for (int iter = 0; iter < maxIter; iter++) {
    // sırala
    final idx = List<int>.generate(s.length, (i) => i)
      ..sort((i, j) => vals[i].compareTo(vals[j]));
    s = [for (final i in idx) s[i]];
    vals = [for (final i in idx) vals[i]];

    // yakınlık kontrolü
    final vbest = vals.first, vworst = vals.last;
    if ((vworst - vbest).abs() < tol) break;

    final c = centroid(s, s.length - 1);
    final xr = op(c, s.last, 1.0); // yansıt
    final fr = f(xr);
    if (fr < vals[0]) {
      // genişlet
      final xe = op(c, s.last, 2.0);
      final fe = f(xe);
      if (fe < fr) {
        s[s.length - 1] = xe;
        vals[s.length - 1] = fe;
      } else {
        s[s.length - 1] = xr;
        vals[s.length - 1] = fr;
      }
    } else if (fr < vals[s.length - 2]) {
      s[s.length - 1] = xr;
      vals[s.length - 1] = fr;
    } else {
      // daralt veya sıkıştır
      final xc = op(c, s.last, 0.5);
      final fc = f(xc);
      if (fc < vals.last) {
        s[s.length - 1] = xc;
        vals[s.length - 1] = fc;
      } else {
        // tümünü sıkıştır
        for (int i = 1; i < s.length; i++) {
          for (int j = 0; j < n; j++) {
            s[i][j] = s[0][j] + 0.5 * (s[i][j] - s[0][j]);
          }
          vals[i] = f(s[i]);
        }
      }
    }
  }
  return s.first;
}