3D sparse matrix implementation?

北城以北 提交于 2020-01-03 17:08:29

问题


I've found a quite good sparse matrix implementation for c# over http://www.blackbeltcoder.com/Articles/algorithms/creating-a-sparse-matrix-in-net.

But as i work in 3d coordinate-system, i need a sparse-matrix implementation that i can use to map the 3d-coordinate system.

Details: I'm storing large amounts of primitive shapes data in memory like cubes. I do have large amounts of them (around 30 million) and i've lots of null (zero) entries around. Given that my each entry costs 1-bytes of entry, i'd like to implement a sparse-matrix so that i can fairly save memory space.

Note: Fast access to matrix cells is a fairly important factor for me, so i'd be trading speed over memory consumption.


回答1:


A very simple solution which I just made is this:

public class Sparse3DMatrix<T>
{
    Dictionary<Tuple<int,int,int>, T> values = new Dictionary<Tuple<int, int, int>, T>();

    public T this[int x, int y, int z]
    {
        get { return values[new Tuple<int, int, int>(x, y, z)]; }
        set { values[new Tuple<int, int, int>(x, y, z)] = value; }
    }

    public bool ContainsKey(int x, int y, int z)
    {
        return values.ContainsKey(new Tuple<int, int, int>(x, y, z));
    }
}

usage:

var test = new Sparse3DMatrix<float>();
test[1, 1, 1] = 1f;
Console.WriteLine(test[1, 1, 1]);

It could be extended with methods like those his version have, and with checks for x, y, z values etc.

I'm sure someone have something to say about its performance. It will be a decent implementation unless you really need something it for high-performance. It depends on the hash-code implementation of Tuple and your specific usage. If we assume the hashes are good, we will have O(1) lookup time. If you know you will have a lot of elements, you could use new Dictionary<...>(initial capacity) to avoid unnecessary resizing when added items.

Unlike his, this only have a single Dictionary with all the items. His version have dictionaries of dictionaries. The benefit of his, is if you have to scan over an entire row, you can just iterate the second-level dictionary (this will not help you is you want to scan over columns) which is faster than individual lookup of the items. But having a single dictionary means smaller memory usage - especially when you have few items per row.




回答2:


Lasse Espeholt's solution is practical but it can be improved by removing elements when they are "zeroed" or nulled. If you don't do this matrix or array can lose sparsity. Here is an alternative solution that assumes if an element of some type has not been inserted that it is the default of that type. For example, for double that means 0.0 and for string that means null.

public class Sparse3DArray<T>
{
  private Dictionary<Tuple<int, int, int>, T> data = new Dictionary<Tuple<int, int, int>, T>();

  public int Nnz { get { return data.Count; } }

  public T this[int x, int y, int z]
  {
    get
    {
      var key = new Tuple<int, int, int>(x, y, z);
      T value;
      data.TryGetValue(key, out value);
      return value;
    }

    set
    {
      var key = new Tuple<int, int, int>(x, y, z);
      if (null == value)
        data.Remove(key);
      else if (value.Equals(default(T)))
        data.Remove(key);
      else
       data[key] = value;
     }
   }
}



回答3:


The fact that you're working in a 3D coordinate system doesn't change whether or not you can use this data structure. A matrix for a 3D space can be contained using a sparse matrix the same as a 2D matrix; it's just the entries that change.

You'd use a sparse matrix for large matricies with lots of zero entries. This is typical in discrete representations of problems in physics that come from finite difference and finite element methods. They have bands of non-zero entries clustered around the diagonal; entries outside the diagonal band are usually zero. A sparse matrix won't store these; decompositions like LU and QR have to be written to know how to deal with the sparsity.

These matricies can describe problems in either 2D or 3D spaces.

I believe you're incorrect if you think you need another data structure.




回答4:


Why not use a KD-Tree or a similar data structure (such as an Octtree)? There are great c++ implementations, for instance: FLANN




回答5:


I would use a Dictionary, but rather than use a Tuple<int, int, int> for the key, you can use a single long as the key and use it to store the coordinates (provided they are shorts). This will reduce your memory footprint and might even improve performance.

private Dictionary<long, T> data = new Dictionary<long, T>();
private long GetKey(short x, short y, short z)
{
   return (x * 10000 + y) * 10000 + z;
}


来源:https://stackoverflow.com/questions/5498761/3d-sparse-matrix-implementation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!