Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,108 @@
package main
import (
"fmt"
"math/rand"
"time"
)
// input, 0-based start position
const startRow = 0
const startCol = 0
func main() {
rand.Seed(time.Now().Unix())
for !knightTour() {
}
}
var moves = []struct{ dr, dc int }{
{2, 1},
{2, -1},
{1, 2},
{1, -2},
{-1, 2},
{-1, -2},
{-2, 1},
{-2, -1},
}
// Attempt knight tour starting at startRow, startCol using Warnsdorff's rule
// and random tie breaking. If a tour is found, print it and return true.
// Otherwise no backtracking, just return false.
func knightTour() bool {
// 8x8 board. squares hold 1-based visit order. 0 means unvisited.
board := make([][]int, 8)
for i := range board {
board[i] = make([]int, 8)
}
r := startRow
c := startCol
board[r][c] = 1 // first move
for move := 2; move <= 64; move++ {
minNext := 8
var mr, mc, nm int
candidateMoves:
for _, cm := range moves {
cr := r + cm.dr
if cr < 0 || cr >= 8 { // off board
continue
}
cc := c + cm.dc
if cc < 0 || cc >= 8 { // off board
continue
}
if board[cr][cc] > 0 { // already visited
continue
}
// cr, cc candidate legal move.
p := 0 // count possible next moves.
for _, m2 := range moves {
r2 := cr + m2.dr
if r2 < 0 || r2 >= 8 {
continue
}
c2 := cc + m2.dc
if c2 < 0 || c2 >= 8 {
continue
}
if board[r2][c2] > 0 {
continue
}
p++
if p > minNext { // bail out as soon as it's eliminated
continue candidateMoves
}
}
if p < minNext { // it's better. keep it.
minNext = p // new min possible next moves
nm = 1 // number of candidates with this p
mr = cr // best candidate move
mc = cc
continue
}
// it ties for best so far.
// keep it with probability 1/(number of tying moves)
nm++ // number of tying moves
if rand.Intn(nm) == 0 { // one chance to keep it
mr = cr
mc = cc
}
}
if nm == 0 { // no legal move
return false
}
// make selected move
r = mr
c = mc
board[r][c] = move
}
// tour complete. print board.
for _, r := range board {
for _, m := range r {
fmt.Printf("%3d", m)
}
fmt.Println()
}
return true
}

View file

@ -0,0 +1,192 @@
/* Adapted from "Enumerating Knight's Tours using an Ant Colony Algorithm"
by Philip Hingston and Graham Kendal,
PDF at http://www.cs.nott.ac.uk/~gxk/papers/cec05knights.pdf. */
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
const boardSize = 8
const nSquares = boardSize * boardSize
const completeTour = nSquares - 1
// task input: starting square. These are 1 based, but otherwise 0 based
// row and column numbers are used througout the program.
const rStart = 2
const cStart = 3
// pheromone representation read by ants
var tNet = make([]float64, nSquares*8)
// row, col deltas of legal moves
var drc = [][]int{{1, 2}, {2, 1}, {2, -1}, {1, -2},
{-1, -2}, {-2, -1}, {-2, 1}, {-1, 2}}
// get square reached by following edge k from square (r, c)
func dest(r, c, k int) (int, int, bool) {
r += drc[k][0]
c += drc[k][1]
return r, c, r >= 0 && r < boardSize && c >= 0 && c < boardSize
}
// struct represents a pheromone amount associated with a move
type rckt struct {
r, c, k int
t float64
}
func main() {
fmt.Println("Starting square: row", rStart, "column", cStart)
// initialize board
for r := 0; r < boardSize; r++ {
for c := 0; c < boardSize; c++ {
for k := 0; k < 8; k++ {
if _, _, ok := dest(r, c, k); ok {
tNet[(r*boardSize+c)*8+k] = 1e-6
}
}
}
}
// waitGroups for ant release clockwork
var start, reset sync.WaitGroup
start.Add(1)
// channel for ants to return tours with pheremone updates
tch := make(chan []rckt)
// create an ant for each square
for r := 0; r < boardSize; r++ {
for c := 0; c < boardSize; c++ {
go ant(r, c, &start, &reset, tch)
}
}
// accumulator for new pheromone amounts
tNew := make([]float64, nSquares*8)
// each iteration is a "cycle" as described in the paper
for {
// evaporate pheromones
for i := range tNet {
tNet[i] *= .75
}
reset.Add(nSquares) // number of ants to release
start.Done() // release them
reset.Wait() // wait for them to begin searching
start.Add(1) // reset start signal for next cycle
// gather tours from ants
for i := 0; i < nSquares; i++ {
tour := <-tch
// watch for a complete tour from the specified starting square
if len(tour) == completeTour &&
tour[0].r == rStart-1 && tour[0].c == cStart-1 {
// task output: move sequence in a grid.
seq := make([]int, nSquares)
for i, sq := range tour {
seq[sq.r*boardSize+sq.c] = i + 1
}
last := tour[len(tour)-1]
r, c, _ := dest(last.r, last.c, last.k)
seq[r*boardSize+c] = nSquares
fmt.Println("Move sequence:")
for r := 0; r < boardSize; r++ {
for c := 0; c < boardSize; c++ {
fmt.Printf(" %3d", seq[r*boardSize+c])
}
fmt.Println()
}
return // task only requires finding a single tour
}
// accumulate pheromone amounts from all ants
for _, move := range tour {
tNew[(move.r*boardSize+move.c)*8+move.k] += move.t
}
}
// update pheromone amounts on network, reset accumulator
for i, tn := range tNew {
tNet[i] += tn
tNew[i] = 0
}
}
}
type square struct {
r, c int
}
func ant(r, c int, start, reset *sync.WaitGroup, tourCh chan []rckt) {
rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
tabu := make([]square, nSquares)
moves := make([]rckt, nSquares)
unexp := make([]rckt, 8)
tabu[0].r = r
tabu[0].c = c
for {
// cycle initialization
moves = moves[:0]
tabu = tabu[:1]
r := tabu[0].r
c := tabu[0].c
// wait for start signal
start.Wait()
reset.Done()
for {
// choose next move
unexp = unexp[:0]
var tSum float64
findU:
for k := 0; k < 8; k++ {
dr, dc, ok := dest(r, c, k)
if !ok {
continue
}
for _, t := range tabu {
if t.r == dr && t.c == dc {
continue findU
}
}
tk := tNet[(r*boardSize+c)*8+k]
tSum += tk
// note: dest r, c stored here
unexp = append(unexp, rckt{dr, dc, k, tk})
}
if len(unexp) == 0 {
break // no moves
}
rn := rnd.Float64() * tSum
var move rckt
for _, move = range unexp {
if rn <= move.t {
break
}
rn -= move.t
}
// move to new square
move.r, r = r, move.r
move.c, c = c, move.c
tabu = append(tabu, square{r, c})
moves = append(moves, move)
}
// compute pheromone amount to leave
for i := range moves {
moves[i].t = float64(len(moves)-i) / float64(completeTour-i)
}
// return tour found for this cycle
tourCh <- moves
}
}