[research/lotterysim] update cascade report with pi vs pid, and pi scripts

This commit is contained in:
ertosns
2023-07-04 22:08:11 +03:00
parent 2762ac41af
commit fc012bb2c4
16 changed files with 393 additions and 30 deletions

View File

@@ -30,12 +30,12 @@ for nodes in numpy.linspace(1,NODES, 10):
effective_airdrop*=float(staked_ratio)
stake_portion = effective_airdrop/airdrop*100
print("network airdrop: {}, staked token: {}/{}% on {} nodes".format(airdrop, effective_airdrop, stake_portion, len(darkies)))
avg_acc = sum(accs)/EXPS*100
avg_acc = sum(accs)/EXPS
plot+=[(stake_portion, avg_acc)]
plt.plot([x[0] for x in plot], [x[1] for x in plot])
plt.xlabel('drk staked %')
plt.ylabel('accuracy %')
plt.savefig('img'+os.sep+'stake.png')
plt.savefig('img'+os.sep+'stake_pid.png')
plt.show()

View File

@@ -0,0 +1,41 @@
from core.lottery import *
import os
import numpy
from matplotlib import pyplot as plt
os.system("rm log/f_output.hist; rm log/f_feedback.hist")
RUNNING_TIME = int(input("running time:"))
ERC20DRK=2.1*10**9
NODES=1000
plot = []
EXPS=10
for nodes in numpy.concatenate((numpy.array([1,5]), numpy.linspace(10,NODES, 10))):
accs = []
for _ in range(EXPS):
darkies = []
egalitarian = ERC20DRK/NODES
darkies += [ Darkie(random.gauss(egalitarian, egalitarian*0.1), strategy=random_strategy(EPOCH_LENGTH)) for id in range(int(nodes)) ]
#darkies += [Darkie() for _ in range(NODES*2)]
airdrop = ERC20DRK
dt = DarkfiTable(airdrop, RUNNING_TIME, CONTROLLER_TYPE_DISCRETE, kp=-0.0104, ki=-0.0366, kd=0.0384, r_kp=-2.53, r_ki=29.5, r_kd=53.77)
#dt = DarkfiTable(airdrop, RUNNING_TIME, CONTROLLER_TYPE_DISCRETE, kp=-0.0104, ki=-0.0366, kd=0, r_kp=-2.53, r_ki=29.5, r_kd=0)
for darkie in darkies:
dt.add_darkie(darkie)
acc, apy, reward, staked_ratio, apr = dt.background(rand_running_time=False)
accs += [acc]
effective_airdrop = 0
for darkie in darkies:
effective_airdrop+=darkie.stake
effective_airdrop*=float(staked_ratio)
stake_portion = effective_airdrop/airdrop*100
print("network airdrop: {}, staked token: {}/{}% on {} nodes".format(airdrop, effective_airdrop, stake_portion, len(darkies)))
avg_acc = sum(accs)/EXPS
plot+=[(stake_portion, avg_acc)]
plt.plot([x[0] for x in plot], [x[1] for x in plot])
plt.xlabel('drk staked %')
plt.ylabel('accuracy %')
plt.savefig('img'+os.sep+'stake_pi.png')
plt.show()

View File

@@ -28,7 +28,8 @@ if __name__ == "__main__":
effective_airdrop+=darkie.stake
print("network airdrop: {}, staked token: {}/{}% on {} nodes".format(airdrop, effective_airdrop, effective_airdrop/airdrop*100, len(darkies)))
#dt = DarkfiTable(airdrop, RUNNING_TIME, CONTROLLER_TYPE_DISCRETE, kp=-0.010399999999938556, ki=-0.0365999996461878, kd=0.03840000000000491, r_kp=-2.53, r_ki=29.5, r_kd=53.77)
dt = DarkfiTable(airdrop, RUNNING_TIME, CONTROLLER_TYPE_DISCRETE, kp=-0.010399999999938556, ki=-0.0365999996461878, kd=0.03840000000000491, r_kp=-0.63, r_ki=3.35, r_kd=-1.11)
#dt = DarkfiTable(airdrop, RUNNING_TIME, CONTROLLER_TYPE_DISCRETE, kp=-0.010399999999938556, ki=-0.0365999996461878, kd=0.03840000000000491, r_kp=-0.63, r_ki=3.35, r_kd=-1.11)
dt = DarkfiTable(airdrop, RUNNING_TIME, CONTROLLER_TYPE_DISCRETE, kp=-0.010399999999938556, ki=-0.0365999996461878, kd=0, r_kp=-0.63, r_ki=3.35, r_kd=0)
for darkie in darkies:
dt.add_darkie(darkie)
acc, avg_apy, avg_reward, stake_ratio, avg_apr = dt.background(rand_running_time=False)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,163 @@
from argparse import ArgumentParser
from core.lottery import DarkfiTable
from core.utils import *
from core.darkie import Darkie
from tqdm import tqdm
import os
from core.strategy import random_strategy
AVG_LEN = 10
KP_STEP=0.01
KP_SEARCH=-0.63
KI_STEP=0.01
KI_SEARCH=3.35
RUNNING_TIME=1000
NODES = 1000
SHIFTING = 0.05
highest_apr = 0.05
highest_acc = 0.2
highest_staked = 0.3
lowest_apr2target_diff = 1
KP='kp'
KI='ki'
KP_RANGE_MULTIPLIER = 2
KI_RANGE_MULTIPLIER = 2
highest_gain = (KP_SEARCH, KI_SEARCH)
parser = ArgumentParser()
parser.add_argument('-p', '--high-precision', action='store_false', default=False)
parser.add_argument('-r', '--randomizenodes', action='store_true', default=True)
parser.add_argument('-t', '--rand-running-time', action='store_true', default=True)
parser.add_argument('-d', '--debug', action='store_false')
args = parser.parse_args()
high_precision = args.high_precision
randomize_nodes = args.randomizenodes
rand_running_time = args.rand_running_time
debug = args.debug
def experiment(controller_type=CONTROLLER_TYPE_DISCRETE, rkp=0, rki=0, distribution=[], hp=True):
dt = DarkfiTable(ERC20DRK, RUNNING_TIME, controller_type, kp=-0.010399999999938556, ki=-0.0365999996461878, kd=0, r_kp=rkp, r_ki=rki, r_kd=0)
RND_NODES = random.randint(5, NODES) if randomize_nodes else NODES
for idx in range(0,RND_NODES):
darkie = Darkie(distribution[idx], strategy=random_strategy(EPOCH_LENGTH))
dt.add_darkie(darkie)
acc, apy, reward, stake_ratio, apr = dt.background(rand_running_time, hp)
return acc, apy, reward, stake_ratio, apr
def multi_trial_exp(kp, ki, distribution = [], hp=True):
global highest_apr
global highest_acc
global highest_staked
global highest_gain
global lowest_apr2target_diff
new_record=False
accs = []
aprs = []
rewards = []
stakes_ratios = []
aprs = []
for i in range(0, AVG_LEN):
acc, apy, reward, stake_ratio, apr = experiment(CONTROLLER_TYPE_DISCRETE, rkp=kp, rki=ki, distribution=distribution, hp=hp)
accs += [acc]
rewards += [reward]
aprs += [apr]
stakes_ratios += [stake_ratio]
avg_acc = float(sum(accs))/AVG_LEN
avg_reward = float(sum(rewards))/AVG_LEN
avg_staked = float(sum(stakes_ratios))/AVG_LEN
avg_apr = float(sum(aprs))/AVG_LEN
buff = 'avg(acc): {}, avg(apr): {}, avg(reward): {}, avg(stake ratio): {}, kp: {}, ki:{}, '.format(avg_acc, avg_apr, avg_reward, avg_staked, kp, ki)
if avg_apr > 0:
gain = (kp, ki)
acc_gain = (avg_apr, gain)
apr2target_diff = math.fabs(avg_apr - float(TARGET_APR))
#if avg_acc > highest_acc and apr2target_diff < 0.08:
if avg_acc > highest_acc:
new_record = True
highest_apr = avg_apr
highest_acc = avg_acc
highest_staked = avg_staked
highest_gain = (kp, ki)
lowest_apr2target_diff = apr2target_diff
with open('log'+os.sep+"highest_gain.txt", 'w') as f:
f.write(buff)
return buff, new_record
def crawler(crawl, range_multiplier, step=0.1):
start = None
if crawl==KP:
start = highest_gain[0]
elif crawl==KI:
start = highest_gain[1]
range_start = (start*range_multiplier if start <=0 else -1*start)
range_end = (-1*start if start<=0 else range_multiplier*start)
# if number of steps under 10 step resize the step to 50
while (range_end-range_start)/step < 10:
range_start -= SHIFTING
range_end += SHIFTING
step /= 10
while True:
try:
crawl_range = np.arange(range_start, range_end, step)
break
except Exception as e:
print('start: {}, end: {}, step: {}, exp: {}'.format(range_start, rang_end, step, e))
step*=10
np.random.shuffle(crawl_range)
crawl_range = tqdm(crawl_range)
distribution = [random.gauss(ERC20DRK/NODES, ERC20DRK/NODES*0.1) for i in range(NODES)]
for i in crawl_range:
kp = i if crawl==KP else highest_gain[0]
ki = i if crawl==KI else highest_gain[1]
buff, new_record = multi_trial_exp(kp, ki, distribution, hp=high_precision)
crawl_range.set_description('highest:{} / {}'.format(highest_acc, buff))
if new_record:
break
while True:
prev_highest_gain = highest_gain
# kp crawl
crawler(KP, KP_RANGE_MULTIPLIER, KP_STEP)
if highest_gain[0] == prev_highest_gain[0]:
KP_RANGE_MULTIPLIER+=1
KP_STEP/=10
else:
start = highest_gain[0]
range_start = (start*KP_RANGE_MULTIPLIER if start <=0 else -1*start) - SHIFTING
range_end = (-1*start if start<=0 else KP_RANGE_MULTIPLIER*start) + SHIFTING
while (range_end - range_start)/KP_STEP >500:
#if KP_STEP < 0.1:
KP_STEP*=2
KP_RANGE_MULTIPLIER-=1
#TODO (res) shouldn't the range also shrink?
# not always true.
# how to distinguish between thrinking range, and large step?
# good strategy is step shoudn't > 0.1
# range also should be > 0.8
# what about range multiplier?
# ki crawl
crawler(KI, KI_RANGE_MULTIPLIER, KI_STEP)
if highest_gain[1] == prev_highest_gain[1]:
KI_RANGE_MULTIPLIER+=1
KI_STEP/=10
else:
start = highest_gain[1]
range_start = (start*KI_RANGE_MULTIPLIER if start <=0 else -1*start) - SHIFTING
range_end = (-1*start if start<=0 else KI_RANGE_MULTIPLIER*start) + SHIFTING
while (range_end - range_start)/KI_STEP >500:
#print('range_end: {}, range_start: {}, ki_step: {}'.format(range_end, range_start, KI_STEP))
#if KP_STEP < 1:
KI_STEP*=2
KI_RANGE_MULTIPLIER-=1

View File

@@ -15,5 +15,6 @@
\@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces cascade PID diagram}}{7}{}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {6}{\ignorespaces with accuracy set point to primary controller}}{8}{}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {7}{\ignorespaces relation between staked DRK ratio and accuracy of secondary controller, with accuracy as set point to primary controller}}{9}{}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {5}conclusion}{10}{}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {5}PI, or PID \dots }{9}{}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {6}conclusion}{10}{}\protected@file@percent }
\gdef \@abspage@last{10}

View File

@@ -1,4 +1,4 @@
This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2022/dev/Debian) (preloaded format=pdflatex 2023.6.2) 22 JUN 2023 02:56
This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2022/dev/Debian) (preloaded format=pdflatex 2023.6.2) 4 JUL 2023 22:04
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
@@ -546,36 +546,53 @@ Overfull \hbox (117.52686pt too wide) in paragraph at lines 181--182
[][]
[]
<acc_stake_1000nodes_10kslots_with_cascade.png, id=44, 462.528pt x 346.896pt>
! LaTeX Error: Lonely \item--perhaps a missing list environment.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.187 \item e
xperiments done on accuracy of cascade control, and relation be...
?
Underfull \hbox (badness 10000) detected at line 187
[][]
[]
[8 <./acc_setpoint_quarterstake.png>]
<acc_stake_1000nodes_10kslots_with_cascade.png, id=48, 462.528pt x 346.896pt>
File: acc_stake_1000nodes_10kslots_with_cascade.png Graphic file (type png)
<use acc_stake_1000nodes_10kslots_with_cascade.png>
Package pdftex.def Info: acc_stake_1000nodes_10kslots_with_cascade.png used on
input line 189.
input line 193.
(pdftex.def) Requested size: 462.52686pt x 346.89514pt.
Overfull \hbox (117.52686pt too wide) in paragraph at lines 189--190
Overfull \hbox (117.52686pt too wide) in paragraph at lines 193--194
[][]
[]
[8 <./acc_setpoint_quarterstake.png>] [9 <./acc_stake_1000nodes_10kslots_with_c
ascade.png>] [10] (./cascade.aux) )
[9 <./acc_stake_1000nodes_10kslots_with_cascade.png>] [10] (./cascade.aux) )
Here is how much of TeX's memory you used:
13365 strings out of 480171
274482 string characters out of 5894490
534248 words of memory out of 5000000
31079 multiletter control sequences out of 15000+600000
13366 strings out of 480171
274498 string characters out of 5894490
534249 words of memory out of 5000000
31080 multiletter control sequences out of 15000+600000
474642 words of font info for 47 fonts, out of 8000000 for 9000
59 hyphenation exceptions out of 8191
100i,8n,104p,461b,754s stack positions out of 5000i,500n,10000p,200000b,80000s
</usr/share/texlive/texmf-dist/fonts/type1/p
ublic/amsfonts/cm/cmbx12.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/
amsfonts/cm/cmmi10.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfon
ts/cm/cmmi7.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/c
mr10.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr12.pf
b></usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr17.pfb></usr
/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr7.pfb></usr/share/t
exlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb>
Output written on cascade.pdf (10 pages, 188489 bytes).
</u
sr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb></usr/sha
re/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb></usr/share/tex
live/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb></usr/share/texlive/te
xmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></usr/share/texlive/texmf-dis
t/fonts/type1/public/amsfonts/cm/cmr12.pfb></usr/share/texlive/texmf-dist/fonts
/type1/public/amsfonts/cm/cmr17.pfb></usr/share/texlive/texmf-dist/fonts/type1/
public/amsfonts/cm/cmr7.pfb></usr/share/texlive/texmf-dist/fonts/type1/public/a
msfonts/cm/cmsy10.pfb>
Output written on cascade.pdf (10 pages, 189605 bytes).
PDF statistics:
91 PDF objects out of 1000 (max. 8388607)
52 compressed objects within 1 object stream

View File

@@ -182,6 +182,10 @@ in stake.
\caption{with accuracy set point to primary controller}
\end{figure}
\section {PI, or PID \dots}
\item experiments done on accuracy of cascade control, and relation between staked ratio, and accuracy of finalization using PI, PID controllers, using same parameters in experiments above, with $kd=0$ in primary, and secondary controller, although secondary controller exhibit high oscillation, but overall accuracy doesn't change if derivative term is dropped.
\begin{description}
\item figure 7 shows the relation between staked DRK tokens ratio, and accuracy
\end{description}

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -8,17 +8,17 @@ import os
AVG_LEN = 5
KP_STEP=0.3
KP_SEARCH= 0.03
KP_STEP=0.01
KP_SEARCH= -0.01
KI_STEP=0.3
KI_SEARCH=1.95
KI_STEP=0.01
KI_SEARCH=-0.036
KD_STEP=0.3
KD_SEARCH=-0.95
KD_STEP=0.01
KD_SEARCH=0.0384
EPSILON=0.0001
RUNNING_TIME=1000
RUNNING_TIME=10000
NODES = 1000
highest_acc = 0

View File

@@ -0,0 +1,136 @@
from argparse import ArgumentParser
from core.lottery import DarkfiTable
from core.utils import *
from core.darkie import Darkie
from tqdm import tqdm
from core.strategy import SigmoidStrategy
import os
AVG_LEN = 5
KP_STEP=0.01
KP_SEARCH= -0.01
KI_STEP=0.01
KI_SEARCH=-0.036
EPSILON=0.0001
RUNNING_TIME=1000
NODES = 1000
highest_acc = 0
KP='kp'
KI='ki'
KP_RANGE_MULTIPLIER = 2
KI_RANGE_MULTIPLIER = 2
highest_gain = (KP_SEARCH, KI_SEARCH)
parser = ArgumentParser()
parser.add_argument('-p', '--high-precision', action='store_true')
parser.add_argument('-r', '--randomize-nodes', action='store_false')
parser.add_argument('-t', '--rand-running-time', action='store_false')
parser.add_argument('-d', '--debug', action='store_false')
args = parser.parse_args()
high_precision = args.high_precision
randomize_nodes = args.randomize_nodes
rand_running_time = args.rand_running_time
debug = args.debug
def experiment(controller_type=CONTROLLER_TYPE_DISCRETE, kp=0, ki=0, distribution=[], hp=True):
dt = DarkfiTable(ERC20DRK, RUNNING_TIME, controller_type, kp=kp, ki=ki, kd=0)
RND_NODES = random.randint(5, NODES) if randomize_nodes else NODES
for idx in range(0,RND_NODES):
darkie = Darkie(distribution[idx], strategy=SigmoidStrategy(EPOCH_LENGTH))
dt.add_darkie(darkie)
acc, apy, reward, stake_ratio, apr = dt.background(rand_running_time, hp)
return acc
def multi_trial_exp(kp, ki, distribution = [], hp=True):
global highest_acc
global highest_gain
new_record=False
exp_threads = []
accs = []
for i in range(0, AVG_LEN):
acc = experiment(CONTROLLER_TYPE_DISCRETE, kp=kp, ki=ki, distribution=distribution, hp=hp)
accs += [acc]
avg_acc = sum(accs)/float(AVG_LEN)
buff = 'accuracy:{}, kp: {}, ki:{}'.format(avg_acc, kp, ki)
if avg_acc > 0:
gain = (kp, ki)
acc_gain = (avg_acc, gain)
if avg_acc > highest_acc:
new_record = True
highest_acc = avg_acc
highest_gain = (kp, ki)
with open('log'+os.sep+"highest_gain.txt", 'w') as f:
f.write(buff)
return buff, new_record
SHIFTING = 0.05
def crawler(crawl, range_multiplier, step=0.1):
start = None
if crawl==KP:
start = highest_gain[0]
elif crawl==KI:
start = highest_gain[1]
range_start = (start*range_multiplier if start <=0 else -1*start)
range_end = (-1*start if start<=0 else range_multiplier*start)
# if number of steps under 10 step resize the step to 50
while (range_end-range_start)/step < 10:
range_start -= SHIFTING
range_end += SHIFTING
step /= 10
crawl_range = np.arange(range_start, range_end, step)
np.random.shuffle(crawl_range)
crawl_range = tqdm(crawl_range)
distribution = [random.gauss(ERC20DRK/NODES, ERC20DRK/NODES*0.1) for i in range(NODES)]
for i in crawl_range:
kp = i if crawl==KP else highest_gain[0]
ki = i if crawl==KI else highest_gain[1]
buff, new_record = multi_trial_exp(kp, ki, distribution, hp=high_precision)
crawl_range.set_description('highest:{} / {}'.format(highest_acc, buff))
if new_record:
break
while True:
prev_highest_gain = highest_gain
# kp crawl
crawler(KP, KP_RANGE_MULTIPLIER, KP_STEP)
if highest_gain[0] == prev_highest_gain[0]:
KP_RANGE_MULTIPLIER+=1
KP_STEP/=10
else:
start = highest_gain[0]
range_start = (start*KP_RANGE_MULTIPLIER if start <=0 else -1*start) - SHIFTING
range_end = (-1*start if start<=0 else KP_RANGE_MULTIPLIER*start) + SHIFTING
while (range_end - range_start)/KP_STEP >500:
if KP_STEP < 0.1:
KP_STEP*=10
KP_RANGE_MULTIPLIER-=1
#TODO (res) shouldn't the range also shrink?
# not always true.
# how to distinguish between thrinking range, and large step?
# good strategy is step shoudn't > 0.1
# range also should be > 0.8
# what about range multiplier?
# ki crawl
crawler(KI, KI_RANGE_MULTIPLIER, KI_STEP)
if highest_gain[1] == prev_highest_gain[1]:
KI_RANGE_MULTIPLIER+=1
KI_STEP/=10
else:
start = highest_gain[1]
range_start = (start*KI_RANGE_MULTIPLIER if start <=0 else -1*start) - SHIFTING
range_end = (-1*start if start<=0 else KI_RANGE_MULTIPLIER*start) + SHIFTING
while (range_end - range_start)/KI_STEP >500:
if KP_STEP < 0.1:
KI_STEP*=10
KI_RANGE_MULTIPLIER-=1