[ot][spam][crazy][spam][confused code] asdf!
i'm a little [read: severely] confused and have a few hours of downtime. i'm thinking of working on a bug in code i wrote that relates to summing integer sequences taken with unpredictable offset from a linear graph, without letting their sum pass a certain threshold which the slope of the graph is calculated to enforce
271 if remaining <= ratelimit_period and ratelimit_period > delay * 2: 272 min_delay = block_time / dividor 273 # min_delay + max_delay / 2 = ratelimited_delay 274 extra_delay = 2 * ratelimited_delay - 3 * min_delay 275 delay = min_delay + extra_delay * (eta - mark_time) / ratelimit_period 276 -> assert mark_time + delay < eta (Pdb) p mark_time, delay, mark_time + delay, eta (1689617957.9965212, 14.028799527978448, 1689617972.0253208, 1689617965.997948) the code is from a progress bar with automated delay that is used in loops that query polling-based api endpoints that are waiting for something slow to happen like a transaction to be mined into a block. some constraints are: - the endpoint may not be queried more than ratelimit_count every ratelimit_period (outside this block, usually delay = ratelimit_period / ratelimit_count ) - the code is never called more than once every "delay" seconds also: - if a total is known, then as n approaches the total, the endpoint should be queried close to min_delay = block_time / dividor instead - things may come up resulting in the code being called at any point in time at all, but it is always called after an api call
so the immediate issue is that it's planning a delay that passes the predicted completion time. rather, the delay should be slightly less than the predicted completion time so that the final successful query can be made as early as possible instead of a little late. it makes sense there is a mistake because i made the linear solution when i was very confused.
variable definitions: eta # expected completion timestamp remaining = eta - now # number of seconds until expected completion time ratelimit_period # number of seconds within which ratelimit is calculated min_delay # target query frequency at eta; this is the ideal frequency without a ratelimit extra_delay # added delay in the last ratelimit period to leave space in the ratelimit prior so as to query more near eta mark_time # time of last query delay # time to wait before next query
daydreaming a little on the general situation; maybe a different solution would be more robust daydream content: we have ratelimit_count total queries available in the last ratelimit_period and we want two of the queries to have set times: eta and eta - min_period
daydream re-attempt: we have ratelimit_count total queries available in the last ratelimit_period and we want two of the queries to have set times: eta and eta - min_period [we can in theory count the queries we have made in the final ratelimit_period. this gives us a number of queries remaining we have. maybe ideally, we would time them so that third-to-last precisely meets the second-to-last.] [other branch of daydream: instead of summing them from the large end, where we can overrun if the integer shift changes from delay, we could sum them backward from the small end. that is, we would plan on the future times, and pick the time that provides for them. maybe we could try an example.
daydream example daydream: uhhhhhhhh ok so ummm we still have this line i guess maybe that extends from min_delay + extra_delay down to min_delay ?
daydream example daydream re-attempt: so we have the last two, and we have ratelimit_count total. the last one would be eta the second to last would be eta - min_period then ratelimit_count / 2 fit in the remaining ones. it would be nice if the third to last were almost to eta - min_period * 2 . and the total sum of the delays is ratelimit_period ! ok i think i have it !!!!!!!!!!! basically we keep track of how many we have left, ratelimit_count - number_of_calls_in_final_period then we do the linear slope thing using this remaining_ratelimit_count rather than the whole ratelimit_count uhhhhhhhhhhhh partially ! partially! and we want to figure it so that it actually works, rather than overflowing.
inference-from-daydreams attempt further daydream: anyway um the basic conclusion is that if we take our immediate current time as the start of a line then we can calculate things appropriately for what the current actual situation is. rather than placing the current time on a line based on old numbers; it's a simpler situation, and still produces just as "correct" a solution i think.
if remaining <= ratelimit_period and ratelimit_period > delay * 2: min_delay = block_time / dividor # min_delay + max_delay / 2 = ratelimited_delay extra_delay = 2 * ratelimited_delay - 3 * min_delay delay = min_delay + extra_delay * (eta - mark_time) / ratelimit_period assert mark_time + delay < eta the old code calculates a linear relation based on mark_time and ratelimit_period it's using ratelimited_delay = ratelimit_period / ratelimit_count instead we could track ratelimit_count - # calls, call it remaining_count or remaining_ratelimit_count [and figure out one single delay (or chart a line again) based on this] [and ensure the last two queries at eta and eta-min_period !]
basically, we have specific delay points based on: time_point = 0 time_point = eta - min_delay time_point = eta - min_delay - min_delay + a little ... time_point = eta - remaining where there are remaining_count time_points total so we just need to cobble those parts together into a new linear thingy and then figure out delay so that the next time_point is reached, rather than taking delay straight from the linear thingy. and then it can be written in a way that is precalculable again, and may even be the exact same thing
so we can actually simplify it to say delay should make sure to wait for the next time_point but given delay can
time_points[-1] = eta time_points[-2] = eta - min_delay time_points[-3] = eta - min_delay - (min_delay + a little) time_points[0] = eta - remaining len(time_points) == remaining_count so this thing: time_points[-3] = eta - min_delay - (min_delay + a little) should be a linear thingy uhh like maybe time_points[-x] = eta - min_delay * x - UNK * x = eta + (-min_delay - UNK) * x helps to think of like graph something is changing over something else in linear manner
think of from different avenue [if you have enough people doing something it can happen [mistake present?]] so a value is changing from 0, to min_delay, to remaining if we assume min_delay < remaining, then we can see that the slope is min_delay in that view, because each index is 1 more. this shows a constraint issue: if our slope is min_delay, and we have remaining_count total, and the value at remaining_count is remaining, then the slope is doubly defined. one of the slope definitions says it should be (remaining / remaining_count) the other says it should be min_delay. options include: making it quadratic, shrinking min_delay, shrinking remaining and tacking extra min_delays on
ok i think part of my confusion is that i defined it as having a regular rate rather than a changing rate
what do i want to happen? what are the constraints? what do they imply? i'm tentatively imagining a delay that linearly reduces to min_delay. if it linearly reduces, then it reduces at some rate, reduce_rate maybe it's simpler to think of it going back in time, from the end where the value could be considered 0 or min_delay or something.
the time points are quadratic if the delays are linear because they integrate them. this is helpful clarity.
time_point = a x^2 + b x + c time_point[remaining_count] = eta time_point[0] = ratelimit_time subtract ratelimit_time time_point[remaining_count] = remaining time_point[remaining_count - 1] = remaining - min_period time_point[0] = 0 reverse indices and direction of time delays_from_end[0] = 0 delays_from_end[1] = min_period delays_from_end[remaining_count] = remaining ax^2 + bx + c = 0
a = (remaining / remaining_count - min_period) / (remaining_count - 1) b = min_period - a c = 0 work [usually made a mistake and have to go back and fix it and propagate the fix through]: remainings[0] = 0 remainings[1] = min_period remainings[remaining_count] = remaining y(x) = ax^2 + bx + c y(0) = c = 0 y(1) = a + b + c = min_period y(remaining_count) = a (remaining_count^2) + b (remaining_count) + c = remaining c = 0 a + b = min_period a(remaining_count^2) + b(remaining_count) = remaining b = min_period - a a(remaining_count^2) + (min_period - a)(remaining_count) = remaining a * remaining_count^2 + min_period * remaining_count - a * remaining_count = remaining a * remaining_count^2 - a * remaining_count = remaining - min_period * remaining_count a * (remaining_count^2 - remaining_count) = remaining - min_period * remaining_count a = (remaining - min_period * remaining_count) / (remaining_count^2 - remaining_count) a = (remaining / remaining_count - min_period) / (remaining_count - 1)
yayyyyyyyyy quadratic formula to check it we put numbers in and see if it works out what is the check ummmm uhhhh i'm thinking that the point is the difference between adjacent remainings sums to remaining, but i think this is already implied by the formula maybe just plugging back in the three known values
def remainings(idx, remaining_count, remaining, min_delay): ... a = (remaining / remaining_count - min_delay) / (remaining_count - 1) ... b = min_delay - a ... return a * idx * idx + b * idx ... import random min_delay = random.random() remaining = random.random() remaining_count = int(random.random() * 64) remainings(0, remaining_count, remaining, min_delay) 0.0 remainings(1, remaining_count, remaining, min_delay) - min_delay 0.0 remainings(remaining_count, remaining_count, remaining, min_delay) - remaining 2.55351295663786e-15
parts moved around to elide mistakes ok, the final issue is there are remaining_count + 1 instances rather than remaining_count ... one at eta and one with remaining left .... ummmm i think that's in line with how remaining_count is calculated. one of them would be part of a different one-sided window. could be wrong.
ok ummmmmmmmmmmmmmm so i can calculate remainings and hence time points of each desired delay then we have current timepoint, how to figure out delay ummmmmm ah-ha if we have remaining_count, then we only need remainings[1] . we don't need the others until called again.
yay coding! remainings[remaining_count-1] is there a way to simplify the work to add as a comment?
# remainings[0] = 0 # remainings[1] = min_period # remainings[remaining_count] = remaining # >>> def remainings(idx, remaining_count, remaining, min_delay): # ... a = (remaining / remaining_count - min_delay) / (remaining_count - 1) # ... b = min_delay - a # ... return a * idx * idx + b * idx noting b depends on a also wondering what form here is useful ... maybe the timepoint rather than remaining, which would be eta - remaining? uhhhhhhhhhhhhhhhhhh also noting that remaining is wrong context maybe stop posting for a bit
# remainings[0] = 0 # remainings[1] = min_period # remainings[remaining_count] = remaining # >>> def remainings(idx, remaining_count, remaining, min_delay): # ... a = (remaining / remaining_count - min_delay) / (remaining_count - 1) # ... b = min_delay - a # ... return a * idx * idx + b * idx
ok hash out context issue. remaining here i'm not sure what it means. it's defined as the time left at remainings[remaining_count] i guess that would be mark_time. the time of last execution. now we want to know the delay for the next time. so then remainings[remaininng_count] = eta - mark_time # remainings[0] = 0 # remainings[1] = min_period # remainings[remaining_count] = eta - mark_time # >>> def remainings(idx, remaining_count, eta, mark_time, min_delay): # ... a = ((eta - mark_time) / remaining_count - min_delay) / (remaining_count - 1) # ... b = min_delay - a # ... return (a * idx + b) * idx we could then recast everything based on absolute times which might be clearer for me after some thought and noting i guess that means just subtracting from eta at first # reversetimepoint[0] = eta # reversetimepoint[1] = eta - min_delay # reversetimepoint[remaining_count] = mark_time # >>> def reversetimepoints(idx, remaining_count, eta, mark_time, min_delay): # ... a = (mark_time / remaining_count - min_delay) / (remaining_count - 1) # ... b = eta - min_delay - a # ... return eta - (a * idx + b) * idx want to solve for a,b,c again
work 2 def reversetimepoints(idx, mark_time, min_delay, eta, remaining_count): a = -((eta - mark_time) / remaining_count - min_delay) / (remaining_count - 1) b = -(a + min_delay) c = eta return (a * idx + b) * idx + c
mark_time = random.random() eta = mark_time + random.random() remaining_count = int(64 * random.random()) min_delay = random.random() * random.random() reversetimepoints(0, mark_time, min_delay, eta, remaining_count) - eta 0.0 reversetimepoints(1, mark_time, min_delay, eta, remaining_count) - (eta - min_delay) 0.0 reversetimepoints(remaining_count, mark_time, min_delay, eta, remaining_count) - mark_time 0.0
reversetimepoints[remaining_count] = mark_time reversetimepoints[1] = eta - min_delay reversetimepoints[0] = eta y(x) = ax^2 + bx + c y(0) = c = eta y(1) = a + b + c = eta - min_delay y(remaining_count) = a (remaining_count^2) + b (remaining_count) + c = mark_time c = eta a + b + c = eta - min_delay a + b = -min_delay a(remaining_count^2) + b(remaining_count) + eta = mark_time b = -a - min_delay a(remaining_count^2) - (a + min_delay)(remaining_count) + eta = mark_time a(remaining_count^2) - (a * remaining_count + min_delay * remaining_count) = mark_time - eta a(remaining_count^2) - a * remaining_count - min_delay * remaining_count = mark_time - eta a(remaining_count^2) - a * remaining_count = mark_time - eta + min_delay * remaining_count a * (remaining_count^2 - remaining_count) = mark_time - eta + min_delay * remaining_count a * (remaining_count^2 - remaining_count) = (mark_time - eta + min_delay * remaining_count) / (remaining_count^2 - remaining_count) a = (mark_time - eta + min_delay * remaining_count) / (remaining_count^2 - remaining_count) a = ((mark_time - eta) / remaining_count + min_delay) / (remaining_count - 1) a = (min_delay + (mark_time - eta) / remaining_count) / (remaining_count - 1) a = (min_delay - (eta - mark_time) / remaining_count) / (remaining_count - 1) a = -((eta - mark_time) / remaining_count - min_delay) / (remaining_count - 1)
yayyyy but a problem remains what if now > remaining_count[1] what shud it do [this is the same problem i started with]
On 7/17/23, Undescribed Horrific Abuse, One Victim & Survivor of Many <gmkarl@gmail.com> wrote:
yayyyy but a problem remains what if now > remaining_count[1] where by remaining_count[1] i mean reversetimepoints[remaining_count-1] what shud it do [this is the same problem i started with]
ok ummmmmmmmmmmmm i think it has to do with ummm treating the current point as the starting time or something. maybe we don't really say reversetimepoints[remaining_count] = mark_time [we could for example set it to now instead] thinking about this a little bit but misplaced thought grumph
ok ummm an event happens at mark_time now it is now, shortly after mark_time the event could be any speed at all, very fast or suddenly very slow what should happen if now_time is farther along? it seems we'd want to change how things are plotted so more events are squeezed into the remaining time, assuming they aren't as slow as that one was. [usually it updates the ratelimit count and period when this happens too] maybe it is a special condition ummmmmmmmmmmmmmmmm i guess we probably have time to send something off immediately in that case! it could send it immediately, which would make a new mark_time from which things could be calculated based on new data this seems to make sense! it's even a quick fix to the old code but maybe i'll add in the new code anyway i like how it can calculate what is minimally needed given the constants could change
asdf asdf asdf :) - we can solve the 2nd order polynomial for idx=remaining_count-1 to figure out delay - if now > mark_time + delay, then we can set delay = 0 and send the next one immediately, assuming the code then updates the delay after this, because we have ratelimit_count remaining anyway def reversetimepoints(idx, mark_time, min_delay, eta, remaining_count): # reversetimepoints[remaining_count] = mark_time # reversetimepoints[1] = eta - min_delay # reversetimepoints[0] = eta # y(x) = ax^2 + bx + c a = -((eta - mark_time) / remaining_count - min_delay) / (remaining_count - 1) b = -(a + min_delay) c = eta return (a * idx + b) * idx + c
yay mark_remaining = eta - mark_time next_mark_time = ( mark_remaining * (mark_time - 3 * min_delay + 2 * mark_remaining / remaining_count) - (mark_time - min_delay) * min_delay * remaining_count ) / (mark_remaining - min_delay * remaining_count) i did 34 manual iterations to expand and factor it as if it was old c code. they are attached. likely done poorly but it's what i did.
oh no a = -((eta - mark_time) / remaining_count - min_delay) / (remaining_count - 1) what happens when remaining_count == 1
ok ummmmmmmmmmmmmmmmmmmm it's because i gave it 3 preconditions and it only has 2 points remaining
here we go. the divide-by-zero cancels out. not sure how this was originally noticed. timepoint37 has one divide, one multiply, and one use of every variable except for eta which has two uses. def timepoint35(mark_time, min_delay, eta, remaining_count): X = remaining_count - 1 NA_X = (eta - mark_time) / remaining_count - min_delay NB_X = min_delay * X - NA_X C = eta return C - NA_X * X - NB_X def timepoint36(mark_time, min_delay, eta, remaining_count): X = remaining_count - 1 NA_X = (eta - mark_time) / remaining_count - min_delay NA_XX = ((eta - mark_time) / remaining_count - min_delay) * X NB_X = min_delay * remaining_count - (eta - mark_time) / remaining_count NAXXBX = (eta - mark_time) / remaining_count * (X - 1) + min_delay * (remaining_count - X) C = eta return C - NAXXBX def timepoint37(mark_time, min_delay, eta, remaining_count): return eta - (eta - mark_time) * (1 - 2 / remaining_count) - min_delay
[what is the point of the code ... long story short it is for timing cosmos-family blockchain autocompounding transactions. [the best time to send them is when the blocks they are likely mined in produce the highest reward, [haven't learned enough about the chains to calculate that precisely, not sure if i will] since the math involves integer truncation multiple times the reward % is different on different blocks.] [my trick for getting into cryptocurrency a little again is to take it very slowly, and doing things supported by more mainstream groups that can back it. for example, i started by simply staking on coinbase, and the staking had issues and i had to raise a support ticket and escalate it and it got resolved eventually] [significant worries/mistakes present. information also missing.]]
boss has wrong assumption makes brain-barfing why are the business people setting up economic systems that move money to smart people
if business people are smart why are smart people getting made stupid shouldn't the business people just out-smart the people they would make stupid?
groups that can back it. for example, i started by simply staking on coinbase, and the staking had issues and i had to raise a support
the reason this works for me is my habits often make kind of "vicious cycles of stopping or harm" bugs and mistakes and network issues develop in a pattern my experiences tries to recognise as confirming the behavior has stopped. with e.g. coinbase, they make it keep going, and it can be a backup of something i do on my own, to prevent things from stopping. it changes the psychological experience significantly.
participants (1)
-
Undescribed Horrific Abuse, One Victim & Survivor of Many