0

I want to calculate power set of string array (consider it as a set). When I am exceeding above 26 elements it is thowing out of memory exception.

List<int> ff = new List<int>();
double length = Math.Pow(2, 29);
for (int i = 0; i < length; i++)
{
   ff.Add(1);
}

Above code will produce the that exception if you run it. The size of the set may go up to 1000. So the size of power set of that set will be 2^1000.

How can I deal with this?

EDIT:

I know that above code is not a function of power set. I was just checking how big array c# will be able to hold.

 private static Dictionary<int, object> PowerSetB(string[] input)
        {
            int n = input.Length;
            // Power set contains 2^N subsets.
            int powerSetCount = 1 << n;
            var ans = new Dictionary<int, object>();

            for (int setMask = 0; setMask < powerSetCount; setMask++)
            {
                var s = new ArrayList();
                for (int i = 0; i < n; i++)
                {
                    // Checking whether i'th element of input collection should go to the current subset.
                    if ((setMask & (1 << i)) > 0)
                        s.Add(input[i]);
                }
                ans[setMask] = s;
            }
            return ans;
        }

Above code is my function of power set.

Thank you in advance.

Artiga
  • 776
  • 2
  • 16
  • 37

1 Answers1

4

Do you really want to store all the items in memory? I suggest using IEnumerable<int> instead of materialized List<int>:

// just enumeration, coefficients aren't stored
public static IEnumerable<int> Serie(Func<int, int> coefByIndex) {
  if (null == coefByIndex)
    throw new ArgumentNullException("coefByIndex");

  for (int i = 0; ; ++i)
    yield return coefByIndex(i);
}

// Let's sum up all 2**29 values, 
// i.e. compute f(1) summing up 2**29 items (it's a long process...)
// sum = 1.44115187606094E+17 (diverges, as we might have expected)
Double sum = Serie(index => index)
  .Select(x => x * 1.0)
  .Take(1 << 29)
  .Sum();

Edit: Once agian, do not materialize (Dictionary<int, object>) huge results! Provide an IReadOnlyDictionary<int, int[]> interface but not implementation as Dictionary<int, object>,
Something like this:

  // ArrayList is an obsolete collection;
  // int[] far more natural here
  public sealed class PowerSet: IReadOnlyDictionary<int, int[]> {
    private int m_Power;

    private int[] getItem(int index) {
      int[] result = new int[m_Power];

      for (int i = 0; i < m_Power; ++i) {
        result[i] = index % 2;

        index /= 2;
      }

      return result;
    }

    public PowerSet(int power) {
      m_Power = power;
    }

    public int[] this[int key] {
      get {
        if (key >= 0 && key < Count)
          return getItem(key);
        else
          throw new ArgumentOutOfRangeException("key");
      }
    }

    public int Count {
      get {
        return 1 << m_Power;
      }
    }

    public IEnumerable<int> Keys {
      get {
        return Enumerable.Range(0, Count);
      }
    }

    public IEnumerable<int[]> Values {
      get {
        return Enumerable.Range(0, Count).Select(index => getItem(index));
      }
    }

    public bool ContainsKey(int key) {
      return key >= 0 && key < Count;
    }

    public IEnumerator<KeyValuePair<int, int[]>> GetEnumerator() {
      return Enumerable
        .Range(0, Count)
        .Select(index => new KeyValuePair<int, int[]>(index, getItem(index)))
        .GetEnumerator();
    }

    public bool TryGetValue(int key, out int[] value) {
      if (key >= 0 && key < Count) {
        value = getItem(key);

        return true;
      }

      value = null;
      return false;
    }

    IEnumerator IEnumerable.GetEnumerator() {
      return this.GetEnumerator();
    }
  }

  ... 

  // Just an easy call
  private static IDictionary<int, int[]> PowerSetB(string[] input) {
    return new PowerSet(input.Length);
  }
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • I have to store all those items, as the power set I get needs to be appended further to attain main results. – Artiga Apr 01 '16 at 03:37
  • 1
    @Artiga: in order to *append* `IEnumerable`, you can try using `.Concat`: `Serie(index => index).Take(10).Concat(Serie(index => index * index))` – Dmitry Bychenko Apr 01 '16 at 06:32
  • how can I modify my "PowerSetB" function (which I have written in the EDIT) with IEnumnertable? – Artiga Apr 01 '16 at 06:55
  • @Artiga what are you trying to do? You can have as big an array as you RAM can handle, but you couldn't even find a big enough *disk array* to store that many 4-byte integers. Whatever your actual problem is, intermediate storage is the wrong approach – Panagiotis Kanavos Apr 01 '16 at 08:26
  • @PanagiotisKanavos what is the correct approach then? – Artiga Apr 01 '16 at 08:40
  • @Artiga to what? You *still* haven't explain what the problem is. Storing more data than there is storeage available globally is not it. *This* answer though shows a good alternative - lazily calculate what is needed. You'll have to either a) explain what you are trying to do or b) look to a map/reduce solution (eg Hadoop, Spark) that will break the actual problem in smaller, more manageable parts, compute them individually and calculate the final answer – Panagiotis Kanavos Apr 01 '16 at 08:42
  • @PanagiotisKanavos All I am trying is: calculating power set of a string array. and to that power set I will be adding more elements satisfying some criteria. – Artiga Apr 01 '16 at 08:45
  • @Artiga just try and calculate what you are asking: an integer is 4 bytes. A petabyte is 2^40 bytes. 2^1000 integers need 2^964 PB of storage. I doubt if the three major clouds have more that 1024 PB (2^10) storage each. – Panagiotis Kanavos Apr 01 '16 at 08:46
  • @Artiga no, that is not the question you are asking, unless you are asking how to generate more data that can be stored in the entire world. What are you going to do with that power set? *Why* do you need it precalculated? Why all at onces instead of calculating it in batches and discarding them once used? – Panagiotis Kanavos Apr 01 '16 at 08:49
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/107929/discussion-between-artiga-and-panagiotis-kanavos). – Artiga Apr 01 '16 at 08:51