From 0ff2d5696d9c9c45cf5481ce9e26eaaf7c8c682b Mon Sep 17 00:00:00 2001 From: vmaksimkina Date: Wed, 10 Jan 2024 20:55:55 +0200 Subject: [PATCH 1/2] find extremum program --- d/main.go | 23 +++++++++++++++++++++++ d/main_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 d/main.go create mode 100644 d/main_test.go diff --git a/d/main.go b/d/main.go new file mode 100644 index 0000000..bc32558 --- /dev/null +++ b/d/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" +) + +func derivative(f func(float64) float64, x, e float64) float64 { + return (f(x+e) - f(x-e)) / (e) +} + +func gradient(f func(x float64) float64, a, x, e float64) float64 { + for derivative(f, x, e) > 1e-6 { + x -= a * derivative(f, x, e) + } + return x +} + +func main() { + e := 1e-6 + f := func(x float64) float64 { return x*x*x*x - 4*x*x*x + 2*x*x + 10*x + 12 } + min := gradient(f, 0.01, 1, e) + fmt.Println(min) +} diff --git a/d/main_test.go b/d/main_test.go new file mode 100644 index 0000000..adc1157 --- /dev/null +++ b/d/main_test.go @@ -0,0 +1,26 @@ +package main + +import ( + "math" + "testing" +) + +func TestSolveSecant(t *testing.T) { + for _, tc := range []struct { + f func(float64) float64 + a, x, eps float64 + want float64 + }{ + {f: func(x float64) float64 { return math.Pow(x, 3) - 2*x - 5 }, a: 0.01, x: 2, eps: 1e-3, want: 0.816}, + {f: func(x float64) float64 { return 3*x*x*x*x - 4*x*x*x - 12*x*x - 5 }, a: 0.01, x: 1, eps: 1, want: 2}, + {f: func(x float64) float64 { return x - 5*math.Sin(x) - 3.5 }, a: 0.09, x: 10, eps: 1e-5, want: 7.65262}, + {f: func(x float64) float64 { return (1+x)*math.Pow(10, 3*x) - 5 }, a: 0.01, x: 0.01, eps: 1e-3, want: -1.145}, + {f: func(x float64) float64 { return -(1+x)*math.Pow(10, (-2)*x) + 8 }, a: 0.001, x: 2, eps: 1e-3, want: -0.783}, + } { + got := gradient(tc.f, tc.a, tc.x, tc.eps) + if math.Abs(got-tc.want) > tc.eps { + t.Errorf("got = %v, want = %v", got, tc.want) + } + + } +} From 5ef600771c493d712766c7610d10a2b145f1cc99 Mon Sep 17 00:00:00 2001 From: vmaksimkina Date: Sun, 14 Jan 2024 23:32:46 +0200 Subject: [PATCH 2/2] normalization --- main.go | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/main.go b/main.go index e39985b..1b85ad7 100644 --- a/main.go +++ b/main.go @@ -3,13 +3,30 @@ package main import ( "image" "log" + "math" "time" "github.com/hajimehoshi/ebiten/v2" ) -func f(x float64) float64 { return x*x + 5*x - 3 } -func df(x float64) float64 { return 2*x + 5 } +func f(x float64) float64 { return -(1+x)*math.Pow(10, (-2)*x) + 8 } + +func derivative(f func(float64) float64, x, e float64) float64 { + return (f(x+e) - f(x-e)) / (2 * e) +} + +func sign(x float64) float64 { + if x > 0 { + return 1 + } else if x < 0 { + return -1 + } + return 0 +} + +func gradientlength(a float64) float64 { + return a / math.Sqrt(a*a) +} func main() { ebiten.SetWindowSize(640, 480) @@ -17,12 +34,17 @@ func main() { img := make(chan *image.RGBA, 1) go func() { + e := 1e-6 p := Plot(-5, 0, 0.1, f) x := 0.0 img <- p(x) - for i := 0; i < 50; i++ { + lr := 1e-3 + for derivative(f, x, e) > 1e-6 { time.Sleep(30 * time.Millisecond) - x -= df(x) * 0.1 + // x -= lr * sign(derivative(f, x, e)) + gradient := derivative(f, x, e) + normalized := (1 / gradientlength(gradient)) * gradient + x -= lr * sign(normalized) img <- p(x) } }()