Related
Given three vectors, a(1,4), b(1, 4), c(4,1). I want to do the following
a = MatrixSymbol('a', 1, 4)
b = MatrixSymbol('a', 1, 4)
c = MatrixSymbol('c', 4, 1)
expr = a*c + b*c
c_coeff = .... # How to get the value of (a+b) here
I tried using coeff and collect but it fails because the C matrix is not square.
If it is linear then
>>> from sympy.solvers.solveset import linear_coeffs
>>> linear_coeffs(expr, c)
[a + b, 0]
note that 0 is the constant term; if you added MatrixSymbol('d', 1, 1) to expr the 2nd element would be d; you named 'b' as 'a' in your example; I named it 'b' to get the output shown above.
How to iterate over multiple tuples, to define +, -, * etc. operations? I would like to add math operations for 2D and 3D points.
Doing it by hand is too verbose
proc `+`(a: (int, int), b: (int, int)): (int, int) =
(a[0]+b[0], a[1]+b[1])
echo (1, 1) + (2, 2)
Would be better to iterate over tuple content. How to do it, it needs to iterate over 3 tuples, a, b and result.
proc `+`[T: tuple](a: T, b: T): T =
# ?
discard
echo (1, 1) + (2, 2)
Additionally, is there a way to restrict the tuple type to only tuple of floats or tuple of floats or ints?
This problem can be solved using ForStmtLoop macros and some magic from std/typetraits. The basic idea is to create a two-stage macro, where the first part would simply generate necessary boilerplate calls to tupleLen and other typetraits features, and second one will do the actual codegen.
import std/[macros, typetraits, sequtils]
macro tuplePairsAux(
lens: static[seq[int]],
body: untyped,
index: static[string],
injectsOf: static[seq[string]],
tuples: varargs[untyped]): untyped =
let len0 = lens[0]
if anyIt(lens, it != len0):
error("'tuplePairs' requires to use tuples of equal lenght", tuples[0])
if injectsOf.len != tuples.len:
error("'tuplePairs' requires " & $tuples.len &
" loop variables to be specified, but got " & $injectsOf.len, tuples[0])
result = newStmtList()
for item in 0 ..< len0:
var declare = newStmtList()
declare.add nnkConstSection.newTree(
nnkConstDef.newTree(ident(index), newEmptyNode(), newLit(item)))
for tup in 0 ..< len(tuples):
let name = ident(injectsOf[tup])
let inTup = tuples[tup]
let itemIdx = newLit(item)
declare.add quote do:
let `name` = `inTup`[`itemIdx`]
result.add nnkBlockStmt.newTree(
newEmptyNode(), newStmtList(declare, body))
echo result.repr()
macro tuplePairs*(x: ForLoopStmt): untyped =
var lens = nnkBracket.newTree()
for tup in x[^2][1..^1]:
lens.add newCall(bindSym"tupleLen", tup)
var call = newCall(
bindSym"tuplePairsAux",
nnkPrefix.newTree(ident"#", lens))
call.add x[^1] # Pass body to aux call
call.add newLit(x[0].strVal()) # Pass index variable to the list
var injects = nnkBracket.newTree()
for inj in x[1 ..^ 3]:
injects.add newLit(inj.strVal())
call.add nnkPrefix.newTree(ident"#", injects) # Pass names of the injected variables
result = newStmtList()
# Pass all argument tuples
for tup in x[^2][1 ..^ 1]:
# If passed tuple is an identifier it can be used directly
if tup.kind in {nnkIdent, nnkSym}:
call.add tup
else:
# Otherwise generate temporary variable in order to avoid multiple
# evaluation of the expression
let gen = genSym(nskLet)
result.add nnkLetSection.newTree(
nnkIdentDefs.newTree(gen, newEmptyNode(), tup))
call.add gen
result.add call
result = nnkBlockStmt.newTree(newEmptyNode(), result)
echo result.repr()
proc `+`(a: (int, int), b: (int, int)): (int, int, int) =
for idx, t1, t2, t3 in tuplePairs(a, b, (1, 2)):
result[idx] = t1 + t2 + t3
When macro is first expanded, it would generate initial code that passes names of the variables, for statement body and other required parameters
block:
let :tmp_5050086 = (1, 2)
tuplePairsAux(#[tupleLen(a), tupleLen(b), tupleLen((1, 2))],
result[idx] = t1 + t2 + t3, "idx", #["t1", "t2", "t3"], a, b, :tmp_5050086)
Then tuplePairsAux will have all the necessary information about tuple lengths, and other things, and can generate this code:
block:
const
idx = 0
let t1 = a[0]
let t2 = b[0]
let t3 = :tmp_5050086[0]
result[idx] = t1 + t2 + t3
block:
const
idx = 1
let t1 = a[1]
let t2 = b[1]
let t3 = :tmp_5050086[1]
result[idx] = t1 + t2 + t3
const idx can be used in order to assign to result, so your code (edited slightly to show handling of the expressions (and not simply identifiers)) might look like
proc `+`(a: (int, int), b: (int, int)): (int, int, int) =
for idx, t1, t2, t3 in tuplePairs(a, b, (1, 2)):
result[idx] = t1 + t2 + t3
Note: this solution can be optimized further by using byaddr annotations in the generated code, or by injecting let ptr_t1 = addr a[0]; template t1(): untyped = ptr_t1[]. In this case using t1 in the body of the loop would not cause any additional copies and allow for iteration over a mutable collection of tuples (analogous to the fieldPairs working for both mutable and immutable entries).
Note: Another possible solution would be to rewrite loop body, replacing all occurrences of t1 with a[0] instead of injecting new variables.
a reply to how do I add math operations for tuples of ints and floats without being too verbose? inspired by how treeform/vmath does it (playground):
# these types are not really necessary you could just use tuples below
type
GVec2*[T] = tuple[x, y: T]
GVec3*[T] = tuple[x, y, z: T]
template genOp(op: untyped) =
proc op*[T](a: GVec2[T], b: GVec2[T]): GVec2[T] =
result.x = op(a.x, b.x)
result.y = op(a.y, b.y)
proc op*[T](a: GVec3[T], b: GVec3[T]): GVec3[T] =
result.x = op(a.x, b.x)
result.y = op(a.y, b.y)
result.z = op(a.z, b.z)
proc op*[T](a: GVec2[T], b: T): GVec2[T] =
result.x = op(a.x, b)
result.y = op(a.y, b)
proc op*[T](a: GVec3[T], b: T): GVec3[T] =
result.x = op(a.x, b)
result.y = op(a.y, b)
result.z = op(a.z, b)
proc op*[T](a: T, b: GVec2[T]): GVec2[T] =
result.x = op(a, b.x)
result.y = op(a, b.y)
proc op*[T](a: T, b: GVec3[T]): GVec3[T] =
result.x = op(a, b.x)
result.y = op(a, b.y)
result.z = op(a, b.z)
genOp(`+`)
genOp(`-`)
genOp(`*`)
echo (2*(1, 2) - (3, 7) + 2)*(-1, 1) + 1
echo (1.0, 2.0) * (2.0, 4.0) - 4.0*(-1.0, 0.5) - 6
# echo (true, false) + (true, true) # if there is no operation defined on the base type it will fail
First of all, here's a concept that matches an N-tuple of a single type:
type UniformTuple[T] = concept c
c is tuple
for i in c.fields:
i is T
that means (x: int, y: int) and (int, int, int) are UniformTuple[int]; similarly (float,float,...) is a UniformTuple[float], but mixed tuples are not accepted.
Here's a sort of applyIt that takes two tuples and an expression, and returns a third. No attempt to be general, to sanity check, or pick a good name--just going for clarity/brevity.
import macros
macro applyThem(x,y: tuple; op: untyped): untyped =
result = nnkTupleConstr.newNimNode
for i in 0 ..< x.getTypeImpl.len:
result.add quote do:
block:
var
a{.inject.} = `x`[`i`]
b{.inject.} = `y`[`i`]
`op`
assert applyThem( (x: 3, y: 4), (u: 4,v: 5), a+b ) == (7,9)
assert applyThem( (1, 2.0), (3, 4.5), a*b) == (3, 9.0)
Putting the two together:
proc `+`[T: UniformTuple[int] or UniformTuple[float]](x,y: T): T = applyThem(x,y,a + b)
assert (x:3,y:4) + (x:4,y:5) == (7,9)
assert (4.5,9.3,9.7) + (3.2,2.1,1.0) == (7.7, 11.4, 10.7)
assert not compiles((3,4.0) + (3,4.0)) #not uniform
assert not compiles((x:3,y:4) + (4,5)) #not the same type
I want to use the ray task method rather than the ray actor method to parallelise a method within a class. The reason being the latter seems to need to change how a class is instantiated (as shown here). A toy code example is below, as well as the error
import numpy as np
import ray
class MyClass(object):
def __init__(self):
ray.init(num_cpus=4)
#ray.remote
def func(self, x, y):
return x * y
def my_func(self):
a = [1, 2, 3]
b = np.random.normal(0, 1, 10000)
result = []
# we wish to parallelise over the array `a`
for sub_array in np.array_split(a, 3):
result.append(self.func.remote(sub_array, b))
return result
mc = MyClass()
mc.my_func()
>>> TypeError: missing a required argument: 'y'
The error arises because ray does not seem to be "aware" of the class, and so it expects an argument self.
The code works fine if we do not use classes:
#ray.remote
def func(x, y):
return x * y
def my_func():
a = [1, 2, 3, 4]
b = np.random.normal(0, 1, 10000)
result = []
# we wish to parallelise over the list `a`
# split `a` and send each chunk to a different processor
for sub_array in np.array_split(a, 4):
result.append(func.remote(sub_array, b))
return result
res = my_func()
ray.get(res)
>>> [array([-0.41929678, -0.83227786, -2.69814232, ..., -0.67379119,
-0.79057845, -0.06862196]),
array([-0.83859356, -1.66455572, -5.39628463, ..., -1.34758239,
-1.5811569 , -0.13724391]),
array([-1.25789034, -2.49683358, -8.09442695, ..., -2.02137358,
-2.37173535, -0.20586587]),
array([ -1.67718712, -3.32911144, -10.79256927, ..., -2.69516478,
-3.1623138 , -0.27448782])]```
We see the output is a list of 4 arrays, as expected. How can I get MyClass to work with parallelism using ray?
a few tips:
It's generally recommended that you only use the ray.remote decorator on functions or classes in python (not bound methods).
You should be very very careful about calling ray.init inside the constructor of a function, since ray.init is not idempotent (which means your program will fail if you instantiate multiple instances of MyClass). Instead, you should make sure ray.init is only run once in your program.
I think there's 2 ways of achieving the results you're going for with Ray here.
You could move func out of the class, so it becomes a function instead of a bound method. Note that in this approach MyClass will be serialized, which means that changes that func makes to MyClass will not be reflected anywhere outside the function. In your simplified example, this doesn't appear to be a problem. This approach makes it easiest to achieve the most parallelism.
#ray.remote
def func(obj, x, y):
return x * y
class MyClass(object):
def my_func(self):
...
# we wish to parallelise over the array `a`
for sub_array in np.array_split(a, 3):
result.append(func.remote(self, sub_array, b))
return result
The other approach you could consider is to use async actors. In this approach, the ray actor will handle concurrency via asyncio, but this comes with the limitations of asyncio.
#ray.remote(num_cpus=4)
class MyClass(object):
async def func(self, x, y):
return x * y
def my_func(self):
a = [1, 2, 3]
b = np.random.normal(0, 1, 10000)
result = []
# we wish to parallelise over the array `a`
for sub_array in np.array_split(a, 3):
result.append(self.func.remote(sub_array, b))
return result
Please see this code:
#ray.remote
class Prime:
# Constructor
def __init__(self,number) :
self.num = number
def SumPrime(self,num) :
tot = 0
for i in range(3,num):
c = 0
for j in range(2, int(i**0.5)+1):
if i%j == 0:
c = c + 1
if c == 0:
tot = tot + i
return tot
num = 1000000
start = time.time()
# make an object of Check class
prime = Prime.remote(num)
print("duration =", time.time() - start, "\nsum_prime = ", ray.get(prime.SumPrime.remote(num)))
I am diving into 3d graphics with PyOpenGL and am thoroughly overwhelmed. I want to be able to implement shadows in my scenes and prevent GL from drawing object through each other. This is the way I see it:
The best way I can see is a custom shader.
According to the PyOpenGL tutorials on SourceForge, I need a whole bunch of libraries. I want to do this with just PyOpenGL if possible.
I need this shader to be PyQt5 compatible.
As much as possible, I would like to render in the GPU. I believe that this would permit the CPU to focus on my data handling, etc. in my project to fully utilize all resources.
If I make a custom shader, I would like to include a basic function to draw lines and faces. Something like I do normally, like glvertex3f.
How do I go about this? I looked at this tutorial, but I cannot sort out what is bare necessity and what is not.
This is what I am using right now, but GL will draw shapes on top of each other. It also has no sort of shadow rendering.
# File structure is as follows:
# imports
# exceptions
# shape classes
# main shader
#---------- imports ----------#
from OpenGL.GL import (
glLoadIdentity, glTranslatef, glRotatef,
glClear, glBegin, glEnd,
glColor3fv, glVertex3fv,
GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT,
GL_QUADS, GL_LINES
)
from OpenGL.GLU import gluPerspective
#---------- exceptions ----------#
class shapeNotFound(Exception):
pass
#---------- shape classes ----------#
class cube():
render = True
def __init__(self, location = (0, 0, 0), size = 0.1, drawWires = True, drawFaces = False, color = (1, 1, 1)):
self.location = location
self.size = size
self.drawWires = drawWires
self.drawFaces = drawFaces
self.color = color
self.compute()
def compute(self):
x, y, z = self.location
s = self.size / 2
self.vertices = [ #8 corner points calculated in reference to the supplied center point
(-s + x, s + y, -s + z), (s + x, s + y, -s + z),
(s + x, -s + y, -s + z), (-s + x, -s + y, -s + z),
(-s + x, s + y, s + z), (s + x, s + y, s + z),
(s + x, -s + y, s + z), (-s + x, -s + y, s + z)
]
self.wires = [ #12 tuples referencing the corner points
(0,1), (0,3), (0,4), (2,1), (2,3), (2,6),
(7,3), (7,4), (7,6), (5,1), (5,4), (5,6)
]
self.facets = [ #6 tuples referencing the corner points
(0, 1, 2, 3), (0, 1, 6, 5), (0, 3, 7, 4),
(6, 5, 1, 2), (6, 7, 4, 5), (6, 7, 3, 2)
]
def show(self):
self.render = True
def hide(self):
self.render = False
def move(self, location):
self.location = location
self.compute()
def recolor(self, col):
if type(col) is tuple:
self.color = col
class mesh():
vertices = []
facets = []
wires = []
render = True
def __init__(self, drawWires = True, drawFaces = False, color = (1, 1, 1)):
self.drawWires = drawWires
self.drawFaces = drawFaces
self.color = color
self.vertices = []
self.facets = []
self.wires = []
self.render = True
def addFacet(self, coords): #takes a tuple of three location tuples.
addr = len(self.vertices)
addrs = [None, None, None]
for i in range(3):
c = coords[i]
if not c in self.vertices:
self.vertices.append(c)
addrs[i] = self.vertices.index(c)
self.facets.append((addrs[0], addrs[1], addrs[2]))
self.wires.append((addrs[0], addrs[1]))
self.wires.append((addrs[2], addrs[1]))
self.wires.append((addrs[2], addrs[0]))
#---------- main shader ----------#
class shader():
#variables
parent = None
shapes = []
shapeTypes = [type(cube), type(mesh)]
#functions
def __init__(self, parent = None):
self.parent = parent
print('Initiated new shader as child of {}.'.format(self.parent))
def resize(self, newSize):
self.sizeX, self.sizeY = newSize
def addShape(self, shapeIn):
if type(shapeIn) not in self.shapeTypes:
raise shapeNotFound("Shape {} not found.".format(shapeIn))
self.shapes.append(shapeIn)
def paintGL(self):
#This function uses shape objects, such as cube() or mesh(). Shape objects require the following:
#a list named 'vertices' - This list is a list of points, from which edges and faces are drawn.
#a list named 'wires' - This list is a list of tuples which refer to vertices, dictating where to draw wires.
#a list named 'facets' - This list is a list of tuples which refer to vertices, ditating where to draw facets.
#a bool named 'render' - This bool is used to dictate whether or not to draw the shape.
#a bool named 'drawWires' - This bool is used to dictate whether wires should be drawn.
#a bool named 'drawFaces' - This bool is used to dictate whether facets should be drawn.
glLoadIdentity()
gluPerspective(45, self.sizeX / self.sizeY, 0.1, 110.0) #set perspective?
glTranslatef(0, 0, self.zoomLevel) #I used -10 instead of -2 in the PyGame version.
glRotatef(self.rotateDegreeV, 1, 0, 0) #I used 2 instead of 1 in the PyGame version.
glRotatef(self.rotateDegreeH, 0, 0, 1)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
if len(self.shapes) != 0:
glBegin(GL_LINES)
for s in self.shapes:
glColor3fv(s.color)
if s.render and s.drawWires:
for w in s.wires:
for v in w:
glVertex3fv(s.vertices[v])
glEnd()
glBegin(GL_QUADS)
for s in self.shapes:
glColor3fv(s.color)
if s.render and s.drawFaces:
for f in s.facets:
for v in f:
glVertex3fv(s.vertices[v])
glEnd()
For a project I am working on, I am creating a class of polynomials that I can operate on. The polynomial class can do addition, subtraction, multiplication, synthetic division, and more. It also represents it properly.
For the project, we are required to do create a class for Newton's Method. I was able to create a callable function class for f, such that
>f=polynomial(2,3,4)
>f
2+3x+4x^2
>f(3)
47
I have a derivative function polynomial.derivative(f) outputs 3+8x.
I want to define a function labeled Df so that in my Newtons Method code, I can say, Df(x). It would work so that if x=2:
>Df(2)
19
The derivative of a polynomial is still a polynomial. Thus, instead of returning the string 3+8x, your polynomial.derivative function should return a new polynomial.
class polynomial:
def __init__(c, b, a):
self.coefs = [c, b, a]
[...]
def derivative(self):
return polynomial(*[i*c for i,c in enumerate(self.coefs) if i > 0], 0)
Hence you can use it as follow:
> f = polynomial(2, 3, 4)
> Df = f.derivative()
> f
2+3x+4x^2
> Df
3+8x+0x^2
> f(3)
47
> Df(2)
19
Edit
Of course, it is enumerate and not enumerates. As well, the __init__ misses the self argument. I code this directly on SO without any syntax check.
Of course you can write this in a .py file. Here is a complete working example:
class Polynomial:
def __init__(self, c, b, a):
self.coefs = [c, b, a]
self._derivative = None
#property
def derivative(self):
if self._derivative is None:
self._derivative = Polynomial(*[i*c for i,c in enumerate(self.coefs) if i > 0], 0)
return self._derivative
def __str__(self):
return "+".join([
str(c) + ("x" if i > 0 else "") + (f"^{i}" if i > 1 else "")
for i, c in enumerate(self.coefs)
if c != 0
])
def __call__(self, x):
return sum([c * (x**i) for i, c in enumerate(self.coefs)])
if __name__ == '__main__':
f = Polynomial(2, 3, 4)
print(f"f: y={f}")
print(f"f(3) = {f(3)}")
print(f"f': y={f.derivative}")
print(f"f'(2) = {f.derivative(2)}")
f: y=2+3x+4x^2
f(3) = 47
f': y=3+8x
f'(2) = 19
You can rename the property with the name you prefer: derivative, Df, prime, etc.