群體智慧演算法-黏菌尋找食物最優路線行為模擬 2
阿新 • • 發佈:2022-05-03
說明:此文章為騰訊雲機器自動從本人csdn部落格搬遷過來。是本人授權操作。
申明:無本人授權,不可轉載本文。如有轉載,本人保留追究其法律責任的權利。
龔浩華,QQ 29185807,月牙寂 道長
第一時間獲取文章,可以關注本人公眾號 月牙寂道長 yueyajidaozhang
經過查詢一些資料,發現目前比較好的理論支撐有元胞自動機,其中的分形理論中的擴散限制凝聚模型與黏菌的網路比較貼切。 經過反覆的調整。現在購機了一個黏菌的網路。如圖: 第一個圖為模擬的過程 第二圖為最終圖的放大
其中依然有有幾個假設 1、黏菌的生命力,隨著擴充套件,生命力降低 2、隨著擴充套件完之後,黏菌在整個擴充套件範圍內,隨機生成一些感觸點,然後感觸點生成網路 感觸點的生長原則,則是最大可能從生命力低的地方向生命力高的地方生長,直至生長到了有網路的地方,或者是黏菌的核心。 不足的地方: 在模擬行為中採用的是元胞為小方塊,所以會出現圖中的一些對角線的直線。 備註: 其中圖片採用的是jpg,為200*200畫素。載入的是一個全白的圖片,後面的黑點為程式模擬出來的 原始碼如下
package main import ( "fmt" "image" "image/jpeg" // "io" "image/color" "math/rand" "os" "path" "runtime" "sync" "time" ) func main() { runtime.GOMAXPROCS(1) for { select {} } } var max_x int = 200 var max_y int = 200 var lock *sync.RWMutex var im image.Image var AllPart []Parts var wg *sync.WaitGroup type Parts []*Part type Part struct { x int y int en int black bool walked bool } func NewPart(x, y int) *Part { p := Part{x, y, 0, false, false} return &p } func initImage() error { f, err := os.Open("200.jpg") if err != nil { fmt.Println(err) return err } defer f.Close() im, err = jpeg.Decode(f) if err != nil { fmt.Println(err) return err } return nil } func Print() { tick := time.Tick(1 * time.Second) count := 1 for { select { case <-tick: func() { p := path.Join("./worm", fmt.Sprintf("%d.jpg", count)) lock.Lock() f, _ := os.OpenFile(p, os.O_RDWR|os.O_CREATE, 0x666) jpeg.Encode(f, im, nil) f.Close() lock.Unlock() count++ }() } } } func init() { initImage() wg = &sync.WaitGroup{} lock = &sync.RWMutex{} AllPart = make([]Parts, max_y, max_y) for y := 0; y < max_y; y++ { AllPart[y] = Parts(make([]*Part, max_x, max_x)) } for y := 0; y < max_y; y++ { for x := 0; x < max_x; x++ { AllPart[y][x] = NewPart(x, y) } } AllPart[max_y/2][max_x/2].en = 200 AllPart[max_y/2][max_x/2].black = true AllPart[max_y/2][max_x/2].walked = true SetBlack(max_x/2, max_y/2) for i := 0; i < 500; i++ { rand.Seed(rand.Int63()) y1 := int(rand.Int31()) % max_y x1 := int(rand.Int31()) % max_x if x1 == max_x/2 && y1 == max_y/2 { continue } AllPart[y1][x1].black = true SetBlack(x1, y1) } for y := 0; y < max_y; y++ { for x := 0; x < max_x; x++ { wg.Add(1) } } for y := 0; y < max_y; y++ { for x := 0; x < max_x; x++ { go AllPart[y][x].run() } } go Print() } func getEn(x, y int) int { if x < 0 || y < 0 { return -1 } if x >= max_x || y >= max_y { return -1 } return AllPart[y][x].en } func SetBlack(x, y int) { p := im.(*image.YCbCr) if !(image.Point{x, y}.In(p.Rect)) { return } yi := p.YOffset(x, y) ci := p.COffset(x, y) p.Y[yi], p.Cb[ci], p.Cr[ci] = color.RGBToYCbCr(0, 0, 0) } func (p *Part) run() { wg.Done() wg.Wait() tick := time.Tick(1 * time.Second) for { select { case <-tick: if p.walked { return } func() { other := make(map[*Part]int) max_node := 0 otherblack := 0 getmax := func(xi, yi int) { en := getEn(xi, yi) if en > 0 { other[AllPart[yi][xi]] = en if AllPart[yi][xi].black { otherblack++ } } if en > max_node { max_node = en } } getmax(p.x-1, p.y-1) getmax(p.x, p.y-1) getmax(p.x+1, p.y-1) getmax(p.x-1, p.y) getmax(p.x+1, p.y) getmax(p.x-1, p.y+1) getmax(p.x, p.y+1) getmax(p.x+1, p.y+1) if p.en == 0 { if max_node > 0 { p.en = max_node - 1 } return } if p.black { //maxwalk ensum := 0 havewalked := 0 nextother := make(map[*Part]int) for np, en := range other { if en > p.en { nextother[np] = en ensum += en if np.walked { havewalked++ } } } if len(nextother) <= 1 { for np, en := range other { if en == p.en { nextother[np] = en ensum += en if np.walked { havewalked++ } } } } if len(nextother) == 0 { for np, en := range other { if en < p.en { nextother[np] = en ensum += en if np.walked { havewalked++ } } } } if havewalked > 0 { p.walked = true return } if ensum > 0 { rand.Seed(rand.Int63()) rn := int(rand.Int31()) % ensum for np, _ := range nextother { rn = rn - np.en if rn <= 0 { np.black = true SetBlack(np.x, np.y) p.walked = true return } } } } }() } } }