├── .gitignore ├── README.md └── unit02 ├── c++ ├── README.markdown ├── Tree.h ├── TreeSearch.h ├── algorithms │ ├── Algorithms.h │ ├── BreadthFirstSearch.h │ └── Path.h └── example.cpp ├── clojure └── unit02 │ ├── .gitignore │ ├── README.markdown │ ├── project.clj │ ├── src │ └── unit02 │ │ ├── graphs.clj │ │ ├── trees.clj │ │ └── viz.clj │ └── test │ └── unit02 │ └── test │ ├── graphs.clj │ └── trees.clj ├── js ├── search.js ├── structures.js └── test │ └── searchtest.html └── python └── u02 ├── __init__.py ├── graph.py ├── search.py └── test ├── __init__.py └── searchtest.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | *.pyc 10 | a.out 11 | 12 | # Packages # 13 | ############ 14 | # it's better to unpack these files and commit the raw source 15 | # git has its own built in compression methods 16 | *.7z 17 | *.dmg 18 | *.gz 19 | *.iso 20 | *.jar 21 | *.rar 22 | *.tar 23 | *.zip 24 | 25 | # Logs and databases # 26 | ###################### 27 | *.log 28 | *.sql 29 | *.sqlite 30 | 31 | # OS generated files # 32 | ###################### 33 | .DS_Store* 34 | ehthumbs.db 35 | Icon? 36 | Thumbs.db 37 | 38 | # Editor generated files # 39 | ########################## 40 | *.swp 41 | *~ 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Stanford AI Class Algorithms 2 | ---------------------------- 3 | 4 | This is the unofficial code chrestomathy repository for the [Stanford Online Introduction to Artificial Intelligence][1] course based on Stanford CS221. The course focuses on machine learning, probabilistic reasoning, robotics, and natural language processing. 5 | 6 | Implementations of any algorithms learned in the course can be developed in any language and put into this repository. All code submitted to this repository will be available freely, and licensed under the [MIT License][2]. 7 | 8 | [1]: http://www.ai-class.com/ 9 | [2]: http://www.opensource.org/licenses/mit-license.php 10 | 11 | Current available languages 12 | ----------------------------- 13 | 14 | * Clojure 15 | * JavaScript 16 | * Python 17 | 18 | How to use 19 | ----------- 20 | 21 | * The repository will be divided into separate directories for each unit in the class ('unit1', 'unit2', etc). 22 | * Each unit will be divided into more directories for each language. ('unit1/python', 'unit1/js', 'unit2/python'). 23 | * For each unit and language, try to write the algorithms with as few external libraries as possible and keep the code commented. 24 | * Unit tests for code, or even better, visualizers, are very appreciated! (but not necessary) 25 | * To contribute, fork the repository and add your code following the directory structure. 26 | * Send a pull request as soon as you're done, and your code will be merged as soon as possible. 27 | 28 | New to Git? 29 | ----------- 30 | 31 | Check out any one of GitHub's [awesome guides][2]. 32 | 33 | [2]:https://github.com/blog/120-new-to-git 34 | 35 | License 36 | ------- 37 | 38 | All code is released under the [MIT License][4]. 39 | 40 | [4]:http://www.opensource.org/licenses/mit-license.php 41 | -------------------------------------------------------------------------------- /unit02/c++/README.markdown: -------------------------------------------------------------------------------- 1 | C++ Implementation - Miguel Bernabeu Diaz < miguel.bernadi[AT]gmail[DOT]com > 2 | 3 | This project is based on the 2011 edition of "Stanford Online Introduction to Artificial Intelligence" (www.ai-class.com). 4 | The code of the example.cpp file is Public Domain. All other code is licensed under MIT License (http://www.opensource.org/licenses/mit-license.php). 5 | 6 | Algorithms: 7 | * Breadth First Search (BFS) => Implemented 8 | * Uniform Cost Search (UCS) 9 | * Cheapest First Search (CFS) 10 | * Depth First Search (DFS) 11 | * A\* Search (ASS) 12 | -------------------------------------------------------------------------------- /unit02/c++/Tree.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * Copyright (c) 2011 Miguel Bernabeu Diaz 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | * associated documentation files (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all copies or substantial 12 | * portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 15 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 16 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 17 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 18 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | */ 20 | 21 | #ifndef Tree_H_ 22 | #define Tree_H_ 23 | 24 | #include 25 | 26 | /** 27 | * Class representing a Binary Tree. 28 | */ 29 | template 30 | class Tree 31 | { 32 | public: 33 | typedef TreeNode value_type; ///< The type of the nodes. 34 | typedef std::list< value_type* > TreeNodeList; 35 | 36 | Tree() : _rootNode(0) { } 37 | ~Tree() { delete _NodeList; } 38 | value_type* getRootPtr() { return _rootNode; } 39 | void setRoot(value_type* rootNode) { _rootNode = rootNode; _NodeList.push_back( _rootNode ); } 40 | void addNode(value_type* Node) { _NodeList.push_back(Node); } 41 | 42 | private: 43 | TreeNodeList _NodeList; 44 | value_type* _rootNode; 45 | 46 | }; 47 | 48 | /** 49 | * Class representing a Node of the Tree. 50 | * @param _Data is the information structure stored in the node. 51 | */ 52 | template 53 | class TreeNode 54 | { 55 | private: 56 | 57 | public: 58 | typedef _Data value_type; 59 | int child_number; 60 | 61 | /// Node contained information. 62 | value_type Data; 63 | /// Pointer to parent node 64 | TreeNode<_Data>* parent; 65 | /// Children of the Node 66 | TreeNode<_Data>* child[nChild]; 67 | 68 | TreeNode(value_type Data) : child_number(nChild), Data(Data), parent(0) { } 69 | ~TreeNode() { for(int i = 0; i < child_number; ++i) delete child[i]; } 70 | 71 | int has_children() { int childs = 0; for(int i = 0; i < child_number; ++i) { if(child[i] != 0) ++childs; } return childs; } 72 | 73 | };// end of BinaryTreeNode definition 74 | 75 | #endif 76 | 77 | -------------------------------------------------------------------------------- /unit02/c++/TreeSearch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * Copyright (c) 2011 Miguel Bernabeu Diaz 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | * associated documentation files (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all copies or substantial 12 | * portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 15 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 16 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 17 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 18 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | */ 20 | 21 | #ifndef TreeSearch_H_ 22 | #define TreeSearch_H_ 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "Tree.h" 29 | #include "algorithms/Algorithms.h" 30 | 31 | template */ > 32 | class TreeSearch 33 | { 34 | public: 35 | typedef std::list< Path* > PathList; 36 | typedef typename TreeType::value_type::value_type GoalType; 37 | 38 | 39 | PathList _frontier; 40 | std::set _explored; 41 | typename TreeType::value_type* TreeRoot; 42 | PathList LPath; 43 | 44 | TreeSearch(typename TreeType::value_type* mNode) : TreeRoot( mNode ) { _frontier.push_back( new Path(TreeRoot) ); } 45 | Path* find(GoalType Goal) 46 | { 47 | /* 48 | Notes: A compare function must be specified to the set container. 49 | 50 | Pseudocode: 51 | Function TreeSearch(problem): 52 | frontier = {[initial]} 53 | loop: 54 | if frontier is empty: FAIL 55 | path = remove_choice(frontier) 56 | s = path.end 57 | if s is a goal: return path 58 | for a in actions: 59 | add [path + a -> Result(s, a)] to frontier 60 | */ 61 | 62 | Path* path; 63 | typename TreeType::value_type* Node; 64 | // Tries using SearchAlgorithm as holder of the actual algorithm implementation. 65 | // SearchAlgorithm sa(); 66 | // return sa.find(Goal); 67 | while(true) 68 | { 69 | if(_frontier.empty()) throw( std::exception() ); 70 | path = _frontier.front(); 71 | _frontier.remove(path); 72 | Node = path->_path.back(); 73 | _explored.insert(Node); 74 | if (Node->Data == Goal) return path; 75 | 76 | // Add the checked Nodes children to a copy of the present path 77 | // and add this path to _frontier. 78 | if( Node->has_children() != 0 ) 79 | { 80 | for(int i = 0; i < Node->child_number; ++i) 81 | { 82 | // Check if the child to be attached has been explored already 83 | if( _explored.find(Node->child[i]) == _explored.end() ) 84 | { 85 | Path* newpath = new Path(*path); 86 | newpath->_path.push_back(Node->child[i]); 87 | _frontier.push_back(newpath); 88 | } 89 | } 90 | _frontier.sort(); 91 | } 92 | } 93 | } 94 | }; 95 | 96 | #endif 97 | 98 | -------------------------------------------------------------------------------- /unit02/c++/algorithms/Algorithms.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * Copyright (c) 2011 Miguel Bernabeu Diaz 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | * associated documentation files (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all copies or substantial 12 | * portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 15 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 16 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 17 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 18 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | */ 20 | 21 | #ifndef Algorithms_H_ 22 | #define Algorithms_H_ 23 | 24 | #include "BreadthFirstSearch.h" 25 | 26 | class UniformCostSearch; // UCS 27 | class CheapestFirstSearch; // CFS 28 | class DepthFirstSearch; // DFS 29 | class AStarSearch; // ASS 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /unit02/c++/algorithms/BreadthFirstSearch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * Copyright (c) 2011 Miguel Bernabeu Diaz 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | * associated documentation files (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all copies or substantial 12 | * portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 15 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 16 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 17 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 18 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | */ 20 | 21 | #ifndef BreadthFirstSearch_H_ 22 | #define BreadthFirstSearch_H_ 23 | 24 | #include "Path.h" 25 | 26 | template 27 | class BreadthFirstSearch // BFS 28 | { 29 | public: 30 | typedef std::list< Path* > PathList; 31 | PathList _frontier; 32 | typename std::set _explored; 33 | typename TreeType::value_type* TreeRoot; 34 | PathList LPath; 35 | 36 | 37 | BreadthFirstSearch() { } 38 | Path* find( typename TreeType::value_type::value_type Goal) 39 | { 40 | Path* path; 41 | typename TreeType::value_type* Node; 42 | /* 43 | * Notes: A compare function must be specified to the set container. 44 | * 45 | * Pseudocode: 46 | * Function TreeSearch(problem): 47 | * frontier = {[initial]} 48 | * loop: 49 | * if frontier is empty: FAIL 50 | * path = remove_choice(frontier) 51 | * s = path.end 52 | * if s is a goal: return path 53 | * for a in actions: 54 | * add [path + a -> Result(s, a)] to frontier 55 | */ 56 | while(true) 57 | { 58 | if(_frontier.empty()) throw( std::exception() ); 59 | path = _frontier.front(); 60 | _frontier.remove(path); 61 | Node = path->_path.back(); 62 | _explored.insert(Node); 63 | if (Node->Data == Goal) return path; 64 | 65 | // Add the checked Nodes children to a copy of the present path 66 | // and add this path to _frontier. 67 | if( Node->has_children() != 0 ) 68 | { 69 | for(int i = 0; i < Node->child_number; ++i) 70 | { 71 | // Check if the child to be attached has been explored already 72 | if( _explored.find(Node->child[i]) == _explored.end() ) 73 | { 74 | Path* newpath = new Path(*path); 75 | newpath->_path.push_back(Node->child[i]); 76 | _frontier.push_back(newpath); 77 | } 78 | } 79 | _frontier.sort(); 80 | } 81 | } 82 | 83 | } 84 | }; 85 | 86 | #endif 87 | 88 | -------------------------------------------------------------------------------- /unit02/c++/algorithms/Path.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * Copyright (c) 2011 Miguel Bernabeu Diaz 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | * associated documentation files (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all copies or substantial 12 | * portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 15 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 16 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 17 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 18 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | */ 20 | 21 | #ifndef Path_H_ 22 | #define Path_H_ 23 | 24 | template 25 | class Path 26 | { 27 | public: 28 | typename TreeType::TreeNodeList _path; 29 | 30 | Path() { } 31 | Path(typename TreeType::value_type* Node) { addToPath(Node); } 32 | 33 | // Path(const Path& orig) { this->_path = orig._path; } 34 | 35 | void addToPath(typename TreeType::value_type* Node) { _path.push_back(Node); } 36 | 37 | //add comparison operator operator< for sorting by length. 38 | }; 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /unit02/c++/example.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The code contained in this file is licensed as Public Domain. 3 | */ 4 | 5 | /* 6 | * Example of usage of headers Tree.h and TreeSearch.h 7 | */ 8 | 9 | #include 10 | 11 | #include "Tree.h" 12 | #include "TreeSearch.h" 13 | 14 | /* 15 | * This class represents the information stored in a node of the tree. 16 | * It may contain lots of information but must implement an equality 17 | * operator (operator==) to detect when the goal is achieved. 18 | */ 19 | class Info 20 | { 21 | public: 22 | std::string Id; 23 | int Count; 24 | 25 | Info() { } 26 | Info(std::string Id, int Count) : Id(Id), Count(Count) { } 27 | 28 | // operator== is a must (used for goal) 29 | bool operator==(const Info &other) const 30 | { 31 | if(this->Id == other.Id) return true; 32 | return false; 33 | } 34 | }; 35 | 36 | // Helpers for less mistakes and easier reading. 37 | typedef TreeNode myNodeType; 38 | typedef Tree myTreeType; 39 | 40 | int main() 41 | { 42 | // Build the tree 43 | myTreeType* mTree = new myTreeType(); 44 | mTree->setRoot( new myNodeType( Info("Root", 1) ) ); 45 | myNodeType* mNode = mTree->getRootPtr(); 46 | mNode->child[0] = new myNodeType( Info("ChildOne", 1) ); 47 | mTree->addNode(mNode->child[0]); 48 | 49 | // Set the starting point for a search. 50 | TreeSearch >* mSearch = new TreeSearch >( mTree->getRootPtr() ); 51 | 52 | /* 53 | * mPath is guaranteed to be the shortest path between the starting point and 54 | * the goal point. 55 | */ 56 | Path* mPath = mSearch->find( Info("ChildOne", 1) ); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /unit02/clojure/unit02/.gitignore: -------------------------------------------------------------------------------- 1 | pom.xml 2 | *jar 3 | /lib/ 4 | /classes/ 5 | .lein-failures 6 | .lein-deps-sum 7 | -------------------------------------------------------------------------------- /unit02/clojure/unit02/README.markdown: -------------------------------------------------------------------------------- 1 | Unit 2 Algorithms in Clojure 2 | ============================ 3 | 4 | Usage 5 | ----- 6 | 7 | lein deps 8 | lein test 9 | 10 | lein repl 11 | 12 | (require '[unit02.trees :as trees]) 13 | (trees/search-breadth trees/sample-tree-1 :e) 14 | (trees/search-depth trees/sample-tree-1 :e) 15 | (trees/search-breadth trees/sample-tree-2 :z) 16 | (trees/search-depth trees/sample-tree-2 :z) 17 | 18 | (require '[unit02.graphs :as graphs]) 19 | (graphs/search-breadth graphs/sample-graph-ny :rochester :albany) 20 | (graphs/search-depth graphs/sample-graph-ny :rochester :albany) 21 | 22 | (require '[unit02.viz :as viz]) 23 | 24 | (viz/search-tree trees/sample-tree-1 trees/search-depth :e) 25 | (viz/search-tree trees/sample-tree-1 trees/search-breadth :e) 26 | 27 | (viz/search-tree trees/sample-tree-3 trees/search-depth :n) 28 | (viz/search-tree trees/sample-tree-3 trees/search-breadth :n) 29 | -------------------------------------------------------------------------------- /unit02/clojure/unit02/project.clj: -------------------------------------------------------------------------------- 1 | (defproject unit02 "1.0.0-SNAPSHOT" 2 | :description "ai-class unit 2 algorithms in Clojure" 3 | :dependencies [[org.clojure/clojure "1.2.1"] 4 | [org.clojure/clojure-contrib "1.2.0"] 5 | [incanter "1.2.4"]] 6 | :dev-dependencies [[lein-marginalia "0.6.1"]]) 7 | -------------------------------------------------------------------------------- /unit02/clojure/unit02/src/unit02/graphs.clj: -------------------------------------------------------------------------------- 1 | (ns unit02.graphs) 2 | 3 | 4 | 5 | ; Undirected Graph ------------------------------------------------------------ 6 | ; 7 | ; A graph is a map of label -> node. 8 | ; Each node has a label and a list of connections. 9 | ; Each connection is a map of label -> cost. 10 | ; 11 | ; Connections between nodes are undirected, and the cost is the same in both 12 | ; directions. 13 | 14 | (defrecord Node [label connections]) 15 | 16 | (defn make-graph [labels connections] 17 | (let [graph (zipmap labels (map #(Node. %1 %2) labels (cycle [{}])))] 18 | (loop [graph graph 19 | connections connections] 20 | (if (empty? connections) 21 | graph 22 | (let [[labels cost] (first connections) 23 | [a b] labels] 24 | (recur (-> graph 25 | (assoc-in [a :connections b] cost) 26 | (assoc-in [b :connections a] cost)) 27 | (rest connections))))))) 28 | 29 | 30 | ; Searches -------------------------------------------------------------------- 31 | (defn- path-cost [path graph] 32 | (loop [prev (first path) 33 | path (rest path) 34 | cost 0] 35 | (if (empty? path) 36 | cost 37 | (recur (first path) 38 | (rest path) 39 | (+ cost ((:connections (graph prev)) 40 | (first path))))))) 41 | 42 | (defn- new-targets [path current-node explored graph] 43 | (let [unseen (filter (complement explored) 44 | (keys (:connections current-node))) 45 | new-paths (map #(conj path %) unseen)] 46 | (map #(with-meta % {:cost (path-cost % graph)}) 47 | new-paths))) 48 | 49 | 50 | (defn search [frontier-conj graph start goal] 51 | (loop [explored #{} 52 | frontier (seq [[start]]) 53 | examined 1] 54 | (let [path (first frontier) 55 | current (last path)] 56 | (if (= current goal) 57 | {:path path 58 | :examined examined 59 | :cost (:cost (meta path))} 60 | (when current 61 | (recur (conj explored current) 62 | (let [current-node (graph current)] 63 | (frontier-conj (rest frontier) 64 | (new-targets path current-node explored graph))) 65 | (inc examined))))))) 66 | 67 | 68 | (defn frontier-conj-breadth [frontier children] 69 | (concat frontier children)) 70 | 71 | (defn frontier-conj-depth [frontier children] 72 | (concat children frontier)) 73 | 74 | 75 | (def search-breadth (partial search frontier-conj-breadth)) 76 | (def search-depth (partial search frontier-conj-depth)) 77 | 78 | ; Sample Graph ---------------------------------------------------------------- 79 | (def sample-graph-ny 80 | (make-graph [:buffalo :rochester :syracuse :binghamton :new-york-city] 81 | {[:buffalo :rochester] 75 82 | [:syracuse :rochester] 90 83 | [:ithaca :rochester] 90 84 | [:ithaca :binghamton] 50 85 | [:ithaca :syracuse] 60 86 | [:binghamton :syracuse] 75 87 | [:binghamton :rochester] 141 88 | [:binghamton :new-york-city] 176 89 | [:syracuse :new-york-city] 247 90 | [:albany :new-york-city] 150 91 | [:albany :syracuse] 150})) 92 | -------------------------------------------------------------------------------- /unit02/clojure/unit02/src/unit02/trees.clj: -------------------------------------------------------------------------------- 1 | (ns unit02.trees) 2 | 3 | 4 | ; Tree ------------------------------------------------------------------------ 5 | ; 6 | ; A tree is equivalent to a single node. A single node is a record: 7 | ; 8 | ; {:label :foo :children [... nodes ...]} 9 | 10 | (defrecord Node [label children]) 11 | 12 | (defn node [label children] 13 | (Node. label children)) 14 | 15 | ; Searches -------------------------------------------------------------------- 16 | (defn- log [log-ref label data] 17 | (when log-ref 18 | (dosync (alter log-ref conj [label data])))) 19 | 20 | (defn- search 21 | ([frontier-conj tree goal] (search frontier-conj tree goal nil)) 22 | ([frontier-conj tree goal log-ref] 23 | ; frontier is a sequence of vectors representing paths we still need to try: 24 | ; ([Node :a, Node :b], [Node :a, Node :c], ...) 25 | (loop [frontier (seq [[tree]]) 26 | examined 1] 27 | (log log-ref :frontier (vec (map (comp :label last) frontier))) 28 | (let [path (first frontier) 29 | current (last path)] 30 | (log log-ref :examine current) 31 | (if (= (:label current) goal) 32 | {:path (map :label path) 33 | :examined examined} 34 | (recur (frontier-conj (rest frontier) 35 | (map #(conj path %) (:children current))) 36 | (inc examined))))))) 37 | 38 | 39 | (defn- frontier-conj-depth [frontier children] 40 | (concat children frontier)) 41 | 42 | (defn- frontier-conj-breadth [frontier children] 43 | (concat frontier children)) 44 | 45 | 46 | (def search-depth (partial search frontier-conj-depth)) 47 | (def search-breadth (partial search frontier-conj-breadth)) 48 | 49 | ; Sample Trees ---------------------------------------------------------------- 50 | 51 | (def sample-tree-1 (node :a [(node :b [(node :d []) 52 | (node :e [])]) 53 | (node :c [(node :f []) 54 | (node :g [])])])) 55 | 56 | (def sample-tree-2 (node :a [(node :b [(node :d []) 57 | (node :e [])]) 58 | (node :q []) 59 | (node :c [(node :f [(node :x []) 60 | (node :y [(node :z [])])]) 61 | (node :g [])])])) 62 | 63 | (def sample-tree-3 (node :a [(node :b [(node :d [(node :i []) 64 | (node :j [])]) 65 | (node :e [])]) 66 | (node :q [(node :l [(node :n [(node :o [(node :p [])])])]) 67 | (node :m [(node :r [])])]) 68 | (node :c [(node :f [(node :x []) 69 | (node :y [(node :z [])])]) 70 | (node :g [])])])) 71 | -------------------------------------------------------------------------------- /unit02/clojure/unit02/src/unit02/viz.clj: -------------------------------------------------------------------------------- 1 | (ns unit02.viz 2 | (:use (incanter core processing)) 3 | (:use [unit02.trees :only (node)])) 4 | 5 | 6 | 7 | (defn- set-node-fill-color [canvas node state] 8 | (if (some #{(:label node)} (:frontier @state)) 9 | (if (= node (:current @state)) 10 | (doto canvas (fill 226 0 55)) ; Red if it's current. 11 | (doto canvas (fill 0 121 184))) ; Otherwise blue if it's in the frontier. 12 | (doto canvas (fill 150)))) ; Otherwise grey. 13 | 14 | (defn- draw-node-circle [canvas node state x y] 15 | (set-node-fill-color canvas node state) 16 | (doto canvas 17 | (stroke 10) 18 | (stroke-weight 2) 19 | (ellipse x y 20 20))) 20 | 21 | (defn- draw-node-text [canvas node x y] 22 | (doto canvas 23 | (fill 250) 24 | (text-align CENTER) 25 | (text (str (:label node)) x (+ y 5)))) 26 | 27 | 28 | (defn- draw-node [canvas node state x y] 29 | (draw-node-circle canvas node state x y) 30 | (draw-node-text canvas node x y)) 31 | 32 | (defn- draw-edge [canvas ax ay bx by] 33 | (doto canvas 34 | (stroke-weight 2) 35 | (stroke 10) 36 | (line ax ay bx by))) 37 | 38 | 39 | (defn- draw-child [canvas state width-per-child width x y child i] 40 | (let [cxs-start (- x (/ width 2)) ; where this node's childrens' space starts [ __________] 41 | cx-end (+ cxs-start (* width-per-child i)) ; where this child's space ends [ _____.....] 42 | cx (- cx-end (/ width-per-child 2)) ; put the child into the center of its space [ _____..c..] 43 | cy (+ y 50)] 44 | (draw-edge canvas x y cx cy) 45 | (draw-tree child canvas state width-per-child cx cy))) 46 | 47 | (defn- draw-tree 48 | ([tree canvas state width] (draw-tree tree canvas state width (/ width 2) 20)) 49 | ([tree canvas state width x y] 50 | (when (seq (:children tree)) 51 | (let [children (:children tree) 52 | width-per-child (/ width (count children))] 53 | (dorun 54 | (map (partial draw-child canvas state width-per-child width x y) 55 | children 56 | (iterate inc 1))))) 57 | (draw-node canvas tree state x y))) 58 | 59 | 60 | (defn- update-state [state [label data]] 61 | (case label 62 | :examine (assoc state 63 | :current data 64 | :count (inc (:count state))) 65 | :frontier (assoc state 66 | :frontier data 67 | :current nil) 68 | state)) 69 | 70 | 71 | (defn- render-search-tree 72 | ([tree] (view-tree tree log)) 73 | ([tree log] 74 | (let [log (ref (seq log)) 75 | state (ref {:frontier [] 76 | :count 0 77 | :current nil}) 78 | sketch-tree (sketch 79 | (setup [] 80 | (doto this 81 | (size 400 400) 82 | (framerate 2) 83 | (text-font (create-font this "Helvetica Neue" 12)) 84 | smooth)) 85 | (draw [] 86 | (dosync 87 | (alter state update-state (first @log)) 88 | (alter log rest)) 89 | (doto this 90 | (background 250) 91 | (text-align LEFT) 92 | (stroke-weight 0) 93 | (fill 10) 94 | (text (str "Examined: " (:count @state)) 5 15)) 95 | (draw-tree tree this state 400)))] 96 | (view sketch-tree :size [400 400])))) 97 | 98 | 99 | (defn search-tree [tree search-fn goal] 100 | (let [log (ref [])] 101 | (search-fn tree goal log) 102 | (render-search-tree tree @log))) 103 | -------------------------------------------------------------------------------- /unit02/clojure/unit02/test/unit02/test/graphs.clj: -------------------------------------------------------------------------------- 1 | (ns unit02.test.graphs 2 | (:use [unit02.graphs]) 3 | (:use [clojure.test])) 4 | 5 | (def graph-1 6 | (make-graph [:buffalo :rochester :syracuse :binghamton :new-york-city] 7 | {[:buffalo :rochester] 75 8 | [:syracuse :rochester] 90 9 | [:ithaca :rochester] 90 10 | [:ithaca :binghamton] 50 11 | [:ithaca :syracuse] 60 12 | [:binghamton :syracuse] 75 13 | [:binghamton :rochester] 141 14 | [:binghamton :new-york-city] 176 15 | [:syracuse :new-york-city] 247 16 | [:albany :new-york-city] 150 17 | [:albany :syracuse] 150})) 18 | 19 | (deftest test-bf-paths 20 | (is (= (:path (search-breadth graph-1 :buffalo :rochester)) 21 | [:buffalo :rochester]) 22 | "Bad path for breadth-first search.") 23 | 24 | (is (= (:path (search-breadth graph-1 :buffalo :binghamton)) 25 | [:buffalo :rochester :binghamton]) 26 | "Bad path for breadth-first search.") 27 | 28 | (is (= (:path (search-breadth graph-1 :buffalo :albany)) 29 | [:buffalo :rochester :syracuse :albany]) 30 | "Bad path for breadth-first search.")) 31 | 32 | (deftest test-df-paths 33 | (is (#{[:buffalo :rochester]} 34 | (:path (search-depth graph-1 :buffalo :rochester))) 35 | "Bad path for depth-first search.") 36 | 37 | (is (#{[:binghamton :ithaca]} 38 | (:path (search-depth graph-1 :binghamton :ithaca))) 39 | "Bad path for depth-first search.") 40 | 41 | (is (#{[:buffalo :rochester :syracuse :albany] 42 | [:buffalo :rochester :syracuse :new-york-city :albany]} 43 | (:path (search-depth graph-1 :buffalo :albany))) 44 | "Bad path for depth-first search.")) 45 | -------------------------------------------------------------------------------- /unit02/clojure/unit02/test/unit02/test/trees.clj: -------------------------------------------------------------------------------- 1 | (ns unit02.test.trees 2 | (:use [unit02.trees]) 3 | (:use [clojure.test])) 4 | 5 | 6 | (def tree-1 (node :a [(node :b [(node :d []) 7 | (node :e [])]) 8 | (node :c [(node :f []) 9 | (node :g [])])])) 10 | 11 | (def tree-2 (node :a [(node :b [(node :d []) 12 | (node :e [])]) 13 | (node :q []) 14 | (node :c [(node :f [(node :x []) 15 | (node :y [(node :z [])])]) 16 | (node :g [])])])) 17 | 18 | 19 | (deftest test-bf-binary-paths 20 | (is (= (:path (search-breadth tree-1 :a)) 21 | [:a]) 22 | "Breadth-first search didn't find the path to the root node") 23 | 24 | (is (= (:path (search-breadth tree-1 :b)) 25 | [:a :b]) 26 | "Breadth-first search didn't find the path to a child node") 27 | 28 | (is (= (:path (search-breadth tree-1 :c)) 29 | [:a :c]) 30 | "Breadth-first search didn't find the path to a child node") 31 | 32 | (is (= (:path (search-breadth tree-1 :d)) 33 | [:a :b :d]) 34 | "Breadth-first search didn't find the path to a leaf node") 35 | 36 | (is (= (:path (search-breadth tree-1 :g)) 37 | [:a :c :g]) 38 | "Breadth-first search didn't find the path to a leaf node")) 39 | 40 | (deftest test-df-binary-paths 41 | (is (= (:path (search-depth tree-1 :a)) 42 | [:a]) 43 | "Depth-first search didn't find the path to the root node") 44 | 45 | (is (= (:path (search-depth tree-1 :b)) 46 | [:a :b]) 47 | "Depth-first search didn't find the path to a child node") 48 | 49 | (is (= (:path (search-depth tree-1 :c)) 50 | [:a :c]) 51 | "Depth-first search didn't find the path to a child node") 52 | 53 | (is (= (:path (search-depth tree-1 :d)) 54 | [:a :b :d]) 55 | "Depth-first search didn't find the path to a leaf node") 56 | 57 | (is (= (:path (search-depth tree-1 :g)) 58 | [:a :c :g]) 59 | "Depth-first search didn't find the path to a leaf node")) 60 | 61 | (deftest test-bf-nonbinary-paths 62 | (is (= (:path (search-breadth tree-2 :a)) 63 | [:a]) 64 | "Breadth-first search didn't find the path to the root node") 65 | 66 | (is (= (:path (search-breadth tree-2 :q)) 67 | [:a :q]) 68 | "Breadth-first search didn't find the path to a leaf node") 69 | 70 | (is (= (:path (search-breadth tree-2 :c)) 71 | [:a :c]) 72 | "Breadth-first search didn't find the path to a child node") 73 | 74 | (is (= (:path (search-breadth tree-2 :y)) 75 | [:a :c :f :y]) 76 | "Breadth-first search didn't find the path to a child node") 77 | 78 | (is (= (:path (search-breadth tree-2 :z)) 79 | [:a :c :f :y :z]) 80 | "Breadth-first search didn't find the path to a leaf node")) 81 | 82 | (deftest test-df-nonbinary-paths 83 | (is (= (:path (search-depth tree-2 :a)) 84 | [:a]) 85 | "Depth-first search didn't find the path to the root node") 86 | 87 | (is (= (:path (search-depth tree-2 :q)) 88 | [:a :q]) 89 | "Depth-first search didn't find the path to a child node") 90 | 91 | (is (= (:path (search-depth tree-2 :c)) 92 | [:a :c]) 93 | "Depth-first search didn't find the path to a child node") 94 | 95 | (is (= (:path (search-depth tree-2 :y)) 96 | [:a :c :f :y]) 97 | "Depth-first search didn't find the path to a leaf node") 98 | 99 | (is (= (:path (search-depth tree-2 :z)) 100 | [:a :c :f :y :z]) 101 | "Depth-first search didn't find the path to a leaf node")) 102 | (deftest test-bf-binary-costs 103 | (is (= (:examined (search-breadth tree-1 :a)) 1) 104 | "Breadth-first search didn't examine the correct number of nodes to find the root node") 105 | 106 | (is (= (:examined (search-breadth tree-1 :b)) 2) 107 | "Breadth-first search didn't examine the correct number of nodes to find a child node") 108 | 109 | (is (= (:examined (search-breadth tree-1 :c)) 3) 110 | "Breadth-first search didn't examine the correct number of nodes to find a child node") 111 | 112 | (is (= (:examined (search-breadth tree-1 :d)) 4) 113 | "Breadth-first search didn't examine the correct number of nodes to find a leaf node") 114 | 115 | (is (= (:examined (search-breadth tree-1 :g)) 7) 116 | "Breadth-first search didn't examine the correct number of nodes to find a leaf node")) 117 | 118 | (deftest test-df-binary-costs 119 | (is (= (:examined (search-depth tree-1 :a)) 1) 120 | "Depth-first search didn't examine the correct number of nodes to find the root node") 121 | 122 | (is (= (:examined (search-depth tree-1 :b)) 2) 123 | "Depth-first search didn't examine the correct number of nodes to find a child node") 124 | 125 | (is (= (:examined (search-depth tree-1 :c)) 5) 126 | "Depth-first search didn't examine the correct number of nodes to find a child node") 127 | 128 | (is (= (:examined (search-depth tree-1 :d)) 3) 129 | "Depth-first search didn't examine the correct number of nodes to find a leaf node") 130 | 131 | (is (= (:examined (search-depth tree-1 :g)) 7) 132 | "Depth-first search didn't examine the correct number of nodes to find a leaf node")) 133 | 134 | (deftest test-bf-nonbinary-costs 135 | (is (= (:examined (search-breadth tree-2 :a)) 1) 136 | "Breadth-first search didn't examine the correct number of nodes to find the root node") 137 | 138 | (is (= (:examined (search-breadth tree-2 :q)) 3) 139 | "Breadth-first search didn't examine the correct number of nodes to find a leaf node") 140 | 141 | (is (= (:examined (search-breadth tree-2 :c)) 4) 142 | "Breadth-first search didn't examine the correct number of nodes to find a child node") 143 | 144 | (is (= (:examined (search-breadth tree-2 :y)) 10) 145 | "Breadth-first search didn't examine the correct number of nodes to find a child node") 146 | 147 | (is (= (:examined (search-breadth tree-2 :z)) 11) 148 | "Breadth-first search didn't examine the correct number of nodes to find a leaf node")) 149 | 150 | (deftest test-df-nonbinary-costs 151 | (is (= (:examined (search-depth tree-2 :a)) 1) 152 | "Depth-first search didn't examine the correct number of nodes to find the root node") 153 | 154 | (is (= (:examined (search-depth tree-2 :q)) 5) 155 | "Depth-first search didn't examine the correct number of nodes to find a child node") 156 | 157 | (is (= (:examined (search-depth tree-2 :c)) 6) 158 | "Depth-first search didn't examine the correct number of nodes to find a child node") 159 | 160 | (is (= (:examined (search-depth tree-2 :y)) 9) 161 | "Depth-first search didn't examine the correct number of nodes to find a leaf node") 162 | 163 | (is (= (:examined (search-depth tree-2 :z)) 10) 164 | "Depth-first search didn't examine the correct number of nodes to find a leaf node")) 165 | -------------------------------------------------------------------------------- /unit02/js/search.js: -------------------------------------------------------------------------------- 1 | // To implement: 2 | // BFS, DFS, UCS, A* 3 | 4 | function tree_search(tree, source, dest, frontier) { 5 | frontier.push(source); 6 | var node; 7 | while (!frontier.empty()) { 8 | node = frontier.pop(); 9 | if (node == dest) { 10 | return node; 11 | } 12 | frontier.expand(tree[node]); 13 | } 14 | return null; 15 | } 16 | 17 | function graph_search(graph, source, dest, frontier) { 18 | frontier.push(source); 19 | var explored = []; 20 | var node; 21 | while (!frontier.empty()) { 22 | node = frontier.pop(); 23 | console.log(node); 24 | if (node == dest) { 25 | return node; 26 | } 27 | explored.push(node); 28 | var successors = []; 29 | for (neighbor in graph[node]) { 30 | if (!frontier.indexOf(neighbor) && !explored.indexOf(neighbor)) { 31 | successors.push(neighbor); 32 | } 33 | } 34 | frontier.expand(successors); 35 | } 36 | return null; 37 | } 38 | 39 | function bf_tree_search(tree, source, dest) { 40 | var queue = new Queue(); 41 | return tree_search(tree, source, dest, queue); 42 | } 43 | 44 | function df_tree_search(tree, source, dest) { 45 | var stack = new Stack(); 46 | return tree_search(tree, source, dest, stack); 47 | } 48 | 49 | function bf_graph_search(graph, source, dest) { 50 | var queue = new Queue(); 51 | return graph_search(graph, source, dest, queue); 52 | } 53 | 54 | function df_graph_search(graph, source, dest) { 55 | var stack = new Stack(); 56 | return graph_search(graph, source, dest, stack); 57 | } 58 | 59 | function uc_graph_search(graph, source, dest) { 60 | var p_queue = new PriorityQueue(); 61 | return graph_search(graph, source, dest, p_queue); 62 | } 63 | 64 | function a_star(graph, source, dest) { 65 | 66 | } 67 | -------------------------------------------------------------------------------- /unit02/js/structures.js: -------------------------------------------------------------------------------- 1 | // Stack acts as a wrapper for the Array object, adding empty() and extend() 2 | // Can probably be written in a better fashion, rather than wrapping like this 3 | 4 | function Stack() { 5 | this.array = []; 6 | this.empty = function() { 7 | return (this.array.length == 0); 8 | }; 9 | this.length = function() { 10 | return this.array.length; 11 | }; 12 | this.indexOf = function(item) { 13 | return this.array.indexOf(item); 14 | }; 15 | this.push = function(item) { 16 | return this.array.push(item); 17 | }; 18 | this.pop = function() { 19 | return this.array.pop(); 20 | }; 21 | this.extend = function(items) { 22 | for (item in items) { this.push(item); } 23 | }; 24 | this.toString = function() { 25 | return this.array.toString(); 26 | }; 27 | } 28 | 29 | function Queue() { } 30 | 31 | Queue.prototype = new Stack(); 32 | 33 | Queue.prototype.pop = function(item) { 34 | return this.array.shift(item); 35 | } 36 | 37 | function PriorityQueue(order) { 38 | this.sorted = false; 39 | this.order = order; 40 | var sort_lo = function(a, b) { return b.pri - a.pri; } 41 | var sort_hi = function(a, b) { return a.pri - b.pri; } 42 | var style; 43 | if (order.lo) { 44 | style = sort_lo; 45 | } else { 46 | style = sort_hi; 47 | } 48 | 49 | this.sort = function() { 50 | this.array.sort(style); 51 | this.sorted = true; 52 | } 53 | } 54 | 55 | PriorityQueue.prototype = new Stack(); 56 | 57 | PriorityQueue.prototype.push = function(item) { 58 | if (!item.pri || !item.obj) { throw "TypeError: Not a valid priority queue object"; } 59 | this.sorted = false; 60 | return this.array.push(item); 61 | } 62 | 63 | PriorityQueue.prototype.pop = function() { 64 | if (!this.sorted) this.sort(); 65 | return this.array.pop(); 66 | } 67 | -------------------------------------------------------------------------------- /unit02/js/test/searchtest.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /unit02/python/u02/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clarle/ai-class/44ca6d34380942600fb3a61a09e6a2dc4a4841c1/unit02/python/u02/__init__.py -------------------------------------------------------------------------------- /unit02/python/u02/graph.py: -------------------------------------------------------------------------------- 1 | # Python graph and tree data structures 2 | # Not needed with this implementation 3 | 4 | -------------------------------------------------------------------------------- /unit02/python/u02/search.py: -------------------------------------------------------------------------------- 1 | # To implement: 2 | # Frontiers for DFS, UCS, A* 3 | 4 | import heapq as hq 5 | 6 | 7 | def treeSearch(pArray, goalState, frontier, debug=True): 8 | """ TreeSearch algorithm - returns path as list of visited states 9 | pArray -- numpy array - connection matrix 10 | goalState -- self explanatory ;) 11 | frontier -- one of implementations of frontiers 12 | defines which kind of search will be performed 13 | debug -- show/don't show visited paths 14 | """ 15 | pathCounter = 0 16 | while True: 17 | # print 'frontier: ', frontier 18 | if not frontier: 19 | return None 20 | 21 | path = frontier.pop() 22 | pathCounter += 1 23 | if debug: 24 | print 'path: ', path 25 | state = path[-1] 26 | 27 | if state == goalState: 28 | print 'Unfolded paths: ', pathCounter 29 | return path 30 | 31 | for i in range(len(pArray)): 32 | if pArray[state, i] > 0: 33 | nPath = list(path) 34 | nPath.append(i) 35 | frontier.push(nPath) 36 | 37 | 38 | def graphSearch(pArray, goalState, frontier, debug=True): 39 | """ GraphSearch algorithm - returns path as list of visited states 40 | pArray -- numpy array - connection matrix 41 | goalState -- self explanatory ;) 42 | frontier -- one of implementations of frontiers 43 | defines which kind of search will be performed 44 | debug -- show/don't show visited paths 45 | """ 46 | pathCounter = 0 47 | explored = [] 48 | while True: 49 | # print 'frontier: ', frontier 50 | if not frontier: 51 | return None 52 | 53 | path = frontier.pop() 54 | pathCounter += 1 55 | if debug: 56 | print 'path: ', path 57 | state = path[-1] 58 | explored.append(state) 59 | 60 | if state == goalState: 61 | print 'Unfolded paths: ', pathCounter 62 | return path 63 | 64 | for i in range(len(pArray)): 65 | if pArray[state, i] > 0 and i not in explored: 66 | nPath = list(path) 67 | nPath.append(i) 68 | frontier.push(nPath) 69 | 70 | 71 | class BFSFrontier: 72 | """ Frontier for BFS - priority queue favorizing shorter paths """ 73 | storage = [] 74 | 75 | def __init__(self, initState): 76 | hq.heappush(self.storage, (1, [initState])) 77 | 78 | def push(self, path): 79 | hq.heappush(self.storage, (len(path), path)) 80 | 81 | def pop(self): 82 | return hq.heappop(self.storage)[1] 83 | 84 | def __repr__(self): 85 | return str(self.storage) 86 | 87 | def ___str___(self): 88 | return str(self.storage) 89 | -------------------------------------------------------------------------------- /unit02/python/u02/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clarle/ai-class/44ca6d34380942600fb3a61a09e6a2dc4a4841c1/unit02/python/u02/test/__init__.py -------------------------------------------------------------------------------- /unit02/python/u02/test/searchtest.py: -------------------------------------------------------------------------------- 1 | # Unit testing for graph algorithms 2 | import numpy as np 3 | from u02.search import treeSearch, BFSFrontier, graphSearch 4 | 5 | def generateArray(nEdge): 6 | """ return connection matrix for board of size nEdge*nEdge """ 7 | oArray = np.zeros([nEdge**2, nEdge**2]) 8 | 9 | for i in range(nEdge**2): 10 | for j in range(nEdge**2): 11 | if j == i+nEdge or j == i-nEdge or j == i+1 and i % nEdge != nEdge-1 or j == i-1 and i % nEdge != 0: # sweet... 12 | oArray[i, j] = 1 13 | 14 | return oArray 15 | 16 | def BFSTreeTest(goalState): 17 | oArray = generateArray(4) 18 | print oArray 19 | print treeSearch(oArray, goalState, BFSFrontier(0)) 20 | 21 | 22 | def BFSGraphTest(goalState): 23 | oArray = generateArray(4) 24 | print oArray 25 | print graphSearch(oArray, goalState, BFSFrontier(0)) --------------------------------------------------------------------------------