I am modeling something that occurs on a square grid that wraps on itself (i.e., if you walk up past the highest point, you end up at the lowest point, like a cylinder; if you walk to the right, you just hit the boundary). I need to keep track of the location of various agents, the amount of resources at different points, and calculate the direction that agents will be moving in based on certain rules.
What's the best way to model this?
Should I make a class that represents points, which has methods to return neighboring points in each direction? If so, I would probably need to make it hashable so that I can use it as keys for the dictionary that contains the full grid (I assume such grid should be a dictionary?)
Or should I make a class that describes the whole grid and not expose individual points as independent objects?
Or should I just use regular (x, y) tuples and have methods elsewhere that allow to look up neighbors?
A lot of what I'll need to model is not yet clearly defined. Furthermore, I expect the geometry of the surface might possibly change one day (e.g., it could wrap on itself in both directions).
EDIT: One additional question: should I attach the information about the quantity of resources to each Point instance; or should I have a separate class that contains a map of resources indexed by Point?
If you want a hashable Point class without too much work, subclass tuple and add your own neighbor methods.
class Point(tuple):
def r_neighbor(self):
return Point((self[0] + 1, self[1]))
def l_neighbor(self):
[...]
x = Point((10, 11))
print x
print x.r_neighbor()
The tuple constructor wants an iterable, hence the double-parens in Point((10, 11)); if you want to avoid that, you can always override __new__ (overriding __init__ is pointless because tuples are immutable):
def __new__(self, x, y):
return super(Point, self).__new__(self, (x, y))
This might also be the place to apply modular arithmetic -- though that will really depend on what you are doing:
def __new__(self, x, y, gridsize=100):
return super(Point, self).__new__(self, (x % gridsize, y % gridsize))
or to enable arbitrary dimension grids, and go back to using tuples in __new__:
def __new__(self, tup, gridsize=100):
return super(Point, self).__new__(self, (x % gridsize for x in tup))
Regarding your question about resources: since Point is an immutable class, it's a poor place to store information about resources that might change. A defaultdict would be handy; you wouldn't have to initialize it.
from collections import defaultdict
grid = defaultdict(list)
p = Point((10, 13))
grid[(10, 13)] = [2, 3, 4]
print grid[p] # prints [2, 3, 4]
print grid[p.r_neighbor] # no KeyError; prints []
If you want more flexibility, you could use a dict instead of a list in defaultdict; but defaultdict(defaultdict) won't work; you have to create a new defaultdict factory function.
def intdict():
return defaultdict(int)
grid = defaultdict(intdict)
or more concisely
grid = defaultdict(lambda: defaultdict(int))
then
p = Point((10, 13))
grid[(10, 13)]["coins"] = 50
print grid[p]["coins"] # prints 50
print grid[p.r_neighbor]["coins"] # prints 0; again, no KeyError
I need to keep track of the location
of various agents, the amount of
resources at different points, and
calculate the direction that agents
will be moving in based on certain
rules.
Sounds like a graph to to me, though I try to see a graph in every problem. All the operations you mentioned (move around, store resources, find out where to move to) are very common on graphs. You would also be able to easily change the topology, from a cylinder to a torus or in any other way.
The only issue is that it takes more space than other representations.
On the plus side you can use a graph library to create the graph and probably even some graph algorithms to calculate where agents go.
Related
I am trying to automate the partitioning of a model in ABAQUS using Python script. So far I have a feeling that I am going down a rabbit hole with no solution. I have a feeling that even if I manage to do it, the algorithm will be very inefficient and slower than manual partitioning.
I want the script to:
to join Interesting Points on each face with lines that are perpendicular to the edges.
to be applicable to any model.
to create partitions that can be deleted/edited later on.
My question is: is automatic partitioning possible? If so, what kind of algorithm should I use?
In the meantime, I have made an initial code below to get an idea of the problem using the Partition by shortest path function:
(note that I am looping through vertices and not Interesting Points because I haven’t found a way to access them.)
The problems I have are:
New faces are created will be created as I partition the faces through the range function. My alternative is to select all the faces.
New interesting points are created as I partition. I could make a shallow copy of the initial interesting points and then extract the coordinates and then use these coordinates to do the partitioning. Before partitioning I will need to convert the coordinates back to a dictionary object.
I cannot seem to access the interesting points from the commands.
from abaqus import *
from abaqusConstants import *
#Define Functions
def Create_cube(myPart,myString):
s = mdb.models[myString].ConstrainedSketch(name='__profile__',sheetSize=200.0)
g, v, d, c = s.geometry, s.vertices, s.dimensions, s.constraints
s.setPrimaryObject(option=STANDALONE)
s.rectangle(point1=(10.0, 10.0), point2=(-10.0, -10.0))
p = mdb.models[myString].Part(name=myPart, dimensionality=THREE_D,type=DEFORMABLE_BODY)
p = mdb.models[myString].parts[myPart]
p.BaseSolidExtrude(sketch=s, depth=20.0)
s.unsetPrimaryObject()
p = mdb.models[myString].parts[myPart]
session.viewports['Viewport: 1'].setValues(displayedObject=p)
del mdb.models[myString].sketches['__profile__']
def subtractTheMatrix(matrix1,matrix2):
matrix = [0,0,0]
for i in range(0, 3):
matrix[i] = matrix1[i] - matrix2[i]
if matrix[i]==0.0:
matrix[i]=int(matrix[i])
return matrix
#Define Variables
myString='Buckling_Analysis'
myRadius= 25.0
myThickness= 2.5
myLength=1526.0
myModel= mdb.Model(name=myString)
myPart='Square'
myOffset=0.0
set_name='foobar'
#-------------------------------------------------------------------MODELLING-----------------------------------------------------------------
#Function1: Create Part
Create_cube(myPart,myString)
#Function2: Extract Coordinates from vertices (using string manipulation)
#Input: vertices in vertex form
#Output: coordinates of vertices in the form [[x,y,z],[x1,y1,z1],[x2,y2,z2]] (name: v1_coordinates)
p = mdb.models[myString].parts[myPart]
v1=p.vertices
v1_coordinates=[]
for x in range(len(v1)):
dictionary_object=v1[x]
dictionary_object_str= str(dictionary_object)
location_pointon=dictionary_object_str.find("""pointOn""")
location_coord=location_pointon+12
coordinates_x_string=dictionary_object_str[location_coord:-5]
coordinates_x_list=coordinates_x_string.split(',') #convert string to list of strings
for lo in range(3):
coordinates_x_list[lo]=float(coordinates_x_list[lo]) #change string list to float list
v1_coordinates.append(coordinates_x_list) #append function. adds float list to existing list
print("""these are all the coordinates for the vertices""",v1_coordinates)
#Function3: Partioning loop though List of Coordinates
#Input: List of Coordinates
#Output: Partioned faces of model (Can only be seen in ABAQUS viewport.)
f = p.faces
v1 = p.vertices
#try and except to ignore when vertex is not in plane
final_number_of_faces=24
for i in range(0,final_number_of_faces,2):
print("this is for face:")
for j in range(len(v1_coordinates)):
fixed_vertex_coord = v1_coordinates[j]
fixed_vertex_dict = v1.getClosest(coordinates=((fixed_vertex_coord[0], fixed_vertex_coord[1], fixed_vertex_coord[2]),))
fixed_vertex_dict_str= str(fixed_vertex_dict[0])
location_1=fixed_vertex_dict_str.find("""],""")
fixed_vertex_index=int(fixed_vertex_dict_str[location_1-1:location_1])
for k in range(len(v1_coordinates)):
try:
if subtractTheMatrix(v1_coordinates[j], v1_coordinates[k])==[0,0,0]:
continue
else:
moving_vertex_coord=v1_coordinates[k]
moving_vertex_dict=v1.getClosest(coordinates=((moving_vertex_coord[0], moving_vertex_coord[1], moving_vertex_coord[2]),))
moving_vertex_dict_str= str(moving_vertex_dict[0])
location_2=moving_vertex_dict_str.find("""],""")
moving_vertex_index=int(moving_vertex_dict_str[location_2-1:location_2])
p.PartitionFaceByShortestPath(point1=v1[fixed_vertex_index], point2=v1[moving_vertex_index], faces=f[i])
except:
print("face error")
continue
Short answer
"Is it possible to automate partitioning in ABAQUS?" -- Yes
"How" -- It depends. For your example you probably will be perfectly fine with the PartitionEdgeByDatumPlane() method.
Long answer
Generally speaking, you cannot create a method that will be applicable to any model. You can automate/generalize partitioning for similar geometries and when partitioning is performed using similar logic.
Depending on your problem you have several methods to perform a partition, for example:
For face: ByShortestPath, BySketch, ByDatumPlane, etc.;
For cell: ByDatumPlane, ByExtrudeEdge, BySweepEdge, etc.
Depending on your initial geometry and required results you could need to use different of those. And your approach (the logic of your script) would evolve accordingly.
Abaqus scripting language is not very optimal for checking intersections, geometrical dependences, etc., so yes, if your geometry/task requires complicated mix of several partitioning methods applied to a complex geometry then it could require some slow approaches (e.g. looping trhough all verticies).
Some additional comments:
no need in re-assigning variable p by p = mdb.models[myString].parts[myPart]: mdb.models[myString].Part(..) already return part object.
do you really need methods setPrimaryObject/unsetPrimaryObject? When automating you generally don't need viewport methods (also session.viewports['Viewport: 1'].setValues(displayedObject=p)).
Please, use attributes of Abaqus objects (as discussed in your previous question);
Don't forget that you can loop through sequences: use for v_i in v1 instead of for x in range(len(v1)) when you don't need to know index explicitly; use enumerate() when you need both object and its index.
I'm working on a geometry in space project and I have different geometrical entities, among which Point. Sometimes two points are equal but for small numerical errors due to calculation, such as 1 and 1.0000000001, so I implemented the __eq__ method with math.isclose() function to sort this things out.
class Point(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __eq__(self, other):
if isinstance(other, Point):
equal_x = math.isclose(other.x, self.x, rel_tol=5e-3, abs_tol=1e-5)
equal_y = math.isclose(other.y, self.y, rel_tol=5e-3, abs_tol=1e-5)
equal_z = math.isclose(other.z, self.z, rel_tol=5e-3, abs_tol=1e-5)
if equal_x and equal_y and equal_z:
return True
return False
How to implement the __hash__ method in order for such two objects to be equal when using sets and dictionaries?
The ultimate goal is to use the following function to "uniquify" a list of such object and remove duplicates:
def f12(seq):
# from Raymond Hettinger
# https://twitter.com/raymondh/status/944125570534621185
return list(dict.fromkeys(seq))
There is a general problem with your equal method.
Most people will expect transitivity in a equal method. This means that when two points a and b are equal and a is also equal to an other point c, then a and c should be also equal. That doesn't have to be the case in your implementation.
Imagine each point, have a sphere around him, where the points are considered equal. The following drawing shows this spheres (or better half the radius of the sphere) and overlapping therefore implies that the points are equal:
So a and b should have the same hash code and b and c should have the same hash code, but not a and c? How should this be possible?
I would propose to add an extra method is_close_to and implement the logic there.
Edit:
#JLPeyret points out, that you can use a grid and compute the hash value of a point corresponding to the quadrant of the grid that contains the point. In this case it is possible, that two near points are close to the division of a grid quadrant and therefore assigned with different hash values. If such a probabilistic approach works for you, take a look at locality-sensitive hashing.
Instead of giving your points an 'invalid' __eq__ method, either give them an isclose method, using the code you already have, and use that instead of == or make them equal in the standard sense by rounding the coordinates.
By 'graph' I mean 'function' in the mathematical sense, where you always find one unchanging y value per x value.
Python's random.Random class's seed behaves as the x-coordinate of a random graph and each new call to random.random() gives a new random graph with all new x-y mappings.
Is there a way to directly refer to random.Random's nth graph, or in other words, the nth value in a certain seed's series without calling random.random() n times?
I am making a set of classes that I call Transformers that take any (x,y) coordinates as input and output another pair of (x,y) coordinates. Each transformer has two methods: transform and untransform. One of the transformers that I want adds a random value to the input y coordinate depending on the the input x coordinate. Say that I then want this transformer to untransform(x, y), now I need to subtract the same value I added from y if x is the same. This can be done by setting the seed to the same value it had when I added to y, so acting like the x value. Now say that I want two different instances of the transformer that adds random values to y. My question is about my options for making this new random transformer give different values than the first one.
Since Python 3.4 apparently removes jumpahead, here's some code that implements a convenient pseudorandom dictionary.
from hashlib import sha256 as _sha256
from hmac import HMAC as _HMAC
from math import ldexp as _ldexp
from os import urandom as _urandom
from sys import byteorder as _byteorder
class PRF():
def __init__(self):
digestmod = _sha256
self._h = _HMAC(_urandom(digestmod().block_size), digestmod=digestmod)
def __getitem__(self, key):
h = self._h.copy()
h.update(repr(key).encode())
b = h.digest()
return _ldexp(int.from_bytes(b, _byteorder), (len(b) * (- 8)))
Example usage:
>>> import prf
>>> f = prf.PRF()
>>> f[0]
0.5414241336009658
>>> f[1]
0.5238549618249061
>>> f[1000]
0.7476468534384274
>>> f[2]
0.899810590895144
>>> f[1]
0.5238549618249061
Is there a way to directly refer to random.Random's nth graph, or in other words, the nth value in a certain seed's series without calling random.random() n times?
Yes, sort of; you use Random.jumpahead(). There aren't really separate functions/graphs, though -- there's only one sequence generated by the PRNG -- but you can get into it at any point.
You seem to be still working on the same problem as your last question, and the code I posted in a comment there should cover this:
from random import Random
class IndependentRepeatableRandom(object):
def __init__(self):
self.randgen = Random()
self.origstate = self.randgen.getstate()
def random(self, val):
self.randgen.jumpahead(int(val))
retval = self.randgen.random()
self.randgen.setstate(self.origstate)
return retval
Well you're probably going to need to come up with some more detailed requirements but yes, there are ways:
pre-populate a dictionary with however many terms in the series you require for a given seed and then at run-time simply look the nth term up.
if you're not fussed about the seed values and/or do not require some n terms for any given seed, then find a O(1) way of generating different seeds and only use the first term in each series.
Otherwise, you may want to stop using the built-in python functionality & devise your own (more predictable) algo.
EDIT wrt the new infos:
Ok. so i also looked at your profile & so you are doing something (musical?) other than any new crypto thing. if that's the case, then it's unfortunately mixed blessings, because while you don't require security, you also still won't want (audible) patterns appearing. so you unfortunately probably do still need a strong prng.
One of the transformers that I want adds a random value to the input y
coordinate depending on the the input x coordinate
It's not yet clear to me if there is actually any real requirement for y to depend upon x...
Now say that I want two different instances of the transformer that
adds random values to y. My question is about my options for making
this new random transformer give different values than the first one.
..because here, i'm getting the impression that all you really require is for two different instances to be different in some random way.
But, assuming you have some object containing tuple (x,y) and you really do want a transform function to randomly vary y for the same x; and you want an untransform function to quickly undo any transform operations, then why not just keep a stack of the state changes throughout the lifetime of any single instance of an object; and then in the untransform implementation, you just pop the last transformation off the stack ?
Write the function sinusoid(a, w, n) that will return a list of ordered pairs representing n cycles of a sinusoid with amplitude a and frequency w. Each cycle should contain 180 ordered pairs.
So far I have:
def sinusoid(a,w,n):
return [a*sin(x) for x in range 180]
Please consider the actual functional form of a sinusoidal wave and how the frequency comes into the equation. (Hint: http://en.wikipedia.org/wiki/Sine_wave).
Not sure what is meant exactly by 'ordered pairs', but I would assume it means the x,y pairs. Currently you're only returning a list of single values. Also you might want to take a look at the documentation for Python's sin function.
Okay, we know this is a homework assignment and we're not going to do it for you. However, I'll give you a couple hints.
The instructions:
Write the function sinusoid(a, w, n) that will return a list of ordered pairs representing n cycles of a sinusoid with amplitude a and frequency w. Each cycle should contain 180 ordered pairs.
... translated into a bullet list of requirements:
Write a function
... named sinusoid()
... taking three arguments: a, w, and n
returning a list
... of n cycles(?)
... (each consisting of?) 180 "ordered pairs"
The example you've given does define a function, by the correct name, and taking the correct number of arguments. That's a start (not much of one, frankly, but it's something).
The obvious failings are that it doesn't use two of the arguments that are required and it doesn't return pairs of anything. It seems that it would return 180 numbers which are based on the argument supplied to its first parameter.
Surely you can do a bit better than that.
Let's start with a stub:
def sinusoid(a, w, n):
'''Return n cycles of the sinusoid for a given amplitude and frequence
where each cycle consists of 180 ordered pairs
'''
results = list()
# do stuff here
return results
That's a function, takes three arguments and returns a list. Now for that list to contain anything before we return it we'll have to append some things to it ... and the instructions tell us how many things it should return (n times 180) and what sorts of things they should be (ordered pairs).
That sounds quite a bit like we'll need a loop (for n) and another (for 180). Hmmm ...
That might look like:
for each_cycle in range(n):
for each_pair in range(180):
# do something here
results.append(something) # where something is a tuple ... an "ordered pair"
... or it might look like:
for each_cycle in range(n):
this_cycle = list()
for each_pair in range(180):
this_cycle.append(something)
results.extend(this_cycle)
... or it might even look like:
for each_pair in range(n*180):
results.append(something)
... though, frankly, that seems unlikely. (If you try flattening the inner loop to the outer loop in this way you might find that you're having to use modulo arithmetic to get n back out for some other intermediate computational purposes).
I have no idea what the instructor is actually asking for. It seems likely that the math.sin() function will be involved and I guess "ordered pairs" might be co-ordinates mapped to some sort of graphics subsystem and suitable for plotting a graph. I guess 180 of these to show the sinusoid wave through a full range of its values. Maybe you're supposed to multiply something by the amplitude and/or divide something else by the frequency and maybe you're supposed to even add something for each cycle ... some sort of offset to keep the plot moving towards the right or something.
But it seems like you might start with that stub of a function definition and try pasting in one or another of these loop bodies and then figuring out how to actually return meaningful values in the parts where I've used "something" as a placeholder.
Going with the assumption that these "ordered pairs" are co-ordinates, for plotting, then it seems likely that each of the things you append to your results should be of the form (x,y) where x is monotonically increasing (fancy way of saying it keeps going up, never goes down) and might even always be the range(0,n*180) and y is probably math.sin() of something involved a and w ... but that's just speculation on my part.
The question is, basically: what would be more preferable, both performance-wise and design-wise - to have a list of objects of a Python class or to have several lists of numerical properties?
I am writing some sort of a scientific simulation which involves a rather large system of interacting particles. For simplicity, let's say we have a set of balls bouncing inside a box so each ball has a number of numerical properties, like x-y-z-coordinates, diameter, mass, velocity vector and so on. How to store the system better? Two major options I can think of are:
to make a class "Ball" with those properties and some methods, then store a list of objects of the class, e. g. [b1, b2, b3, ...bn, ...], where for each bn we can access bn.x, bn.y, bn.mass and so on;
to make an array of numbers for each property, then for each i-th "ball" we can access it's 'x' coordinate as xs[i], 'y' coordinate as ys[i], 'mass' as masses[i] and so on;
To me it seems that the first option represents a better design. The second option looks somewhat uglier, but might be better in terms of performance, and it could be easier to use it with numpy and scipy, which I try to use as much as I can.
I am still not sure if Python will be fast enough, so it may be necessary to rewrite it in C++ or something, after initial prototyping in Python. Would the choice of data representation be different for C/C++? What about a hybrid approach, e.g. Python with C++ extension?
Update: I never expected any performance gain from parallel arrays per se, but in a mixed environment like Python + Numpy (or whatever SlowScriptingLanguage + FastNativeLibrary) using them may (or may not?) let you move more work out of you slow scripting code and into the fast native library.
Having an object for each ball in this example is certainly better design. Parallel arrays are really a workaround for languages that do not support proper objects. I wouldn't use them in a language with OO capabilities unless it's a tiny case that fits within a function (and maybe not even then) or if I've run out of every other optimization option and the profiler shows that property access is the culprit. This applies twice as much to Python as to C++, as the former places a large emphasis on readability and elegance.
I agree that parallel arrays are almost always a bad idea, but don't forget that you can use views into a numpy array when you're setting things, up, though... (Yes, I know this is effectively using parallel arrays, but I think it's the best option in this case...)
This is great if you know the number of "balls" you're going to create beforehand, as you can allocate an array for the coordinates, and store a view into that array for each ball object.
You have to be a bit careful to do operations in-place on the coords array, but it makes updating coordinates for numerous "balls" much, much, much faster.
For example...
import numpy as np
class Ball(object):
def __init__(self, coords):
self.coords = coords
def _set_coord(self, i, value):
self.coords[i] = value
x = property(lambda self: self.coords[0],
lambda self, value: self._set_coord(0, value))
y = property(lambda self: self.coords[1],
lambda self, value: self._set_coord(1, value))
def move(self, dx, dy):
self.x += dx
self.y += dy
def main():
n_balls = 10
n_dims = 2
coords = np.zeros((n_balls, n_dims))
balls = [Ball(coords[i,:]) for i in range(n_balls)]
# Just to illustrate that that the coords are updating
ball = balls[0]
# Random walk by updating coords array
print 'Moving all the balls randomly by updating coords'
for step in xrange(5):
# Add a random value to all coordinates
coords += 0.5 - np.random.random((n_balls, n_dims))
# Display the coords for a particular ball and the
# corresponding row of the coords array
print ' Value of ball.x, ball.y:', ball.x, ball.y
print ' Value of coords[0,:]:', coords[0,:]
# Move an individual ball object
print 'Moving a ball individually through Ball.move()'
ball.move(0.5, 0.5)
print ' Value of ball.x, ball.y:', ball.x, ball.y
print ' Value of coords[0,:]:', coords[0,:]
main()
Just to illustrate, this outputs something like:
Moving all the balls randomly by updating coords
Value of ball.x, ball.y: -0.125713650677 0.301692195466
Value of coords[0,:]: [-0.12571365 0.3016922 ]
Value of ball.x, ball.y: -0.304516863495 -0.0447543559805
Value of coords[0,:]: [-0.30451686 -0.04475436]
Value of ball.x, ball.y: -0.171589457954 0.334844443821
Value of coords[0,:]: [-0.17158946 0.33484444]
Value of ball.x, ball.y: -0.0452864552743 -0.0297552313656
Value of coords[0,:]: [-0.04528646 -0.02975523]
Value of ball.x, ball.y: -0.163829876915 0.0153203173857
Value of coords[0,:]: [-0.16382988 0.01532032]
Moving a ball individually through Ball.move()
Value of ball.x, ball.y: 0.336170123085 0.515320317386
Value of coords[0,:]: [ 0.33617012 0.51532032]
The advantage here is that updating a single numpy array is going to be much, much faster than iterating through all of your ball objects, but you retain a more object-oriented approach.
Just my thoughts on it, anyway..
EDIT: To give some idea of the speed difference, with 1,000,000 balls:
In [104]: %timeit coords[:,0] += 1.0
100 loops, best of 3: 11.8 ms per loop
In [105]: %timeit [item.x + 1.0 for item in balls]
1 loops, best of 3: 1.69 s per loop
So, updating the coordinates directly using numpy is roughly 2 orders of magnitude faster when using a large number of balls. (the difference is smaller when using 10 balls, as per the example, roughly a factor of 2x, rather than 150x)
I think it depends on what you're going to be doing with them, and how often you're going to be working with (all attributes of one particle) vs (one attribute of all particles). The former is better suited to the object approach; the latter is better suited to the array approach.
I was facing a similar problem (although in a different domain) a couple of years ago. The project got deprioritized before I actually implemented this phase, but I was leaning towards a hybrid approach, where in addition to the Ball class I would have an Ensemble class. The Ensemble would not be a list or other simple container of Balls, but would have its own attributes (which would be arrays) and its own methods. Whether the Ensemble is created from the Balls, or the Balls from the Ensemble, depends on how you're going to construct them.
One of my coworkers was arguing for a solution where the fundamental object was an Ensemble which might contain only one Ball, so that no calling code would ever have to know whether you were operating on just one Ball (do you ever do that for your application?) or on many.
Will you be having any forces between the balls (hard sphere/collision, gravity, electromagnetic)? I'm guessing so. Will you be having a large enough number of balls to want to use Barnes-Hut simulation ideas? If so, then you should definitely use the Ball class idea so that you can store them easily in octrees or something else along those lines. Also, using the Barnes-Hut simulation will cut down the complexity of the simulation to O(N log N) from O(N^2).
Really though, if you don't have forces between the balls or aren't using many balls, you don't need the possible speed gains from using parallel arrays and should go with the Ball class idea for that as well.