07-nelder-mead.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package main
  2. import (
  3. "image/color"
  4. "math"
  5. "math/rand"
  6. "gonum.org/v1/gonum/optimize"
  7. "gonum.org/v1/plot"
  8. "gonum.org/v1/plot/palette/moreland"
  9. "gonum.org/v1/plot/plotter"
  10. "gonum.org/v1/plot/vg"
  11. "gonum.org/v1/plot/vg/draw"
  12. )
  13. func main() {
  14. points := plotter.XYs{}
  15. for i := 0; i < 10; i++ {
  16. points = append(points, plotter.XY{
  17. X: 100 * rand.Float64(),
  18. Y: 100 * rand.Float64(),
  19. })
  20. }
  21. scatter, err := plotter.NewScatter(points)
  22. if err != nil {
  23. panic(err)
  24. }
  25. scatter.Shape = draw.CircleGlyph{}
  26. heatmap := plotter.NewHeatMap(Heat(points), moreland.SmoothBlueRed().Palette(100))
  27. Func := func(x []float64) float64 {
  28. if len(x) != 2 {
  29. panic("illegal x")
  30. }
  31. var sum float64
  32. for _, point := range points {
  33. sum += math.Sqrt(math.Pow(point.X-x[0], 2) + math.Pow(point.Y-x[1], 2))
  34. }
  35. return sum
  36. }
  37. problem := optimize.Problem{
  38. Func: Func,
  39. }
  40. result, err := optimize.Minimize(problem, []float64{1, 1}, &optimize.Settings{}, &optimize.NelderMead{})
  41. if err != nil {
  42. panic(err)
  43. }
  44. aim, err := plotter.NewScatter(plotter.XYs{{
  45. X: result.X[0],
  46. Y: result.X[1],
  47. }})
  48. if err != nil {
  49. panic(err)
  50. }
  51. aim.Shape = draw.CircleGlyph{}
  52. aim.Color = color.White
  53. plt := plot.New()
  54. plt.Y.Min, plt.X.Min, plt.Y.Max, plt.X.Max = 0, 0, 100, 100
  55. plt.Add(heatmap, scatter, aim)
  56. if err := plt.Save(5*vg.Inch, 5*vg.Inch, "07-nelder-mead.png"); err != nil {
  57. panic(err)
  58. }
  59. }
  60. type Heat plotter.XYs
  61. func (h Heat) Dims() (c, r int) { return 100, 100 }
  62. func (h Heat) X(c int) float64 { return float64(c) }
  63. func (h Heat) Y(r int) float64 { return float64(r) }
  64. func (h Heat) Z(c, r int) float64 {
  65. var sum float64
  66. for _, p := range h {
  67. sum += math.Sqrt(math.Pow(p.X-h.X(c), 2) + math.Pow(p.Y-h.Y(r), 2))
  68. }
  69. return -sum
  70. }