How to Create Piecewise Function in SymPy with Intervals - python

i need to create a piece-wise function inside an interval but sympy piecewise can't use and (&). I read that the function can't recieve Boolean values so I tried to add them together and it doesn't seem to be right. The code is as follows:
import numpy as np
import sympy as sp
import matplotlib as plt # This is all the library's i need
import mpmath
n = 10
x = sp.symbols('x', positive=True)
c = list(sp.symbols('c0:%d'%(n + 1)))
f = 1+(((sp.exp(x) * (1 - np.exp(-1))) + (sp.exp(-x)) * (np.exp(1) - 1)) / (np.exp(-1) - np.exp(1)))
xx = np.linspace(0, 1, n + 1)
i = 0
N = []
a = sp.Piecewise(
(0, x < float(xx[i])),
(((xx[i + 1] - x) / (xx[i + 1] - xx[i])), (x >= float((xx[i])))),
((xx[i + 1] - x) / (xx[i + 1] - xx[i]), x <= float((xx[i + 1]))),
(0, x > float(xx[i + 1])),
)
N.append(a)
for i in range(1, n):
a = sp.Piecewise(
(0, x < float(xx[i - 1])),
((xx[i - 1] - x) / xx[i - 1] - xx[i], x >= float((xx[i - 1]))),
((xx[i - 1] - x) / (xx[i - 1] - xx[i]), x <= float(xx[i])),
(0, x > float(xx[i])),
)
b = sp.Piecewise(
(0, x < float(xx[i])),
((xx[i + 1] - x) / (xx[i + 1] - xx[i]), x >= float(xx[i])),
((xx[i + 1] - x) / (xx[i + 1] - xx[i]), x <= float(xx[i + 1])),
(0, x > float(xx[i + 1])),
)
N.append(a + b)
i = i + 1
a = sp.Piecewise(
(0, x < float(xx[i - 1])),
((xx[i - 1] - x) / (xx[i - 1] - xx[i]), x >= float((xx[i - 1]))),
((xx[i - 1] - x) / (xx[i - 1] - xx[i]), x <= float(xx[i])),
(0, x > float(xx[i])),
)
N.append(a)

It would be helpful if you give an example of how Piecewise did not do what you wanted. Piecewise will work with And (and intervals expressed with the same):

Related

Renumbering vertices in a graph in Networkx

I am generating a network using the code below for N=2. However, I would like to renumber the vertices starting from 0 and not 1. I present the current and expected outputs.
import networkx as nx
N=2
def pos():
x, y = 1, N + 3 - 1
for _ in range(2 * N * (N + 1)):
yield (x, y)
y -= (x + 2) // (N + 3)
x = (x + 2) % (N + 3)
G = nx.Graph()
it_pos = pos()
for u in range(2 * N * (N + 1)):
G.add_node(u+1, pos=next(it_pos))
if u % (2 * N + 1) < N:
for v in (u - 2 * N - 1, u - N - 1, u - N):
if G.has_node(v + 1):
G.add_edge(u + 1, v + 1)
elif u % (2 * N + 1) == N:
G.add_edge(u + 1, u - N + 1)
elif u % (2 * N + 1) < 2 * N:
for v in (u - 1, u - N - 1, u - N):
G.add_edge(u + 1, v + 1)
else:
for v in (u - 1, u - N - 1):
G.add_edge(u + 1, v + 1)
nx.draw(G, nx.get_node_attributes(G, 'pos'), with_labels=True, font_weight='bold')
The current output is
The expected output is
You could use the nx.relabel_nodes function (doc here):
import networkx as nx
N=2
def pos():
x, y = 1, N + 3 - 1
for _ in range(2 * N * (N + 1)):
yield (x, y)
y -= (x + 2) // (N + 3)
x = (x + 2) % (N + 3)
G = nx.Graph()
it_pos = pos()
for u in range(2 * N * (N + 1)):
G.add_node(u+1, pos=next(it_pos))
if u % (2 * N + 1) < N:
for v in (u - 2 * N - 1, u - N - 1, u - N):
if G.has_node(v + 1):
G.add_edge(u + 1, v + 1)
elif u % (2 * N + 1) == N:
G.add_edge(u + 1, u - N + 1)
elif u % (2 * N + 1) < 2 * N:
for v in (u - 1, u - N - 1, u - N):
G.add_edge(u + 1, v + 1)
else:
for v in (u - 1, u - N - 1):
G.add_edge(u + 1, v + 1)
#relabelling nodes
G=nx.relabel_nodes(G,{i:i-1 for i in range(1,G.number_of_nodes()+1)},copy=False)
nx.draw(G, nx.get_node_attributes(G, 'pos'), with_labels=True, font_weight='bold')

how to convert a method type to a type that can be multiplied: TypeError: unsupported operand type(s) for *: 'method' and 'Piecewise'

i have a problem that i need to multiply the type {method} and a piecewise function, all in symbolic sympy.
i try to multiply a Piecewise expression with Derivative of another expression that. the result of the Derivative expression is from a type 'method'
here is my code:
import sympy as sp
import numpy as np
import matplotlib as plt # This is all the library's i need
import mpmath
n = 10
x = sp.symbols('x', positive=True)
c = list(sp.symbols('c0:%d'%(n + 1)))
f = 1+(((sp.exp(x) * (1 - np.exp(-1))) + (sp.exp(-x)) * (np.exp(1) - 1)) / (np.exp(-1) - np.exp(1)))
xx = np.linspace(0, 1, n + 1)
i = 0
N = []
a = sp.Piecewise(
(((xx[i + 1] - x) / (xx[i + 1] - xx[i])), (x >= float((xx[i]))) and x <= float((xx[i + 1]))),
(0, x > float(xx[i + 1])),
)
N.append(a)
for i in range(1, n):
a = sp.Piecewise(
(0, x < float(xx[i - 1])),
((xx[i - 1] - x) / (xx[i - 1] - xx[i]), ((x >= float((xx[i - 1]))) & (x <= float(xx[i])))),
((xx[i + 1] - x) / (xx[i + 1] - xx[i]), ((x >= float(xx[i])) & (x <= float(xx[i + 1])))),
(0, x > float(xx[i + 1])),
(0, True),
)
N.append(a)
i = i + 1
a = sp.Piecewise(
(0, x < float(xx[i - 1])),
((xx[i - 1] - x) / (xx[i - 1] - xx[i]), ((x >= float((xx[i - 1]))) & (x <= float(xx[i])))),
(0, True),
)
N.append(a)
k = []
#u = []
for i in range(0, n + 1):
if i == 0:
u = c[i] * N[i]
else:
u = c[i] * N[i] +u
Ntag = []
for i in range(0, n + 1):
tag = N[i].diff(x)
Ntag.append(tag)
utag = u.diff
try:
res= utag*Ntag[i]# for any integer
except:
traceback.print_exc()
and the output is:
TypeError: unsupported operand type(s) for *: 'method' and 'Piecewise'
and the line that making the error is the last line:
utag*Ntag[i]
and the traceback is :
Traceback (most recent call last):
File ".py", line 56, in <module>
res= utag*Ntag[i]# for any integer
TypeError: unsupported operand type(s) for *: 'method' and 'Piecewise'
Okay well the mistake is obvious. u.diff is clearly a function, not a number; but it's not being called like a function. The function itself is being assigned to utag. So, you're trying to multiply the function u.diff with the value Ntag[i]. But u.diff is not a numerical value, it is just a function. You'd have to call the function if you wanted it to return an actual value. But you're not calling it, you're just referencing it.

How can I make this PyTorch heatmap function faster and more efficient?

I have this function that creates a sort if heatmap for 2d tensors, but it's painfully slow when using larger tensor inputs. How can I speed it up and make it more efficient?
import torch
import numpy as np
import matplotlib.pyplot as plt
def heatmap(
tensor: torch.Tensor,
) -> torch.Tensor:
assert tensor.dim() == 2
def color_tensor(x: torch.Tensor) -> torch.Tensor:
if x < 0:
x = -x
if x < 0.5:
x = x * 2
return (1 - x) * torch.tensor(
[0.9686, 0.9686, 0.9686]
) + x * torch.tensor([0.5725, 0.7725, 0.8706])
else:
x = (x - 0.5) * 2
return (1 - x) * torch.tensor(
[0.5725, 0.7725, 0.8706]
) + x * torch.tensor([0.0196, 0.4431, 0.6902])
else:
if x < 0.5:
x = x * 2
return (1 - x) * torch.tensor(
[0.9686, 0.9686, 0.9686]
) + x * torch.tensor([0.9569, 0.6471, 0.5098])
else:
x = (x - 0.5) * 2
return (1 - x) * torch.tensor(
[0.9569, 0.6471, 0.5098]
) + x * torch.tensor([0.7922, 0.0000, 0.1255])
return torch.stack(
[torch.stack([color_tensor(x) for x in t]) for t in tensor]
).permute(2, 0, 1)
x = torch.randn(3,3)
x = x / x.max()
x_out = heatmap(x)
x_out = (x_out.permute(1, 2, 0) * 255).numpy()
plt.imshow(x_out.astype(np.uint8))
plt.axis("off")
plt.show()
An example of the output:
You need to get rid of ifs and the for loop and make a vectorized function. To do that, you can use masks and calculate all in one. Here it is:
def heatmap(tensor: torch.Tensor) -> torch.Tensor:
assert tensor.dim() == 2
# We're expanding to create one more dimension, for mult. to work.
xt = x.expand((3, x.shape[0], x.shape[1])).permute(1, 2, 0)
# this part is the mask: (xt >= 0) * (xt < 0.5) ...
# ... the rest is the original function translated
color_tensor = (
(xt >= 0) * (xt < 0.5) * ((1 - xt * 2) * torch.tensor([0.9686, 0.9686, 0.9686]) + xt * 2 * torch.tensor([0.9569, 0.6471, 0.5098]))
+
(xt >= 0) * (xt >= 0.5) * ((1 - (xt - 0.5) * 2) * torch.tensor([0.9569, 0.6471, 0.5098]) + (xt - 0.5) * 2 * torch.tensor([0.7922, 0.0000, 0.1255]))
+
(xt < 0) * (xt > -0.5) * ((1 - (-xt * 2)) * torch.tensor([0.9686, 0.9686, 0.9686]) + (-xt * 2) * torch.tensor([0.5725, 0.7725, 0.8706]))
+
(xt < 0) * (xt <= -0.5) * ((1 - (-xt - 0.5) * 2) * torch.tensor([0.5725, 0.7725, 0.8706]) + (-xt - 0.5) * 2 * torch.tensor([0.0196, 0.4431, 0.6902]))
).permute(2, 0, 1)
return color_tensor

How to multiply the pseudo-inverse (from SVD) of every column in a matrix by another vector in Python

I have a matrix H of size, for example, 4 x 4, and a vector x of size 4 x 1, I need to multiply the inverse of each column in H by the vector x and put the output in a vector.
for example, suppose I have the matrix H:
H =
0.4657 + 0.4162j -0.4419 + 0.0632j -1.1432 - 0.2708j 0.3158 + 0.3111j
0.1696 - 0.5686j -0.2734 - 0.8657j -0.1369 - 0.2353j -1.2032 + 0.4967j
0.5696 + 0.1004j -0.1986 - 1.1916j 0.3550 - 0.9894j 0.5620 + 0.4882j
-0.2774 - 0.7854j -0.8613 - 0.7542j 0.4103 + 0.5212j -0.4590 + 0.8673j
and vector x :
x =
0.3572 + 0.2677i
-0.4189 + 0.8054i
-0.7021 + 0.9831i
0.0757 + 1.1424i
In MATLAB, I did it straightforward as below:
clear all; clc
H = [0.4657 + 0.4162i, -0.4419 + 0.0632i, -1.1432 - 0.2708i, 0.3158 + 0.3111i;
0.1696 - 0.5686i, -0.2734 - 0.8657i, -0.1369 - 0.2353i, -1.2032 + 0.4967i;
0.5696 + 0.1004i, -0.1986 - 1.1916i, 0.3550 - 0.9894i, 0.5620 + 0.4882i;
0.5696 + 0.1004i, -0.1986 - 1.1916i, 0.3550 - 0.9894i, 0.5620 + 0.4882i]
x = [0.3572 + 0.2677i;
-0.4189 + 0.8054i;
-0.7021 + 0.9831i;
0.0757 + 1.1424i]
xn = [];
for yy = 1 : size(H, 2)
nn = H(:,yy);
x2= pinv(nn).*x;
X3 = [xn x2];
end
as result, vector X3 = [-0.8307 + 0.1398i, -0.7071 - 0.7071i, -0.4029 - 0.1116i, 0.6284 - 0.1415i]
Now, I try to do the same thing in python but I get an error, as below:
import numpy as np
H = [[0.4657 + 0.4162i, -0.4419 + 0.0632i, -1.1432 - 0.2708i, 0.3158 + 0.3111i],
[0.1696 - 0.5686i, -0.2734 - 0.8657i, -0.1369 - 0.2353i, -1.2032 + 0.4967i],
[0.5696 + 0.1004i, -0.1986 - 1.1916i, 0.3550 - 0.9894i, 0.5620 + 0.4882i],
[0.5696 + 0.1004i, -0.1986 - 1.1916i, 0.3550 - 0.9894i, 0.5620 + 0.4882i]]
x = [[0.3572 + 0.2677j], [0 + 0j], [0 + 0j], [0 + 0j]]
X3 = np.zeros((1, 4), dtype=np.complex)
for i in range(4):
X3 = np.linalg.pinv(h[:,i]) # y
but, X3 is giving an error in that case! it doesn't give the expected results.
thank you in advance
First, imaginary in Python is j. Use numpy.array() and reshape before passing into pinv():
import numpy as np
H = np.array([[0.4657 + 0.4162j, -0.4419 + 0.0632j, -1.1432 - 0.2708j, 0.3158 + 0.3111j],
[0.1696 - 0.5686j, -0.2734 - 0.8657j, -0.1369 - 0.2353j, -1.2032 + 0.4967j],
[0.5696 + 0.1004j, -0.1986 - 1.1916j, 0.3550 - 0.9894j, 0.5620 + 0.4882j],
[0.5696 + 0.1004j, -0.1986 - 1.1916j, 0.3550 - 0.9894j, 0.5620 + 0.4882j]])
x = np.array([[0.3572 + 0.2677j], [0 + 0j], [0 + 0j], [0 + 0j]])
X3 = np.zeros((1, 4), dtype=np.complex)
for j in range(4):
X3[:,j] = np.linalg.pinv(H[:,j].reshape(-1,1)).dot(x)

Need advice on optimizing python 2d tileset rendering

I've been working on a 2D isometric tile-based MORPG for a few months now and realized that my game screen rendering is at a really low frame rate.
I've been researching and testing for a few weeks now and can only make marginal gains to my frame rate. I've used cProfile and tested my frame rate and I can achieve 100+ FPS on the program normally, but once my "render()" function is called it drops to 5 FPS.
Here is a (somewhat) condensed version of that function:
for y in range(0, 42):
for x in range(0, 42):
if (player.mapY + y - 21 > 0) and (player.mapY + y - 21 < 128) and (player.mapX + x - 21 > 0) and (
player.mapX + x - 21 < 128):
if (startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX) > -64 and (startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX)+halfGraphicSizeX < 1024+32 and\
(startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY) > -32 and (startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY)+halfGraphicSizeY < 600+32:
if self.getGroundAtYX(player.mapY + (y - 21), player.mapX + (x - 21)) is not 0:
canvas.create_image((startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
(startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY),
image=groundGraphics[
self.getGroundAtYX(player.mapY + (y - 21), player.mapX + (x - 21))],
anchor=NW)
if (self.getObjectAtYX(player.mapY + (y - 21), player.mapX + (x - 21)) is not 0):
canvas.create_image((startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
(startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 34),
# -34 for img height diff between ground & objects
image=objectGraphics[
self.getObjectAtYX(player.mapY + (y - 21), player.mapX + (x - 21))],
anchor=NW)
ghostCopy = list(gameState.itemsOnGround)
for i in range(0, len(ghostCopy)):
if ghostCopy[i].idNum > 0:
if (player.mapX - 21 + x == ghostCopy[i].mapX and player.mapY - 21 + y ==
ghostCopy[i].mapY):
canvas.create_image((startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
(startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY),
image=itemGraphics[ghostCopy[i].idNum],
anchor=NW)
ghostCopy = ""
ghostCopy = list(gameState.monster)
for i in range(0, len(ghostCopy)):
if ghostCopy[i].active == True and ghostCopy[i].hp > 0:
if (player.mapX - 21 + x == ghostCopy[i].mapX and player.mapY - 21 + y ==
ghostCopy[i].mapY):
canvas.create_image((startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
(startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 34),
# -34 for img height diff between ground & objects
image=monsterGraphics[ghostCopy[i].type],
anchor=NW)
canvas.create_rectangle(
(startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX) + 15,
(startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 35),
(startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX) + 16 + 33,
(startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 29), fill="black",
width=0)
canvas.create_rectangle(
(startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX) + 16,
(startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 30),
(startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX) + 16 + (
32 * (ghostCopy[i].hp / ghostCopy[i].maxHp)),
(startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 34), fill="green",
width=0)
ghostCopy = ""
ghostCopy = list(gameState.sprite)
for i in range(0, len(ghostCopy)):
if ghostCopy[i].graphic[0:1] == "0":
if ghostCopy[i].active == True and ghostCopy[i].username != "ME":
if (player.mapX - 21 + x == ghostCopy[i].mapX and player.mapY - 21 + y ==
ghostCopy[i].mapY):
#"graphicToDraw" variable is derived from an animation state but has
#been removed from here to make it easier to read
canvas.create_image((startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
(startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 34),
# -34 for img height diff between ground & objects
image=graphicToDraw,
anchor=NW)
if (y == 21):
if (x == 21):
#"graphicToDraw" variable is derived from an animation state but has
#been removed from here to make it easier to read
canvas.create_image(
(startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
(startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 34),
# -34 for img height diff between ground & sprites
image=graphicToDraw,
anchor=NW)
ghostCopy = ""
ghostCopy = list(gameState.spells)
for i in range(0, len(ghostCopy)):
if ghostCopy[i].active:
if (player.mapX - 21 + x == ghostCopy[i].mapX and player.mapY - 21 + y ==
ghostCopy[i].mapY):
canvas.create_image((startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX),
(startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY - 34),
image=spellGraphics[ghostCopy[i].id],
anchor=NW)
the render() function belongs to the map object (self refers to the map in this code segment). It effectively goes through the tiles -21 .. 21 on the x,y axis and if the tile is within the maps tile bounds (0 .. 128) and the tile is within the screen size (1024x600) it draws it to the screen.
The "ghostCopy" takes a snapshot of the current gamestate element (spells for example) so that it isn't updated by the thread receiving server data mid-iteration.
In some optimization testing I did I reduced the y, x range at the start to minimize the amount of total loop iterations.
I read that using a texture atlas/spritesheet could improve rendering speed but I couldn't make an improvement using one.
I tried just manually drawing the amount of images that would normally render in a general scene in a for loop and got around 30+ fps. So my render function is 25 fps slower than it could be.
I'm assuming that the constant checks every loop iteration to whether the tile is within the screen could be optimized, but i'm not really sure how to do that without using a loop like this.
If anyone has any recommendations I would greatly appreciate it.. i've been stuck on this problem for weeks and haven't made any real progress with my game at all :(
** [EDIT] **
Most recommendations seem to be towards limiting the amount of mathematical expressions. I haven't had a chance to test this, but is it likely just limiting the amount of math would optimize frame rate considerably?
You could pull all expressions involving constants and y to be computed just inside the outer (for y) loop; for example, player.mapY + y - 21, y * halfGraphicSizeX, y * halfGraphicSizeY, etc.: computer each just once, tuck in a variable, and use throughout the code. Similarly for x, but not quite as effective.
Here is an update of the first 19 lines of code that should improve the performance. In this example all I have done was reduce the total number of times you are preforming math operations.
for y in range(0, 42):
for x in range(0, 42):
player_y = player.mapY + y - 21
player_x = player.mapX + x -21
if player_y > 0 and player_y < 128 and player_x > 0 and player_x < 128:
start_drawing_x_half_graphic_size = startDrawingPosX + x * halfGraphicSizeX - y * halfGraphicSizeX
start_drawing_y_half_graphic_size = startDrawingPosY + x * halfGraphicSizeY + y * halfGraphicSizeY
if start_drawing_x_half_graphic_size > -64 and start_drawing_x_half_graphic_size + halfGraphicSizeX < 1024+32 and\
start_drawing_y_half_graphic_size > -32 and start_drawing_y_half_graphic_size + halfGraphicSizeY < 600+32:
if self.getGroundAtYX(player.mapY + (y - 21), player.mapX + (x - 21)) is not 0:
canvas.create_image(start_drawing_x_half_graphic_size,
start_drawing_y_half_graphic_size,
image=groundGraphics[
self.getGroundAtYX(player.mapY + (y - 21), player.mapX + (x - 21))],
anchor=NW)

Categories