Presentation is loading. Please wait.

Presentation is loading. Please wait.

Induction & Recursion Discrete Mathematics and Its Applications Baojian Hua

Similar presentations


Presentation on theme: "Induction & Recursion Discrete Mathematics and Its Applications Baojian Hua"— Presentation transcript:

1 Induction & Recursion Discrete Mathematics and Its Applications Baojian Hua bjhua@ustc.edu.cn

2 Our Goal How to write data types (math.) via inductive definitions? How to turn inductive definitions into data structures? How to write algorithms operated on these data structures? How to argue the correctness of the algorithms?

3 Dead-simple Example: nat // Data types: 1. A zero, or 2. a number follow another nat. // Rewrite into inductive definition form: nat -> Zero -> Succ nat // Q: how to turn this into data structures?

4 Tagged Union in C // Rewrite into inductive definition form: nat -> Zero -> Succ nat typedef natStruct *nat; struct natStruct { enum natKind {Zero, Succ} kind; union { nat n; } u; }; u kind

5 Interface #ifndef NAT_H #define NAT_H typedef natStruct *nat; struct natStruct { enum natKind {Zero, Succ} kind; union { nat n; } u; };

6 Interface Continued nat newNatZero (); nat newNatSucc (nat n); nat natAdd (nat n1, nat n2); int natToInt (nat n); #endif

7 Generate nat nat newNatZero () { nat t = (nat)malloc (sizeof (*t)); t->kind = Zero; return t; } nat newNatSucc (nat n) { nat t = (nat)malloc (sizeof (*t)); t->kind = Succ; t->u.n = n; return t; } u kind nat -> Zero -> Succ nat

8 Example: 3 3: Succ(Succ(Succ(Zero))); three = newNatSucc( newNatSucc( newNatZero()))); u kind u u u three

9 Example: 3 3: Succ(Succ(Succ(Zero))); three = newNatSucc( newNatSucc( newNatZero()))); u Zero u Succ u u three

10 Addition n1 ⊕ n2 = { n2, if n1==Zero; { Succ (m ⊕ n2), if n1==Succ(m). nat natAdd (nat n1, nat n2) { switch (n1->kind) { case Zero: return n2; case Succ: return newNatSucc (natAdd (n1->u.n, n2)); default: error (…); } return NULL; } u kind

11 toInt toInt(n) = { 0, if n==Zero; { 1+toInt(m), if n1==Succ(m). int natToInt (nat n) { switch (n->kind) { case Zero: return 0; case Succ: return 1+(natToInt(n->u.n)); default: error (…); } return -1; } u kind

12 Linked List // Data types: 1. An empty list, or 2. a node, followed by another list. // Rewrite into inductive definition form: list -> Empty -> Cons T, list // Q: how to turn this into data structures?

13 Tagged Union in C // Rewrite into inductive definition form: list -> Empty -> Cons (T, list) typedef listStruct *list; struct listStruct { enum listKind {Empty, Cons} kind; union { struct { void *data; list next; } node; } u; }; u kind

14 Interface #ifndef LIST_H #define LIST_H typedef listStruct *list; struct listStruct { enum listKind {Empty, Cons} kind; union { struct { void *data; list next; } node; } u; };

15 Interface Continued list newListEmpty (); list newListCons (void *data, list next); int length (list l); list insertHead (list l, void *data); list insertTail (list l, void *data); #endif

16 Generate a List list newListEmpty () { list t = (list)malloc (sizeof (*t)); t->kind = Empty; return t; } list newListCons (void *data, list l) { list t = (list)malloc (sizeof (*t)); t->kind = Cons; t->u.node.data = data; t->u.node.next = l; return t; } u kind list -> Empty -> Cons (T, list)

17 Length length(l) = { 0, if l==Empty; { 1+length(m), if l==Cons (T, m) int length (list l) { switch (l->kind) { case Empty: return 0; case Cons: return 1 + length(l->u.node.next); default: error (…); } return -1; } u kind

18 Insert at Head f(d, l) = Cons (d, l) list insertHead (void *d, list l) { return newListCons (d, l); } u kind

19 Insert at Tail f(d, l) = { Cons (d, l), if l==Empty; { Cons (x, f(d, m)), if l==Cons(x, m). list insertTail (void *d, list l) { switch (l->kind) { case Empty: return newListCons (d, l); case Cons: return newListCons (l->u.node.data, insertTail (d, l->u.node.next)); default: error (…); } return NULL; } u kind How can you argue this is correct?

20 How does it Work? u Empty 3 Cons 6 4 list insert 9 at tail u Empty 9 Cons 3 6 newList 4 Cons

21 Persistent Data Structures Data structures never change once created you may want to compare the list here with the ones we discussed in Lab #1 Good for many purpose reason the correctness of the code local debugging important in emerging fields such as concurrent programming or multi-core

22 Functional Programming Stemming from mathematics Church and Turing, etc. Programming (and the resulting code) just behaves like writing mathematical functions persistent data structures h recursive functions An important programming idioms I personally love it more than procedural, OO, generic, etc. Stepping into industry Such as F# from M … S …

23 Summary Inductive Def ’ == Persistent DS Deduction == Recursion Math Proof == Program Correctness

24 Local Class Hierarchy abstract class List {} class ListEmpty extends List {} class ListCons extends List { X data; List next; ListCons (X data, List next) {…} }

25 Ugly Cast class Match { public int size (List l) { if (l instanceof ListEmpty ) return 0; else if (l instanceof ListCons ) …; else …; } // Or the visitor pattern

26 In C++ template class List { public: virtual void foo()=0; }; template class ListEmpty: public List { public: void foo (){}; };

27 In C++ template class ListCons: public List { public: X data; List next; ListCons(X adata, List anext) :data(adata), next(anext) {}; void foo () {}; }


Download ppt "Induction & Recursion Discrete Mathematics and Its Applications Baojian Hua"

Similar presentations


Ads by Google