diff --git a/.flake8 b/.flake8 index c944f27ed..688024601 100644 --- a/.flake8 +++ b/.flake8 @@ -1,4 +1,4 @@ [flake8] max-line-length = 100 -ignore = E121,E123,E126,E221,E222,E225,E226,E242,E701,E702,E704,E731,W503,F405 +ignore = E121,E123,E126,E221,E222,E225,E226,E242,E701,E702,E704,E731,W503,F405,F841 exclude = tests diff --git a/agents.py b/agents.py index bca09f3e7..edab6891c 100644 --- a/agents.py +++ b/agents.py @@ -86,9 +86,12 @@ def __init__(self, program=None): self.holding = [] self.performance = 0 if program is None or not isinstance(program, collections.Callable): - print("Can't find a valid program for {}, falling back to default.".format(self.__class__.__name__)) + print("Can't find a valid program for {}, falling back to default.".format( + self.__class__.__name__)) + def program(percept): return eval(input('Percept={}; action? '.format(percept))) + self.program = program def can_grab(self, thing): diff --git a/canvas.py b/canvas.py index f78556cce..faabef6dd 100644 --- a/canvas.py +++ b/canvas.py @@ -121,6 +121,7 @@ def update(self): self.exec_list = [] display_html(exec_code) + def display_html(html_string): from IPython.display import HTML, display display(HTML(html_string)) diff --git a/csp.py b/csp.py index deb1efc12..d410b1428 100644 --- a/csp.py +++ b/csp.py @@ -20,7 +20,7 @@ class CSP(search.Problem): the other variables that participate in constraints. constraints A function f(A, a, B, b) that returns true if neighbors A, B satisfy the constraint when they have values A=a, B=b - + In the textbook and in most mathematical definitions, the constraints are specified as explicit pairs of allowable values, but the formulation here is easier to express and more compact for @@ -347,6 +347,7 @@ def topological_sort(X, root): build_topological(root, None, neighbors, visited, stack, parents) return stack, parents + def build_topological(node, parent, neighbors, visited, stack, parents): """Builds the topological sort and the parents of each node in the graph""" visited[node] = True @@ -356,7 +357,7 @@ def build_topological(node, parent, neighbors, visited, stack, parents): build_topological(n, node, neighbors, visited, stack, parents) parents[node] = parent - stack.insert(0,node) + stack.insert(0, node) def make_arc_consistent(Xj, Xk, csp): @@ -533,10 +534,12 @@ def display(self, assignment): # Sudoku -def flatten(seqs): return sum(seqs, []) +def flatten(seqs): + return sum(seqs, []) + -easy1 = '..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..' # noqa -harder1 = '4173698.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......' # noqa +easy1 = '..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..' +harder1 = '4173698.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......' _R3 = list(range(3)) _CELL = itertools.count().__next__ diff --git a/learning.py b/learning.py index 06a719745..b1dc5f68a 100644 --- a/learning.py +++ b/learning.py @@ -184,8 +184,8 @@ def split_values_by_classes(self): target_names = self.values[self.target] for v in self.examples: - item = [a for a in v if a not in target_names] # Remove target from item - buckets[v[self.target]].append(item) # Add item to bucket of its class + item = [a for a in v if a not in target_names] # Remove target from item + buckets[v[self.target]].append(item) # Add item to bucket of its class return buckets @@ -199,7 +199,7 @@ def find_means_and_deviations(self): feature_numbers = len(self.inputs) item_buckets = self.split_values_by_classes() - + means = defaultdict(lambda: [0 for i in range(feature_numbers)]) deviations = defaultdict(lambda: [0 for i in range(feature_numbers)]) @@ -216,7 +216,6 @@ def find_means_and_deviations(self): return means, deviations - def __repr__(self): return ''.format( self.name, len(self.examples), len(self.attrs)) @@ -769,7 +768,6 @@ def LinearLearner(dataset, learning_rate=0.01, epochs=100): for i in range(len(w)): w[i] = w[i] + learning_rate * (dotproduct(err, X_col[i]) / num_examples) - def predict(example): x = [1] + example return dotproduct(w, x) diff --git a/logic.py b/logic.py index c5aaa64ba..3ba1857bc 100644 --- a/logic.py +++ b/logic.py @@ -845,23 +845,8 @@ def subst(s, x): return Expr(x.op, *[subst(s, arg) for arg in x.args]) -def fol_fc_ask(KB, alpha): - """A simple forward-chaining algorithm. [Figure 9.3]""" - while new is not None: - new = [] - for rule in KB: - p, q = parse_definite_clause(standardize_variables(rule)) - for p_ in random.KB.clauses: - if p != p_: - for theta in (subst(theta, p) == subst(theta, p_)): - q_ = subst(theta, q) - if not unify(q_,KB.sentence in KB) or not unify(q_, new): - new.append(q_) - phi = unify(q_,alpha) - if phi is not None: - return phi - KB.tell(new) - return None +def fol_fc_ask(KB, alpha): # TODO + raise NotImplementedError def standardize_variables(sentence, dic=None): @@ -936,16 +921,15 @@ def fetch_rules_for_goal(self, goal): ])) crime_kb = FolKB( - map(expr, - ['(American(x) & Weapon(y) & Sells(x, y, z) & Hostile(z)) ==> Criminal(x)', # noqa - 'Owns(Nono, M1)', - 'Missile(M1)', - '(Missile(x) & Owns(Nono, x)) ==> Sells(West, x, Nono)', - 'Missile(x) ==> Weapon(x)', - 'Enemy(x, America) ==> Hostile(x)', - 'American(West)', - 'Enemy(Nono, America)' - ])) + map(expr, ['(American(x) & Weapon(y) & Sells(x, y, z) & Hostile(z)) ==> Criminal(x)', + 'Owns(Nono, M1)', + 'Missile(M1)', + '(Missile(x) & Owns(Nono, x)) ==> Sells(West, x, Nono)', + 'Missile(x) ==> Weapon(x)', + 'Enemy(x, America) ==> Hostile(x)', + 'American(West)', + 'Enemy(Nono, America)' + ])) def fol_bc_ask(KB, query): diff --git a/mdp.py b/mdp.py index 902582b19..aaf1d10a5 100644 --- a/mdp.py +++ b/mdp.py @@ -6,7 +6,7 @@ dictionary of {state:number} pairs. We then define the value_iteration and policy_iteration algorithms.""" -from utils import argmax, vector_add, print_table # noqa +from utils import argmax, vector_add from grid import orientations, turn_right, turn_left import random @@ -173,6 +173,8 @@ def policy_evaluation(pi, U, mdp, k=20): >>> sequential_decision_environment.to_arrows(pi) [['>', '>', '>', '.'], ['^', None, '^', '.'], ['^', '>', '^', '<']] +>>> from utils import print_table + >>> print_table(sequential_decision_environment.to_arrows(pi)) > > > . ^ None ^ . diff --git a/nlp.py b/nlp.py index bd26d0a7b..523d6c081 100644 --- a/nlp.py +++ b/nlp.py @@ -58,16 +58,16 @@ def __repr__(self): E0 = Grammar('E0', Rules( # Grammar for E_0 [Figure 22.4] S='NP VP | S Conjunction S', - NP='Pronoun | Name | Noun | Article Noun | Digit Digit | NP PP | NP RelClause', # noqa + NP='Pronoun | Name | Noun | Article Noun | Digit Digit | NP PP | NP RelClause', VP='Verb | VP NP | VP Adjective | VP PP | VP Adverb', PP='Preposition NP', RelClause='That VP'), Lexicon( # Lexicon for E_0 [Figure 22.3] - Noun="stench | breeze | glitter | nothing | wumpus | pit | pits | gold | east", # noqa + Noun="stench | breeze | glitter | nothing | wumpus | pit | pits | gold | east", Verb="is | see | smell | shoot | fell | stinks | go | grab | carry | kill | turn | feel", # noqa Adjective="right | left | east | south | back | smelly", - Adverb="here | there | nearby | ahead | right | left | east | south | back", # noqa + Adverb="here | there | nearby | ahead | right | left | east | south | back", Pronoun="me | you | I | it", Name="John | Mary | Boston | Aristotle", Article="the | a | an", @@ -166,7 +166,7 @@ def add_edge(self, edge): self.predictor(edge) def scanner(self, j, word): - "For each edge expecting a word of this category here, extend the edge." # noqa + "For each edge expecting a word of this category here, extend the edge." for (i, j, A, alpha, Bb) in self.chart[j]: if Bb and self.grammar.isa(word, Bb[0]): self.add_edge([i, j+1, A, alpha + [(Bb[0], word)], Bb[1:]]) @@ -384,16 +384,18 @@ def __init__(self, address, hub=0, authority=0, inlinks=None, outlinks=None): def HITS(query): """The HITS algorithm for computing hubs and authorities with respect to a query.""" - pages = expand_pages(relevant_pages(query)) # in order to 'map' faithfully to pseudocode we - for p in pages.values(): # won't pass the list of pages as an argument + pages = expand_pages(relevant_pages(query)) + for p in pages.values(): p.authority = 1 p.hub = 1 while True: # repeat until... convergence authority = {p: pages[p].authority for p in pages} hub = {p: pages[p].hub for p in pages} for p in pages: - pages[p].authority = sum(hub[x] for x in getInlinks(pages[p])) # p.authority ← ∑i Inlinki(p).Hub - pages[p].hub = sum(authority[x] for x in getOutlinks(pages[p])) # p.hub ← ∑i Outlinki(p).Authority + # p.authority ← ∑i Inlinki(p).Hub + pages[p].authority = sum(hub[x] for x in getInlinks(pages[p])) + # p.hub ← ∑i Outlinki(p).Authority + pages[p].hub = sum(authority[x] for x in getOutlinks(pages[p])) normalize(pages) if convergence(): break diff --git a/planning.py b/planning.py index 89c963c01..da00ee5d5 100644 --- a/planning.py +++ b/planning.py @@ -663,9 +663,8 @@ def act(self, action): if list_action is None: raise Exception("Action '{}' not found".format(action.name)) list_action.do_action(self.jobs, self.resources, self.kb, args) - # print(self.resources) - - def refinements(hla, state, library): # TODO - refinements may be (multiple) HLA themselves ... + + def refinements(hla, state, library): # TODO - refinements may be (multiple) HLA themselves ... """ state is a Problem, containing the current state kb library is a dictionary containing details for every possible refinement. eg: @@ -709,24 +708,23 @@ def refinements(hla, state, library): # TODO - refinements may be (multiple) HLA } """ e = Expr(hla.name, hla.args) - indices = [i for i,x in enumerate(library["HLA"]) if expr(x).op == hla.name] + indices = [i for i, x in enumerate(library["HLA"]) if expr(x).op == hla.name] for i in indices: - action = HLA(expr(library["steps"][i][0]), [ # TODO multiple refinements + action = HLA(expr(library["steps"][i][0]), [ # TODO multiple refinements [expr(x) for x in library["precond_pos"][i]], [expr(x) for x in library["precond_neg"][i]] - ], + ], [ [expr(x) for x in library["effect_pos"][i]], [expr(x) for x in library["effect_neg"][i]] ]) if action.check_precond(state.kb, action.args): yield action - + def hierarchical_search(problem, hierarchy): """ [Figure 11.5] 'Hierarchical Search, a Breadth First Search implementation of Hierarchical Forward Planning Search' - The problem is a real-world prodlem defined by the problem class, and the hierarchy is a dictionary of HLA - refinements (see refinements generator for details) """ @@ -734,14 +732,14 @@ def hierarchical_search(problem, hierarchy): frontier = FIFOQueue() frontier.append(act) while(True): - if not frontier: #(len(frontier)==0): + if not frontier: return None plan = frontier.pop() print(plan.state.name) - hla = plan.state #first_or_null(plan) + hla = plan.state # first_or_null(plan) prefix = None if plan.parent: - prefix = plan.parent.state.action #prefix, suffix = subseq(plan.state, hla) + prefix = plan.parent.state.action # prefix, suffix = subseq(plan.state, hla) outcome = Problem.result(problem, prefix) if hla is None: if outcome.goal_test(): @@ -864,4 +862,3 @@ def goal_test(kb): return Problem(init, [add_engine1, add_engine2, add_wheels1, add_wheels2, inspect1, inspect2], goal_test, [job_group1, job_group2], resources) - diff --git a/search.py b/search.py index 428648614..d104d7793 100644 --- a/search.py +++ b/search.py @@ -6,8 +6,7 @@ from utils import ( is_in, argmin, argmax, argmax_random_tie, probability, weighted_sampler, - weighted_sample_with_replacement, memoize, print_table, DataFile, Stack, - FIFOQueue, PriorityQueue, name + memoize, print_table, DataFile, Stack, FIFOQueue, PriorityQueue, name ) from grid import distance @@ -419,7 +418,7 @@ def or_search(state, problem, path): return [action, plan] def and_search(states, problem, path): - """Returns plan in form of dictionary where we take action plan[s] if we reach state s.""" # noqa + """Returns plan in form of dictionary where we take action plan[s] if we reach state s.""" plan = {} for s in states: plan[s] = or_search(s, problem, path) @@ -461,8 +460,8 @@ def __call__(self, percept): if len(self.unbacktracked[s1]) == 0: self.a = None else: - # else a <- an action b such that result[s', b] = POP(unbacktracked[s']) # noqa - unbacktracked_pop = self.unbacktracked[s1].pop(0) # noqa + # else a <- an action b such that result[s', b] = POP(unbacktracked[s']) + unbacktracked_pop = self.unbacktracked[s1].pop(0) for (s, b) in self.result.keys(): if self.result[(s, b)] == unbacktracked_pop: self.a = b @@ -546,7 +545,7 @@ def __call__(self, s1): # as of now s1 is a state rather than a percept # an action b in problem.actions(s1) that minimizes costs self.a = argmin(self.problem.actions(s1), - key=lambda b:self.LRTA_cost(s1, b, self.problem.output(s1, b), self.H)) + key=lambda b: self.LRTA_cost(s1, b, self.problem.output(s1, b), self.H)) self.s = s1 return self.a @@ -573,17 +572,17 @@ def genetic_search(problem, fitness_fn, ngen=1000, pmut=0.1, n=20): """Call genetic_algorithm on the appropriate parts of a problem. This requires the problem to have states that can mate and mutate, plus a value method that scores states.""" - + # NOTE: This is not tested and might not work. # TODO: Use this function to make Problems work with genetic_algorithm. - + s = problem.initial_state states = [problem.result(s, a) for a in problem.actions(s)] random.shuffle(states) return genetic_algorithm(states[:n], problem.value, ngen, pmut) -def genetic_algorithm(population, fitness_fn, gene_pool=['0', '1'], f_thres=None, ngen=1000, pmut=0.1): +def genetic_algorithm(population, fitness_fn, gene_pool=['0', '1'], f_thres=None, ngen=1000, pmut=0.1): # noqa """[Figure 4.8]""" for i in range(ngen): new_population = [] @@ -954,7 +953,7 @@ def print_boggle(board): print() -def boggle_neighbors(n2, cache={}): # noqa +def boggle_neighbors(n2, cache={}): """Return a list of lists, where the i-th element is the list of indexes for the neighbors of square i.""" if cache.get(n2): diff --git a/tests/test_csp.py b/tests/test_csp.py index 301fd643d..9c4804c3d 100644 --- a/tests/test_csp.py +++ b/tests/test_csp.py @@ -1,5 +1,5 @@ import pytest -from csp import * # noqa +from csp import * def test_csp_assign(): diff --git a/tests/test_games.py b/tests/test_games.py index 35df9c827..5dcf0af07 100644 --- a/tests/test_games.py +++ b/tests/test_games.py @@ -5,7 +5,7 @@ import pytest -from games import * # noqa +from games import * # Creating the game instances f52 = Fig52Game() diff --git a/tests/test_grid.py b/tests/test_grid.py index aad9ebc91..6cd5f6d24 100644 --- a/tests/test_grid.py +++ b/tests/test_grid.py @@ -1,5 +1,5 @@ import pytest -from grid import * # noqa +from grid import * def compare_list(x, y): diff --git a/tests/test_logic.py b/tests/test_logic.py index 5ae9189a9..be172e664 100644 --- a/tests/test_logic.py +++ b/tests/test_logic.py @@ -1,5 +1,5 @@ import pytest -from logic import * # noqa +from logic import * from utils import expr_handle_infix_ops, count, Symbol diff --git a/tests/test_mdp.py b/tests/test_mdp.py index f5cb40510..dc975c7f1 100644 --- a/tests/test_mdp.py +++ b/tests/test_mdp.py @@ -1,4 +1,4 @@ -from mdp import * # noqa +from mdp import * def test_value_iteration(): diff --git a/tests/test_planning.py b/tests/test_planning.py index e9c639c95..2c355f54c 100644 --- a/tests/test_planning.py +++ b/tests/test_planning.py @@ -1,4 +1,4 @@ -from planning import * # noqa +from planning import * from utils import expr from logic import FolKB diff --git a/tests/test_probability.py b/tests/test_probability.py index 9f8ed5cd1..cfffee5bd 100644 --- a/tests/test_probability.py +++ b/tests/test_probability.py @@ -1,5 +1,5 @@ import random -from probability import * # noqa +from probability import * from utils import rounder @@ -183,7 +183,7 @@ def test_particle_filtering(): >>> P['rain'] #doctest:+ELLIPSIS 0.2... -# A Joint Probability Distribution is dealt with like this [Figure 13.3]: # noqa +# A Joint Probability Distribution is dealt with like this [Figure 13.3]: >>> P = JointProbDist(['Toothache', 'Cavity', 'Catch']) >>> T, F = True, False >>> P[T, T, T] = 0.108; P[T, T, F] = 0.012; P[F, T, T] = 0.072; P[F, T, F] = 0.008 diff --git a/tests/test_search.py b/tests/test_search.py index d50eacfe1..ebc02b5ab 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -1,5 +1,5 @@ import pytest -from search import * # noqa +from search import * romania_problem = GraphProblem('Arad', 'Bucharest', romania_map) diff --git a/tests/test_text.py b/tests/test_text.py index ac1f9c996..757e6fe17 100644 --- a/tests/test_text.py +++ b/tests/test_text.py @@ -2,7 +2,7 @@ import os import random -from text import * # noqa +from text import * from utils import isclose, DataFile @@ -304,7 +304,7 @@ def test_bigrams(): >>> P3.samples(20) 'flatland by edwin a abbott 1884 to the wake of a certificate from nature herself proving the equal sided triangle' -""" # noqa +""" if __name__ == '__main__': pytest.main() diff --git a/tests/test_utils.py b/tests/test_utils.py index d158833d0..90548069b 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,5 +1,5 @@ import pytest -from utils import * # noqa +from utils import * import random def test_removeall_list(): diff --git a/text.py b/text.py index 2faac1049..3cce44e6d 100644 --- a/text.py +++ b/text.py @@ -26,7 +26,6 @@ def samples(self, n): return ' '.join(self.sample() for i in range(n)) - class NgramTextModel(CountingProbDist): """This is a discrete probability distribution over n-tuples of words. @@ -80,7 +79,7 @@ def samples(self, nwords): class NgramCharModel(NgramTextModel): def add_empty(self, words, n): - return ' ' * (n - 1) + words + return ' ' * (n - 1) + words def add_sequence(self, words): for word in words: @@ -362,14 +361,13 @@ def decode(self, ciphertext): solution.state[' '] = ' ' return translate(self.ciphertext, lambda c: solution.state[c]) - def score(self, code): """Score is product of word scores, unigram scores, and bigram scores. This can get very small, so we use logs and exp.""" # remake code dictionary to contain translation for all characters full_code = code.copy() - full_code.update({x:x for x in self.chardomain if x not in code}) + full_code.update({x: x for x in self.chardomain if x not in code}) full_code[' '] = ' ' text = translate(self.ciphertext, lambda c: full_code[c]) diff --git a/utils.py b/utils.py index 5afa43760..b67153999 100644 --- a/utils.py +++ b/utils.py @@ -7,6 +7,7 @@ import os.path import random import math +import functools # ______________________________________________________________________________ # Functions on Sequences and Iterables @@ -258,6 +259,7 @@ def step(x): """Return activation value of x with sign function""" return 1 if x >= 0 else 0 + def gaussian(mean, st_dev, x): """Given the mean and standard deviation of a distribution, it returns the probability of x.""" return 1/(math.sqrt(2*math.pi)*st_dev)*math.e**(-0.5*(float(x-mean)/st_dev)**2) @@ -656,7 +658,7 @@ def extend(self, items): def pop(self): if len(self.queue) > 0: return self.queue.popleft() - else : + else: raise Exception('FIFOQueue is empty') def __len__(self):