Optimizing sparse matrix solve time - sparse-matrix

Our simulations have large very sparse sets of SPD equations (a resistive network with current sources). We solve Ax = b, where A is conductance matrix and b is the current vector. We have effective solution methods (Eigen/sparse and/or Tim Davis's LDL). During the simulation, only a few of the elements in A change between time steps, but we need to factorize the entire matrix for the new solution (though we can avoid the ordering step in many cases).
We are wondering if there are methods that could segregate the fixed portion in A from the dynamic portions, factorize the fixed portions separately from the dynamic, then combine the two for the solution (forward/back substitution). From a top level understanding of standard solution methods, my sense is that this is not possible. But .... ??
Thanks in advance
Kevin

Related

Using Eigen rankupdate

We solve (via Cholesky decomp) large electrical networks in which only a small percentage of values change between iterations. The network is very sparse and SPD. Solve requires that need to factorize the entire matrix at each step.
My understanding (if correct) is that there are methods available, such as rankUpdate, to directly adjust the factorized matrix which may improve solve times. In our case, each element change results in a change to 2 or 3 rows, and the corresponding 2 or 3 columns.
Can anyone offer a brief discussion and simple example of how rankUpdate is used, or correct my understanding?
This would be very much appreciated.
Thanks
Kevin
In Eigen's Cholesky solvers, rank-updates are available only for dense solvers, e.g.:
LDLT chol(A); // initial factorization
chol.rankUpdate(V,s);
At this stage chol is equvalent to the factorization of A+s*V*V^T.
For sparse problems, this is not supported yet but CHOLMOD from Suite-Sparse does support rank-updates. The best, and likely simplest, way would be add such a rankUpdate method to the Eigen::CholmodLLT class as a thin wrapper to the underlying CHOLMOD routine.

computing function of neighbors efficiently on lattice

I'm studying the Ising model, and I'm trying to efficiently compute a function H(σ) where σ is the current state of an LxL lattice (that is, σ_ij ∈ {+1, -1} for i,j ∈ {1,2,...,L}). To compute H for a particular σ, I need to perform the following calculation:
where ⟨i j⟩ indicates that sites σ_i and σ_j are nearest neighbors and (suppose) J is a constant.
A couple of questions:
Should I store my state σ as an LxL matrix or as an L2 list? Is one better than the other for memory accessing in RAM (which I guess depends on the way I'm accessing elements...)?
In either case, how can I best compute H?
Really I think this boils down to how can I access (and manipulate) the neighbors of every state most efficiently.
Some thoughts:
I see that if I loop through each element in the list or matrix that I'll be double counting, so is there a "best" way to return the unique neighbors?
Is there a better data structure that I'm not thinking of?
Your question is a bit broad and a bit confusing for me, so excuse me if my answer is not the one you are looking for, but I hope it will help (a bit).
An array is faster than a list when it comes to indexing. A matrix is a 2D array, like this for example (where N and M are both L for you):
That means that you first access a[i] and then a[i][j].
However, you can avoid this double access, by emulating a 2D array with a 1D array. In that case, if you want to access element a[i][j] in your matrix, you would now do, a[i * L + j].
That way you load once, but you multiply and add your variables, but this may still be faster in some cases.
Now as for the Nearest Neighbor question, it seems that you are using a square-lattice Ising model, which means that you are working in 2 dimensions.
A very efficient data structure for Nearest Neighbor Search in low dimensions is the kd-tree. The construction of that tree takes O(nlogn), where n is the size of your dataset.
Now you should think if it's worth it to build such a data structure.
PS: There is a plethora of libraries implementing the kd-tree, such as CGAL.
I encountered this problem during one of my school assignments and I think the solution depends on which programming language you are using.
In terms of efficiency, there is no better way than to write a for loop to sum neighbours(which are actually the set of 4 points{ (i+/-1,j+/-1)} for a given (i,j). However, when simd(sse etc) functions are available, you can re-express this as a convolution with a 2d kernel {0 1 0;1 0 1;0 1 0}. so if you use a numerical library which exploits simd functions you can obtain significant performance increase. You can see the example implementation of this here(https://github.com/zawlin/cs5340/blob/master/a1_code/denoiseIsingGibbs.py) .
Note that in this case, the performance improvement is huge because to evaluate it in python I need to write an expensive for loop.
In terms of work, there is in fact some waste as the unecessary multiplications and sum with zeros at corners and centers. So whether you can experience performance improvement depends quite a bit on your programming environment( if you are already in c/c++, it can be difficult and you need to use mkl etc to obtain good improvement)

Preconditioning of a linear system

I have a large sparse linear system generated as a part of PDE solution for flows in the form Ax=b. The condition number of matrix A is very bad - of the order 3000!. But I get expected solutions with direct solvers. So, now I want to precondition the matrix so that I can use iterative solvers and use the sparseness. I have tried Jacobi preconditioner, but it does not work well as the matrix is not diagonally dominant. I need some help in proceeding further:
1) Imagine I get an approximate solution for x (generated by one run of biconjugate gradient solver). Now can I get "inverse of A" (for preconditioning) from this, seems like it must be possible but I am unable to figure out how! i.e knowing x and b can I calculate the A inverse (which may be used as preconditioner!).
2) Any other way of preconditioning which you feel would be worth a try?
3) Any way to circumvent pre-conditioning for iterative schemes for bad condition number systems?
Thanks a lot in advance for any help. Any comments are welcome.

Evenly distribute scent in a collaborative diffusion matrix

I am trying to implement a collaborative diffusion behaviour for the first time and I am stuck with a problem. I understand how to make obstacles not diffusing scents and how to dampen scent for other friendly agents if one of them already pursues it. What I cannot understand is how do I make scents to evenly distribute in the matrix. It seems to me that every way of iterating in the matrix, determines the scent to distribute faster and better in the tiles I check later in the iteration. I mean if I iterate from i to maxRows and j to maxCols and then I apply the diffusion equation in every tile, on the 'north' and 'west' side of the goal I will have only one tile with the correct potential, whereas in the 'east' and 'south' side I will have more of them since their neighbours already have an assigned potential. How can I make the values distribute evenly? A double iteration from both extremities of the matrix and them combining the result seems like a memory-eater, as do a goal-oriented approach, since if I try to start from the goals and work around them I will have to execute the calculations for every goal and every tile with assigned potential, which means that I will have to do it for 4^(turn since starter diffusion)*nrOfGoals more every turn, which seems inefficient in a large matrix with a lot of goals.
My question is how can I evenly distribute the values in the matrix in an efficient way. I'm using the AiChallenge Ants, if that helps in any way!
I thank you in anticipation and I'm sorry for the grammar mistakes I've made in this post.
There may be a better solution, but the easiest way to do it is to use something similar to how a simple implementation of the game of life is done.
You have two buffers. One has the current "generation" of scent (and if you are doing multitasking, can be locked so only readers can look at it)... and another has the next generation of sent being calculated. You only "mix" scents from the current generation.
Once you are done, you swap the two buffers by simply changing the pointers / references.
Another way to think about it would be to have all the tiles calculate their new sent by asking their neighbors and averaging. When asked by their neighbors what their scent level is, they report their pre-calculated values from the previous pass. The new sent is only locked in once everyone has finished calculating.

Solving the problem of finding parts which work well with each other

I have a database of items. They are for cars and similar parts (eg cam/pistons) work better than others in different combinations (eg one product will work well with another, while another combination of 2 parts may not).
There are so many possible permutations, what solutions apply to this problem?
So far, I feel that these are possible approaches (Where I have question marks, something tells me these are solutions but I am not 100% confident they are).
Neural networks (?)
Collection-based approach (selection of parts in a collection for cam, and likewise for pistons in another collection, all work well with each other)
Business rules engine (?)
What are good ways to tackle this sort of problem?
Thanks
The answer largely depends on how do you calculate 'works better'?
1) Independent values
Assuming that 'works better' function f of x combination of items x=(a,b,c,d,...) and(!) that there are no regularities that can be used to decide if f(x') is bigger or smaller then f(x) knowing only x, f(x) and x' (which could allow to find the xmax faster) you will have to calculate f for all combinations at least once.
Once you calculate it for all combinations you can sort. If you will need to look up data in a partitioned way, using SQL/RDBMS might be a good approach (for example, finding top 5 best solutions but without such and such part).
For extra points after calculating all of the results and storing them you could analyze them statistically and try to establish patterns
2) Dependent values
If you can establish some regularities (and maybe you can) regarding the values the search for the max value can be simplified and speeded up.
For example if you know that function that you try to maximize is linear combination of all the parameters then you could look into linear programming
If it is not...

Resources