2019-09-25 06:38:15 +00:00
package main
import (
"flag"
2019-09-30 04:52:01 +00:00
"fmt"
2019-09-25 06:38:15 +00:00
"git.openprivacy.ca/sarah/microworlds/core"
"git.openprivacy.ca/sarah/microworlds/experiments"
2019-11-17 21:08:02 +00:00
"github.com/faiface/pixel/pixelgl"
2019-09-25 06:38:15 +00:00
"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" )
2019-09-25 06:38:15 +00:00
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-09-25 06:38:15 +00:00
2019-10-01 22:25:06 +00:00
var isolate = flag . Bool ( "isolate" , false , "also run the isolate algorithm" )
2019-10-01 19:10:48 +00:00
2019-10-01 22:25:06 +00:00
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
2019-10-01 19:10:48 +00:00
2019-09-25 06:38:15 +00:00
type Snowball struct {
2019-10-01 22:25:06 +00:00
color int
Probability float64
sureness float32
Byztantine bool
2019-10-01 19:10:48 +00:00
colourCounts [ ] int
2019-10-01 22:25:06 +00:00
accept bool
2019-09-25 06:38:15 +00:00
}
func ( sm * Snowball ) Setup ( env * core . Environment , t * core . Turtle ) {
2019-10-01 22:25:06 +00:00
if sm . Byztantine {
2019-09-25 06:38:15 +00:00
sm . color = 1
2019-10-01 19:10:48 +00:00
} else {
2019-10-01 22:25:06 +00:00
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
}
2019-09-25 06:38:15 +00:00
}
2019-10-01 22:25:06 +00:00
2019-09-30 04:52:01 +00:00
sm . sureness = float32 ( * initialSureness )
2019-10-01 22:25:06 +00:00
2019-09-30 04:52:01 +00:00
}
func ( sm * Snowball ) GetColor ( ) int {
2019-10-01 22:25:06 +00:00
return sm . color + 1
2019-09-25 06:38:15 +00:00
}
func ( sm * Snowball ) Run ( env * core . Environment , t * core . Turtle ) {
if sm . Byztantine {
t . Wiggle ( )
2019-10-01 22:25:06 +00:00
am1 := t . AmountAll ( env , 1 , "1" )
am2 := t . AmountAll ( env , 1 , "2" )
k := float32 ( am1 + am2 )
2019-09-30 04:52:01 +00:00
2019-10-01 22:25:06 +00:00
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" )
}
}
2019-09-30 04:52:01 +00:00
}
2019-10-01 22:25:06 +00:00
sm . sureness ++
t . Step ( env )
2019-09-30 04:52:01 +00:00
t . SetColor ( color . RGBA { 255 , 0 , 0 , 0 } )
2019-09-25 06:38:15 +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 } )
}
2019-09-25 06:38:15 +00:00
t . Wiggle ( )
2019-10-01 22:25:06 +00:00
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 {
2019-10-01 19:10:48 +00:00
sm . colourCounts [ 0 ] ++
2019-10-01 22:25:06 +00:00
} else if am2 > k * float32 ( * alpha ) && am2 > am1 {
2019-10-01 19:10:48 +00:00
sm . colourCounts [ 1 ] ++
2019-09-25 06:38:15 +00:00
}
2019-10-01 19:10:48 +00:00
2019-10-01 22:25:06 +00:00
sm . sureness ++
2019-10-01 19:10:48 +00:00
2019-10-01 22:25:06 +00:00
if sm . colourCounts [ sm . color ] < sm . colourCounts [ ( sm . color + 1 ) % 2 ] {
sm . color = ( sm . color + 1 ) % 2
sm . sureness = 0
}
2019-09-25 06:38:15 +00:00
2019-10-01 22:25:06 +00:00
if sm . sureness > float32 ( * beta ) {
sm . accept = true
}
}
2019-10-01 19:10:48 +00:00
// Add a vote for our new colour if we are sure
2019-10-01 22:25:06 +00:00
if sm . sureness >= 1 {
2019-10-01 19:10:48 +00:00
t . Drop ( env , 1 , strconv . Itoa ( sm . color + 1 ) )
2019-09-25 06:38:15 +00:00
}
t . Step ( env )
}
}
2019-11-17 21:08:02 +00:00
func mainrun ( ) {
2019-09-25 06:38:15 +00:00
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 } )
2019-09-30 04:52:01 +00:00
experiment . InitPheromone ( "3" , color . RGBA { 0xFF , 0x00 , 0x00 , 0x00 } )
2019-10-01 22:25:06 +00:00
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" )
2019-09-30 04:52:01 +00:00
experiment . OnStep = func ( env * core . Environment , turtles [ ] * core . Turtle , step int ) {
num1 := 0
num2 := 0
2019-10-01 22:25:06 +00:00
bnum1 := 0
bnum2 := 0
2019-09-30 04:52:01 +00:00
env . EvaporateAndDiffuse ( 0.99 , "1" )
env . EvaporateAndDiffuse ( 0.99 , "2" )
env . EvaporateAndDiffuse ( 0.99 , "3" )
2019-10-01 22:25:06 +00:00
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
2019-09-30 04:52:01 +00:00
} else {
2019-10-01 22:25:06 +00:00
vote1Ahead = false
2019-09-30 04:52:01 +00:00
}
}
//if step == 0 {
2019-10-01 22:25:06 +00:00
fmt . Printf ( "%v,%v,%v,%v,%v, %v,%v\n" , step , num1 + bnum1 , num2 + bnum2 , num1 , num2 , bnum1 , bnum2 )
2019-09-30 04:52:01 +00:00
//}
}
2019-09-25 06:38:15 +00:00
experiment . Run ( )
}
2019-11-17 21:08:02 +00:00
func main ( ) {
pixelgl . Run ( mainrun )
}