package main import ( "flag" "fmt" "git.openprivacy.ca/sarah/microworlds/core" "git.openprivacy.ca/sarah/microworlds/experiments" "github.com/faiface/pixel/pixelgl" "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.") 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") var cleverByzantineTurtles = flag.Bool("cleverByzantineTurtles", true, "byzantine turtles try to find each other") var isolate = flag.Bool("isolate", false, "also run the isolate algorithm") var alpha = flag.Float64("alpha", 0.8, "the proportion of votes in a voting round that a color must have before it is considered a vote for that colour") var beta = flag.Float64("beta", 100, "acceptance threshold, the number of steps of consistent votes after which a node will no longer change its opinon") var vote1Ahead = false type Snowball struct { color int Probability float64 sureness float32 Byztantine bool colourCounts []int accept bool } func (sm *Snowball) Setup(env *core.Environment, t *core.Turtle) { if sm.Byztantine { sm.color = 1 } else { sm.colourCounts = make([]int, 2) num := rand.Intn(100) if num >= int(sm.Probability*100.0) { sm.color = 0 sm.colourCounts[0] = 1 } else { sm.color = 1 sm.colourCounts[1] = 1 } } sm.sureness = float32(*initialSureness) } func (sm *Snowball) GetColor() int { return sm.color + 1 } func (sm *Snowball) Run(env *core.Environment, t *core.Turtle) { if sm.Byztantine { t.Wiggle() am1 := t.AmountAll(env, 1, "1") am2 := t.AmountAll(env, 1, "2") k := float32(am1 + am2) if *cleverByzantineTurtles == false { if am1 > k*float32(*alpha) && am1 > am2 { sm.color = 1 t.Drop(env, 1, "2") } else if am2 > k*float32(*alpha) && am2 > am1 { sm.color = 0 t.Drop(env, 1, "1") } } else { if *isolate { t.FollowGradient(env, 10, 0, "3") t.Drop(env, 1, "3") } if (*isolate) && sm.sureness > 50 || (*isolate) == false { if vote1Ahead { sm.color = 1 t.Drop(env, 1, "2") } else { sm.color = 0 t.Drop(env, 1, "1") } } } sm.sureness++ t.Step(env) t.SetColor(color.RGBA{255, 0, 0, 0}) } else { if sm.color == 1 { t.SetColor(color.RGBA{0, 255, 0, 0}) } else { t.SetColor(color.RGBA{255, 0, 255, 0}) } t.Wiggle() if !sm.accept { am1 := t.AmountAll(env, 1, "1") am2 := t.AmountAll(env, 1, "2") k := float32(am1 + am2) if am1 > k*float32(*alpha) && am1 > am2 { sm.colourCounts[0]++ } else if am2 > k*float32(*alpha) && am2 > am1 { sm.colourCounts[1]++ } sm.sureness++ if sm.colourCounts[sm.color] < sm.colourCounts[(sm.color+1)%2] { sm.color = (sm.color + 1) % 2 sm.sureness = 0 } if sm.sureness > float32(*beta) { sm.accept = true } } // Add a vote for our new colour if we are sure if sm.sureness >= 1 { t.Drop(env, 1, strconv.Itoa(sm.color+1)) } t.Step(env) } } func mainrun() { experiment := new(experiments.Experiment) experiment.InitializeExperiment() 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}) experiment.InitPheromone("3", color.RGBA{0xFF, 0x00, 0x00, 0x00}) fmt.Printf("Step, Votes for 1, Votes for 2, Honest Votes for 1, Honest Votes for 2, Byzantine Vots for 1, Byzantine Votes for 2\n") experiment.OnStep = func(env *core.Environment, turtles []*core.Turtle, step int) { num1 := 0 num2 := 0 bnum1 := 0 bnum2 := 0 env.EvaporateAndDiffuse(0.99, "1") env.EvaporateAndDiffuse(0.99, "2") env.EvaporateAndDiffuse(0.99, "3") if (*isolate) && step == 50 || !(*isolate) && step == 0 { honestTurtles := experiment.GetNumTurtles() - (*byzantineTurtles) experiment.InitNTurtles(func() core.Actor { sm := new(Snowball) sm.Probability = *prob return sm }, honestTurtles) } else { for _, turtle := range turtles { agent := turtle.GetActor().(*Snowball) if agent.Byztantine == false { if agent.GetColor() == 1 { num1++ } else { num2++ } } else { if agent.GetColor() == 1 { bnum1++ } else { bnum2++ } } } if num1 > num2 { vote1Ahead = true } else { vote1Ahead = false } } //if step == 0 { fmt.Printf("%v,%v,%v,%v,%v, %v,%v\n", step, num1+bnum1, num2+bnum2, num1, num2, bnum1, bnum2) //} } experiment.Run() } func main() { pixelgl.Run(mainrun) }