Case Study: Route Finding Lecture 6, Programmeringsteknik del A.

Slides:



Advertisements
Similar presentations
Functional Programming Lecture 10 - type checking.
Advertisements

Decision Maths Networks Kruskals Algorithm Wiltshire Networks A Network is a weighted graph, which just means there is a number associated with each.
A number of MATLAB statements that allow us to control the order in which statements are executed in a program. There are two broad categories of control.
Python Mini-Course University of Oklahoma Department of Psychology Lesson 28 Classes and Methods 6/17/09 Python Mini-Course: Lesson 28 1.
The Recursion Theorem Sipser – pages Self replication Living things are machines Living things can self-reproduce Machines cannot self reproduce.
Recursion (define tell-story (lambda () (print ‘’Once upon a time there was a mountain. ‘’) (print ‘’On the mountain, there was a temple. ‘’) (print ‘’In.
Recursion - see Recursion. RHS – SOC 2 Recursion We know that: –We can define classes –We can define methods on classes –Mehtods can call other methods.
Chapter 16 Recursion: Another Control Mechanism. "The Practice of Computing Using Python", Punch & Enbody, Copyright © 2013 Pearson Education, Inc. a.
1 Introduction to Computability Theory Lecture12: Reductions Prof. Amos Israeli.
Higher-Order Functions Koen Lindström Claessen. What is a “Higher Order” Function? A function which takes another function as a parameter. Examples map.
Algorithms and Problem Solving-1 Algorithms and Problem Solving.
0 PROGRAMMING IN HASKELL Chapter 4 - Defining Functions.
Lisp. Versions of LISP Lisp is an old language with many variants –LISP is an acronym for List Processing language Lisp is alive and well today Most modern.
16-Jun-15 Recursion. 2 Definitions I A recursive definition is a definition in which the thing being defined occurs as part of its own definition Example:
Recursion. Objectives At the conclusion of this lesson, students should be able to Explain what recursion is Design and write functions that use recursion.
Algorithms and Problem Solving. Learn about problem solving skills Explore the algorithmic approach for problem solving Learn about algorithm development.
Recursion. 2 CMPS 12B, UC Santa Cruz Solving problems by recursion How can you solve a complex problem? Devise a complex solution Break the complex problem.
Program Design and Development
0 PROGRAMMING IN HASKELL Chapter 6 - Recursive Functions Most of this should be review for you.
CS 201 Functions Debzani Deb.
Advanced Programming Andrew Black and Tim Sheard Lecture 4 Intro to Haskell.
Recursion A recursive function is a function that calls itself either directly or indirectly through another function. The problems that can be solved.
Algorithms. Introduction Before writing a program: –Have a thorough understanding of the problem –Carefully plan an approach for solving it While writing.
EPSII 59:006 Spring Topics Using TextPad If Statements Relational Operators Nested If Statements Else and Elseif Clauses Logical Functions For Loops.
Tuples and Lists Lecture 3, Programmeringsteknik del A.
Haskell Chapter 1, Part I. Highly Recommended  Learn you a Haskell for Great Good. Miran Lipovaca.
Iteration. Adding CDs to Vic Stack In many of the programs you write, you would like to have a CD on the stack before the program runs. To do this, you.
Recursion l Powerful Tool l Useful in simplifying a problem (hides details of a problem) l The ability of a function to call itself l A recursive call.
Fundamentals of Algorithms MCS - 2 Lecture # 7
School of Computer Science & Information Technology G6DICP - Lecture 9 Software Development Techniques.
Advanced Functional Programming 2009 Ulf Norell (lecture by Jean-Philippe Bernardy)
Programming for Beginners Martin Nelson Elizabeth FitzGerald Lecture 5: Software Design & Testing; Revision Session.
Day 2 – Logic and Algorithms REACHING WIDER SUMMER SCHOOL.
11 Project 2 Towers of Hanoi. 22 Towers of Hanoi is a well known puzzle that can be very difficult to solve manually but can be programmed very easily.
0 Odds and Ends in Haskell: Folding, I/O, and Functors Adapted from material by Miran Lipovaca.
Chapter 3 Top-Down Design with Functions Part II J. H. Wang ( 王正豪 ), Ph. D. Assistant Professor Dept. Computer Science and Information Engineering National.
Recursion Unit 15. Recursion: Recursion is defined as the process of a subprogram calling itself as part of the solution to a problem. It is a problem.
Graphs A ‘Graph’ is a diagram that shows how things are connected together. It makes no attempt to draw actual paths or routes and scale is generally inconsequential.
Function Definition by Cases and Recursion Lecture 2, Programmeringsteknik del A.
1 ICS103 Programming in C Lecture 8: Functions I.
Recursion on Lists Lecture 5, Programmeringsteknik del A.
Pictures: A Case Study Lecture 4, Programmeringsteknik del A.
Haskell Chapter 9. More Input and More Output  Files and Streams  Transforming Input  Not covered  brackets  command-line arguments  bytestrings.
CSE 143 Lecture 13 Recursive Backtracking slides created by Ethan Apter
Guards1. 2 Let’s test this function. Main> maxi Here is a trace of the function: n m maxi 3 2 Guards or conditions are used to express various cases.
1 Testing in Haskell: using HUnit Notes, thanks to Mark P Jones Portland State University.
Data Structures Arrays and Lists Part 2 More List Operations.
Recursion Higher Order Functions CSCE 314 Spring 2016.
Functions CSE 1310 – Introduction to Computers and Programming Vassilis Athitsos University of Texas at Arlington 1.
Functional Programming Lecture 3 - Lists Muffy Calder.
CSCI 161 Lecture 3 Martin van Bommel. Operating System Program that acts as interface to other software and the underlying hardware Operating System Utilities.
LECTURE 5 Scanning. SYNTAX ANALYSIS We know from our previous lectures that the process of verifying the syntax of the program is performed in two stages:
CS Class 04 Topics  Selection statement – IF  Expressions  More practice writing simple C++ programs Announcements  Read pages for next.
Recursion. Objectives At the conclusion of this lesson, students should be able to Explain what recursion is Design and write functions that use recursion.
Today… Modularity, or Writing Functions. Winter 2016CISC101 - Prof. McLeod1.
Introduction to Computer Programming Concepts M. Uyguroğlu R. Uyguroğlu.
Advanced Functional Programming 2010
Polymorphic Functions
Recursion Version 1.0.
Types CSCE 314 Spring 2016.
A lightening tour in 45 minutes
Programming Problem steps must be able to be fully & unambiguously described Problem types; Can be clearly described Cannot be clearly described (e.g.
Higher-Order Functions
Data Structures Recursion CIS265/506: Chapter 06 - Recursion.
PROGRAMMING IN HASKELL
Networks Kruskal’s Algorithm
CSCE 314: Programming Languages Dr. Dylan Shell
Lecture 5 Scanning.
PROGRAMMING IN HASKELL
Presentation transcript:

Case Study: Route Finding Lecture 6, Programmeringsteknik del A.

The Problem GöteborgBorås Jönköping ÖrebroStockholm Which is the shortest route to Stockholm?

The Program > route ”Göteborg” ”Stockholm” 71 Borås 160 Jönköping 324 Norrköping 495 Stockholm

The Map Data Keep the map data in a file, so it is easy to modify. GöteborgBorås71 BoråsJönköping89 JönköpingNorrköping164 NorrköpingÖrebro105 NorrköpingUppsala243 NorrköpingVästerås153 Norrköping Stockholm roads

Overall Plan We begin with a top-down design: Read the names of the starting point and end point. Read the roads data. Find the shortest route. Display the result.

Main Program main :: IO () main = do(from, to) <- readArguments roads <- readRoads putStr (formatRoute (route roads from to)) What are the types here? readArguments :: IO (Town, Town) readRoads :: IO [Road] route :: [Road] -> Town -> Town -> Route formatRoute :: Route -> String The ”main program” is always a command called main.

Top-Down Design We have broken the problem down into parts, and written the top-level program. We go on to solve each part. When we put the solutions together, we obtain a complete program.

Reading the Arguments Haskell programs communicate with UNIX using a standard library called System. In this library we find getArgs :: IO [String] To use it, we must add import System at the top of our program. A list of the arguments on the command line.

readArguments Let us represent towns by strings: type Town = String readArguments :: IO (Town, Town) readArguments = do[from,to] <- getArgs return (from, to)

The Road Data The roads file contains: GöteborgBorås71 BoråsJönköping89 JönköpingNorrköping164 NorrköpingÖrebro In our program, we represent this information in a form which is convenient to manipulate: [(”Göteborg”, ”Borås”, 71), (”Borås”, ”Jönköping”, 89), …]

The Road Type We make an appropriate type definition: type Road = (Town, Town, Int) Now we must define readRoads :: IO [Road]

Reading the Roads Data Break the problem into simpler stages: GöteborgBorås71 BoråsJönköping89... [”GöteborgBorås71”, ”BoråsJönköping89”, …] Break the input into a list of lines.

Reading the Roads Data Ctd Break the problem into simpler stages: [”GöteborgBorås71”, ”BoråsJönköping89”, …] Break each line into a list of ”words”. [[”Göteborg”, ”Borås”, ”71”], [”Borås”, ”Jönköping”, ”89”], …]

Reading the Roads Data Ctd Break the problem into simpler stages: Turn each list of words into a road. [[” Göteborg”, ”Borås”, ”71”], [”Borås”, ”Jönköping”, ”89”], …] [(” Göteborg”, ”Borås”, 71), (”Borås”, ”Jönköping”, 89), …]

Breaking a String into Lines ”a\nb\nc”[”a”, ”b”, ”c”] We must go through the list -- but a list comprehension won’t help. We could try recursion -- but it still isn’t easy. Can we solve a simpler problem?

Taking One Line from a String ”a\nb\nc””a” \n...ba ”” a...\nbab takeLine :: String -> String takeLine (’\n’:xs) = ”” takeLine (x : xs) = x : takeLine xs takeLine ”” = ””

Dropping One Line from a String ”a\nb\nc””b\nc” \n...ba a \nb dropLine :: String -> String dropLine (’\n’:xs) = xs dropLine (x : xs) = dropLine xs dropLine ”” = ””...ba

Splitting a String into Lines ”ab\ncd\nef” ”ab” ”cd\nef” [”cd”, ”ef”] [”ab”, ”cd”, ”ef”] takeLinedropLine lines :

Defining lines lines :: String -> [String] lines [] = [] lines xs = takeLine xs : lines (dropLine xs) This is actually a standard function…!

Defining readRoads Reminder:type Road = (Town, Town, Int) readRoads :: IO [Road] readRoads = do xs <- readFile ”roads” return [road (words line) | line <- lines xs] road :: [String] -> Road road [from, to, dist] = (from, to, read dist) For each line Split into words (very like lines) Convert to a road Convert a String to e.g. a number.

Reminder: The Main Program main :: IO () main = do(from, to) <- readArguments roads <- readRoads putStr (formatRoute (route roads from to)) What remains to define? route :: [Road] -> Town -> Town -> Route formatRoute :: Route -> String

Representing a Route What do we need to know about a route? Where it leads from. Where it leads to. How long it is (so we can choose the shorter of two alternatives). Which towns it leads through (so we can print it out). 71 Borås 160 Jönköping 324 Norrköping 495 Stockholm

Representing a Route: First Try 71 Borås 160 Jönköping 324 Norrköping 495 Stockholm type Route = (Town, Town, Int, [(Town, Int)]) example = (”Göteborg”, ”Stockholm”, 495, [(”Borås”, 71), (”Jönköping”, 160), (”Norrköping”, 324), (”Stockholm”, 495)])

Formatting a Route Once again, solve the problem in stages. formatRoute :: Route -> String formatRoute (from, to, dist, stages) = unlines [formatStage s | s <- stages] Join up the lines with line breaks. Format one stage of the route.

Formatting a Stage formatStage :: (String, Int) -> String First try:formatStage (t, d) = show d ++ ” ” ++ t Output: 71 Borås 160 Jönköping 324 Norrköping 495 Stockholm

Padding with Spaces Second try: formatStage (t, d) = pad 5 (show d) ++ ” ” ++ t pad :: Int -> String -> String pad n s = [’ ’ | i<-[length s+1..n]] ++ s As many spaces as are needed to fill the gap between length s and n.

Joining Up Lines ”ab””ef””cd” ”cd\nef\n” ”ab\ncd\nef\n” unlines :: [String] -> String unlines (x : xs) = x ++ ”\n” ++ unlines xs unlines [] = [] Another standard function.

Remaining Problem All that remains to do is to define route :: [Road] -> Town -> Town -> Route This is the hard part!

How Can We Get from Göteborg to Stockholm? GöteborgBorås Jönköping ÖrebroStockholm Find the best routes from Örebro and Borås, add the distance from Göteborg, and choose the best.

Choosing the Better of Two Routes Which choice is better? A shorter route is better than a longer one. If two routes have the same length, then the one with more stages is better (because it gives a more detailed route description). (”Goteborg”, ”Stockholm”, 496, [(”Orebro”,285), (”Stockholm”,496)]) is better than (”Goteborg”, ”Stockholm”, 496, [(”Stockholm”, 496)])

better better :: Route -> Route -> Route better (from,to,dist,stgs) (from',to',dist',stgs') | dist < dist' = (from,to,dist,stgs) | dist > dist' = (from',to',dist',stgs') | length stgs > length stgs' = (from,to,dist,stgs) | length stgs <= length stgs' = (from',to',dist',stgs') best :: [Route] -> Route best [r] = r best (r : rs) = better r (best rs) Choose the best of many routes.

Joining Routes Together We will need to combine a one-stage route (e.g. Goteborg to Boras) with the route onwards. How can we join two routes? The first route must end where the second begins. We add the distances. We must adjust the stages in the second route, by adding the length of the first route to their distances.

Example of Joining Routes Joining (”Goteborg”, ”Boras”, 71, [(”Boras”, 71)]) with (”Boras”, ”Jonkoping”, 89, [(”Jonkoping”, 89)]) should give (”Goteborg”, ”Jonkoping”, 160, [(”Boras”, 71), (”Jonkoping”, 160)]) First stage unchanged. Second stage with adjusted distance.

joinRoutes joinRoutes :: Route -> Route -> Route joinRoutes (from,to,dist,stgs) (from',to',dist',stgs') | to==from' = (from,to',dist+dist', stgs++[(c,d+dist) | (c,d)<-stgs']) For each stage in the second route... Adjust the distance.

Making a One Stage Route We will need to convert a road into a one-stage route, so that we can use joinRoute on it. Recalltype Road = (Town, Town, Int) roadRoute :: Road -> Route roadRoute (from,to,dist) = (from,to,dist,[(to,dist)]) Example: roadRoute (”Goteborg”, ”Boras”, 71) (”Goteborg”, ”Boras”, 71, [(”Boras”, 71)])

Roads Go Both Ways To keep the route finder simple, for every road in the roads data, we add a road in the opposite direction. bothWays :: [Road] -> [Road] bothWays roads = roads ++ [(to,from,dist) | (from,to,dist) <- roads]

Programming the Route Finder route :: [Road] -> City -> City -> Route route roads from to = best [joinRoutes (roadRoute road) (route roads (endPoint road) to) | road <- bothWays roads, startPoint road == from] startPoint, endPoint :: Road -> Town startPoint (from, to, dist) = from endPoint (from, to, dist) = to Useful auxiliary functions.

The Base Case When we are already in Stockholm, the route there is trivial! Add before the recursive case: route roads from to | from == to = trivialRoute from We must be able to create a trivial route: trivialRoute :: Town -> Route trivialRoute t = (t, t, 0, [])

Testing the Program > runhugs Route.hs Goteborg Stockholm ERROR: Control stack overflow. Every time hugs calls a function, it must record what it was doing beforehand, so as to be able to continue when the function call is complete. Imagine that hugs writes a little note. These notes are piled up on the `control stack’. Now the stack is overfull -- because we have a recursion without end.

Understanding the Recursion GöteborgBorås Jönköping ÖrebroStockholm What is getting smaller? Which are the best routes from Boras to Stockholm?

Avoiding Circles GöteborgBorås Jönköping ÖrebroStockholm Find the best route from Boras to Stockholm avoiding Goteborg. Find the best route from Jonkoping to Stockholm avoiding Goteborg and Boras.

Finding Routes Avoiding Towns Define routeAvoiding :: [Town] -> [Road] -> Town -> Town -> Route Avoiding these towns. Then route roads from to = routeAvoiding [] roads from to

routeAvoiding routeAvoiding avoid roads from to | from == to = trivialRoute from | otherwise = best [joinRoutes (roadRoute road) (routeAvoiding (from : avoid) roads (endPoint road) to) | road <- bothWays roads, startPoint road == from, not (endPoint road `elem` avoid)] Avoid returning to from. Add another condition: do not follow a road to a town to be avoided.

A New Problem > runhugs Route.hs Goteborg Stockholm Program error: {best []} It is possible that every road from a town leads to a town we should avoid! Then no route can be found!

One Solution: Changing the Route Representation We need to be able to represent an invalid route. Redefine type Route = (Bool, … as before …) invalidRoute :: Route invalidRoute = (False, ””, ””, 0, []) True if the route is valid.

Adjust The Functions on Routes formatRoute (False, _, _, _, _) = ”No valid route” formatRoute (True, …) = …as before… better (True, …) (True, …) = …as before… better (False, _, _, _, _) r = r better r (False, _, _, _, _) = r best [] = invalidRouteand so on... Always prefer a valid route.

At Last, It Works! > runhugs Route.hs Goteborg Stockholm 71 Borås 160 Jönköping 324 Norrköping 495 Stockholm

Refinements The program works, but it is slow. As we add more roads, it becomes much much slower. Goteborg Orebro Stockholm Jonkoping It is much better to work out all the shortest routes, between every pair of towns, at the same time!

Lessons Top-down design enables us to solve difficult problems in many stages. Lists are a natural way to represent much real world data. Recursion is a powerful tool for solving difficult problems. ’Obvious’ solutions can have subtle errors. Algorithm design is a subtle art: there is a lot to learn!