使用Golang編寫優化演算法 (1)

獨木發表於2014-09-17

動手寫點東西是學習新知識很重要的一個階段。之前用 Python 和 JavaScript 實現優化演算法,現在用 Golang 來實現。語法上略有不爽,某些C語言的思維又回來了。

- Golang 用 package 來組織程式碼,同一 package 下不同檔案之間的識別符號是共享的,不能包含兩個相同名稱的函式。而且只有 package main 能夠包含 main 函式。所以將公用的函式提取出來,放在package common。同時,每種例子程式移動到 examples 目錄下。

- 在 CleverAlgorithms 中都是隨機優化演算法,最常用的是隨機數或向量的生成函式。因為預設採用Fixed Seed,所以需要自行設定成執行時刻的納秒值作為種子。

- 在缺乏靈活的dict型別之後,需要定義struct組合型別來滿足陣列單元中儲存不同型別值的需求。

 

package common

import (
	"math/rand"
	"time"
)

// InitSeed set random seed with current time value
func InitSeed() {
	rand.Seed(time.Now().UnixNano())
}

// RandomVector generates a random vector from min_max bound.
// It returns the generated random vector.
func RandomVector(min_max [][2]float64) []float64 {
	var v = make([]float64, len(min_max))
	for i, mm := range min_max {
		v[i] = mm[0] + (mm[1]-mm[0])*rand.Float64()
	}
	return v
}

// RandomBound generates a random value from the bound.
// It returns the random value.
func RandomBound(bound [2]float64) float64 {
	return bound[0] + (bound[1]-bound[0])*rand.Float64()
}

// FRange simulates range in python for float64.
// It yields values in the range.
func FRange(start float64, stop float64, step float64) (c chan float64) {
	c = make(chan float64)
	go func() {
		for x := start; x<stop;	x += step {
			c <- x
		}
		close(c)
	}()

	return
}

// Entity stores cost and vector.
type Entity struct {
	Cost   float64
	Vector []float64
}

 

然後,隨機搜尋的程式碼變成:

//
// Random Search
//

package stochastic

import (
	"clever_algorithms/common"
	"fmt"
)

func objective_function(v []float64) float64 {
	return common.SphereFunction(v)
}

func RandomSearch(search_space [][2]float64, max_iteration int) common.Entity {
	var best common.Entity

	common.InitSeed()

	for i := 0; i < max_iteration; i++ {
		candidate := common.Entity{
			0.0,
			common.RandomVector(search_space),
		}
		candidate.Cost = objective_function(candidate.Vector)
		if best.Vector == nil || best.Cost > candidate.Cost {
			best = candidate
		}
		fmt.Println("Iteration ", i+1, ", best=", best.Cost)
	}

	return best
}

 新增簡單的單元測試:

package stochastic

import (
	"fmt"
	"testing"
)

func TestObjectiveFunction(t *testing.T) {
	if 5 != objective_function([]float64{1, 2}) {
		t.Error("Objetive function failed")
	}
}

func TestSearch(t *testing.T) {
	//
	var problem_size = 2
	var search_space = make([][2]float64, problem_size)
	for i, _ := range search_space {
		search_space[i] = [2]float64{-5, 5}
	}
	//
	const max_iteration = 100
	//
	var best = RandomSearch(search_space, max_iteration)
	if best.Vector == nil {
		t.Error("Search result should not be nil.")
	}
	fmt.Println("Done. Best Solution: c=", best.Cost, ", v= [")
	for i, v := range best.Vector {
		fmt.Print("  ", v)
		if v < search_space[i][0] || v > search_space[i][1] {
			t.Error("vector values should be in the search space.")
		}
	}
	fmt.Println("]")

}

 

[1]https://coding.net/u/huys03/p/clever_algorithms_go/git

 

相關文章