// Partially mapped crossover. func (a *GAOrderedIntGenome) Crossover(bi GAGenome, p1, p2 int) (GAGenome, GAGenome) { ca := a.Copy().(*GAOrderedIntGenome) b := bi.(*GAOrderedIntGenome) cb := b.Copy().(*GAOrderedIntGenome) copy(ca.Gene[p1:p2+1], b.Gene[p1:p2+1]) copy(cb.Gene[p1:p2+1], a.Gene[p1:p2+1]) //Proto child needs fixing amap := new(vector.IntVector) bmap := new(vector.IntVector) for i := p1; i <= p2; i++ { ma, found := ca.pmxmap(ca.Gene[i], p1, p2) if found { amap.Push(ma) if bmap.Len() > 0 { i1 := amap.Pop() i2 := bmap.Pop() ca.Gene[i1], cb.Gene[i2] = cb.Gene[i2], ca.Gene[i1] } } mb, found := cb.pmxmap(cb.Gene[i], p1, p2) if found { bmap.Push(mb) if amap.Len() > 0 { i1 := amap.Pop() i2 := bmap.Pop() ca.Gene[i1], cb.Gene[i2] = cb.Gene[i2], ca.Gene[i1] } } } ca.Reset() cb.Reset() return ca, cb }
func (t *GoTracker) dead() []int { dead := new(vector.IntVector) cp := t.Copy().(*GoTracker) color := BLACK move := 0 for { vertex := cp.weights.Rand(color) cp.Play(color, vertex) move++ if move > 3*t.sqsize || cp.Winner() != EMPTY { break } color = Reverse(color) } for i := 0; i < t.sqsize; i++ { if t.board[i] != EMPTY && cp.board[i] != t.board[i] { dead.Push(i) } } stones := make([]int, dead.Len()) for i := 0; i < dead.Len(); i++ { stones[i] = dead.At(i) } return stones }
// capture any points connected to vertex, resetting their parent, rank and weight, and liberties // check if chains adjacent to captured are now out of atari func (t *GoTracker) capture(vertex int) *vector.IntVector { // do a linear search for connected points captured := new(vector.IntVector) for i := 0; i < t.sqsize; i++ { if find(i, t.parent) == vertex { captured.Push(i) } } // reset for i := 0; i < captured.Len(); i++ { capture := captured.At(i) t.parent[capture] = capture t.rank[capture] = 1 t.liberties[capture][0] = 0 t.liberties[capture][1] = 0 t.board[capture] = EMPTY t.weights.Set(BLACK, capture, INIT_WEIGHT) t.weights.Set(WHITE, capture, INIT_WEIGHT) } // update liberties for i := 0; i < captured.Len(); i++ { capture := captured.At(i) for j := 0; j < 4; j++ { adj := t.adj[capture][j] if adj != -1 { root := find(adj, t.parent) t.liberties[root][0] |= t.mask[capture][0] t.liberties[root][1] |= t.mask[capture][1] } } } return captured }
func checkValues(trie *Trie, s string, v *vector.IntVector, t *testing.T) { value, ok := trie.GetValue(s) values := value.(*vector.IntVector) if !ok { t.Fatalf("No value returned for string '%s'", s) } if values.Len() != v.Len() { t.Fatalf("Length mismatch: Values for '%s' should be %v, but got %v", s, *v, *values) } for i := 0; i < values.Len(); i++ { if values.At(i) != v.At(i) { t.Fatalf("Content mismatch: Values for '%s' should be %v, but got %v", s, *v, *values) } } }
func (quartiles *Quartiles) Rollup(time int64, key string, samples *vector.IntVector) { if samples.Len() < 2 { return } sort.Sort(samples) lo := samples.At(0) hi := samples.At(samples.Len() - 1) number := samples.Len() lo_c := number / 2 hi_c := number - lo_c data := &QuartilesItem{} if lo_c > 0 && hi_c > 0 { lo_samples := samples.Slice(0, lo_c) hi_samples := samples.Slice(lo_c, hi_c) lo_sum := 0 hi_sum := 0 lo_samples.Do(func(elem interface{}) { lo_sum += elem.(int) }) hi_samples.Do(func(elem interface{}) { hi_sum += elem.(int) }) q1 := lo_sum / lo_c q2 := (lo_sum + hi_sum) / (lo_c + hi_c) q3 := hi_sum / hi_c data.time = time data.lo = lo data.q1 = q1 data.q2 = q2 data.q3 = q3 data.hi = hi data.total = number } quartiles.save(time, key, data) }
func AreTwoIntVectorEquals(vector1, vector2 *vector.IntVector) bool { if vector1.Len() != vector2.Len() { return false } for i := 0; i < vector1.Len(); i++ { if vector1.At(i) != vector2.At(i) { return false } } return true }
func (t *GoTracker) playHeuristicMove(color byte) int { if len(t.atari[color]) > 0 { // play a random saving move saves := new(vector.IntVector) for _, last_liberty := range t.atari[color] { if t.weights.Get(color, last_liberty) > 0 { saves.Push(last_liberty) } } if saves.Len() > 0 { return saves.At(rand.Intn(saves.Len())) } } if len(t.atari[Reverse(color)]) > 0 { // play a random capture move captures := new(vector.IntVector) for _, last_liberty := range t.atari[Reverse(color)] { captures.Push(last_liberty) } return captures.At(rand.Intn(captures.Len())) } return -1 }
// apply color to vertex, modifying board and updating liberties of any go_adj strings func (t *GoTracker) Play(color byte, vertex int) { if vertex != -1 { t.passes = 0 if t.koVertex != -1 { t.weights.Set(t.koColor, t.koVertex, INIT_WEIGHT) t.koVertex = -1 t.koColor = EMPTY } if t.superko { if t.history.Len() == 0 { t.history.Push(*NewHash(t.boardsize)) } cp := t.Copy() cp.(*GoTracker).superko = false cp.Play(color, vertex) t.history.Push(*MakeHash(cp)) } // modify the board t.board[vertex] = color // update parents and liberties of adjacent stones opp := Reverse(color) root := vertex for i := 0; i < 4; i++ { adj := t.adj[vertex][i] if adj != -1 && t.board[adj] == color { adj := find(adj, t.parent) // take adjacent chain out of atari (may be added back later) t.atari[color][adj] = 0, false // or in liberties to friendly chains new_root, old_root := union(root, adj, t.parent, t.rank) t.liberties[new_root][0] |= t.liberties[old_root][0] t.liberties[new_root][1] |= t.liberties[old_root][1] // xor out liberty from self t.liberties[new_root][0] &= ^t.mask[adj][0] t.liberties[new_root][1] &= ^t.mask[adj][1] root = new_root } else if adj != -1 && t.board[adj] == EMPTY { // xor out liberty from empty vertices t.liberties[adj][0] &= ^t.mask[vertex][0] t.liberties[adj][1] &= ^t.mask[vertex][1] } else if adj != -1 { // xor out liberties from enemy chains enemy := find(adj, t.parent) t.liberties[enemy][0] &= ^t.mask[vertex][0] t.liberties[enemy][1] &= ^t.mask[vertex][1] } } // xor out liberty from self t.liberties[root][0] &= ^t.mask[vertex][0] t.liberties[root][1] &= ^t.mask[vertex][1] // capture any adjacent enemies reduced to zero liberties var captured *vector.IntVector for i := 0; i < 4; i++ { adj := t.adj[vertex][i] if adj != -1 && t.board[adj] == opp { enemy := find(adj, t.parent) libs := t.libs(enemy) if libs == 0 { // take chain out of atari t.atari[opp][enemy] = 0, false if captured == nil { captured = t.capture(enemy) } else { captured.AppendVector(t.capture(enemy)) } } } } // check for suicide of affected empty points for i := 0; i < 4; i++ { adj := t.adj[vertex][i] if adj != -1 && t.board[adj] == EMPTY && t.libs(adj) == 0 { t.check_suicide(adj) } else if adj != -1 && (t.board[adj] == BLACK || t.board[adj] == WHITE) { adj = find(adj, t.parent) if t.libs(adj) == 1 { last_liberty := t.lastliberty(adj) if t.libs(last_liberty) == 0 { t.check_suicide(last_liberty) } } } } // ko check if captured != nil && captured.Len() == 1 { capture := captured.At(0) t.check_suicide(capture) if t.libs(root) == 1 { t.koColor = opp t.koVertex = capture } } // check if capture took adjacent chains out of atari // if so, check suicide status of their previous last liberty for i := 0; captured != nil && i < captured.Len(); i++ { capture := captured.At(i) for j := 0; j < 4; j++ { adj := t.adj[capture][j] if adj != -1 && t.board[adj] == color { adj = find(adj, t.parent) if last_liberty, exists := t.atari[color][adj]; exists { t.check_suicide(last_liberty) t.atari[color][adj] = 0, false } } } } // cannot play on occupied vertex t.weights.Set(BLACK, vertex, 0) t.weights.Set(WHITE, vertex, 0) // update atari status of adjacent chains for i := 0; i < 4; i++ { adj := t.adj[vertex][i] if adj != -1 && (t.board[adj] == BLACK || t.board[adj] == WHITE) { adj = find(adj, t.parent) if t.libs(adj) == 1 { t.atari[t.board[adj]][adj] = t.lastliberty(adj) } } } // update atari status of current chain if t.libs(root) == 1 { t.atari[color][root] = t.lastliberty(root) } // apply patterns neighbors := t.neighbors[1][vertex] for i := range neighbors { if neighbors[i] != -1 && t.board[neighbors[i]] == EMPTY { t.updateWeights(neighbors[i]) } } for i := 0; captured != nil && i < captured.Len(); i++ { t.updateWeights(captured.At(i)) } // mark vertex as played for AMAF if t.played[vertex] == EMPTY { t.played[vertex] = color } } else { t.passes++ } t.moves.Push(vertex) }
// Fisher-Yates (Knuth) Shuffle func shuffle(v *vector.IntVector) { for i := v.Len() - 1; i >= 1; i-- { v.Swap(i, rand.Intn(i+1)) } }
func TestTombStream(t *testing.T) { var v vec.IntVector ts := NewTombStream(&v) ts.InsertChars(7) if v.Len() != 1 || v.At(0) != 7 { t.Fatal("Error in TombStream 1") } ts = NewTombStream(&v) ts.InsertChars(1) chars, err1 := ts.Skip(2) if err1 != nil { t.Fatal("TombStream reached end too soon") } if chars != 2 { t.Fatal("Invalid number of chars") } ts.InsertChars(1) chars, err1 = ts.Skip(5) if err1 != nil { t.Fatal("TombStream reached end too soon") } if chars != 5 { t.Fatal("Invalid number of chars") } ts.InsertChars(1) _, err1 = ts.Skip(1) if err1 == nil { t.Fatal("TombStream did not detect end") } if v.Len() != 1 || v.At(0) != 10 { t.Fatal("Error in TombStream 2") } ts = NewTombStream(&v) chars, _ = ts.Skip(3) if chars != 3 { t.Fatal("Invalid number of chars") } n, err1 := ts.Bury(2) if err1 != nil || n != 2 { t.Fatal("Cannot bury") } if v.Len() != 3 || v.At(0) != 3 || v.At(1) != -2 || v.At(2) != 5 { t.Fatal("Error in TombStream 3") } ts = NewTombStream(&v) chars, _ = ts.Skip(5) if chars != 3 { t.Fatal("Invalid number of chars") } n, err2 := ts.Bury(2) if err2 != nil || n != 2 { t.Fatal("Cannot bury") } if v.Len() != 3 || v.At(0) != 3 || v.At(1) != -4 || v.At(2) != 3 { t.Fatal("Error in TombStream 4") } ts = NewTombStream(&v) chars, _ = ts.Skip(2) if chars != 2 { t.Fatal("Invalid number of chars") } n, err3 := ts.Bury(1) if err3 != nil || n != 1 { t.Fatal("Cannot bury") } if v.Len() != 3 || v.At(0) != 2 || v.At(1) != -5 || v.At(2) != 3 { t.Fatal("Error in TombStream 5") } ts = NewTombStream(&v) chars, _ = ts.Skip(1) if chars != 1 { t.Fatal("Invalid number of chars") } n, err4 := ts.Bury(7) if err4 != nil || n != 2 { t.Fatal("Cannot bury") } chars, _ = ts.Skip(2) if chars != 2 { t.Fatal("Invalid number of chars") } if v.Len() != 3 || v.At(0) != 1 || v.At(1) != -7 || v.At(2) != 2 { t.Fatal("Error in TombStream 6") } ts = NewTombStream(&v) chars, _ = ts.Skip(9) if chars != 2 { t.Fatal("Invalid number of chars") } ts.InsertTombs(3) // Middle of char chars, _ = ts.Skip(1) if chars != 1 { t.Fatal("Invalid number of chars") } if v.Len() != 5 || v.At(0) != 1 || v.At(1) != -7 || v.At(2) != 1 || v.At(3) != -3 || v.At(4) != 1 { t.Fatal("Error in TombStream 7") } ts = NewTombStream(&v) ts.InsertTombs(2) // Beginning of seq if v.Len() != 6 || v.At(0) != -2 || v.At(1) != 1 || v.At(2) != -7 || v.At(3) != 1 || v.At(4) != -3 || v.At(5) != 1 { t.Fatal("Error in TombStream 8") } ts = NewTombStream(&v) chars, _ = ts.Skip(15) if chars != 3 { t.Fatal("Invalid number of chars") } ts.InsertTombs(1) // End of seq if v.Len() != 7 || v.At(0) != -2 || v.At(1) != 1 || v.At(2) != -7 || v.At(3) != 1 || v.At(4) != -3 || v.At(5) != 1 || v.At(6) != -1 { t.Fatal("Error in TombStream 9") } ts = NewTombStream(&v) chars, _ = ts.Skip(2) if chars != 0 { t.Fatal("Invalid number of chars") } ts.InsertTombs(1) // End of tomb if v.Len() != 7 || v.At(0) != -3 || v.At(1) != 1 || v.At(2) != -7 || v.At(3) != 1 || v.At(4) != -3 || v.At(5) != 1 || v.At(6) != -1 { t.Fatal("Error in TombStream 10") } ts = NewTombStream(&v) chars, _ = ts.Skip(4) if chars != 1 { t.Fatal("Invalid number of chars") } ts.InsertTombs(1) // Beginning of tomb if v.Len() != 7 || v.At(0) != -3 || v.At(1) != 1 || v.At(2) != -8 || v.At(3) != 1 || v.At(4) != -3 || v.At(5) != 1 || v.At(6) != -1 { t.Fatal("Error in TombStream 11") } ts = NewTombStream(&v) chars, _ = ts.Skip(1) if chars != 0 { t.Fatal("Invalid number of chars") } ts.InsertTombs(1) // Midle of tomb if v.Len() != 7 || v.At(0) != -4 || v.At(1) != 1 || v.At(2) != -8 || v.At(3) != 1 || v.At(4) != -3 || v.At(5) != 1 || v.At(6) != -1 { t.Fatal("Error in TombStream 11") } }