Statistical results of random trade:
Start from the uniform situation where everyone has the same money,
repeat the cycle to exchange a constant dollars with a randomly selected person.

randomtrade.py

import sys
import random
from math import exp
from matplotlib import pyplot as plt

"""
Statistical results of random trade:
Start from the uniform situation where everyone has the same money,
repeat the cycle to exchange a constant dollars with a randomly selected person.
"""


#=============================
# 大域変数の定義
#=============================
# Number of persons
npersons = 50
# The initial money that the persons have, equal to the average money
value = 50
# The money traded at each cycle
vtrade = 1
# The number of maximum iteration
niter = 500
# The cycle to update graph
nplotinterval = 100

# The number of x mesh for distribution function
nfx = 21


# Treat argments
argv = sys.argv
if len(argv) == 1:
    print("Usage: python randomtrade.py npersons value(average) vtrade n(maxiteration) n(plotinterval) n(distribution func)")
    print(" ex: python randomtrade.py 200 50 1 10000 100 21")
    exit()

if len(argv) >= 2:
    npersons = int(argv[1])
if len(argv) >= 3:
    value = int(argv[2])
if len(argv) >= 4:
    vtrade = int(argv[3])
if len(argv) >= 5:
    niter = int(argv[4])
if len(argv) >= 6:
    nplotinterval = int(argv[5])
if len(argv) >= 7:
    nfx = int(argv[6])


def main():
# 初期化
    xindex = range(npersons) # list of indexes of the persons to be used for x axis
    v = [] # list of money the persons have
    for i in range(npersons):
        v.append(value)

#=============================
# グラフの表示
#=============================
# theoretical distribution: f = A * exp(-bv)
# A and b are determined by the number of persons and the money average
    print("")
    print("Analyatical distribution:")
    xmax = value * 10.0
    nftx = 101
    xstep = xmax / (nftx - 1)
    b = 1.0 / value
    A = npersons * b
    print(" x range: 0 - %g" % (xmax))
    print(" x step: %g" % (xstep))
    print(" f(x) = %g * exp(-%g * x)" % (A, b))
    ftx = []
    fty = []
    for i in range(nftx+1):
        x = i * xstep
        ftx.append(x)
        fty.append(A * exp(-b * x))

# Prepare plot
    fig = plt.figure()

    ax1 = fig.add_subplot(3, 1, 1)
    ax2 = fig.add_subplot(3, 1, 2)
    ax3 = fig.add_subplot(3, 1, 3)
    plt.subplots_adjust(wspace = 0.2, hspace = 0.3)

# trade
    for i in range(niter):
        for ip in range(npersons):
            itarget = int(random.random() * npersons)
            if v[ip] >= vtrade:
                v[itarget] += vtrade
                v[ip] -= vtrade
            else:
                v[itarget] += v[ip]
                v[ip] = 0

        vs = sorted(v)

        if i == 0 or (i+1) % nplotinterval == 0 or i == niter - 1:
# calculate distribution function f(x)
            vmax = max(v)
            vstep = vmax / (nfx - 1)

            fx = []
            fy = []
            for ifx in range(nfx):
                vlim0 = ifx * vstep
                vlim1 = (ifx+1) * vstep
                fx.append(vlim0)
                fy.append(0.0)
                for ip1 in range(npersons):
                    if vlim0 < vs[ip1] <= vlim1:
                        fy[ifx] += 1.0 / vstep

            ax1.cla()
            ax2.cla()
            ax3.cla()

            ax1.bar(xindex, v, width = 1.5)
            ax1.plot([0, npersons], [value, value], linestyle = 'dashed', color = 'red', linewidth = 0.5)
            ax1.set_title('Random trade (i = %d/%d, n=%d, avg=%d)' % (i+1, niter, npersons, value))
            ax1.set_xlabel("i")
            ax1.set_ylabel("value")
            ax1.set_xlim([0, npersons])

            ax2.bar(xindex, vs, width = 1.5)
            ax2.plot([0, npersons], [value, value], linestyle = 'dashed', color = 'red', linewidth = 0.5)
            ax2.set_xlim([0, npersons])
            ax2.set_xlabel("i")
            ax2.set_ylabel("value (sorted)")

            ax3.plot(fx, fy, label = 'distrib')
            ax3.plot(ftx, fty, label = 'exponential', color = "red", linewidth = 0.5, linestyle = 'dashed')
            ax3.set_xlim([0, vmax])
            ax3.set_ylim([0, max(fy) + 1])
            ax3.set_xlabel("value")
            ax3.set_ylabel("frequency / value")
            ax3.legend()

            plt.pause(0.1)

    print("Press ENTER to exit>>", end = '')
    input()


if __name__ == '__main__':
    main()