def tsp1(nodes, dist): """ 巡回セールスマン問題 入力 nodes: 点(dist未指定時は、座標)のリスト dist: (i,j)をキー、距離を値とした辞書 出力 距離と点番号リスト """ from more_itertools import iterate, take n = len(nodes) df = pd.DataFrame( [(i, j, dist[i, j]) for i in range(n) for j in range(n) if i != j], columns=["NodeI", "NodeJ", "Dist"], ) m = LpProblem() df["VarIJ"] = addbinvars(len(df)) df["VarJI"] = df.sort_values(["NodeJ", "NodeI"]).VarIJ.values u = [0] + addvars(n - 1) m += lpDot(df.Dist, df.VarIJ) for _, v in df.groupby("NodeI"): m += lpSum(v.VarIJ) == 1 # 出次数制約 m += lpSum(v.VarJI) == 1 # 入次数制約 for i, j, _, vij, vji in df.query("NodeI!=0 & NodeJ!=0").itertuples(False): m += u[i] + 1 - (n - 1) * (1 - vij) + (n - 3) * vji <= u[ j] # 持ち上げポテンシャル制約(MTZ) for _, j, _, v0j, vj0 in df.query("NodeI==0").itertuples(False): m += 1 + (1 - v0j) + (n - 3) * vj0 <= u[j] # 持ち上げ下界制約 for i, _, _, vi0, v0i in df.query("NodeJ==0").itertuples(False): m += u[i] <= (n - 1) - (1 - vi0) - (n - 3) * v0i # 持ち上げ上界制約 m.solve() df["ValIJ"] = df.VarIJ.apply(value) dc = df[df.ValIJ > 0.5].set_index("NodeI").NodeJ.to_dict() return value(m.objective), list(take(n, iterate(lambda k: dc[k], 0)))
def evolve(state, D): offset = [o for o in product([-1, 0, +1], repeat=D) if any(o)] counts = lambda state: ( (p, sum(tuple(a + b for (a, b) in zip(p, q)) in state for q in offset)) for p in product(*[itercoord(state, d) for d in range(D)])) return iterate( lambda state: { p for (p, c) in counts(state) if (c in {2, 3} if p in state else c == 3) }, state)
def part_1(data): r''' >>> part_1("""\ ... .#. ... ..# ... ###""") 112 ''' grid = GridPart1.parse(data) final = mit.nth(mit.iterate(GridPart1.next, grid), 6) return len(final)
def part_2(data): r''' >>> part_2("""\ ... .#. ... ..# ... ###""") 848 ''' grid = GridPart2.parse(data) final = mit.nth(mit.iterate(GridPart2.next, grid), 6) return len(final)
def tsp(nodes, dist=None): """ 巡回セールスマン問題 入力 nodes: 点(dist未指定時は、座標)のリスト dist: (i,j)をキー、距離を値とした辞書 出力 距離と点番号リスト """ import numpy as np import pandas as pd from more_itertools import iterate, take from pulp import LpProblem, LpVariable, LpBinary, lpDot, lpSum, value n = len(nodes) if not dist: dist = {(i, j): np.linalg.norm(np.subtract(nodes[i], nodes[j])) for i in range(n) for j in range(i + 1, n)} dist.update({(j, i): d for (i, j), d in dist.items()}) a = pd.DataFrame( [(i, j, dist[i, j]) for i in range(n) for j in range(n) if i != j], columns=["NodeI", "NodeJ", "Dist"], ) m = LpProblem() a["VarIJ"] = [LpVariable("x%d" % i, cat=LpBinary) for i in a.index] a["VarJI"] = a.sort_values(["NodeJ", "NodeI"]).VarIJ.values u = [0] + [LpVariable("y%d" % i, lowBound=0) for i in range(n - 1)] m += lpDot(a.Dist, a.VarIJ) for _, v in a.groupby("NodeI"): m += lpSum(v.VarIJ) == 1 # 出次数制約 m += lpSum(v.VarJI) == 1 # 入次数制約 for _, (i, j, _, vij, vji) in a.query("NodeI!=0 & NodeJ!=0").iterrows(): m += u[i] + 1 - (n - 1) * (1 - vij) + (n - 3) * vji <= u[ j] # 持ち上げポテンシャル制約(MTZ) for _, (_, j, _, v0j, vj0) in a.query("NodeI==0").iterrows(): m += 1 + (1 - v0j) + (n - 3) * vj0 <= u[j] # 持ち上げ下界制約 for _, (i, _, _, vi0, v0i) in a.query("NodeJ==0").iterrows(): m += u[i] <= (n - 1) - (1 - vi0) - (n - 3) * v0i # 持ち上げ上界制約 m.solve() a["ValIJ"] = a.VarIJ.apply(value) dc = dict(a[a.ValIJ > 0.5][["NodeI", "NodeJ"]].values) return value(m.objective), list(take(n, iterate(lambda k: dc[k], 0)))
def part_two(): input_lines = get_input() coordinates = create_coordinates(input_lines, 4) cycles = iterate(generate_cycle, coordinates) return len(nth(cycles, 6))
def _walk_parents(command): """Walks up a command's parent chain.""" return iter(iterate(operator.attrgetter('parent'), command).__next__, None)
def generate_state(agent, environment): """Run a single planning interval for the given number of steps.""" initial_step_data = StepData(environment.initial_state(), None, 0, agent) # Initial state with step_id 0 return iterate(lambda step_data: run_step(step_data, environment), initial_step_data)
def tsp(nodes, list_of_homes, dist=None): """ 巡回セールスマン問題 入力 nodes: 点(dist未指定時は、座標)のリスト dist: (i,j)をキー、距離を値とした辞書 出力 距離と点番号リスト """ n = len(nodes) if not dist: dist = {(i, j): np.linalg.norm(np.subtract(nodes[i], nodes[j])) for i in range(n) for j in range(i + 1, n)} dist.update({(j, i): d for (i, j), d in dist.items()}) # data farme containing distances from node i to node j print(dist) a = pd.DataFrame([(nodes[i], i, j, dist[(i, j)]) for i in range(n) for j in range(n) if i != j], columns=['Name', 'NodeI', 'NodeJ', 'Dist']) m = LpProblem() # creates x_ij for every edge in the graph a['VarIJ'] = [LpVariable('x%d' % i, cat=LpBinary) for i in a.index] a['VarJI'] = a.sort_values(['NodeJ', 'NodeI']).VarIJ.values # u = [0] + [LpVariable('y%d' % i, lowBound=0) for i in range(n - 1)] print(a) # gives the total distance, m += lpDot(a.Dist, a.VarIJ) print(list_of_homes) for _, v in a.groupby('NodeI'): print(v) print(v.iloc[0, :].NodeI) print('*****') if v.iloc[0, :].Name in list_of_homes: print('*&&&&', v.iloc[0, :].Name) m += lpSum( v.VarIJ) == 1 # constraint for one edge exiting each vertex m += lpSum( v.VarJI) == 1 # constraint for one edge entering each vertex for _, (name, i, j, _, vij, vji) in a.query('NodeI!=0 & NodeJ!=0').iterrows(): m += u[i] + 1 - (n - 1) * (1 - vij) + (n - 3) * vji <= u[ j] # 持ち上げポテンシャル制約(MTZ) for _, (name, _, j, _, v0j, vj0) in a.query('NodeI==0').iterrows(): m += 1 + (1 - v0j) + (n - 3) * vj0 <= u[j] # lower bound constraints for _, (name, i, _, _, vi0, v0i) in a.query('NodeJ==0').iterrows(): m += u[i] <= (n - 1) - (1 - vi0) - (n - 3) * v0i # upper bound constraints m.solve() a['ValIJ'] = a.VarIJ.apply(value) dc = dict(a[a.ValIJ > 0.5][['NodeI', 'NodeJ']].values) return value(m.objective), list(take(n, iterate(lambda k: dc[k], 0)))