I am trying to implement a differential evolution optimization algorithm and I need a way to take from a list distinct entities. They can be the same values, but can't be the same entities.
solutions = [[random.uniform(0, 1) for _ in range(30)] \
for _ in range(100)]
for base_agent in solutions:
agents = []
while len(agents) < 3:
p = solutions[random.randint(0, len(solutions))]
if p in agents or p is base_agent:
continue
else:
agents.add(p)
if base_agent in agents \
or agents[0] is agents[1] \
or agents[1] is agents[2] \
or agents[2] is agents[0]:
print("Bad execution")
exit(1)
print("Correct execution")
This is the (non-working) general idea of what I'm after.
I want base_agent
to not be in agents
, and I want agents
to contain no duplicate entries. Entries can be the same value (e.g. they can ==
), but they cannot be the same entity (e.g. they cannot ===
). agents
should have 3 elements within at the end of this while loop.
random.sample
can give me, well, a random sample from a list, but it will still possibly include base_agent
.
Any ideas?
The simplest code is to just use random.sample
, excluding the single element you're trying to avoid. Sure, it involves slicing out all elements save the base_element
, but O(n²)
work isn't all that much of a problem when n
is only 30:
import random
for i, base_agent in enumerate(solutions):
agents = random.sample(solutions[:i] + solutions[i+1:], 3)
# Do stuff with base_agent which is distinct from all elements of agents
If you really hate slicing or using index values at all, you can do cheesy hacks with itertools.combinations
to make it generate all the values that don't match the current base_agent
for you:
import random
from itertools import combinations
for base_agent, other_agents in zip(solutions, combinations(reversed(solutions), len(solutions) - 1)):
agents = random.sample(other_agents, 3)
Making combinations of "all but one element", using solutions
in reverse order means each output from combinations
is all the elements but the one you get on each iteration over solutions
, so no slicing is needed.