I was wanting to create a physics simulation, in which the initial values would be the initial position vectors of all the bodies, the initial velocity vectors of all the bodies, the masses of all the bodies, the charges of all the bodies, and 0 for the initial time passed.
The distance formula for calculating the distance between two bodies in the simulation should be the same as the distance formula in euclidean space.
The force vector on any body from any other body would depend on the product of the charges of both bodies multiplied by a function of the distance f(distance) between both bodies multiplied by (the position vector of that body minus the position vector of the other body) divided by the distance between both bodies. The total force vector on any body would depend on the sum of all the force vectors on that body from the other bodies. The acceleration vector for any body would depend on the total force vector on that body divided by the mass of that body.
In each time step after the initial time step the new position vector for each body would depend on 1/2 multiplied by the previous acceleration vector multiplied by the previous time step squared plus the previous velocity vector multiplied by the previous time step plus the previous position vector. The new velocity vector would depend on the previous acceleration vector multiplied by the previous time step plus the previous velocity vector. Also the new time passed would depend on the previous time passed plus the previous time step.
The formulas need to automatically adjust to continue matching what I said previously if I change the number of dimensions, add a new body, remove an existing body, change the mass of an existing body, change the charge of an existing body, change the position vector of an existing body, change the velocity vector for an existing body, or change the function of distance in the formula for force that I mentioned earlier.
The simulation should work in more than three dimensions of space. Also for the function of distance f(distance) that I mentioned in paragraph three the simulation should support as many functions of distance as possible including trigonometric functions of the distance such as the sin(distance) and cos(distance) of the distance, hyperbolic trig functions of the distance such as cosh(distance) and sinh(distance) polynomials of the distance, powers of the distance such as e^distance, logarithms of the distance, Bessel functions of the distance, the error function of the distance, and combinations of these functions and if possible other functions.
Ideally it should be possible for the simulation to run through millions of time steps per minute in order for the simulation to be fast while minimizing the accumulated errors in the calculations of the simulation.
How would I code a physics simulation that follows all of my criteria above and what type of program would be best for this type of simulation?
Lets address these issues one at a time:
To handle an arbitrary number of dimensions, you'll have to store your position, velocity, and acceleration vectors as arrays, and then map some function over those arrays, instead of explicitly accepting x, y, and z or something.
Store your position / velocity / acceleration / force arrays and charge in some object or structure representing that object, and store all of these in a larger array, which you can then iterate over to calculate the force vectors, and update the force arrays accordingly. Once all forces are accounted for, update the position / velocity / acceleration, and reset the force vector.
In order to meet your accuracy and performance requirements, you'll probably have to either write this simulation a compiled language like C. Additionally, to support all your functions of distance you listed, you'll probably need to use a combination of lookup tables, and arithmetic tricks / approximations to obtain the values quickly enough.
Try to write out all your formulas first, and see what algebraic simplifications you can apply, to save yourself extra computational steps (can you double everything to avoid a division by two, can you square something to avoid a square root, etc). Know that division is far slower than multiplication, and square roots are even more expensive (think distance magnitude).
Related
I have a large array of floating point values that vary widely in magnitude. Does it help rescaling those in [0,1] for precision purposes (e.g. if I want to perform arithmetic operations on the array)? I can think of the smaller values getting truncated if I do so, but on the other hand small values will not contribute much to the absolute error. If I do the rescaling on an array of already computed values, I believe this can only make things worse as I would only introduce additional round-off error. On the other hand, I believe I can decrease the error if the scaling is instead involved at the point when I generate said values.
I am mainly referring to the fact that absolute distance between consecutive error grows 2 times for values in subsequent intervals (i.e. [0,1) vs [1,2) vs [2,4), etc.). Am I interpreting this correctly in the current context? I have seen such effect of floating point errors due to large scaling when trying to render a massively scaled 3D scene versus a less scaled version of it (similar effects occur when a camera in 3D space is too far from the origin, since absolute distances between floats become larger).
Considering the above, is there an optimal way to choose the scaling factor for an array of values I plan to generate (provided I know what the minimum and maximum will be without scaling). I was thinking of just generating it so that all values are within [0,1], however I was worried that the truncation of the smallest element may be an issue. Are there known heuristics based on the largest and smallest elements that allow to find a semi-optimal rescaling wrt precision. On an unrelated note, I am aware of the Kahan summation algorithm and its variants and I do use it for the summation of said array. My question is rather whether a choice of scale can help further, or will this not matter?
Scaling by powers of two in a binary floating-point format (or, generally, by powers of b in a base-b floating-point format) has no error as long as the results stay within normal exponent bounds. That is, for any x, the result of computing x•be has the same significand as x, as long as x•be is in the normal range.
Again as long as results stay in the normal range, the operations of adding, subtracting, multiplying, and dividing scaled numbers produce results with identical significands as the same operations on unscaled numbers that stay in the normal range. Any rounding errors that occur in the unscaled operations are identical to the rounding errors in the scaled operations, as adjusted by the scale.
Therefore, scaling numbers by a power of b, performing the same operations, and undoing the scaling will not improve or alter floating-point rounding errors. (Note that multiplications and divisions will affect the scaling, and this can be compensated for either after each operation, after all the operations, or periodically. For example, given X = x*16 and Y = y*16, X*Y would equal x*16*y*16 = x*y*256. So undoing its scaling requires dividing by 256 rather than 16.)
If other operations are used, the rounding errors may differ. For example, if a square root is performed and the scaling in its operand is not an even power of b, its result will include a scaling that is not an integral power of b, and so the significand must be different from the significand of the corresponding unscaled result, and that allows the rounding errors to be different.
Of course, if sines, cosines, or other trigonometric functions are used on scaled numbers, drastically different results will be obtained, as these functions do not scale in the required way (f(x•s) generally does not equal f(x)•s). However, if the numbers that are being scaled represent points in space, any angles computed between them would be identical in the scaled and unscaled implementations. That is, the computed angles would be free of scaling, and so applying trigonometric functions would produce identical results.
If any intermediate results exceed the normal exponent range in either the scaled or the unscaled computations, then different significands may be produced. This includes the case where the results are subnormal but have not underflowed to zero—subnormal results may have truncated signficands, so some information is lost compared to a differently-scaled computation that produces a result in the normal range.
An alternative to scaling may be translation. When working with points from the origin, the coordinates may be large, and the floating-point resolution may be large relative to distances between the points. If the points are translated to near the origin (a fixed amount is subtracted from each coordinate [fixed per dimension]), the geometric relationships between them are preserved, but the coordinates will be in a finer range of the floating-point format. This can improve the floating-point rounding errors that occur.
Given a set of embeddings, i.e. set of [name, vector representation]
how should I store it such that queries on the closest points are computed quickly. For example given 100 embeddings in 2-d space, if I query the data struct on the 5 closest points to (10,12), it returns { [a,(9,11.5)] , [b,(12,14)],...}
The trivial approach is calculate all distances, sort and return top-k points. Alternatively, one might think of storing in a 2-d array in blocks/units of mXn space to cover the range of the embedding space. I don't think this is extensible to higher dimensions, but I'm willing to be corrected.
There are standard approximate nearest neighbors library such as faiss, flann, java-lsh etc. (which are either LSH or Product Quantization based), which you may use.
The quickest solution (which I found useful) is to transform a vector of (say 100 dimensions) to a long variable (64 bits) by using the Johnson–Lindenstrauss transform. You can then use Hamming similarity (i.e. 64 minus the number of bits set in a XOR b) to compute the similarity between bit vectors a and b. You could use the POPCOUNT machine instruction to this effect (which is very fast).
In effect, if you use POPCOUNT in C, even if you do a complete iteration over the whole set of binary transformed vectors (long variables of 64 bits), it still will be very fast.
In my path finding school project, the user is given 3 options to navigate between two points:
Shortest path (Kilometers). I've defined the cost function for each 2 points to be the distance of the road that connects them.
Fastest path (Each road has a speed limit). I've defined the cost function between each 2 points to be 1/(SpeedLimit).
Simplest path (Minimizes turns, a turn is defined if the road changes direction by more than alpha degrees). I've defined a state to be a tuple of a point and direction, and defined the cost function to be 1 if the change of direction is larger than alpha and 0 otherwise.
The user then supplies 3 real numbers between 0 and 1 to specify the importance of each navigating option.
So basically the cost function should be the sum of the three cost functions described above, each multiplied by the number supplied. My problem is that each cost function is of different units, for example, the first cost function is in kilometers and the third cost function is boolean (0 or 1).
How can I convert them so that it makes sense?
Define a cost function for each criteria that maps from a path to a real number.
f1(path) = cost associated with the distance of the path
f2(path) = cost of the time taken to traverse the path
f3(path) = cost of the complexity of the route
Defining f1 and f2 should be fairly straightforward. f3 is more complex and subjective but I suspect it really shouldn't be a boolean unless there's some very specific reason why you would need it to be. Perhaps the function for path complexity could be something like the sum of the number of degrees (radians) in every turn taken in the trip. There's certainly quite a few other choices for such a function that immediately come to mind, (for example the length of the representation required to describe the path). For f3 you will have to choose whatever one suits your purposes best.
Once you have defined the individual cost functions you could get an overall cost for the path by taking a linear combination of those 3 functions:
cost(path) = a1*f1(path) + a2*f2(path) + a3*f3(path)
Finding sensible values for a1, a2, a3 is most of the challenge. There are a few statistical methods you might want to use to do this.
I need to write a function that returns on of the numbers (-2,-1,0,1,2) randomly, but I need the average of the output to be a specific number (say, 1.2).
I saw similar questions, but all the answers seem to rely on the target range being wide enough.
Is there a way to do this (without saving state) with this small selection of possible outputs?
UPDATE: I want to use this function for (randomized) testing, as a stub for an expensive function which I don't want to run. The consumer of this function runs it a couple of hundred times and takes an average. I've been using a simple randint function, but the average is always very close to 0, which is not realistic.
Point is, I just need something simple that won't always average to 0. I don't really care what the actual average is. I may have asked the question wrong.
Do you really mean to require that specific value to be the average, or rather the expected value? In other words, if the generated sequence were to contain an extraordinary number of small values in its initial part, should the rest of the sequence atempt to compensate for that in an attempt to get the overall average right? I assume not, I assume you want all your samples to be computed independently (after all, you said you don't want any state), in which case you can only control the expected value.
If you assign a probability pi for each of your possible choices, then the expected value will be the sum of these values, weighted by their probabilities:
EV = − 2p−2 − p−1 + p1 + 2p2 = 1.2
As additional constraints you have to require that each of these probabilities is non-negative, and that the above four add up to a value less than 1, with the remainder taken by the fifth probability p0.
there are many possible assignments which satisfy these requirements, and any one will do what you asked for. Which of them are reasonable for your application depends on what that application does.
You can use a PRNG which generates variables uniformly distributed in the range [0,1), and then map these to the cases you described by taking the cumulative sums of the probabilities as cut points.
As per the title, is the best way to calculate the n-dimensional cross product just using the determinant definition and using the LU Decomposition method of doing as such or could you guys suggest a better one?
Thanks
Edit: for clarity I mean http://en.wikipedia.org/wiki/Cross_product and not the Cartesian Product
Edit: It also seems that using the Leibniz Formula might help - though I don't know how that compares to LU Decomp. at the moment.
From your comment, it seems like you are looking for an operation which takes n −1 vectors as input and computes a single vector as its result, which will be orthogonal to all the input vectors and perhaps have a well-defined length as well.
With defined length
You can characterize the 3-dimensional cross product v =a ×b using the identity v ∙w =det(a,b,w). In other words, taking the cross product of the input vectors and then computing the dot product with any other vector w is the same as plugging the input vectors and that other vector into a matrix and computing its determinant.
This definition can be generalized to arbitrary dimensions. Due to the way a determinant can be computed using Laplace expansion along the last column, the resulting coordinates of that cross product will be the values of all (n −1)×(n −1) sub-determinants you can form from the input vectors, with alternating signs. So yes, Leibniz might be useful in theory, although it is hardly suitable for real-world computations. In practice, you'll soon have to figure out ways to avoid repeating computationswhile computing these n determinants. But wait for the last section of this answer…
Just the direction
Most applications however can do with a weaker requirement. They don't care about the length of the resulting vector, but only about its direction. In that case, what you are asking for is the kernel of the (n −1)×n matrix you can form by taking the input vectors as rows. Any element of that kernel will be orthogonal to the input vectors, and since computing kernels is a common task, you can build on a lot of existing implementations, e.g. Lapack. Details might depend on the language you are using.
Combining these
You can even combine the two approaches above: compute one element of the kernel, and for a non-zero entry of that vector, also compute the corresponding (n −1)×(n −1) determinant which would give you that single coordinate using the first approach. You can then simply scale the vector so that the selected coordinate reaches the computed value, and all the other coordinates will match that one.