简体   繁体   中英

Probability modelling issue in Python

I am in the middle of making a program that simulates chemical equilibrium. In theory, it is simple, it takes in initial concentrations of A (B is size of grid-A) and a probability of having A (B's probability is 1-A). Then it sets up an n by n grid with the initial conditions; randomly distributing each A. It then simulates what would occur to the concentration over time, but it disregards the initial conditions and calculates from a 1:0 ratio of A:B. I know why it does that, but I do not know how to make my program consider the initial conditions. My code is the following:

n = 100
A=3000
B=(n*n)-A
time = 25
probA = 70 #where probability of getting A is probA/prob
prob = 100


#Specifications
width = 5
height = width
x_position = width
y_position = height

#Functions

concA = []
concB = []
time1 = []

color1=[170,10,0]
color2=[0,170,170]

So far these are just empty lists and constants I need to run the program and display the data I want at the end.

def draw_initial(n):
    countA_int=0
    countB_int=0
    for i in range(n):
        for j in range(n):
            y = y_position * j
            x = x_position * i
            r = randint(0,int(A+B))
            if r<A:
                clr=color1
                countA_int +=1
            else:
                clr=color2
                countB_int +=1
            rect(x, y, width, height,*clr)
        rect(x, y, width, height,*clr)
    concA.append(100*countA_int/(n*n))
    concB.append(100*countB_int/(n*n))
    time1.append(0)
    print('Initial concentrations:')
    print('A = {} and B = {}'.format(concA[-1],concB[-1]))
    wait_mouse_press()
    clear()

So far I have made the initial grid. However, I know how to randomly distribute n amount of A in the grid. I just know how to make it so that roughly n percentage of the grid is A. Please instruct me here.

def start_reaction(n):
    t = 1
    while True:
        countA_final = 0
        countB_final = 0
        for i in range(n):
            for j in range(n):
                y = y_position * j
                x = x_position * i
                r = randint(0,prob)
                v=(-math.e**(-(1/math.e)*t))+1
                if r <= v*probA:
                    clr = color1
                    countA_final += 1

                else:
                    clr = color2
                    countB_final += 1
                rect(x, y, width, height,*clr)
        rect(x, y, width, height,*clr)
        concA.append(100*countA_final/(n*n))
        concB.append(100*countB_final/(n*n))
        t += 1
        time1.append(t-1)
        print ('New round, time ={}'.format(t-1))
        print('A = {}'.format(concA[-1]))
        print('B = {}'.format(concB[-1]))
        wait_mouse_press()
        if t > time:
            break
    print(concA)
    print(concB)
    print(time1)

This next bit calculates how the grid looks for each iteration. It uses an odd formula to model the probability accurately. By the end it shows you this graph:

在此处输入图片说明

Clearly, there is an issue. At the very beginning, the data points jump instantly and then are modeled as they should be. The jump occurs because the second function doesn't know how the grid started and instead calculates a grid with only A at first and then does the iterations. I want my program to reach equilibrium from any given concentration, not only from 100% A. Can someone please help me?

Well, maybe it isn't of much interest for people, but I've managed to fix the issue. I won't bother explaining in detail but the issue had to do with the formula I used that modeled the increase or decrease in probability. I created another equation that would yield a variable that would shift the curve to the left in order to match the current concentration. If anyone wants the medialib file in order to run the code yourself, please write it in the comments. The code is the following:

from medialib import *
from random import randint  # import randint() function
import matplotlib.pyplot as plt
import math

#Input variables
n = 100
A=1000 #must be between 0 and n*n
B=(n*n)-A
time = 25
probA = 50 #where probability of getting A is probA/prob
prob = 100


#Specifications
width = 5
height = width
x_position = width
y_position = height

#Functions

concA = []
concB = []
time1 = []

color2=[170,10,0]
color1=[0,170,170]

def draw_initial(n):
    countA_int=0
    countB_int=0
    for i in range(n):
        for j in range(n):
            y = y_position * j
            x = x_position * i
            r = randint(0,int(A+B))
            if r<A:
                clr=color1
                countA_int +=1
            else:
                clr=color2
                countB_int +=1
            rect(x, y, width, height,*clr)
        rect(x, y, width, height,*clr)
    concA.append(100*countA_int/(n*n))
    concB.append(100*countB_int/(n*n))
    time1.append(0)
    print('Initial concentrations:')
    print('A = {} and B = {}'.format(concA[-1],concB[-1]))
    wait_mouse_press()
    clear()

def start_reaction(n):
    t = 1
    while True:
        countA_final = 0
        countB_final = 0
        if concA[-1]<probA:
            l=math.e*math.log(1/(abs(1-(concA[-1]/probA))))
            v=(-math.e**((-1/math.e)*(t+l)))+1
        elif concA[-1]==probA:
            l=math.e*math.log(1/(abs(1-((concA[-1]+0.1)/probA))))
            v=(-math.e**((-1/math.e)*(t+l)))+1
        elif concA[-1]>probA:
            l=math.e*math.log(1/(abs(1-(concA[-1]/probA))))
            v=(math.e**((-1/math.e)*(t+l)))+1
            
        for i in range(n):
            for j in range(n):
                
                y = y_position * j
                x = x_position * i
                r = randint(0,prob)
            
                if r < v*probA:
                    clr = color1
                    countA_final += 1

                else:
                    clr = color2
                    countB_final += 1
                rect(x, y, width, height,*clr)
        rect(x, y, width, height,*clr)
        concA.append(100*countA_final/(n*n))
        concB.append(100*countB_final/(n*n))
        t += 1
        time1.append(t-1)
        print ('New round, time ={}'.format(t-1))
        print('A = {}'.format(concA[-1]))
        print('B = {}'.format(concB[-1]))
        wait_mouse_press()
        if t > time:
            break
    print(concA)
    print(concB)
    print(time1)

draw_initial(n)
start_reaction(n)

wait_mouse_press()
import matplotlib.pyplot as plt
axes = plt.axes()
axes.set_ylim([0, 100])

plt.plot(time1,concA, label="Conc.A")
plt.plot(time1,concB, label="Conc.B")
plt.ylabel('% concentration')
plt.xlabel('time')
plt.show()

wait_mouse_press()

all_done() # always the last instruction of the program

在此处输入图片说明

That's the graph, see how the concentrations do not have to begin at 100:0 anymore.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM