def is_stable_or_dead(protocol, valuation, disabled): # Dead? dead = True for t in protocol.transitions: p, q = tuple(t.pre) if (not t.silent() and (t.pre not in disabled) and (valuation[Var(p)] is not False) and (valuation[Var(q)] is not False)): dead = False break if dead: return True # Stable? V = protocol.states - valuation.absent_states() out = {protocol.output(q) for q in V} if len(out) > 1: return False else: x = out.pop() R = set() for t in protocol.transitions: for q in t.post: if protocol.output(q) != x: R.add(t.pre) formula = Formula(valuation, disabled) return formula.implies_all_absent_tautology_check(R)
def new_stage(protocol, stage, valuation, mem): new_valuation = new_stage_valuation(protocol, valuation, stage.disabled) if is_stable_or_dead(protocol, new_valuation, stage.disabled): return Stage(Formula(new_valuation), new_valuation, stage.disabled, speed=Speed.ZERO, parent=stage) F, J = eventually_disabled(protocol, new_valuation, stage.disabled, mem) # Compute new_formula (Φ) and new_disabled (T) if len(F) > 0: if len(J) > 0: new_disabled = set(stage.disabled) | set(J) new_formula = Formula(new_valuation, new_disabled) if v_disabled(J, valuation): new_formula.assert_valuation(valuation) elif v_enabled(J, valuation): K = posts_from_pres(protocol, new_valuation, J) new_formula.assert_some_pair_present(K) # Compute speed if is_very_fast(protocol, new_valuation, stage.disabled): new_speed = Speed.QUADRATIC elif is_fast(protocol, new_valuation, stage.disabled): new_speed = Speed.QUADRATIC_LOG else: new_speed = Speed.CUBIC else: new_disabled = set(stage.disabled) | set(F) new_formula = Formula(new_valuation, new_disabled) new_speed = Speed.POLYNOMIAL else: new_disabled = set(stage.disabled) new_formula = Formula(new_valuation, new_disabled) new_speed = Speed.EXPONENTIAL I = compute_I(protocol, new_valuation, stage.disabled) if any(valuation[Var(q)] is True for q in I): L = compute_L(protocol, new_valuation, stage.disabled, I) new_formula.assert_all_states_absent(I) new_formula.assert_some_pair_present(L) elif all(valuation[Var(q)] is False for q in I): new_formula.assert_valuation(valuation) else: new_formula.assert_all_states_absent(I) return Stage(new_formula, new_valuation, new_disabled, speed=new_speed, parent=stage)
def v_enabled(pairs, valuation): for pair in pairs: p, q = tuple(pair) if ((p != q and (valuation[Var(p)] is True and valuation[Var(q)] is True)) or (p == q and (valuation[Var(p)] is True and valuation[Var(p, True)] is False))): return True return False
def ai_move(self, delta_x): if not self.gameover and not self.paused: # 게임 종료, 정지 상태가 아니라면 new_x = self.stone_x + delta_x # 새로운 x 좌표는 기존의 stone의 x좌표 + 이동좌표수 if new_x < Var.board_start_x: # 새로운 좌표가 0보다 작다면 new_x = Var.board_start_x # 새로운 좌표는 0 ( 변경 없음 ) if new_x > self.board.width - len(Var.piece_length( self.stone)): # 새로운 좌표 > 열의개수(10) - 블럭의 x축 길이 new_x = self.board.width - len(Var.piece_length( self.stone)) # 이동 불가 (변경 없음) if not self.board.ai_check_collision( self.ai_board, self.stone, (new_x, self.stone_y)): # 벽과 부딪히지 않는 다면 self.stone_x = new_x # 새로운 좌표로 이동
def compute_J(protocol, valuation, disabled, F, mem, graph, vertices): key = (valuation, frozenset(disabled)) if key in mem: return mem[key] newM = set() M = set() sF = set(F) distance = shortest_distance(graph, directed=True) while not (len(newM) == len(sF)): newM = nextH(newM, sF.difference(newM), distance, vertices) M = newM stable = (len(M) == 0) while not stable: to_remove = set() for pair in M: # AB constraints = [] for t in protocol.transitions: if (t.post == pair): constraints.append(([], [], t.pre)) elif len(set(pair) & t.postset) == 1: p = tuple(set(pair) & t.postset)[0] # E q = pair.other(p) # F q_ = t.post.other(p) # G if (q_ != q): # G != F if p != q: # E != F constraints.append(([Var(q)], [Var(p)], t.pre)) elif p not in t.pre: # E = F and E not in AB constraints.append(([Var(p, True)], [], t.pre)) formula = Formula(valuation, disabled | M) if not formula.tautology_check(constraints): to_remove.add(pair) if len(to_remove) > 0: M -= to_remove else: stable = True if len(M) > 0: break mem[key] = M return M
def projectPieceDown(self, piece, offsetX, workingPieceIndex): if offsetX + len(Var.piece_length( piece)) > self.width or offsetX < Var.board_start_x: return None # result = copy.deepcopy(self) offsetY = self.height for y in range(Var.board_start_y, self.height): if Ai.check_collision(self.field, piece, (offsetX, y)): offsetY = y break for x in range(Var.block_start_index, len(Var.piece_length(piece))): for y in range(Var.block_start_index, len(piece)): value = piece[y][x] if value > Var.board_empty_state: self.field[offsetY - Var.for_index_var + y][offsetX + x] = -workingPieceIndex return self
def transformation_graph(protocol, valuation, disabled, stable=False): V = protocol.states - valuation.absent_states() T = { t for t in protocol.transitions if (not t.silent()) and ( t.preset <= V) and (t.postset <= V) and (t.pre not in disabled) } graph = Graph(directed=True) vertices = {v: i for (i, v) in enumerate(V)} edges = dict() def add_edge(p, q, t): graph.add_edge(vertices[p], vertices[q]) if (p, q) in edges: edges[p, q].add(t) else: edges[p, q] = {t} graph.add_vertex(len(V)) for t in T: common_states = t.preset & t.postset # Case: AB -> AC, AA -> AC, AB -> AA if len(common_states) == 1: p = tuple(common_states)[0] q = t.pre.other(p) q_ = t.post.other(p) if not stable or valuation[Var(p)] is True: add_edge(q, q_, t) # Case: AA -> BB, AA -> BC, AB -> CC, AB -> CD elif len(common_states) == 0: if stable: continue new_edges = {(p, q) for p in t.preset for q in t.postset} for (p, q) in new_edges: p_ = t.pre.other(p) if not stable or valuation[Var(p_)] is True: add_edge(p, q, t) return (graph, vertices, edges, V)
def compute_J(protocol, valuation, disabled, F, mem): key = (valuation, frozenset(disabled)) if key in mem: return mem[key] M = set(F) stable = (len(M) == 0) while not stable: to_remove = set() for pair in M: # AB constraints = [] for t in protocol.transitions: if (t.post == pair): constraints.append(([], [], t.pre)) elif len(set(pair) & t.postset) == 1: p = tuple(set(pair) & t.postset)[0] # E q = pair.other(p) # F q_ = t.post.other(p) # G if (q_ != q): # G != F if p != q: # E != F constraints.append(([Var(q)], [Var(p)], t.pre)) elif p not in t.pre: # E = F and E not in AB constraints.append(([Var(p, True)], [], t.pre)) formula = Formula(valuation, disabled | M) if not formula.tautology_check(constraints): to_remove.add(pair) if len(to_remove) > 0: M -= to_remove else: stable = True mem[key] = M return M
def _states_constraints(states): conjuncts = [] domain = set() for q in states: var = Var(q) conjuncts.append(z3.Not(Formula._id(var))) domain.add(var) return (z3.And(conjuncts), domain)
def _states_constraints_or(states, unique_states): conjuncts = [] domain = set() for q in states: var = Var(q, unique=unique_states) conjuncts.append(z3.Not(Formula._id(var))) domain.add(var) return (z3.Or(conjuncts), domain)
def ai_new_stone(self): self.stone = self.next_stone[:] self.next_stone = Var.ai_tetris_shapes[random.randint( Var.ai_block_choice_start, Var.ai_block_choice_end)] # 다음 블럭 랜덤으로 고르기 0~6 사이의 랜덤 숫자를 통해 고르기 self.stone_x = int( (self.board.width - len(Var.piece_length(self.stone))) * Var.ai_stone_start_x_rate) # self.width 기준 스톤의 위치 x self.stone_y = Var.ai_stone_start_y if self.board.ai_check_collision(self.ai_board, self.stone, (self.stone_x, self.stone_y)): self.gameover = True # 블럭이 부딪히는 판단, 새점로 생성한 블럭이 벽에 부딪히면은 게임 종료
def compute_L(protocol, valuation, disabled, I): V = protocol.states - valuation.absent_states() L = set() for t in protocol.transitions: take = (t.preset <= V) and (t.postset <= V) take = take and (t.pre not in disabled) take = take and (len(t.preset & I) > 0) and (len(t.postset & I) == 0) take = take and (len(t.preset) != 1 or valuation[Var(t.pre.some(), True)] is not True) if take: L.add(t.post) return L
def _pairs_constraints(pairs): conjuncts = [] domain = set() for pair in pairs: p, q = tuple(pair) if p != q: domain |= {Var(p), Var(q)} conjuncts.append( z3.Or(z3.Not(Formula._id(Var(p))), z3.Not(Formula._id(Var(q))))) else: domain |= {Var(p), Var(p, True)} conjuncts.append( z3.Or(z3.Not(Formula._id(Var(p))), Formula._id(Var(p, True)))) return (z3.And(conjuncts), domain)
def new_stage_valuation(protocol, valuation, disabled): def f(M, N): M_, N_ = set(M), set(N) def cannot_occur(t): return (len(t.preset & M) > 0 or (t.pre in disabled) or (len(t.preset) == 1 and t.pre.some() in N)) for q in M: T = {t for t in protocol.transitions if q in t.post} to_remove = any(not cannot_occur(t) for t in T) if to_remove: M_.remove(q) for q in N: S = { t for t in protocol.transitions if (q in t.pre) and ( t.pre.other(q) != q) and (not t.unchanged(q)) } T = {t for t in protocol.transitions if q not in t.pre} to_remove = any(not ((t.pre.other(q) in M) or (t.pre in disabled)) for t in S) to_remove = to_remove or any(not cannot_occur(t) for t in T) if to_remove: N_.remove(q) return (M_, N_) # Compute greatest fixed point (M, N) of f M, N = valuation.absent_states(), valuation.unique_states() M_, N_ = f(M, N) while (M, N) != (M_, N_): M, N = M_, N_ M_, N_ = f(M, N) # Compute E E = set() P = valuation.present_states() for q in P: T = { t for t in protocol.transitions if (q in t.pre and q not in t.post) } if all((t.pre.other(q) in M) or (t.pre in disabled) or ( t.pre.other(q) == q and q in N) for t in T): E.add(q) # Construct new valuation new_valuation = Valuation() for q in M: new_valuation[Var(q)] = False for q in E: new_valuation[Var(q)] = True for q in N: new_valuation[Var(q, True)] = True return new_valuation
def rotate_clockwise(shape): # 회전 시킨 모양 만들어 주기 return [[shape[y][x] for y in range(len(shape))] for x in range( len(Var.piece_length(shape)) - Var.for_index_var, Var.search_rotate_next_index, Var.last_rotate_index_prev)]