def _resample_balanced_n( samples: _tp.List[np.ndarray], size: int, rng: np.random.Generator) -> _tp.Generator[np.ndarray, None, None]: n = len(samples[0]) indices = rng.permutation(n * size) for i in range(size): m = indices[i * n:(i + 1) * n] % n yield tuple(s[m] for s in samples)
def _resample_balanced_1( sample: np.ndarray, size: int, rng: np.random.Generator) -> _tp.Generator[np.ndarray, None, None]: # effectively computes a random permutation of `size` concatenated # copies of `sample` and returns `size` equal chunks of that n = len(sample) indices = rng.permutation(n * size) for i in range(size): m = indices[i * n:(i + 1) * n] % n yield sample[m]
def _random_backtrack(rng: np.random.Generator, board: Board, *, _depth=0) -> Tuple[Board, List[Tuple[int, int, int]]]: """Generate or solve a Sudoku puzzle by backtracking and propagating. Depth-first exploration of the under-determined constraints. Chooses branch randomly. At `_depth=0` or higher, it picks from the locations with fewest possibilities, to prune the search as much as possible; otherwise it is very hard to terminate. At negative depths, picks a constraint to add uniformly over locations. """ if board.is_solved(): return board, [] if _depth >= 0: min_choices = np.min(board.possibilities[board.possibilities >= 2]) locations = np.where(board.possibilities == min_choices) else: locations = np.where(board.possibilities >= 2) i = rng.integers(len(locations[0])) x, y = (int(dim[i]) for dim in locations) possible_digits = rng.permutation(board.possible_digits(x, y)) for digit in possible_digits: try: next_board = board.copy() next_board.eliminate_([(x, y, digit)]) solution, next_moves = _random_backtrack(rng, next_board, _depth=_depth + 1) return solution, [(x, y, digit)] + next_moves except NoMovesError: pass raise NoMovesError("backtrack")
def shuffle(dataset: Dataset, rng: np.random.Generator) -> Dataset: length = len(dataset) indices = rng.permutation(range(length)) return Subset(dataset, indices)