def edge_covering_checker(p: Phase) -> Optional[Tuple[Phase, Diagram]]: t = self.solver.get_translator(KEY_NEW, KEY_OLD) f = self.fs[-1] prog = syntax.the_program with self.solver: for c in f.summary_of(p): self.solver.add(t.translate_expr(c, old=True)) transitions_from_phase = self.automaton.transitions_from(p) for trans in prog.transitions(): edges_from_phase_matching_prog_trans = [ t for t in transitions_from_phase if t.prog_transition_name() == trans.name ] if any(delta.precond is None for delta in edges_from_phase_matching_prog_trans): utils.logger.debug( 'transition %s is covered trivially by %s' % (trans.name, p.name())) continue utils.logger.debug( 'checking transition %s is covered by %s' % (trans.name, p.name())) with self.solver: self.solver.add(t.translate_transition(trans)) preconds = ( z3.Not( t.translate_precond_of_transition( delta.precond(), trans)) for delta in edges_from_phase_matching_prog_trans) self.solver.add(z3.And(*preconds)) if self.solver.check() != z3.unsat: utils.logger.debug( 'phase %s cex to edge covering of transition %s' % (p.name(), trans.name)) z3m: z3.ModelRef = self.solver.model() mod = Trace.from_z3([KEY_OLD, KEY_NEW], z3m) self.record_state(mod) diag = mod.as_diagram(i=0) return (p, diag) utils.logger.debug( 'transition %s is covered non-trivially by %s' % (trans.name, p.name())) continue utils.logger.debug('all edges covered from phase %s' % p.name()) return None
def safety_property_checker( p: Phase) -> Optional[Tuple[Phase, Diagram]]: res = logic.check_implication(self.solver, f.summary_of(p), (inv.expr for inv in phases.phase_safety(p))) if res is None: utils.logger.debug( "Frontier frame phase %s implies safety, summary is %s" % (p.name(), f.summary_of(p))) return None utils.logger.debug("Frontier frame phase %s cex to safety" % p.name()) z3m: z3.ModelRef = res mod = Trace.from_z3([KEY_ONE], z3m) self.record_state(mod) diag = mod.as_diagram() return (p, diag)
def add(self, p: Phase, e: Expr, depth: Optional[int] = None) -> None: self.counter += 1 self.record_predicate(e) if depth is None: depth = len(self) if utils.args.smoke_test and utils.logger.isEnabledFor(logging.DEBUG): utils.logger.debug('smoke testing at depth %s...' % (depth, )) logic.check_bmc(self.solver, e, depth) self.debug_assert_inductive_trace() for i in range(depth + 1): self[i].strengthen(p, e) utils.logger.debug("%d %s %s" % (i, p.name(), e)) self.debug_assert_inductive_trace() self.debug_assert_inductive_trace()
def find_predecessor( self, pre_frame: Frame, current_phase: Phase, diag: Diagram ) -> Tuple[z3.CheckSatResult, Union[Optional[MySet[int]], Tuple[ PhaseTransition, Tuple[Phase, Diagram]]]]: t = self.solver.get_translator(KEY_NEW, KEY_OLD) if utils.args.use_z3_unsat_cores: core: Optional[MySet[int]] = MySet() else: core = None with self.solver: with self.solver.mark_assumptions_necessary(): self.solver.add(diag.to_z3(t)) transitions_into = self.automaton.transitions_to_grouped_by_src( current_phase) for src in self._predecessor_precedence( current_phase, list(transitions_into.keys())): transitions = transitions_into[src] assert transitions utils.logger.debug( "check predecessor of %s from %s by %s" % (current_phase.name(), src.name(), transitions)) (sat_res, pre_diag) = self.find_predecessor_from_src_phase( t, pre_frame, src, transitions, diag, core) if sat_res == z3.unsat: continue return (sat_res, pre_diag) if utils.args.use_z3_unsat_cores: assert core is not None ret_core: Optional[MySet[int]] = MySet(sorted(core)) else: ret_core = None return (z3.unsat, ret_core)
def __init__(self, game, player_number, game_type): GameState.__init__(self, game) self.player_number = player_number self.game_type = game_type self.board = Board(field=self, size=c.grid_count) self.hands = [Hand(field=self, owner=0), Hand(field=self, owner=1)] for hand in self.hands: hand.add_random_cards(count=2) self.player_turn = 0 # Player 'id' of the player whose turn it is. self.player_healths = [20, 20] self.hand_area_height = 80 self.phase = Phase(['Build', 'Act', "_ActAnimate"]) self.turn_display = TurnDisplay(self.phase, fonts.ui_font) self.hand_origin = self.board.grid.get_grid_pos(align=('left', 'down'), offset=(0, 50)) self.hand_center = (c.screen_size[0] // 2, c.screen_size[1] - 100) self.hand_spacing = (110, 0) self.drag_card = None self.card_grab_point = None self.act_animating = False self.act_animation_frame_count = 0 self.total_animation_frame_count = 30 self.animation_jerk = 0.4 self.player_count = 2 # self.turn_button = UI.Button( pos=self.board.grid.get_grid_pos(align=('left','down'),offset=(-100,-50)), # align=('right','up'), # font=fonts.ui_font, # text="End Turn", # parent_container=self) if player_number == 0: self.player_health_labels = [ UI.Label(pos=self.board.grid.get_grid_pos(align=('right', 'down'), offset=(10, -30)), font=fonts.ui_font, text='Player 0: %s' % self.player_healths[0]), UI.Label(pos=self.board.grid.get_grid_pos(align=('right', 'up'), offset=(10, 0)), font=fonts.ui_font, text='Player 1: %s' % self.player_healths[1]) ] elif player_number == 1: self.player_health_labels = [ UI.Label(pos=self.board.grid.get_grid_pos(align=('right', 'up'), offset=(10, 0)), font=fonts.ui_font, text='Player 0: %s' % self.player_healths[0]), UI.Label(pos=self.board.grid.get_grid_pos(align=('right', 'down'), offset=(10, -50)), font=fonts.ui_font, text='Player 1: %s' % self.player_healths[1]) ] #self.ui_container.add_element(self.turn_button) for label in self.player_health_labels: self.ui_container.add_element(label) self.input_map = { # Input(key='any'): lambda key, mod, unicode_key: self.any_key_pressed(key, mod, unicode_key), Input(mouse_button=1): lambda mouse_pos: self.left_mouse_pressed(mouse_pos), Input(mouse_button=1, type='release'): lambda mouse_pos: self.left_mouse_released(mouse_pos), Input(mouse_button=3): lambda mouse_pos: self.right_mouse_pressed(mouse_pos), Input(key=pg.K_SPACE): lambda mouse_pos: self.space_pressed(), #Input(key=pg.K_2): lambda mouse_pos: self.hands[self.player_turn].add_card("Goblin"), Input(key=pg.K_DELETE): lambda mouse_pos: self.hands[self.player_turn].clear_hand(), Input(key=pg.K_ESCAPE): lambda mouse_pos: self.go_to_main_menu() }
class Field(GameState): def __init__(self, game, player_number, game_type): GameState.__init__(self, game) self.player_number = player_number self.game_type = game_type self.board = Board(field=self, size=c.grid_count) self.hands = [Hand(field=self, owner=0), Hand(field=self, owner=1)] for hand in self.hands: hand.add_random_cards(count=2) self.player_turn = 0 # Player 'id' of the player whose turn it is. self.player_healths = [20, 20] self.hand_area_height = 80 self.phase = Phase(['Build', 'Act', "_ActAnimate"]) self.turn_display = TurnDisplay(self.phase, fonts.ui_font) self.hand_origin = self.board.grid.get_grid_pos(align=('left', 'down'), offset=(0, 50)) self.hand_center = (c.screen_size[0] // 2, c.screen_size[1] - 100) self.hand_spacing = (110, 0) self.drag_card = None self.card_grab_point = None self.act_animating = False self.act_animation_frame_count = 0 self.total_animation_frame_count = 30 self.animation_jerk = 0.4 self.player_count = 2 # self.turn_button = UI.Button( pos=self.board.grid.get_grid_pos(align=('left','down'),offset=(-100,-50)), # align=('right','up'), # font=fonts.ui_font, # text="End Turn", # parent_container=self) if player_number == 0: self.player_health_labels = [ UI.Label(pos=self.board.grid.get_grid_pos(align=('right', 'down'), offset=(10, -30)), font=fonts.ui_font, text='Player 0: %s' % self.player_healths[0]), UI.Label(pos=self.board.grid.get_grid_pos(align=('right', 'up'), offset=(10, 0)), font=fonts.ui_font, text='Player 1: %s' % self.player_healths[1]) ] elif player_number == 1: self.player_health_labels = [ UI.Label(pos=self.board.grid.get_grid_pos(align=('right', 'up'), offset=(10, 0)), font=fonts.ui_font, text='Player 0: %s' % self.player_healths[0]), UI.Label(pos=self.board.grid.get_grid_pos(align=('right', 'down'), offset=(10, -50)), font=fonts.ui_font, text='Player 1: %s' % self.player_healths[1]) ] #self.ui_container.add_element(self.turn_button) for label in self.player_health_labels: self.ui_container.add_element(label) self.input_map = { # Input(key='any'): lambda key, mod, unicode_key: self.any_key_pressed(key, mod, unicode_key), Input(mouse_button=1): lambda mouse_pos: self.left_mouse_pressed(mouse_pos), Input(mouse_button=1, type='release'): lambda mouse_pos: self.left_mouse_released(mouse_pos), Input(mouse_button=3): lambda mouse_pos: self.right_mouse_pressed(mouse_pos), Input(key=pg.K_SPACE): lambda mouse_pos: self.space_pressed(), #Input(key=pg.K_2): lambda mouse_pos: self.hands[self.player_turn].add_card("Goblin"), Input(key=pg.K_DELETE): lambda mouse_pos: self.hands[self.player_turn].clear_hand(), Input(key=pg.K_ESCAPE): lambda mouse_pos: self.go_to_main_menu() } def change_health(self, amount, player, sync): if player == 0 or player == 1: self.player_healths[player] += amount self.player_health_labels[player].text = 'Player %d: %d' % ( player, self.player_healths[player]) if sync == True: send_string = 'health changed;' + str(amount) + ';' + str( player) + ';[END]' self.game.queue_network_data(send_string.encode('utf-8')) else: print("Tried to change health of invalid player.") @property def active_hand(self): return self.hands[self.player_number] @property def hand_rect(self): card_coords = self.generate_hand_card_positions() if len(card_coords) == 0: hand_left = self.hand_center[0] else: hand_left = card_coords[0][0] return pg.Rect((hand_left, self.hand_center[1]), (self.active_hand.card_count * self.hand_spacing[0], c.hand_card_size[1])) def space_pressed(self): if self.game_type == 'SP' or self.is_current_player_active(): if self.phase.name != '_ActAnimate': self._advance_turn(sync=True) @property def action_panel_rect(self): pos = self.board.grid.get_grid_pos( align=('right', 'center'), offset=(50, -c.action_panel_size[1] // 2)) return pg.Rect(pos, c.action_panel_size) def left_mouse_pressed(self, mouse_pos): if self.hand_rect.collidepoint(mouse_pos): # mouse is hovering hand hand_left = self.get_left_side_of_hand() relative_x = int((mouse_pos[0] - hand_left) % self.hand_spacing[0]) relative_y = int(mouse_pos[1] - self.hand_center[1]) clicked_card_index = int( (mouse_pos[0] - hand_left) // self.hand_spacing[0]) if relative_x >= 0 and relative_x < c.hand_card_size[1]: if clicked_card_index >= 0 and clicked_card_index < self.active_hand.card_count: self.drag_card = self.active_hand.pop_card( clicked_card_index) self.drag_card.board = self.board self.drag_card.location = CardLocation.Drag # d.debugger.print(values={'drag_card': self.drag_card}) self.card_grab_point = (relative_x, relative_y) if self.board.grid.rect.collidepoint( mouse_pos): # mouse is hovering board self.board.selected_cell = self.board.grid.get_cell_at_pos( pos=mouse_pos, player=self.player_number) else: self.board.selected_cell = None def is_current_player_active(self): if self.player_turn == self.player_number: return True else: return False def left_mouse_released(self, mouse_pos): if self.drag_card is not None: placed_in_board = False # True if card is placed onto the board during this mouse release if self.is_current_player_active() and self.phase.name == 'Build': cell = self.board.grid.get_cell_at_pos( pos=mouse_pos, player=self.player_number) if cell != None: # d.debugger.print(values={'drag_card': self.drag_card}) self.drag_card.queue(board=self.board, cell=cell, owner=self.player_number) placed_in_board = True if placed_in_board == False: self.active_hand.add_card(card=self.drag_card) self.drag_card = None self.card_grab_point = None # Probably not necessary # TODO: Move this to the proper place (the event queue?) # if self.turn_button.left_mouse_released(mouse_pos=mouse_pos): # if button was pressed # if self.game_type == 'SP': # self._end_turn(sync=True) # elif self.game_type == 'MP': # if self.is_current_player_active(): # self._end_turn(sync=True) def right_mouse_pressed(self, mouse_pos): # If a cell is selected if self.board.grid.rect.collidepoint(mouse_pos): if self.board.selected_cell != None: selected_building = self.board.building_cards[ self.board.selected_cell] if selected_building != None and selected_building.owner == self.player_number and self.is_current_player_active( ): clicked_cell = self.board.grid.get_cell_at_pos( pos=mouse_pos, player=self.player_number) selected_building.target_cell = clicked_cell selected_building.act() def set_active_player(self, player_number): self.player_turn = player_number self._end_turn(sync=True) def swap_active_player(self): if self.player_turn == 0: self.player_turn = 1 elif self.player_turn == 1: self.player_turn = 0 def _end_turn(self, sync): end_of_turn = self._advance_turn(sync=sync) while end_of_turn == False: end_of_turn = self._advance_turn(sync=sync) def start_act_animations(self): self.act_animating = True self.act_animation_frame_count = 0 def _advance_turn(self, sync): if self.phase.name == 'Act': for lane in range(self.board.lane_count): for rank in range(self.board.rank_count): cell = (lane, rank) if self.player_turn == 0: absolute_cell = cell else: absolute_cell = ( cell[0], self.board.rank_count - 1 - cell[1] ) # Corrected for player orientation (actual grid coords) building_card = self.board.building_cards[absolute_cell] unit_card = self.board.get_unit_in_cell(cell=absolute_cell) if building_card != None and building_card.owner == self.player_turn: building_card.act() if unit_card != None and unit_card.owner == self.player_turn: unit_card.act() # Transfer queued cards to battlefield in closest rank for lane_number, queued_card in enumerate( self.board.queued_cards[self.player_turn]): if queued_card != None: if self.player_turn == 0: cell = (lane_number, self.board.size[1] - 1) elif self.player_turn == 1: cell = (lane_number, 0) queued_card.place_queued() #self.board.place_card(cell=cell, card=queued_card, owner=self.player_turn, sync=sync) self.board.queued_cards[ self.player_number][lane_number] = None self.board.refresh_fow() self.act_animating = True self.act_animation_frame_count = 0 if sync == True: send_string = 'phase advanced' + ';[END]' self.game.queue_network_data(send_string.encode('utf-8')) self.phase.advance_phase() if self.phase.turn_ended == True: for card in self.board: if card is not None: card.end_turn() self.phase.end_turn() self.swap_active_player() self.hands[self.player_turn].add_random_cards(count=1) if self.game_type == 'SP' and self.player_turn == 1: # Single player and it's the computer's turn. # For now, we just want to play 1 random card from their hand to a random square on the board and end their turn. hand = self.hands[self.player_turn] card = hand.cards.pop(random.randrange(0, hand.card_count)) cell_x = random.randrange(0, self.board.size[0]) cell_y = random.randrange(0, self.board.size[1]) dont_queue = False if isinstance(card, BuildingCard): if self.board.building_cards[(cell_x, cell_y)] is not None: dont_queue = True if dont_queue is False: card.queue(board=self.board, cell=(cell_x, cell_y), owner=1) return True else: return False def process_network_data(self, data): raw_data_string = data.decode('utf-8') event_strings = raw_data_string.split(';[END]') for event_string in event_strings: print('event_string=', event_string) args = event_string.split(';') try: if args[0] == 'card placed': # This doesn't have permanence in card values (like creature health), since it only sends the card name # However, maybe this is ok, if this is only used when the card is played from hand or moved on from lane queue self.board.place_card( cell=(int(args[2]), int(args[3])), card=self.game.card_pool.get_card_by_name(args[1]), owner=args[4], sync=False) elif args[0] == 'unit deleted': self.board.delete_unit_from_board(cell=(int(args[1]), int(args[2])), sync=False) elif args[0] == 'building deleted': self.board.delete_building_from_board(cell=(int(args[1]), int(args[2])), sync=False) elif args[0] == 'unit moved': self.board.move_unit(start_cell=(int(args[1]), int(args[2])), target_cell=(int(args[3]), int(args[4])), sync=False) elif args[0] == 'building moved': self.board.move_building(start_cell=(int(args[1]), int(args[2])), target_cell=(int(args[3]), int(args[4])), sync=False) elif args[0] == 'card removed': self.board.return_card_to_hand( (int(args[2]), int(args[3]))) elif args[0] == 'cards fought': self.board.fight_cards(attacker_cell=(int(args[1]), int(args[2])), defender_cell=(int(args[3]), int(args[4])), sync=False) elif args[0] == 'turn ended': self._end_turn(sync=False) elif args[0] == 'phase advanced': self._advance_turn(sync=False) elif args[0] == 'health changed': self.change_health(amount=int(args[1]), player=int(args[2]), sync=False) elif args[0] == 'message sent': self.game.chat_window.add_message(args[1], args[2]) except: print('Invalid arguments for network event string') def go_to_main_menu(self): send_string = 'quit field' + ';[END]' self.game.queue_network_data(send_string.encode('utf-8')) self.queue_state_transition(MainMenu(self.game)) def generate_hand_card_positions(self): total_width = self.active_hand.card_count * self.hand_spacing[0] return [ (self.hand_center[0] + i * self.hand_spacing[0] - total_width // 2, self.hand_center[1]) for i in range(self.active_hand.card_count) ] def get_left_side_of_hand(self): card_coords = self.generate_hand_card_positions() if len(card_coords) == 0: return self.hand_center[0] else: return card_coords[0][0] def _generate_hovered_card_index(self, mouse_pos): if self.hand_rect.collidepoint(mouse_pos): for i, card_pos in enumerate(self.generate_hand_card_positions()): card_left = card_pos[0] card_right = card_pos[0] + c.hand_card_size[0] if mouse_pos[0] >= card_left and mouse_pos[0] < card_right: self.hovered_card_index = i return self.hovered_card_index = None def get_action_icon_pos(self, action_index): row = i // pan def _draw_action_panel(self): action_panel_surface = pg.Surface(c.action_panel_size) action_panel_surface.fill(c.black) icon_width, icon_height = c.action_icon_size panel_width, panel_height = c.action_panel_size panel_count_x = panel_width // icon_width panel_count_y = panel_height // icon_height if self.board.selected_cell != None: selected_card = self.board.building_cards[self.board.selected_cell] if selected_card != None: for i, action in enumerate(selected_card.active_actions): row = i // panel_count_x col = i % panel_count_y cell_pos = (col * icon_width, row * icon_height) pg.draw.rect(action_panel_surface, c.dark_grey, (cell_pos, c.action_icon_size)) pg.draw.rect(action_panel_surface, c.light_grey, (cell_pos, c.action_icon_size), 1) draw.draw_surface_aligned( target=action_panel_surface, source=fonts.action_font.render(action, True, c.white), pos=(cell_pos[0] + icon_width // 2, cell_pos[1] + icon_height // 2), align=('center', 'center')) pg.draw.rect(action_panel_surface, c.white, ((0, 0), c.action_panel_size), 1) draw.screen.blit(action_panel_surface, self.action_panel_rect.topleft) def update(self, dt, mouse_pos): self.board.update(dt=dt, mouse_pos=mouse_pos) if self.drag_card is not None: self.drag_card.update(dt=dt, mouse_pos=mouse_pos) self._generate_hovered_card_index(mouse_pos=mouse_pos) if self.act_animating is True: self.act_animation_frame_count += 1 if self.act_animation_frame_count > self.total_animation_frame_count: self.act_animating = False self._advance_turn(sync=False) def draw(self): if self.player_number == 0: current_player_color = c.red other_player_color = c.blue elif self.player_number == 1: current_player_color = c.blue other_player_color = c.red if self.player_turn == 0: active_player_color = c.red elif self.player_turn == 1: active_player_color = c.blue self.board.draw(screen=self.game.screen, player_perspective=self.player_number) # Draw queued cards for lane_number, queued_card in enumerate( self.board.queued_cards[self.player_number]): if queued_card != None: pos = self.board.grid.get_cell_pos( cell=(lane_number, self.board.size[1] - 1), align=('left', 'down')) pos[0] += c.board_card_size[0] queued_card.draw(pos=pos) self._draw_action_panel() if self.board.selected_cell != None: self.board.building_cards[self.board.selected_cell] # pg.draw.rect(self.action_panel_surface, c.white, ((0,0), c.action_panel_size), 1) # Calculate colors for card areas based on which player is active if self.is_current_player_active(): my_card_area_color = util.darken_color(current_player_color, 0.65) other_card_area_color = c.dark_grey else: my_card_area_color = c.dark_grey other_card_area_color = util.darken_color(other_player_color, 0.65) # Draw my card area pg.draw.rect(draw.screen, my_card_area_color, ((0, c.screen_size[1] - self.hand_area_height), (c.screen_size[0], self.hand_area_height))) pg.draw.line( draw.screen, util.lighten_color(my_card_area_color, 0.5), (0, c.screen_size[1] - self.hand_area_height), (c.screen_size[0], c.screen_size[1] - self.hand_area_height)) # Draw enemy card area pg.draw.rect(draw.screen, other_card_area_color, ((0, 0), (c.screen_size[0], self.hand_area_height))) pg.draw.line(draw.screen, util.lighten_color(other_card_area_color, 0.5), (0, self.hand_area_height), (c.screen_size[0], self.hand_area_height)) # Draw cards in hand for i, card_pos in enumerate(self.generate_hand_card_positions()): if i == self.hovered_card_index: hover = True else: hover = False self.active_hand[i].draw(pos=card_pos, hover=hover) # Draw active player text and circle active_player_text = "Player %d" % self.player_turn text_h_padding = 10 text_size = fonts.ui_font.size(active_player_text) padded_size = (text_size[0] + 2 * text_h_padding, text_size[1]) active_player_text_surface = pg.Surface(padded_size) pg.draw.rect(active_player_text_surface, c.white, ((0, 0), (padded_size))) active_player_text_surface.blit( fonts.ui_font.render(active_player_text, True, active_player_color), (text_h_padding, 0)) draw_pos = (20, c.screen_size[1] // 2) offset = draw.draw_surface_aligned(target=draw.screen, source=active_player_text_surface, pos=draw_pos, align=('left', 'down')) pg.draw.circle(draw.screen, active_player_color, (int(draw_pos[0] + offset[0] + active_player_text_surface.get_width() + 20), int(draw_pos[1] + offset[1] + active_player_text_surface.get_height() // 2)), 15) pg.draw.circle(draw.screen, c.white, (int(draw_pos[0] + offset[0] + active_player_text_surface.get_width() + 20), int(draw_pos[1] + offset[1] + active_player_text_surface.get_height() // 2)), 15, 1) # Draw turn display self.turn_display.draw(target=draw.screen, pos=self.board.grid.get_grid_pos( align=('left', 'center'), offset=(-150, 0))) # Draw card being dragged if self.drag_card: drawn_in_board = False # True if the drag card gets drawn in the board this frame rather than floating on screen if self.is_current_player_active() and self.phase.name == 'Build': if isinstance(self.drag_card, CreatureCard): # TODO: Shouldn't be getting the mouse position in this way. Fetch it in update() cell = self.board.grid.get_cell_at_pos( pos=pg.mouse.get_pos(), player=self.player_number) if cell != None: lane = cell[0] lane_down_center = self.board.grid.get_cell_pos( cell=(lane, self.board.size[1] - 1), align=('left', 'down')) lane_down_center[0] += c.board_card_size[0] self.drag_card.draw(pos=lane_down_center) drawn_in_board = True elif isinstance(self.drag_card, BuildingCard): cell = self.board.grid.get_cell_at_pos( pos=pg.mouse.get_pos(), player=self.player_number) if cell != None: if self.player_number == 0: pos = cell elif self.player_number == 1: pos = (cell[0], self.board.size[1] - 1 - cell[1]) if self.board.building_cards[pos] == None: cell_top_center = self.board.grid.get_cell_pos( cell, align=('left', 'top')) self.drag_card.draw(pos=cell_top_center) drawn_in_board = True if drawn_in_board == False: mouse_coords = pg.mouse.get_pos() pos = (mouse_coords[0] - self.card_grab_point[0], mouse_coords[1] - self.card_grab_point[1]) self.drag_card.draw(pos=pos)
def block(self, diag: Diagram, j: int, p: Phase, trace: Optional[RelaxedTrace] = None, safety_goal: bool = True) -> Union[Blocked, CexFound]: if trace is None: trace = [] if j == 0 or (j == 1 and self.valid_in_initial_frame( self.solver, p, diag) is not None): if safety_goal: utils.logger.always_print('\n'.join( ((t.pp() + ' ') if t is not None else '') + str(diag) for t, diag in trace)) print( 'abstract counterexample: the system has no universal inductive invariant proving safety' ) # TODO: placeholder for analyzing relaxed trace # import relaxed_traces # print(relaxed_traces.diagram_trace_to_explicitly_relaxed_trace(trace, phases.phase_safety(p))) if utils.args.checkpoint_out: self.store_frames(utils.args.checkpoint_out) raise AbstractCounterexample() else: if utils.logger.isEnabledFor(logging.DEBUG): utils.logger.debug('failed to block diagram') return CexFound() while True: with utils.LogTag(utils.logger, 'block-attempt'): if utils.logger.isEnabledFor(logging.DEBUG): utils.logger.debug('blocking diagram in frame %s' % j) utils.logger.debug(str(diag)) self.print_frame(j - 1, lvl=logging.DEBUG) res, x = self.find_predecessor(self[j - 1], p, diag) if res == z3.unsat: utils.logger.debug('no predecessor: blocked!') assert x is None or isinstance(x, MySet) core: Optional[MySet[int]] = x self.augment_core_for_init(p, diag, core) break assert isinstance(x, tuple), (res, x) trans, (pre_phase, pre_diag) = x trace.append((trans, pre_diag)) ans = self.block(pre_diag, j - 1, pre_phase, trace, safety_goal) if not isinstance(ans, Blocked): return ans trace.pop() if utils.logger.isEnabledFor(logging.DEBUG) and core is not None: utils.logger.debug('core %s' % core) utils.logger.debug('unminimized diag\n%s' % diag) diag.minimize_from_core(core) diag.generalize(self.solver, self[j - 1], self.automaton.transitions_to_grouped_by_src(p), p == self.automaton.init_phase(), j) e = syntax.Not(diag.to_ast()) if utils.logger.isEnabledFor(logging.DEBUG): utils.logger.debug( 'adding new clause to frames 0 through %d phase %s' % (j, p.name())) if utils.logger.isEnabledFor(logging.INFO): utils.logger.info("[%d] %s" % (j, str(e))) self.add(p, e, j) utils.logger.debug("Done blocking") return Blocked()
def push_conjunct(self, frame_no: int, c: Expr, p: Phase, frame_old_count: Optional[int] = None) -> None: is_safety = c in phases.phase_safety(p) f = self.fs[frame_no] while True: with utils.LogTag(utils.logger, 'pushing-conjunct-attempt', lvl=logging.DEBUG, frame=str(frame_no), conj=str(c)): utils.logger.debug('frame %s phase %s attempting to push %s' % (frame_no, p.name(), c)) res = self.clause_implied_by_transitions_from_frame( f, p, c, minimize=is_safety or utils.args.block_may_cexs) if res is None: utils.logger.debug('frame %s phase %s managed to push %s' % (frame_no, p.name(), c)) if utils.args.smoke_test and utils.logger.isEnabledFor( logging.DEBUG): utils.logger.debug('smoke testing...') # TODO: phases logic.check_bmc(self.solver, c, frame_no + 1) # assert self.clause_implied_by_transitions_from_frame(f, p, c) is None self[frame_no + 1].strengthen(p, c) self.debug_assert_inductive_trace() break pre_phase, (m, t) = res mod = Trace.from_z3([KEY_OLD, KEY_NEW], m) self.record_state(mod) diag = mod.as_diagram(i=0) if utils.logger.isEnabledFor(logging.DEBUG): utils.logger.debug( 'frame %s failed to immediately push %s due to ' 'transition %s' % (frame_no, c, t.pp())) # utils.logger.debug(str(mod)) if is_safety: utils.logger.debug( 'note: current clause is safety condition') self.block(diag, frame_no, pre_phase, [(None, c), (t, diag)], safety_goal=True) else: if utils.args.block_may_cexs: ans = self.block(diag, frame_no, pre_phase, [(None, c), (t, diag)], safety_goal=False) if isinstance(ans, CexFound): break else: break
def block(self, diag: Diagram, j: int, p: Phase, trace: Optional[List[Tuple[Optional[PhaseTransition], Union[Diagram, Expr]]]] = None, safety_goal: bool = True) -> Union[Blocked, CexFound]: if trace is None: trace = [] if j == 0 or (j == 1 and self.valid_in_initial_frame( self.solver, p, diag) is not None): if safety_goal: utils.logger.always_print('\n'.join( ((t.pp() + ' ') if t is not None else '') + str(diag) for t, diag in trace)) print('abstract counterexample') raise Exception('abstract counterexample') else: if utils.logger.isEnabledFor(logging.DEBUG): utils.logger.debug('failed to block diagram') # utils.logger.debug(str(diag)) return CexFound() # print fs while True: with utils.LogTag(utils.logger, 'block-attempt'): if utils.logger.isEnabledFor(logging.DEBUG): utils.logger.debug('blocking diagram in frame %s' % j) utils.logger.debug(str(diag)) self.print_frame(j - 1, lvl=logging.DEBUG) res, x = self.find_predecessor(self[j - 1], p, diag) if res == z3.unsat: utils.logger.debug('no predecessor: blocked!') assert x is None or isinstance(x, MySet) core: Optional[MySet[int]] = x self.augment_core_for_init(p, diag, core) break assert isinstance(x, tuple), (res, x) trans, (pre_phase, pre_diag) = x trace.append((trans, pre_diag)) ans = self.block(pre_diag, j - 1, pre_phase, trace, safety_goal) if not isinstance(ans, Blocked): return ans trace.pop() if utils.logger.isEnabledFor(logging.DEBUG) and core is not None: utils.logger.debug('core %s' % core) utils.logger.debug('unminimized diag\n%s' % diag) diag.minimize_from_core(core) diag.generalize(self.solver, self[j - 1], self.automaton.transitions_to_grouped_by_src(p), p == self.automaton.init_phase(), j) e = syntax.Not(diag.to_ast()) if utils.logger.isEnabledFor(logging.DEBUG): utils.logger.debug( 'adding new clause to frames 0 through %d phase %s' % (j, p.name())) if utils.logger.isEnabledFor(logging.INFO): utils.logger.info("[%d] %s" % (j, str(e))) self.add(p, e, j) utils.logger.debug("Done blocking") return Blocked()