def create_chart(plot_data, image_path): blue = '#2e7eb3' light_blue = '#81b1d1' green = '#4aa635' light_green = '#7db471' ylabels = ['0 %', '25 %', '50 %', '75%', '100 %'] xlabels = [0, 2, 4, 6, 8, 10, '12 hours'] plot = Chart(xlabels=xlabels, ylabels=ylabels, inverseX=True, padding_top=30, height=450) plot.set_minimal_canvas([0, 0], [12, 100]) for p in plot_data['history charging']: plot.add(xs=p['xs'], ys=p['ys'], stroke=green, fill=green, drop=green) for p in plot_data['history discharging']: plot.add(xs=p['xs'], ys=p['ys'], stroke=blue, fill=blue, drop=blue) for p in plot_data['future charging']: plot.add(xs=p['xs'], ys=p['ys'], stroke=green, stroke_dash=True) for p in plot_data['future discharging']: plot.add(xs=p['xs'], ys=p['ys'], stroke=blue, stroke_dash=True) plot.render_to_svg(image_path)
class Game: def __init__(self, grid): self.__grid = grid self.__score = 0 self.__chart = Chart() self.__history = [] self.__state = State.running self.__undo_counter = 0 def slide_to(self, direction): if direction not in ['left', 'right', 'up', 'down']: return try: grid_before_slide = self.__grid.copy() points_gained, must_generate = { 'left': self.__grid.slide_left, 'right': self.__grid.slide_right, 'up': self.__grid.slide_up, 'down': self.__grid.slide_down }.get(direction)() except GridWinScoreReachedException as e: self.__state = State.game_won points_gained, must_generate = e.value if must_generate: self.__history.append((grid_before_slide, points_gained)) if len(self.__history) > constants.DEFAULT_HISTORY_LENGTH: self.__history.pop(0) self.__grid.generate_number() self.__score += points_gained else: if not self.__grid.can_slide(): if self.__state != State.game_won: self.__state = State.game_over def undo(self): if self.__undo_counter == constants.DEFAULT_HISTORY_LENGTH: return if len(self.__history) > 0: grid, score = self.__history.pop() self.__grid = grid self.__score -= score self.__undo_counter += 1 def start(self): self.__grid.generate_number() self.__grid.generate_number() def get_value_at(self, position): return self.__grid[position] def score(self): return self.__score def reset(self): self.__grid.reset() self.__history = [] self.__state = State.running self.__score = 0 self.__undo_counter = 0 self.start() def grid_dimensions(self): return self.__grid.dimensions() def get_state(self): return self.__state def change_state(self, state): if state in [State.running, State.game_over, State.game_won]: self.__state = state def undos_left(self): return constants.DEFAULT_HISTORY_LENGTH - self.__undo_counter def check_score(self): return self.__chart.is_top_score(self.__score) def add_player_to_chart(self, name, score): self.__chart.add(name, score) # TODO file not found handling def save_top_scores(self, filename): self.__chart.save(filename) def load_top_scores(self, filename): self.__chart.load(filename) def get_top_players(self): return self.__chart def reset_high_scores(self): self.__chart.reset()
class ChartTests(unittest.TestCase): def setUp(self): self.test_chart = Chart() def test_empty_chart(self): for top_player in self.test_chart: self.assertEqual(top_player[0], '') self.assertEqual(top_player[1], 0) def test_chart_add(self): self.test_chart.add('User1', 100) self.test_chart.add('User2', 200) self.test_chart.add('User3', 300) self.test_chart.add('User4', 400) self.test_chart.add('User5', 500) self.test_chart.add('User6', 600) self.test_chart.add('User7', 700) self.test_chart.add('User8', 800) self.test_chart.add('User9', 900) self.test_chart.add('User10', 1000) self.test_chart.add('User11', 50) for index in range(10): self.assertEqual( self.test_chart.top_players[index][0], ('User' + str(10 - index))) self.assertEqual( self.test_chart.top_players[index][1], (1000 - index * 100)) for top_player in self.test_chart.top_players: self.assertNotEqual(top_player[0], 'User11') def test_chart_is_top_score(self): self.test_chart.add('User1', 100) self.test_chart.add('User2', 200) self.test_chart.add('User3', 300) self.test_chart.add('User4', 400) self.test_chart.add('User5', 500) self.test_chart.add('User6', 600) self.test_chart.add('User7', 700) self.test_chart.add('User8', 800) self.test_chart.add('User9', 900) self.test_chart.add('User10', 1000) self.assertTrue(self.test_chart.is_top_score(1500)) self.assertTrue(self.test_chart.is_top_score(500)) self.assertTrue(self.test_chart.is_top_score(100)) self.assertFalse(self.test_chart.is_top_score(50)) def test_chart_reset(self): self.test_chart.add('User1', 100) self.test_chart.add('User2', 200) self.test_chart.add('User3', 300) self.test_chart.add('User4', 400) self.test_chart.add('User5', 500) self.test_chart.add('User6', 600) self.test_chart.add('User7', 700) self.test_chart.add('User8', 800) self.test_chart.add('User9', 900) self.test_chart.add('User10', 1000) self.test_chart.reset() for top_player in self.test_chart: self.assertEqual(top_player[0], '') self.assertEqual(top_player[1], 0) def test_chart_save(self): self.test_chart.add('User10', 100) self.test_chart.add('User9', 200) self.test_chart.add('User8', 300) self.test_chart.add('User7', 400) self.test_chart.add('User6', 500) self.test_chart.add('User5', 600) self.test_chart.add('User4', 700) self.test_chart.add('User3', 800) self.test_chart.add('User2', 900) self.test_chart.add('User1', 1000) self.test_chart.save('save_test.dat') import os self.assertTrue(os.path.isfile('save_test.dat')) def test_chart_load(self): self.test_chart.load('save_test.dat') for index in range(10): self.assertEqual( self.test_chart.top_players[index][0], ('User' + str(index + 1))) self.assertEqual( self.test_chart.top_players[index][1], (1000 - index * 100))
class Decoder(object): def __init__(self, fwords, grammars, features, local_grm=None): self.N = len(fwords) self.chart = Chart(fwords, FLAGS.start_symbol) self.agenda = Agenda() self.fwords = fwords self.grammars = grammars self.features = features self.features.decoder = self self.local_grm = local_grm self.dotcharts = [] # statistics self.closed = 0 self.neighbors_tried = 0 self.neighbors_closed = 0 self.cubes_built = 0 self.unary_edges_proposed = 0 self.nonunary_edges_proposed = 0 def decode_earley(self): """Returns None if no goal item found""" self.initialize_earley() #logger.level = 5 for i, j in cyk_spans(self.N): if logger.level >= 4: logger.writeln() logger.writeln('---- span (%s %s) ----' % (i, j)) # finish dot chart, build a cube new_items = Cube() new_virtual_items = Cube() for dotchart in self.dotcharts: if logger.level >= 4: logger.writeln() logger.writeln('dot chart for %s' % dotchart.grammar.name) dotchart.expand(i, j) for dotitem in dotchart.bins[i][j]: if dotitem.node.filled: for lhs, rulebin in dotitem.node.iter_rulebins(): bins = (rulebin, ) + dotitem.ants if is_virtual(lhs): new_virtual_items.add_cube( bins, self.get_cube_op(i, j)) else: new_items.add_cube(bins, self.get_cube_op(i, j)) self.cubes_built += 1 if logger.level >= 4: logger.writeln(' -- cubes --') logger.writeln(new_items) logger.writeln(' -- cubes for virtual items--') logger.writeln(new_virtual_items) # pop new items from the cube for cube in [new_items, new_virtual_items]: #print '================' #print cube for new_item in cube.iter_top_univar(FLAGS.bin_size): self.nonunary_edges_proposed += 1 #if logger.level >= 4: # logger.writeln('cube pop: %s' % new_item) # logger.writeln(new_item.incoming[0]) added = self.chart.add(new_item) #if logger.level >= 4: # logger.writeln('added: %s' % added) if logger.level >= 4 and added: logger.writeln('cube pop and add: %s' % new_item) logger.writeln(new_item.incoming[0]) #print '----------------' # apply unary rules self.unary_expand(i, j) # generate dot items like A->B.C (first nonterminal matched) # after the unary derivations are all finished for dotchart in self.dotcharts: if logger.level >= 4: logger.writeln() logger.writeln('unary expand for dot chart %s' % dotchart.grammar.name) dotchart.unary_expand(i, j) return self.get_goal(True) def decode_cyk(self): """Returns None if no goal item found""" self.initialize() for i, j in cyk_spans(self.N): self.binary_expand(i, j) self.unary_expand(i, j) return self.get_goal() def decode(self): """Returns None if no goal item found""" self.initialize() while len(self.agenda) > 0: item = self.agenda.pop() if item is None: # agenda empty return if item.goal(): # goal item return item if item.closed: continue item.closed = True self.closed += 1 # binary for litem in self.chart.leftneighbors(item): self.neighbors_tried += 1 if litem.closed: self.neighbors_closed += 1 for newitem in self.deduce([litem, item]): if self.chart.add(newitem): self.agenda.push(newitem) for ritem in self.chart.rightneighbors(item): self.neighbors_tried += 1 if ritem.closed: self.neighbors_closed += 1 for newitem in self.deduce([item, ritem]): if self.chart.add(newitem): self.agenda.push(newitem) for newitem in self.deduce([item]): if self.chart.add(newitem): self.agenda.push(newitem) def agenda_stats(self): header = '{:-^50}\n' field = '{:<35}{:>15}\n' result = header.format('Decoding Stats') result += field.format('[non-unary edges proposed]:', self.nonunary_edges_proposed) result += field.format('[unary edges proposed]:', self.unary_edges_proposed) result += field.format( '[total edges proposed]:', self.unary_edges_proposed + self.nonunary_edges_proposed) result += field.format('[cubes (non-unary -LM edges)]:', self.cubes_built) result += '\n' result += header.format('Agenda Stats') result += field.format('[pushed]:', self.agenda.pushed) result += field.format('[popped]:', self.agenda.popped) result += field.format('[dead pop]:', self.agenda.deadpop) result += field.format('[closed]:', self.closed) result += field.format('[final agenda size]:', len(self.agenda)) result += field.format('[neighbors closed]:', self.neighbors_closed) result += field.format('[neighbors tried]:', self.neighbors_tried) return result # ----------- begin of methods class users usually do not need------------ def initialize_earley(self): for grammar in self.grammars: dotchart = DotChart(self.chart, grammar) self.dotcharts.append(dotchart) if self.local_grm is not None: dotchart = DotChart(self.chart, self.local_grm) self.dotcharts.append(dotchart) # handling unknown words for item in self.iter_unknown_items(): self.chart.add(item) def initialize(self): "use lexical grammar to initialize" for grammar in self.grammars: self.initialize_with_lexgrammar(grammar.lexgrammar) # handling unknown words for item in self.iter_unknown_items(): self.agenda.push(item) self.chart.add(item) def initialize_with_lexgrammar(self, lexgrammar): """initialize chart and agenda with a pure lexical grammar""" # items in lexchart are pointers to TrieNodes in lexgrammar lexchart = [[None for i in range(self.N + 1)] for j in range(self.N + 1)] # seed the chart for i in range(self.N): lexchart[i][i] = lexgrammar.root #TODO: insertion? for i, j in cyk_spans(self.N): prevnode = lexchart[i][j - 1] word = self.fwords[j - 1] if prevnode and word in prevnode: curnode = lexchart[i][j - 1][word] # scan one word lexchart[i][j] = curnode for rule in curnode.iter_rules(): item = self.features.make_new_item(rule, (), i, j) self.agenda.push(item) self.chart.add(item) def unknown_word_rule(self, word): """generated a rule for a unknown word""" # delete or pass? rule = Rule() if FLAGS.pass_unknown_words: rule.fromstr('%s ||| %s ||| %s ||| 1 1 1 1 1' % (FLAGS.unknown_nonterminal, word, word)) else: rule.fromstr('%s ||| %s ||| %s ||| 1 1 1 1 1' % (FLAGS.unknown_nonterminal, word, '')) rule.is_unknown = True # for computing feature scores self.features.score_rule(rule) return rule def deduce(self, items): """given one or two item(s), try applying all possible ITG rules and yield the deduced items""" for grammar in self.grammars: for item in self.deduce_with_itg(grammar.itg, items): if logger.level >= 4: logger.writeln('new item:') logger.writeln(item) logger.writeln(item.incoming[0]) yield item def deduce_with_itg(self, itg, items): # unary if len(items) == 1: item = items[0] for new_item in self.unary_deduce(item): yield new_item # binary elif len(items) == 2: item1, item2 = items sym_list = [item.var for item in items] for rule in itg.iter_rules(sym_list): # derive start symbol only for spans [0,i] if rule.lhs == FLAGS.start_symbol and item1.i != 0: continue new_item = self.features.make_new_item(rule, items, item1.i, item2.j) yield new_item # by freesunshine, shouldn't be called under Eealey decoding method def binary_expand(self, i, j): assert False if logger.level >= 4: logger.writeln('span %s %s' % (i, j)) new_items = Cube() for k in range(i + 1, j): for lvar, lbin in self.chart.iter_items_by_nts(i, k): for rvar, rbin in self.chart.iter_items_by_nts(k, j): for grammar in self.grammars: rulebin = grammar.itg.get_sorted_rules((lvar, rvar)) if rulebin: new_items.add_cube((rulebin, lbin, rbin), self.get_cube_op(i, j)) for new_item in new_items.iter_top(FLAGS.bin_size): if logger.level >= 4: logger.writeln(new_item) self.chart.add(new_item) def unary_expand(self, i, j): if logger.level >= 4: logger.writeln() logger.writeln('-- Unary expand (%s,%s) --' % (i, j)) queue = [] for var, bin in self.chart.iter_items_by_nts(i, j): for item in bin: queue.append(item) heapify(queue) while queue: item = heappop(queue) if logger.level >= 4: logger.writeln('unary queue pop: %s' % item) if item.dead: continue if logger.level >= 4: logger.writeln('new items:') for new_item in self.unary_deduce(item): self.unary_edges_proposed += 1 if logger.level >= 4: logger.writeln(new_item) if self.chart.add(new_item): if logger.level >= 4: logger.writeln('added') heappush(queue, new_item) else: if logger.level >= 4: logger.writeln('not added') def unary_deduce(self, item): # TODO: this is made compatible with both LexicalITG and SCFG for now grammars = [] for grammar in self.grammars: if type(grammar) is LexicalITG: grammars.append(grammar.itg) else: grammars.append(grammar) for grammar in grammars: nt = item.var if FLAGS.nt_mismatch: nt = nocat(item.var) for rule in grammar.iter_rules((nt, )): # derive start symbol only for spans [0,i] if rule.lhs == FLAGS.start_symbol and item.i != 0: continue # derive goal symbol only for span [0,N] if (rule.lhs == FLAGS.goal_symbol and not (item.i == 0 and item.j == self.N)): continue new_item = self.features.make_new_item(rule, (item, ), item.i, item.j) yield new_item def get_cube_op(self, i, j): """Return a cube operator (a function) that takes as input a list [rule, item1, item2, ...] and returns a new item. The reason to generate a function on the fly here is to hide span for new item (i,j) in the generated function, so that it conforms to the cube operator interface.""" def cube_op(operands): rule = operands[0] items = operands[1:] return self.features.make_new_item(rule, items, i, j) return cube_op def get_goal(self, outfake=False): # TODO: ugly # TODO: there can be more than one goal item if 'GOAL' in self.chart.bins: goal_items = [item for item in self.chart.bins['GOAL']] goal_items.sort() if len(goal_items) > 0: return (goal_items[0], True) elif outfake: # TODO: this is probably wrong for leng in range(self.N, 1, -1): for st in range(0, self.N - leng + 1): ed = st + leng goal_items = [item for item in self.chart.items(st, ed)] if len(goal_items) > 0: goal_items.sort() return (goal_items[0], False) def iter_unknown_items(self): # unknown word rules are genereted for all words, because if rules # produce only intermediate nonterminals for the word, the decoder may # still get stuck for i in range(self.N): rule = self.unknown_word_rule(self.fwords[i]) item = self.features.make_new_item(rule, (), i, i + 1) yield item
class Game: def __init__(self, grid): self.__grid = grid self.__score = 0 self.__chart = Chart() self.__history = [] self.__state = State.game_waiting self.__undo_counter = 0 self.__difficulty = Difficulty.NORMAL self.__slider = { 'left': self.__grid.slide_left, 'right': self.__grid.slide_right, 'up': self.__grid.slide_up, 'down': self.__grid.slide_down } def slide_to(self, direction): if self.__slider.get(direction) == None: return try: grid_before_slide = self.__grid.copy() points_gained, must_generate = self.__slider.get(direction)() except GridWinScoreReachedException as e: self.__state = State.game_won points_gained, must_generate = e.value if must_generate: self.__history.append((grid_before_slide, points_gained)) if len(self.__history) > constants.DEFAULT_HISTORY_LENGTH: self.__history.pop(0) self.__grid.generate_number(self.__difficulty.value[0]) self.__score += points_gained else: if not self.__grid.can_slide(): if self.__state != State.game_won: self.__state = State.game_over def undo(self): if self.__undo_counter == constants.DEFAULT_HISTORY_LENGTH: return if len(self.__history) > 0: grid, score = self.__history.pop() self.__grid = grid self.__score -= score self.__undo_counter += 1 def start(self): if(self.__state == State.game_waiting): self.__grid.generate_number(int(self.__difficulty.value[0])) self.__grid.generate_number(int(self.__difficulty.value[0])) self.__state = State.running def set_difficulty(self, selected): self.__difficulty = selected def get_value_at(self, position): return self.__grid[position] def score(self): return self.__score def reset(self): self.__grid.reset() self.__history = [] self.__state = State.running self.__score = 0 self.__undo_counter = 0 self.start() def grid_dimensions(self): return self.__grid.dimensions() def get_state(self): return self.__state def change_state(self, state): if state in [State.running, State.game_over, State.game_won]: self.__state = state def undos_left(self): return constants.DEFAULT_HISTORY_LENGTH - self.__undo_counter def check_score(self): return self.__chart.is_top_score(self.__score) def add_player_to_chart(self, name, score): self.__chart.add(name, score) def save_top_scores(self, filename): self.__chart.save(filename) def load_top_scores(self, filename): self.__chart.load(filename) def get_top_players(self): return self.__chart def reset_high_scores(self): self.__chart.reset()