handle trajectory singularity: delete photons causing error - python

I am coding a black hole (actually photons orbiting a black hole) and I need to handle an exception for radius values that are smaller than the limit distance
I've tried using if and while True
def Hamiltonian(r, pt, pr, pphi):
H = (-((1-rs/r)**-1)*(pt**2)/2 + (1-rs/r)*(pr**2)/2 + (pphi**2)/(2* (r**2)))
if np.amax(H) < 10e-08:
print("Your results are correct")
else:
print("Your results are wrong")
return(H)
def singularity(H, r):
if (r).any < 1.5*rs:
print(H)
else:
print("0")
return(H, r)
print(Hamiltonian(r00, pt00, pr00, pphi00))
I'd like to handle the case r < 1.5*rs so that I don't have the division error message and weird orbits anymore. So far my code doesn't change anything to the problem, I still get this error message :
"RuntimeWarning: divide by zero encountered in true_divide
H = (-((1-rs/r)**-1)*(pt**2)/2 + (1-rs/r)*(pr**2)/2 + (pphi**2)/(2*(r**2)))"
and my orbits are completely wrong (for example my photon should go right in the black hole, but since there's a singularity at r < 1.5*rs, they go in and leave again and so on)
I'd like to delete the photons causing the problem but I don't know how, can anyone please help me?

I think you mention that we do not know exactly what goes on at a singularity. Any answer provided here most likely would not be accurate, but let's just assume that you know the behavior/dynamics at the near 0 neighborhood. I do not know how you are calling the Hamiltonian function but I can imagine you are doing it one of two ways.
You have a pre-defined loop that loops through each value you are passing into the function and outputting the resulting H for each value in that pre-defined loop.
You are passing in vectors of the same length and doing element by element math in the H function.
In the first case, you could either do a pre-check and write a new function for the near 0 behavior and call that new function if you are in the near zero neighborhood. You could also just have the check in the hamiltonian function itself and call the new function if you are in the near 0 neighborhood. This latter method is what I would prefer as it keeps the front-end (the best word I have for it) fairly clean and encapsulates the logic/math in your Hamiltonian function. In your comments you say you want to delete the photon within some radius, and that would be extremely easy to do with this method by just terminating the for loop by breaking out at that time step and plotting what you had until that time step.
In the second case, you would have to manually build the new vector by having checks throughout your vectors if they fall within the singularity neighborhood. This would be a little more difficult and would depend on the shape of your inputs and doing element by element math is more difficult to debug in my opinion.

Related

Unusual behaviour of Z3py optimization program

I'm writing a program that scrapes option_chain data off the TMX website and suggests an optimized Covered Call options portfolio based on those data. for the optimization process, I used the z3py library as discussed on this website by many users. the optimization process works by maximizing the premiums and setting the portfolio delta to a user-specified amount.
initially, I made a mistake in my calculation for portfolio delta which made everything work so smoothly but I'm facing issues after correcting it. portfolio delta is calculated by taking the Weighted average delta of non-zero positions in the portfolio. to achieve this I used the following setup:
eng = Optimize()
Weights = [Real(row.symbol) for row in df.itertuples()]
#to count non-zero positions
TotCount = Real("TotCount")
eng.add(TotCount == Sum([If(w > 0, 1, 0) for w in Weights]))
eng.add(TotCount == If(TotCount >= 0, TotCount, 1))
#to get portfolio delta
eng.add(TotDelta == (Sum([(w * row.delta) for w, row in zip(Weights, df.itertuples())]) / TotCount))
eng.add(TotDelta == delta)
res = eng.check()
the weird behavior happens when I run this as a function in a loop with different values for delta, the first loop actually does the calculation and spits out an answer but after that my code gets stuck on the last line for hours without any progress. i tried a few things like completely reformatting it but nothing seems to make a difference. I was wondering if anyone knows what's happening here or not?
Unfortunately, there isn't much in your description for anyone to go on without knowing further details of your setup. All one can deduce from your text is that the constraints are hard to solve for those values of delta where it takes longer. Without seeing the rest of your program, it's impossible to opine on what else might be going on.
See if you can isolate the value of delta that it runs slowly on, and just run it for that one instance separately to see if there's interaction coming from elsewhere. That's by no means a solution of course, but it's one way to get started.
One thing I noticed, though, is this line you have:
eng.add(TotCount == If(TotCount >= 0, TotCount, 1))
Let's see what this line is saying: If TotCount >= 0, then it says TotCount == TotCount. i.e., it puts no restrictions on it. Otherwise, it says TotCount == 1; i.e., if TotCount < 0, then TotCount == 1. Well this latter statement is obviously false. That is if, the other constraints force TotCount < 0, then your program would be unsat. This essentially means that whole line is functionally equivalent to:
eng.add(TotCount >= 0)
It's hard for anyone to tell if that's what you intended; but I suspect perhaps it isn't; since you'd have just written the simpler form above. Perhaps you wanted to say something more along the lines of if TotCount < 0, then make it 1. But looking at the previous line, (i.e., the Sum expression), we see that this'll never be the case. So, something is fishy there.
Hope that helps to get you started; note that you cannot model "sequential assignment" like in a programming language in this way. (You'd need to do what's known as single static assignment, a.k.a. SSA, conversion.) But then again, without knowing your exact intention, it's hard to opine.

Python SciPy ODE solver not converging

I'm trying to use scipy's ode solver to plot the interaction between a 2D system of equations. I'm attempting to alter the parameters passed to the solver by the following block of code:
# define maximum number of iteration steps for ode solver iteration
m = 1 #power of iteration
N = 2**m #number of steps
# setup a try-catch formulation to increase the number of steps as needed for solution to converge
while True:
try:
z = ode(stateEq).set_integrator("vode",nsteps=N,method='bdf',max_step=5e5)
z.set_initial_value(x0, t0)
for i in range(1, t.size):
if i%1e3 == 0:
print 'still integrating...'
x[i, :] = z.integrate(t[i]) # get one more value, add it to the array
if not z.successful():
raise RuntimeError("Could not integrate")
break
except:
m += 1
N = 2**m
if m%2 == 0:
print 'increasing nsteps...'
print 'nsteps = ', N
Running this never breaks the while loop. It keeps increasing the nsteps forever and the system never gets solved. If I don't put it in the while loop, the system gets solved, I think, because the solution gets plotted. Is the while loop necessary? Am I formulating the solver incorrectly?
The parameter nsteps regulates how many integration steps can be maximally performed during one sampling step (i.e., a call of z.integrate). Its default value is okay if your sampling step is sufficiently small to capture the dynamics. If you want to integrate over a huge time span in one large sampling step (e.g., to get rid of transient dynamics), the value can easily be too small.
The point of this parameter is to avoid problems arising from unexpectedly very long integrations. For example, if you want to perform a given integration for 100 values of a control parameter in a loop over night, you do not want to see on the next morning that the No. 14 was pathological and is still running.
If this is not relevant to you, just set nsteps to a very high value and stop worrying about it. There is certainly no point to successively increase nsteps, you are just performing the same calculations all over again.
Running this never breaks the while loop. It keeps increasing the nsteps forever and the system never gets solved.
This suggests that you have a different problem than nsteps being exceeded, most likely that the problem is not well posed. Carefully read the error message produced by the integrator. I also recommend that you check your differential equations. It may help to look at the solutions until the integration fails to see what is going wrong, i.e., plot x after running this:
z = ode(stateEq)
z.set_integrator("vode",nsteps=1e10,method='bdf',max_step=5e5)
z.set_initial_value(x0, t0)
for i,time in enumerate(t):
x[i,:] = z.integrate(time)
if not z.successful():
break
Your value for max_step is very high (this should not be higher than the time scale of your dynamics). Depending on your application, this may very well be reasonable, but then it suggests that you are working with large numbers. This in turn may mean that the default values of the parameters atol and first_step are not suited for your situation and you need to adjust them.

Python performance questions for: toggling +/-1, set instantiation, set membership check

I've been working on the following code which sort of maximizes the number of unique (in lowest common denominator) p by q blocks with some constraints. It is working perfectly. For small inputs. E.g. input 50000, output 1898.
I need to run it on numbers greater than 10^18, and while I have a different solution that gets the job done, this particular version gets super slow (made my desktop reboot at one point), and this is what my question is about.
I'm trying to figure out what is causing the slowdown in the following code, and to figure out in what order of magnitude they are slow.
The candidates for slowness:
1) the (-1)**(i+1) term? Does Python do this efficiently, or is it literally multiplying out -1 by itself a ton of times?
[EDIT: still looking for how operation.__pow__ works, but having tested setting j=-j: this is faster.]
2) set instantiation/size? Is the set getting too large? Obviously this would impact membership check if the set can't get built.
3) set membership check? This indicates O(1) behavior, although I suppose the constant continues to change.
Thanks in advance for insight into these processes.
import math
import time
a=10**18
ti=time.time()
setfrac=set([1])
x=1
y=1
k=2
while True:
k+=1
t=0
for i in xrange(1,k):
mo = math.ceil(k/2.0)+((-1)**(i+1))*(math.floor(i/2.0)
if (mo/(k-mo) not in setfrac) and (x+(k-mo) <= a and y+mo <= a):
setfrac.add(mo/(k-mo))
x+=k-mo
y+=mo
t+=1
if t==0:
break
print len(setfrac)+1
print x
print y
to=time.time()-ti
print to

Circles touching edges

I am struggling with a program to tell whether a created disk touches the edge of a predefined box. The parser keeps saying things such as
NameError: global name 'disksdescription' is not defined
Warning: variable 'left' is assigned to, but never used
The code so far is:
import numpy.random as nr
def touch_sides(disk, radius, x, y):
for disk in disksdescription:
for left in disk.values()[2]:
if x <= radius:
left = True
else:
left = False
for right in disk.values()[3]:
if x >= 1-radius:
right = True
else:
right = False
def run_code():
radius = 0.1
coordinates = nr.uniform(size=(1,2))
print coordinates
disksdescription = []
for row in range(0, coordinates):
x = coordinates[row, 0]
y = coordinates[row, 1]
disksdescription.append({'x': x, 'y': y, 'left': left, 'right': right})
touch_sides(coordinates, radius, x, y)
print disksdescription
Overview
You have quite a few basic problems in this code. I'm going to back off and try to solve a couple of your process problems.
Most of all, I strongly recommend that you adopt incremental programming: write a few lines of code, just a single step or two of logic. Then test that until you're sure it does what you want. Only then do you write more code.
The advantage of this is that problems are usually easy to debug: only the new 2-5 lines are suspect. Contrast this with your current situation: you have several errors; fixing any one of them won't give you an appreciably better result, so it's hard for you to learn what you did wrong until you get all of them at once.
What is a function?
Think of it like some sort of security set-up, perhaps like the pass-through window to a diner's kitchen. The server sticks an order (slip of paper) through the window. When the cook is done, plates of food come back. All of the communication goes through that window. When we ask for an omelet, for all we know, the cook is slicing meat bits off a full side of beef on a rotisserie ... or nuking some frozen stuff. Can't see it, can't tell; that's a separate room with opaque walls.
Which means what to me?
You have three "rooms" in your program: the (trivial) main program, run_code, and touch_sides. None of them can see inside the others. The variable left in run_code has no relation to the variable left in touch_sides. These are entirely separate entities, no more connected than, say, Kim Jong Il and Kim Kardashian.
In particular, the first line of touch_sides is an ultimate huh? moment for the Python compiler. There is no defined thing called diskdescription. Farther down, you spend work to get values for left and right, but then you don't slide them back through the window. run_code has no idea that you did anything useful in there.
What to fix
Go back and do the simple exercises that you skipped. Their purpose was to keep you from making all these mistakes at once. Write trivial functions and trivial calls. Learn to use the input parameters and return values.
Practice incremental programming. Comment out the bodies of your functions. Now, run the program, a simple call to run_code(). It won't do anything, but it does so without error.
Next, put "stub" code into touch_sides: don't compute anything, but print the parameter values. Ignore the input parameters and return False for left and right. Add code to run_code that calls touch_sides and prints the results.
At this point, you know that you can reliably pass values between the functions. Now you can add the actual code.
What else?
Get comfortable with the concept of a boolean expression. Learn that your original code
if x <= radius:
left = True
else:
left = False
Reduces directly to
left = (x <= radius) # the parentheses aren't necessary
Note that you have two variables, left and right, which are trying to describe properties of a list of disks.
Note that these are the same variables that you're using to iterate through a list of coordinates. They can't do both at once -- make a couple more storage areas, such as left_touches and right_touches.
That should be enough for now. Live Long, And Program.

How can I avoid recursion between move generation and check validation in python chess implementation?

I'm currently working on a simple python 3 implementation of a chess game where legal moves can be calculated and things like check, checkmate, and stalemate can be determined. I've encountered a logic error which results in recursion and I'm not sure how I change my current approach to avoid this.
I've got some pseudo-code here (my actual code several hundred lines long and it would be impractical to paste it all for a logic problem).
Where am I going wrong with my thought process behind this code?
class ChessBoard:
def get_position():
# returns fen of position
def set_position(position_code):
# sets the board's position and values using the fen code given
# assume its white's turn right now
def calculate_moves():
# uses vectors to calculate moves for all pieces
for each_move in candidate_moves:
if passes_all_general_conditions:
# now I need to check if the potential
# legal move will leave the user in check
# obviously if the white king can be taken in the next turn
# by the other color then the move cannot be considered legal
temp_board = ChessBoard()
temp_board.set_position(self.get_position())
temp_board.make_move(the_selected_move_that_needs_checking)
if not temp_board.incheck():
# add move to list of legal moves
def incheck():
# player is in check if a piece can take it on the next turn
# don't I need to know what moves can be made before I can know if its check??
# let k equal the current turn (or half-turn as chess players call it)
# in order to calculate the moves for position at turn k
# the moves for position k + 1 must be known
# obviously this just enters infinite recursion
It looks like incheck() is not implemented. The default return value of a python method is the None type.
>>> not None == True
True
So the deepest-nested conditional in your loop always evaluates to True.
I appreciate that you didn't copy paste you whole code, but it would have been useful to at least show SOME part of it, in order to fix your issue.
Since I cannot debug your code without seeing it, I will just make a guess:
I think you use calculate_moves() in incheck(), and incheck to verify wether calculated_moves are legal ones.
If you do that, you have got two options:
-Split calculate_moves into two functions: one generates pseudo legals, and the other then controls these pseudolegals on legality. You will just ave to replace calculate_moves() in incheck() by calculate_pseudolegals(). This approach is a little bit inefficient though.
-The more efficient solution is to fully delete your incheck() routine and write a new, efficient one. There you would replace the king you wish to test on check by every figure of its own color onece, and then test if it could hit a figure of the same type of the opponent. If it can, your king is in check. Be aware that you will still need a calculate_pseudolegals() function for this to work.

Categories