~edwargix/tallyard

06d1065bb91fc2b2ddc20195b58a9e8051a67a6c — David Florness 5 years ago 2da3af8
Find the constant term of the result polynomial
2 files changed, 56 insertions(+), 13 deletions(-)

M linalg.go
M voter.go
M linalg.go => linalg.go +16 -10
@@ 6,26 6,32 @@ import (

type Matrix [][]big.Rat

func (M Matrix) Rows() int {
	return len(M)
}

func (M Matrix) Cols() int {
	if len(M) == 0 {
		return 0
	}
	return len(M[0])
}

func (M Matrix) RREF() {
	lead := 0
	rowCount := len(M)
	if rowCount == 0 {
		return
	}
	columnCount := len(M[0])
	zero := big.NewRat(0, 1)

	for r := 0; r < rowCount; r++ {
		if lead >= columnCount {
	for r := 0; r < M.Rows(); r++ {
		if lead >= M.Cols() {
			return
		}
		i := r
		for M[i][lead].Cmp(zero) == 0 {
			i++
			if rowCount == i {
			if M.Rows() == i {
				i = r
				lead++
				if columnCount == lead {
				if M.Cols() == lead {
					return
				}
			}


@@ 36,7 42,7 @@ func (M Matrix) RREF() {
		for j := range M[r] {
			M[r][j].Mul(&M[r][j], f)
		}
		for i = 0; i < rowCount; i++ {
		for i = 0; i < M.Rows(); i++ {
			if i != r {
				f.Set(&M[i][lead])
				for j, e := range M[r] {

M voter.go => voter.go +40 -3
@@ 188,7 188,7 @@ func findPeers(closeElection <-chan int) {
	discovery.Advertise(me.ctx, routingDiscovery, string(rendezvousNonce))
	logger.Info("successfully announced!")

	logger.Info("searching for other voters...")
	fmt.Println("finding other voters...")
	peerChan, err := routingDiscovery.FindPeers(me.ctx, string(rendezvousNonce))
	if err != nil {
		panic(err)


@@ 203,7 203,7 @@ func findPeers(closeElection <-chan int) {
			if peer.ID == me.ID() {
				continue
			}
			logger.Info("found voter:", peer)
			fmt.Printf("found voter: %s\n", peer)
			logger.Info("connecting to:", peer)

			err = me.Connect(me.ctx, peer)


@@ 230,7 230,7 @@ func findPeers(closeElection <-chan int) {

func (voter *Voter) fetchNumber(cmd string, args ...string) *big.Int {
	printErr := func(err error, msg string) {
		logger.Errorf("%s: %s fetcing `%s'; retrying in 2 seconds",
		logger.Errorf("%s: %s while fetcing `%s'; retrying in 2 seconds",
			voter.addrInfo.ID, msg, cmd)
		time.Sleep(time.Second * 2)
	}


@@ 289,11 289,13 @@ func startVoting() {
	logger.Infof("our input: %s", me.input)

	ballot := vote(candidates)
	logger.Info("our ballot:", ballot)

	// no +1 since we want degree k-1 where k is total number of voters
	me.polyMu.Lock()
	me.poly = NewRandomPoly(uint(len(election.remoteVoters)), 1024, ballot)
	me.polyMu.Unlock()
	logger.Infof("our constant: %s", me.poly.constant)

	// get outputs
	var wg sync.WaitGroup


@@ 314,6 316,7 @@ func startVoting() {
		me.sum.Add(me.sum, voter.output)
	}
	me.sumMu.Unlock()
	logger.Infof("our sum: %s", me.sum)

	// get sums
	for _, voter := range election.remoteVoters {


@@ 327,6 330,40 @@ func startVoting() {
	}
	wg.Wait()

	mat := constructPolyMatrix()
	mat.RREF()

	result := mat[0][len(mat[0])-1]

	// temporary
	select {}
}

func constructPolyMatrix() Matrix {
	mat := make(Matrix, len(election.remoteVoters) + 1) // row for everyone (including ourselves)

	i := 0
	for _, voter := range election.remoteVoters {
		mat[i] = make([]big.Rat, len(mat) + 1) // includes column for sum
		row := mat[i]
		row[0].SetInt64(1)
		var j int64
		for j = 1; j <= int64(len(election.remoteVoters)); j++ {
			row[j].SetInt(new(big.Int).Exp(voter.input, big.NewInt(j), nil))
		}
		row[j].SetInt(voter.sum)
		i++
	}

	// row for ourselves
	mat[i] = make([]big.Rat, len(mat) + 1)
	row := mat[i]
	row[0].SetInt64(1)
	var j int64
	for j = 1; j <= int64(len(election.remoteVoters)); j++ {
		row[j].SetInt(new(big.Int).Exp(me.input, big.NewInt(j), nil))
	}
	row[j].SetInt(me.sum)

	return mat
}