def test_assignment(): y = [1, 2, 3] x = LazySequenceCopy(y) x[-1] = 5 assert list(x) == [1, 2, 5] x[-1] = 7 assert list(x) == [1, 2, 7]
def do_draw(self, data): should_draw = cu.many( data, min_size=self.min_size, max_size=self.max_size, average_size=self.average_size, ) seen_sets = tuple(set() for _ in self.keys) result = [] remaining = LazySequenceCopy(self.element_strategy.elements) while remaining and should_draw.more(): i = len(remaining) - 1 j = cu.integer_range(data, 0, i) if j != i: remaining[i], remaining[j] = remaining[j], remaining[i] value = self.element_strategy._transform(remaining.pop()) if value is not filter_not_satisfied and all( key(value) not in seen for key, seen in zip(self.keys, seen_sets)): for key, seen in zip(self.keys, seen_sets): seen.add(key(value)) if self.tuple_suffixes is not None: value = (value, ) + data.draw(self.tuple_suffixes) result.append(value) else: should_draw.reject() assert self.max_size >= len(result) >= self.min_size return result
def do_draw(self, data): should_draw = cu.many( data, min_size=self.min_size, max_size=self.max_size, average_size=self.average_size, ) seen_sets = tuple(set() for _ in self.keys) result = [] remaining = LazySequenceCopy(self.element_strategy.elements) while should_draw.more(): i = len(remaining) - 1 j = cu.integer_range(data, 0, i) if j != i: remaining[i], remaining[j] = remaining[j], remaining[i] value = remaining.pop() if all( key(value) not in seen for (key, seen) in zip(self.keys, seen_sets)): for key, seen in zip(self.keys, seen_sets): seen.add(key(value)) result.append(value) else: should_draw.reject() assert self.max_size >= len(result) >= self.min_size return result
def test_pop(): x = LazySequenceCopy([2, 3]) assert x.pop() == 3 assert x.pop() == 2 with pytest.raises(IndexError): x.pop()
def test_pop_with_mask(): y = [1, 2, 3] x = LazySequenceCopy(y) x[-1] = 5 t = x.pop() assert t == 5 assert list(x) == [1, 2] assert y == [1, 2, 3]
def test_out_of_range(): x = LazySequenceCopy([1, 2, 3]) with pytest.raises(IndexError): x[3] with pytest.raises(IndexError): x[-4]
def test_pop_without_mask(): y = [1, 2, 3] x = LazySequenceCopy(y) x.pop() assert list(x) == [1, 2] assert y == [1, 2, 3]
def test_can_assign_without_changing_underlying(): underlying = [1, 2, 3] x = LazySequenceCopy(underlying) x[1] = 10 assert x[1] == 10 assert underlying[1] == 2
def test_pass_through(): x = LazySequenceCopy([1, 2, 3]) assert x[0] == 1 assert x[1] == 2 assert x[2] == 3
def add(self, data): """Attempts to add ``data`` to the pareto front. Returns True if ``data`` is now in the front, including if data is already in the collection, and False otherwise""" data = data.as_result() if data.status < Status.VALID: return False if not self.front: self.front.add(data) return True if data in self.front: return True # We add data to the pareto front by adding it unconditionally and then # doing a certain amount of randomized "clear down" - testing a random # set of elements (currently 10) to see if they are dominated by # something else in the collection. If they are, we remove them. self.front.add(data) assert self.__pending is None try: self.__pending = data # We maintain a set of the current exact pareto front of the # values we've sampled so far. When we sample a new element we # either add it to this exact pareto front or remove it from the # collection entirely. front = LazySequenceCopy(self.front) # We track which values we are going to remove and remove them all # at the end so the shape of the front doesn't change while we're # using it. to_remove = [] # We now iteratively sample elements from the approximate pareto # front to check whether they should be retained. When the set of # dominators gets too large we have sampled at least 10 elements # and it gets too expensive to continue, so we consider that enough # due diligence. i = self.front.index(data) # First we attempt to look for values that must be removed by the # addition of the data. These are necessarily to the right of it # in the list. failures = 0 while i + 1 < len(front) and failures < 10: j = self.__random.randrange(i + 1, len(front)) swap(front, j, len(front) - 1) candidate = front.pop() dom = dominance(data, candidate) assert dom != DominanceRelation.RIGHT_DOMINATES if dom == DominanceRelation.LEFT_DOMINATES: to_remove.append(candidate) failures = 0 else: failures += 1 # Now we look at the points up to where we put data in to see if # it is dominated. While we're here we spend some time looking for # anything else that might be dominated too, compacting down parts # of the list. dominators = [data] while i >= 0 and len(dominators) < 10: swap(front, i, self.__random.randint(0, i)) candidate = front[i] already_replaced = False j = 0 while j < len(dominators): v = dominators[j] dom = dominance(candidate, v) if dom == DominanceRelation.LEFT_DOMINATES: if not already_replaced: already_replaced = True dominators[j] = candidate j += 1 else: dominators[j], dominators[-1] = ( dominators[-1], dominators[j], ) dominators.pop() to_remove.append(v) elif dom == DominanceRelation.RIGHT_DOMINATES: to_remove.append(candidate) break elif dom == DominanceRelation.EQUAL: break else: j += 1 else: dominators.append(candidate) i -= 1 for v in to_remove: self.__remove(v) return data in self.front finally: self.__pending = None
def selection_order(depth, n): pending = LazySequenceCopy(range(n)) while pending: yield pop_random(random, pending)