microworlds/experiments/snowball/main.go

131 lines
3.3 KiB
Go
Raw Normal View History

package main
import (
"flag"
2019-09-30 04:52:01 +00:00
"fmt"
"git.openprivacy.ca/sarah/microworlds/core"
"git.openprivacy.ca/sarah/microworlds/experiments"
"image/color"
"math/rand"
"strconv"
)
var prob = flag.Float64("distribution", .51, "drives the probability of color assignment of turtles in consensus models, closer to .5 results in more even assignment, closer to 0 or 1 biases in favor of a color.")
2019-09-30 04:52:01 +00:00
var initialSureness = flag.Int("initialSureness", 2, "how sure an honest node is of their first received colour")
var byzantineTurtles = flag.Int("byzantineTurtles", 50, "in consensus simlulations, the number of turtles who will always vote 2")
2019-09-30 04:52:01 +00:00
var cleverByzantineTurtles = flag.Bool("cleverByzantineTurtles", true, "byzantine turtles try to find each other")
2019-10-01 19:10:48 +00:00
var alpha = flag.Float64("alpha", 0.5, "the proportion of votes in a voting round that a color must have before it is considered a vote for that colour")
type Snowball struct {
color int
Probability float64
sureness float32
Byztantine bool
2019-10-01 19:10:48 +00:00
colourCounts []int
}
func (sm *Snowball) Setup(env *core.Environment, t *core.Turtle) {
num := rand.Intn(100)
if num >= int(sm.Probability*100.0) {
sm.color = 1
2019-10-01 19:10:48 +00:00
} else {
sm.color = 0
}
2019-09-30 04:52:01 +00:00
sm.sureness = float32(*initialSureness)
2019-10-01 19:10:48 +00:00
sm.colourCounts = make([]int,2)
2019-09-30 04:52:01 +00:00
}
func (sm *Snowball) GetColor() int {
return sm.color
}
func (sm *Snowball) Run(env *core.Environment, t *core.Turtle) {
if sm.Byztantine {
t.Wiggle()
2019-09-30 04:52:01 +00:00
if *cleverByzantineTurtles {
t.FollowGradient(env, 5, 2, "3")
t.Drop(env, 1, "3")
}
2019-10-01 19:10:48 +00:00
sm.color = 1
2019-09-30 04:52:01 +00:00
t.SetColor(color.RGBA{255, 0, 0, 0})
t.Drop(env, 1, "2")
2019-09-30 04:52:01 +00:00
} else {
2019-09-30 04:52:01 +00:00
if sm.color == 1 {
t.SetColor(color.RGBA{0, 255, 0, 0})
} else {
t.SetColor(color.RGBA{255, 0, 255, 0})
}
t.Wiggle()
2019-09-30 04:52:01 +00:00
am1 := t.AmountAll(env, 1, "1")
am2 := t.AmountAll(env, 1, "2")
2019-10-01 19:10:48 +00:00
k := float32(am1 + am2)
2019-10-01 19:10:48 +00:00
if am1 > k*float32(*alpha) && am1 > am2 {
sm.colourCounts[0]++
} else if am2 > k*0.5 && am2 > am1 {
sm.colourCounts[1]++
}
2019-10-01 19:10:48 +00:00
sm.sureness++
if sm.colourCounts[sm.color] < sm.colourCounts[(sm.color+1)%2] {
sm.color = (sm.color+1) %2
sm.sureness = 0
}
2019-10-01 19:10:48 +00:00
// Add a vote for our new colour if we are sure
if sm.sureness > 1 {
2019-10-01 19:10:48 +00:00
t.Drop(env, 1, strconv.Itoa(sm.color+1))
}
t.Step(env)
}
}
func main() {
experiment := new(experiments.Experiment)
experiment.InitializeExperiment()
honestTurtles := experiment.GetNumTurtles() - (*byzantineTurtles)
experiment.InitNTurtles(func() core.Actor {
sm := new(Snowball)
sm.Probability = *prob
return sm
}, honestTurtles)
experiment.InitNTurtles(func() core.Actor {
sm := new(Snowball)
sm.Probability = *prob
sm.Byztantine = true
return sm
}, (*byzantineTurtles))
experiment.InitPheromone("1", color.RGBA{0x00, 0xFF, 0x00, 0x00})
experiment.InitPheromone("2", color.RGBA{0xFF, 0x00, 0xFF, 0x00})
2019-09-30 04:52:01 +00:00
experiment.InitPheromone("3", color.RGBA{0xFF, 0x00, 0x00, 0x00})
2019-10-01 19:10:48 +00:00
fmt.Printf("Step, Votes for 1, Votes for 2\n")
2019-09-30 04:52:01 +00:00
experiment.OnStep = func(env *core.Environment, turtles []*core.Turtle, step int) {
num1 := 0
num2 := 0
env.EvaporateAndDiffuse(0.99, "1")
env.EvaporateAndDiffuse(0.99, "2")
env.EvaporateAndDiffuse(0.99, "3")
for _, turtle := range turtles {
agent := turtle.GetActor().(*Snowball)
2019-10-01 19:10:48 +00:00
if agent.GetColor() == 0 {
2019-09-30 04:52:01 +00:00
num1++
} else {
num2++
}
}
//if step == 0 {
fmt.Printf("%v,%v,%v\n", step, num1, num2)
//}
}
experiment.Run()
}