Alternatives to itertools.product()?

Question:

I have the following code:

# Mec capacity to hold a vnf
served_vnfs         = [0,1,2]

# All possible mec states as far as holded vnfs
mec_capacity_states = [copy.deepcopy(list(s)) for s in itertools.product(served_vnfs, repeat=2)]

# All possible states with defined number of mecs
mecs_states = [copy.deepcopy(list(p)) for p in itertools.product(mec_capacity_states, repeat=2)]

When I execute the following:

mec_states[0][0][0] = 'A'
print(mec_states)

The first value i get is:

[['A', 0], ['A', 0]]

Which is not what is supposed to be, instead it should be:

[['A', 0], [0, 0]],

I’ve been using copy.deepcopy() in order to avoid this but I think the problem is in the code line:

mecs_states = [copy.deepcopy(list(p)) for p in itertools.product(mec_capacity_states, repeat=NUM_MECS)]

This problem happens in any combination where the sublists are equals.

Any alternatives that I could use?

Asked By: krm76

||

Answers:

Using deepcopy will give you a data structure where any shared references in the orginal object also are reflected in the copy.

If you want to remove any shared references, you can use json to serialize and deserialize.

import json

# All possible states with defined number of mecs
mecs_states = itertools.product(mec_capacity_states, repeat=2)
mecs_states = json.loads(json.dumps(list(mecs_states)))

Note that deepcopy will work on any python data structure. The json approach only work if the data structure is well behaved. It must be acyclic and children must be simple types such as lists, ints, strings etc.

Answered By: Håken Lid

Serialising and deserialising your list of lists of lists, as in @HĂ„kenLid‘s answer will certainly work if the elements in served_vnfs are simple serializable objects (such as integers) which don’t require preservation of identity. But it seems like a lot of unnecessary work, particularly if the lists might be longer.

A possibly simpler approach is just to copy each list returned from the outer invocation of itertools.product. Since this is just a shallow copy of a list, there is no need to use the copy module:

served_vnfs         = [0,1,2]
mec_capacity_states = list(itertools.product(served_vnfs, repeat=2))
mecs_states         = [list(map(list, p))
                       for p in itertools.product(mec_capacity_states,
                                                  repeat=2)]

Test (truncated to avoid scroll):

>>> mecs_states[0][0][0] = 'a'
>>> mecs_states
[[['a', 0], [0, 0]], [[0, 0], [0, 1]], [[0, 0], [0, 2]], [[0, 0], [1, 0]], ...
Answered By: rici
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.