algorithm to deal with series of values - objective-c

With a series with a START, INCREMENT, and MAX:
START = 100
INCREMENT = 30
MAX = 315
e.g. 100, 130, 160, 190, 220, 250, 280, 310
Given an arbitrary number X return:
the values remaining in the series where the first value is >= X
the offset Y (catch up amount needed to get from X to first value of the series).
Example
In:
START = 100
INCREMENT = 30
MAX = 315
X = 210
Out:
Y = 10
S = 220, 250, 280, 310
UPDATE -- From MBo answer:
float max = 315.0;
float inc = 30.0;
float start = 100.0;
float x = 210.0;
float k0 = ceil( (x-start) / inc) ;
float k1 = floor( (max - start) / inc) ;
for (int i=k0; i<=k1; i++)
{
NSLog(#" output: %d: %f", i, start + i * inc);
}
output: 4: 220.000000
output: 5: 250.000000
output: 6: 280.000000
output: 7: 310.000000
MBo integer approach will be nicer.

School math:
Start + k0 * Inc >= X
k0 * Inc >= X - Start
k0 >= (X - Start) / Inc
Programming math:
k0 = Ceil(1.0 * (X - Start) / Inc)
k1 = Floor(1.0 * (Max - Start) / Inc)
for i = k0 to k1 (including both ends)
output Start + i * Inc
Integer math:
k0 = (X - Start + Inc - 1) / Inc //such integer division makes ceiling
k1 = (Max - Start) / Inc //integer division makes flooring
for i = k0 to k1 (including both ends)
output Start + i * Inc
Example:
START = 100
INCREMENT = 30
MAX = 315
X = 210
k0 = Ceil((210 - 100) / 30) = Ceil(3.7) = 4
k1 = Floor((315 - 100) / 30) = Floor(7.2) = 7
first 100 + 4 * 30 = 220
last 100 + 7 * 30 = 310

Solve the inequation
X <= S + K.I <= M
This is equivalent to
K0 = Ceil((X - S) / I) <= K <= Floor((M - S) / I) = K1
and
Y = X - (S + K0.I).
Note that it is possible to have K0 > K1, and there is no solution.

Related

Division by Zero error in calculating series

I am trying to compute a series, and I am running into an issue that I don't know why is occurring.
"RuntimeWarning: divide by zero encountered in double_scalars"
When I checked the code, it didn't seem to have any singularities, so I am confused. Here is the code currently(log stands for natural logarithm)(edit: extending code if that helps):
from numpy import pi, log
#Create functions to calculate the sums
def phi(z: int):
k = 0
phi = 0
#Loop through 1000 times to try to approximate the series value as if it went to infinity
while k <= 100:
phi += ((1/(k+1)) - (1/(k+(2*z))))
k += 1
return phi
def psi(z: int):
psi = 0
k = 1
while k <= 101:
psi += ((log(k))/( k**(2*z)))
k += 1
return psi
def sig(z: int):
sig = 0
k = 1
while k <= 101:
sig += ((log(k))**2)/(k^(2*z))
k += 1
return sig
def beta(z: int):
beta = 0
k = 1
while k <= 101:
beta += (1/(((2*z)+k)^2))
k += 1
return beta
#Create the formula to approximate the value. For higher accuracy, either calculate more derivatives of Bernoulli numbers or increase the boundry of k.
def Bern(z :int):
#Define Euler–Mascheroni constant
c = 0.577215664901532860606512
#Begin computations (only approximation)
B = (pi/6) * (phi(1) - c - 2 * log(2 * pi) - 1) - z * ((pi/6) * ((phi(1)- c - (2 * log(2 * pi)) - 1) * (phi(1) - c) + beta(1) - 2 * psi(1)) - 2 * (psi(1) * (phi(1) - c) + sig(1) + 2 * psi(1) * log(2 * pi)))
#output
return B
A = int(input("Choose any value: "))
print("The answer is", Bern(A + 1))
Any help would be much appreciated.
are you sure you need a ^ bitwise exclusive or operator instead of **? I've tried to run your code with input parameter z = 1. And on a second iteration the result of k^(2*z) was equal to 0, so where is from zero division error come from (2^2*1 = 0).

Rounding Non-LinearExpr with google or-tools SAT solver

Using CP-SAT of google or-tools I'm trying to write this constraint:
q >= (50x + 100y + 150z + 200k + 250p + 300v) / (x + y + z + k + p + v)
Where q is a simple integer.
The thing is I need to round the right side of the equation (let's call it expression) as follows:
if(expression < 75) {
expression = 50;
} else if(expression < 125) {
expression = 100;
} else if(expression < 175) {
expression = 150;
} else if(expression < 225) {
expression = 200;
} else if(expression < 275) {
expression = 250;
} else {
expression = 300;
}
So I need to round the expression
(50x + 100y + 150z + 200k + 250p + 300v) / (x + y + z + k + p + v)
So that it gets one of the following values:
{50, 100, 150, 200, 250, 300}
Let's review 2 cases:
Case 1
q = 180 and expression = 176.
Although the condition 180 >= 176 is true, after rounding up 176 to 200 the tested condition should be 180 >= 200 which is false.
So for q = 180 and expression = 176 I would like the condition to return false.
Case 2
q = 210 and expression = 218.
Although the condition 210 >= 218 is false, after rounding down 218 to 200 the tested condition should be 210 >= 200 which is true.
So for q = 210 and expression = 218 I would like the condition to return true.
I got a great answer here for resolving this challenge over a linear expression but now I need to resolve it for a non-linear expression.
Any suggestions?
Let's rephrase
you have an integer variable e with a value between 0 and 300.
You want to round it to the nearest multiple of 50
if you do:
(e div 50) * 50
you will get the max multiple of 50 less or equal to e
(70 / 50) * 50 -> 50
(99 / 50) * 50 -> 50
(102 / 50) * 50 -> 100
To get a round to nearest, you need to add 25 to e before the division
((e + 25) div 50) * 50
Which will do the correct rounding
((70 + 25) / 50) * 50 -> 50
((99 + 25) / 50) * 50 -> 100
((102 + 25) / 50) * 50 -> 100
with the correct or-tools CP-SAT python code:
numerator = model.NewIntVar(...)
model.Add(numerator == 50x + 100y + 150z + 200k + 250p + 300v)
denom = model.NewIntVar(...)
model.Add(denom == 50x + 100y + 150z + 200k + 250p + 300v)
e = model.NewIntVar(0, 300, 'e')
model.AddDivisionEquality(e, numerator, denom)
shifted_e = model.NewIntVar(25, 325, 'shifted_e')
model.Add(shifted_e == e + 25)
multiple_of_fifty = model.NewIntVar(0, 6, 'multiple_of_fifty')
model.AddDivisionEquality(multiple_of_fifty, shifted_e, 50)
result = model.NewIntVar(0, 300, 'result')
model.Add(result = multiple_of_fifty * 50)
if a and b are positive then
a div b >= q
is equivalent to
a >= q * b
now, your example does not specify how to round (nearest or down)
if you want to round down
q * (x + y + z + k + p + v) <= (50x + 100y + 150z + 200k + 250p + 300v)
If you want to round to nearest, you need to add q / 2 in the right place
q * (x + y + z + k + p + v) <= (50x + 100y + 150z + 200k + 250p + 300v + q / 2)
Now, if you want the other direction
a div b <= q
is equivalent to
a <= q * b + q - 1
The rest of the transformation is the same.

Convert number to float in bytes

I know that lua uses double precision number formats so I wonder if there is a way to convert number directly into string as float value (4 bytes) so that I could send it over udp socket
For Lua 5.3+
local function float32_binary_dump(value)
return ("<f"):pack(value)
end
For Lua 5.1+
local function float32_binary_dump(value)
local img, s, h, d = 2^32 - 2^22, "", 1
if value == value then
img = 2^31 - 2^23
if value < 0 or value == 0 and 1/value < 0 then
value, img = -value, 2^32 - 2^23
end
if value > 0.5 * 2^-149 and value < 2^128 then
-- rounding 64-bit double to 32-bit float
d = math.floor(math.log(value)/math.log(2) + 0.5)
d = value < 2^d and d - 1 or d
local e = 2^(d < -126 and -149 or d - 23)
value = value + 0.5 * e
local r = value % e
value = value - (r == 0 and value % (e + e) or r)
end
-- dumping 32-bit image of float
if value < 2^-149 then
img = img - (2^31 - 2^23)
elseif value <= 2^128 - 2^104 then
if d < -126 then
d, h = -126, 0
end
img = img + (value / 2^d + (d - (-126)) * h - 255) * 2^23
end
end
-- convert 32-bit image to little-endian string
while #s < 4 do
local b = img % 256
s = s..string.char(b)
img = (img - b) / 256
end
return s
end

Visual basic function for intermittent antibiotic dosing

I am a beginner in VB. I wrote a little program to simulate dosing regimens of antibiotics using some exponential equations and pharmacokinetic data.
The problem I have is that I want to display on a graph the following mathematical function:
That simulates the concentration variation at different intervals of time:
Where:
b(t) is the concentration at time t that will be plotted as Y axis, t is time (plotted on the x-axis).
b(0) is the concentration at time 0 and it is a known variable.
u(t-a1) is a function that has the value u(t-a1)=b(o) if t=a1 or 0 if t<>a1
a1 is the time at which a next dose is given.
alpha is the elimination rate constant, a variable that is known.
What I have so far:
Dim y, x As Double
For x = 0 To 24 Step 1
For n As Double = 1 To 24 / tau
y = (1 - test_condition(n * tau, x)) * css * Math.Exp(-ke * x) + test_condition(n * tau, x) * css * Math.Exp(-ke * (x - n * tau))
Chart1.Series("Concentratie1").Points.AddXY(x, y)
Next
Next
The test_condition:
if x=tau then test_condition= 1 else 0
It is close but I don't get an exponential decay after a dose ... don't know how to make that happen.
This works!! for tau (dosing interval) every 4 hours. Can it be rearranged somehow because the tau (dosing interval) will vary (sometimes 4 hours, sometimes every 6 hours)?:
Dim y, x, y2, x2, y3, x3, y4, x4, x5, x6, y5, y6 As Double
For x = 0 To tau Step 1
y = exponential_decay(css, ke, x) + test_condition(tau, x) * (css - Val(mic))
Chart1.Series("Bolus 1").Points.AddXY(x, y)
Next
For x2 = tau To 2 * tau Step 1
y2 = exponential_decay(css, ke, x2 - tau) + test_condition(2 * tau, x2) * (css - Val(mic))
Chart1.Series("Bolus 2").Points.AddXY(x2, y2)
Next
For x3 = 2 * tau To 3 * tau Step 1
y3 = exponential_decay(css, ke, x3 - 2 * tau) + test_condition(3 * tau, x3) * (css - Val(mic))
Chart1.Series("Bolus 3").Points.AddXY(x3, y3)
Next
For x4 = 3 * tau To 4 * tau Step 1
y4 = exponential_decay(css, ke, x4 - 3 * tau) + test_condition(4 * tau, x4) * (css - Val(mic))
Chart1.Series("Bolus 4").Points.AddXY(x4, y4)
Next
For x5 = 4 * tau To 5 * tau Step 1
y5 = exponential_decay(css, ke, x5 - 4 * tau) + test_condition(5 * tau, x5) * (css - Val(mic))
Chart1.Series("Bolus 4").Points.AddXY(x5, y5)
Next
For x6 = 5 * tau To 32 Step 1
y6 = exponential_decay(css, ke, x6 - 5 * tau)
Chart1.Series("Bolus 4").Points.AddXY(x6, y6)
Next
End Sub
I managed to solve the problem:
this function f relates time (t) to dosing interval (tau)
Private Function f(ByVal t As Double, ByVal tau As Double)
Dim n As Integer
For n = 0 To 24 / tau
If t = n * tau Then
f = n * tau
ElseIf t < tau Then
f = 0
ElseIf t > n * tau And t < (n + 1) * tau Then
f = n * tau
ElseIf t >= (n + 1) * tau Then
f = n * tau
End If
Next
End Function
And this is what I draw on the chart:
For x = 0 To 36 Step 0.5
y = exponential_decay(css, ke, x - f(x, tau))
Chart1.Series("Intermitent Dosage").Points.AddXY(x, y)
Next

Conditional if sum

I want to sum over a range (Areas) except if j is not equal to k.
Can anybody help me?
I tried:
forall( k in Areas )
sum ( j in Areas: j!=k ) X[k][j] == 1;
Also tried:
forall( k in Areas )
sum ( j in Areas) (j!=k)*X[k][j] == 1;
int NbAreas = 5;
range Areas = 1..NbAreas;
float P[Areas] = [0, 0.3, 0.65, 0.2, 0.1];
float D[Areas] = [0, 7, 5, 3, 9];
float FROMTO[Areas][Areas] = [
[0, 2, 5, 1, 3],
[2, 0, 4, 3, 8],
[5, 4, 0, 6, 2],
[1, 3, 6, 0, 7],
[3, 8, 2, 7, 0]];
dvar int Y[Areas];
dvar int T[Areas];
dvar int X[Areas][Areas] in 0..1;
maximize sum( i in Areas ) P[i] * Y[i];
subject to {
forall( k in Areas )
sum ( j in Areas: j!=k) X[k][j] == 1;
forall( k in Areas)
sum ( i in Areas: i!=k) X[i][k] == 1;
forall( i in Areas) forall (j in Areas) T[i] + FROMTO[i][j] - T[j] - 100*(1-X[i][j]) <= 0;
T[1] == 0;
forall( i in Areas: i!=1) T[i] - D[i] - 1000*(1-Y[i]) <= 0;
}
I take it you meant
I want to sum over a range (Areas) except if j is equal (instead
of "not equal") to k.
I also assume that your issue is that the model you posted is infeasible. You should label your constraints so that the conflict refiner can run and then look at the results of the conflict refiner. If I label your constraints like so:
maximize sum( i in Areas ) P[i] * Y[i];
subject to {
forall( k in Areas )
sum1: sum ( j in Areas: j!=k) X[k][j] == 1;
forall( k in Areas)
sum2: sum ( i in Areas: i!=k) X[i][k] == 1;
forall( i in Areas) forall (j in Areas)
fromto: T[i] + FROMTO[i][j] - T[j] - 100*(1-X[i][j]) <= 0;
T[1] == 0;
forall( i in Areas: i!=1)
limit: T[i] - D[i] - 1000*(1-Y[i]) <= 0;
Then I get this conflict:
sum1(1): X(1)(2) + X(1)(3) + X(1)(4) + X(1)(5) = 1
sum1(2): X(2)(1) + X(2)(3) + X(2)(4) + X(2)(5) = 1
sum1(3): X(3)(1) + X(3)(2) + X(3)(4) + X(3)(5) = 1
sum1(4): X(4)(1) + X(4)(2) + X(4)(3) + X(4)(5) = 1
sum1(5): X(5)(1) + X(5)(2) + X(5)(3) + X(5)(4) = 1
fromto(1)(2): 100 X(1)(2) + T(1) - T(2) <= 98
fromto(1)(3): 100 X(1)(3) + T(1) - T(3) <= 95
fromto(1)(4): 100 X(1)(4) + T(1) - T(4) <= 99
fromto(1)(5): 100 X(1)(5) + T(1) - T(5) <= 97
fromto(2)(1): 100 X(2)(1) - T(1) + T(2) <= 98
fromto(2)(3): 100 X(2)(3) + T(2) - T(3) <= 96
fromto(2)(4): 100 X(2)(4) + T(2) - T(4) <= 97
fromto(2)(5): 100 X(2)(5) + T(2) - T(5) <= 92
fromto(3)(1): 100 X(3)(1) - T(1) + T(3) <= 95
fromto(3)(2): 100 X(3)(2) - T(2) + T(3) <= 96
fromto(3)(4): 100 X(3)(4) + T(3) - T(4) <= 94
fromto(3)(5): 100 X(3)(5) + T(3) - T(5) <= 98
fromto(4)(1): 100 X(4)(1) - T(1) + T(4) <= 99
fromto(4)(2): 100 X(4)(2) - T(2) + T(4) <= 97
fromto(4)(3): 100 X(4)(3) - T(3) + T(4) <= 94
fromto(4)(5): 100 X(4)(5) + T(4) - T(5) <= 93
fromto(5)(1): 100 X(5)(1) - T(1) + T(5) <= 97
fromto(5)(2): 100 X(5)(2) - T(2) + T(5) <= 92
fromto(5)(3): 100 X(5)(3) - T(3) + T(5) <= 98
fromto(5)(4): 100 X(5)(4) - T(4) + T(5) <= 93
So it seems your data in FROMTO and T does not allow a feasible solution.
You wrote "except if j is not equal to k".
So instead of
forall( k in Areas)
sum ( i in Areas: i!=k) X[i][k] == 1;
I would write
forall( k in Areas)
sum ( i in Areas: i==k) X[i][k] == 1;