Menú del dı́a Resolviendo problemas del TP 1 Lenguaje C++ STL C++ STL - Pilas y Colas C++ STL - Conjuntos y Diccionarios Trucos y Tips 2 Mediciones 3 Gráficos Laboratorio de Algoritmos y Estructuras de Datos III Departamento de Computación Facultad de Ciencias Exactas y Naturales Universidad de Buenos Aires 27 de Agosto de 2010 Labo de Algo III (Sabi) Resolviendo problemas del TP Lenguaje 27 de Agosto de 2010 1 / 56 Labo de Algo III (Sabi) C++ STL Resolviendo problemas del TP Lenguaje C++ STL 27 de Agosto de 2010 2 / 56 C++ STL C++ STL - Estructuras de datos Estructuras de datos: Arrays dimensionables (de longitud variable) (vector) Pilas (stack) La Standard Template Library es un conjunto de estructuras y algoritmos comunes, que ya están hechos. Colas (queue) Documentación: http://www.sgi.com/tech/stl/, http://www.cppreference.com/. Conjunto y Diccionario (sobre árbol, sobre hash) (set, map, hash set, hash map) Conjunto sobre bits (bitset) Multiconjuntos y Multidiccionarios. (multiset, multimap, hash multiset, hash multimap) Listas enlazadas (doble y simplemente enlazadas) (list y slist) Heap o parva (priority queue) Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 3 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 4 / 56 Lenguaje C++ STL Lenguaje C++ STL C++ STL - Algoritmos Importante Algoritmos: Ordenamiento (sort, merge, make heap, sort heap, etc) Mirar la documentación Para buscar la especificación de las operaciones Búsqueda secuencial o binaria (find, binary search, lower bound, upper bound) Para buscar la complejidad de las operaciones Reduce (min element, max element) Para ver si está implementada la operación que necesitamos de la estructura (o un conjuntito que lo realice). Permutaciones (next permutation, prev permutation, accumulate) Otros: reverse, rotate, unique Labo de Algo III (Sabi) Resolviendo problemas del TP Lenguaje 27 de Agosto de 2010 5 / 56 Labo de Algo III (Sabi) C++ STL - Pilas y Colas Resolviendo problemas del TP Lenguaje 27 de Agosto de 2010 6 / 56 C++ STL - Pilas y Colas Pilas Colas Una pila es una colección de elementos con orden con estas operaciones: Una cola es una colección de elementos con orden con estas operaciones: push: Agrega un elemento encima de todos los demás. push: Agrega un elemento detrás de todos los demás. pop: Retira el elemento de arriba de todo. pop: Retira el elemento de adelante. top: Devuelve el elemento de arriba de todo. front: Devuelve el elemento de adelante. empty: Dice si la pila está vacı́a. empty: Dice si la cola está vacı́a. En C++: En C++: stack<int> s: s.push(3); s.push(1); s.push(2); while(!s.empty()) { cout << s.top() << " "; s.pop(); } queue<int> q: q.push(3); q.push(1); q.push(2); while(!q.empty()) { cout << q.front() << " "; q.pop(); } Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 7 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 8 / 56 Lenguaje C++ STL - Conjuntos y Diccionarios Lenguaje Conjuntos C++ STL - Conjuntos y Diccionarios C++ STL con pretenciones Un conjunto es una colección de elementos distintos y sin orden con estas operaciones: insert: Agrega un elemento al conjunto (si no está). Magia oculta find: Devuelve un iterador al elemento buscado. ¡Los conjuntos no sólo sirven para insertar y preguntar pertenece! erase: Elimina un elemento del conjunto. ¡Los iteradores no sólo sirven para iterar! empty: Dice si el conjunto está vacı́o. Los algoritmos pre-hechos, aunque sean fáciles de programar por nosotros mismos, alivianan el código (menos informe, menos debuggeo, menos corrección...). En C++: set<int> c: c.insert(1); c.insert(4); c.insert(2); c.insert(3); for(set<int>::iterator it = c.begin(); it != c.end(); ++it) { cout << *it << " "; } Labo de Algo III (Sabi) Resolviendo problemas del TP Lenguaje 27 de Agosto de 2010 9 / 56 Labo de Algo III (Sabi) C++ STL - Conjuntos y Diccionarios Resolviendo problemas del TP Lenguaje C++ STL - Iteradores 27 de Agosto de 2010 10 / 56 C++ STL - Conjuntos y Diccionarios C++ STL - Iteradores - Ejemplo Tenemos un vector<int> v ordenado con los siguientes elementos: v = 3 5 5 6 8 8 10 Las funciones lower bound y upper bound permiten encontrar un elemento o un rango dentro de un contenedor ordenado: lower bound dice el menor lugar donde se puede insertar ordenado un elemento dado. Un vector<> o array de C con sus elementos ordenados. upper bound dice el mayor lugar donde se puede insertar ordenado un elemento dado. Un set<>... ...y sus variantes: map<>, multiset<>, multimap<> Obs: Si el elemento no está, ambas dan el mismo resultado. lower bound(v.begin(), v.end(), 5) = el iterador v.begin()+1. upper bound(v.begin(), v.end(), 5) = el iterador v.begin()+3. Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 11 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 12 / 56 Lenguaje C++ STL - Conjuntos y Diccionarios Lenguaje C++ STL - Iteradores - Ejemplo C++ STL - Conjuntos y Diccionarios C++ STL - Iteradores ¿...y si quiero el último elemento menor o menor o igual? v = 3 5 5 6 8 8 10 (abreviando la escritura) ¡Ojo! lower bound(7) = v+4. La pregunta no está bien definida. El lugar del último elemento menor (o igual) que 2 no existe. upper bound(7) = v+4. Observación: lower bound(x) da el lugar del primer elemento mayor o igual que x. upper bound(x) da el lugar del primer elemento mayor que x. Resolviendo problemas del TP Lenguaje 27 de Agosto de 2010 Si existen, entonces: El lugar del último elemento menor que x es lower bound(x)-1 El lugar del último elemento menor o igual que x es upper bound(x)-1 ¿...y si quiero el último elemento menor o menor o igual? Labo de Algo III (Sabi) v = 3 5 5 6 8 8 10 13 / 56 Labo de Algo III (Sabi) C++ STL - Conjuntos y Diccionarios Resolviendo problemas del TP Lenguaje Multi-conjuntos 27 de Agosto de 2010 14 / 56 Trucos y Tips Modularización Un multiconjunto es una colección de elementos sin orden, pontencialmente repetidos con las mismas operaciones que un conjunto: insert: Agrega un elemento al conjunto (aún si ya está). Modularizar el código no es solamente dividirlo en clases/objetos/módulos. También se pueden atomizar las responsabilidades, separando: find: Devuelve un iterador al elemento buscado. erase: Elimina un elemento del conjunto. empty: Dice si el conjunto está vacı́o. Algoritmos Estructuras de datos Estructuras de control Definiciones propias del problema Entidades del problema En C++: multiset<int> mc: mc.insert(1); mc.insert(2); mc.insert(3); c.insert(2); ¿Cómo queda el multiconjunto después de ejecutar mc.erase(2);? mc.erase(mc.find(2)); vs. mc.erase(2); Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 15 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 16 / 56 Lenguaje Trucos y Tips Lenguaje Sobremodularización Ejemplo - Multiplicación de matrices La multiplicación de matrices cuadradas de n × n se define como ¡Alerta! La sobremodularización1 Trucos y Tips resi,j = es perjudicial para la salud. n X (ai,k · bk,j ) k=1 Para representar una matriz, usamos un arreglo bidimensional, o un arreglo de arreglos (vector<vector<int> >). Ahora sı́, veamos un ejemplo. 1 Si esta palabra existiera Labo de Algo III (Sabi) Resolviendo problemas del TP Lenguaje 27 de Agosto de 2010 17 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP Trucos y Tips Lenguaje 27 de Agosto de 2010 18 / 56 Trucos y Tips Ejemplo - Multiplicación de matrices cuadradas Tips - typedef vector<vector<int> > mult(const vector<vector<int> > &a, const vector<vector<int> > &b) { int n = a.size(); vector<vector<int> > res(n, vector<int>(n, 0)); for(int i = 0; i < n; i++) { for(int j = 0; j < n; i++) { for(int k = 0; k < n; k++) { res[i][j] += a[i][k] * b[k][j]; } } } return res; } La instrucción typedef permite renombrar un tipo de datos de C++. Por ejemplo: Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 typedef vector<int> vint; typedef vector<vint> vvint; Con esto la declaración es mucho más simple: vvint mult(const vvint &a, const vvint &b) { int n = a.size(); vvint res(n, vint(n, 0)); ... Esto representa la estrucutra de datos de una matriz. 19 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 20 / 56 Lenguaje Trucos y Tips Lenguaje Ejemplo - Multiplicación de matrices cuadradas Trucos y Tips Tips - define La instrución for es a veces demasiado expresiva. vvint mult(const vvint &a, const vvint &b) { int n = a.size(); vvint res(n, vint(n, 0)); for(int i = 0; i < n; i++) { for(int j = 0; j < n; i++) { for(int k = 0; k < n; k++) { res[i][j] += a[i][k] * b[k][j]; } } } return res; } Es común recorrer un rango de números de 0 a n − 1. #define es nuestro amigo. #define forn(i, n) for(int i = 0; i < (int)(n); ++i) Este macro evita escribir 3 veces la variable de control: vvint mult(const vvint &a, const vvint &b) { int n = a.size(); vvint res(n, vint(n, 0)); forn(i, n) forn(j, n) forn(k, n) { res[i][j] += a[i][k] * b[k][j]; } return res; } ¿Alguien notó el bug? Esto modulariza una estructura de control. Labo de Algo III (Sabi) Resolviendo problemas del TP Lenguaje 27 de Agosto de 2010 21 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP Trucos y Tips Lenguaje Tips - define 27 de Agosto de 2010 22 / 56 27 de Agosto de 2010 24 / 56 Trucos y Tips Ejemplo - Mergesort Si tuviéramos una lista definida como: void ordena(int v[], int a, int b) { if (a == b) return; int c = (a+b)/2; ordena(v, a, c-1); ordena(v, c, b); /* Merge */ ... /* STL: inplace_merge(...); */ } struct nodo { nodo* next; int elem; } Recorrer toda la lista se podrı́a hacer de la siguiente forma: for(nodo* i = lista; i != NULL; i = i->next) { ... } Esta estructura de control también se puede separar: ¿Alguien notó el bug? #define forlst(i, l) for(nodo* i = (l); i != NULL; i = i->next) Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 23 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP Lenguaje Trucos y Tips Lenguaje Tips - Rangos y fronteras Ejemplo - Mergesort Siempre los rangos se nombran cerrado a izquierda y abierto a derecha: [a, b). void ordena(int v[], int a, int b) { if (b-a <= 1) return; int c = (a+b)/2; ordena(v, a, c); ordena(v, c, b); /* Merge */ ... /* STL: inplace_merge(...); */ } ¿Siempre? Sı́ ¿De verdad? Sı́ ¿Posta? Sı́ Jefe de los minisuper Tamaño Subrangos Rango vacı́o Labo de Algo III (Sabi) [a, b] b−a+1 [a, c − 1] y [c, b] [a, c] y [c + 1, b] [a, a − 1] Resolviendo problemas del TP Lenguaje Trucos y Tips [a, b) b−a [a, c) y [c, b) [a, a) 27 de Agosto de 2010 25 / 56 Labo de Algo III (Sabi) Trucos y Tips Resolviendo problemas del TP Lenguaje Ejemplo - Iteradores 27 de Agosto de 2010 26 / 56 Trucos y Tips Ejemplo - Iteradores Todos los contenedores de C++ permiten ser iterados. Siempre los rangos se nombran cerrado a izquierda y abierto a derecha: [a, b). Mostrar un diccionario de string en int: void show(const map<string, int> &v) { for(map<string, int>::const_iterator it = v.begin(); it != v. end(); ++it) { cout << it->first << " --> " << it->second << endl; } } En iteradores, los rangos son desde X.begin() hasta X.end(). Mostrar un arreglo de números: void show(vector<int> v) { vector<int>::iterator it; for(it = v.begin(); it != v.end(); ++it) cout << *it << " "; cout << endl; } Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 27 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 28 / 56 Lenguaje Trucos y Tips Lenguaje Tips - define Trucos y Tips Tips - define Otras estructuras de control usuales: Es común iterar toda una estructura. #define forn(i, n) for(int i = 0; i < (int)(n); ++i) #define dforn(i, n) for(int i = (int)(n)-1; i >= 0; --i) #define es nuestro amigo. #define forall(it, X) for(typeof((X).begin()) it = (X).begin(); it != (X).end(); ++it) #define forsn(i, s, n) for(int i=(s); i<(int)(n); ++i) #define dforsn(i, s, n) for(int i=(int)(n)-1;i>=(s);--i) Esto modulariza una estructura de control. #define it #define (); void show(const map<string, int> &v) { forall(it, v) { cout << it->first << " --> " << it->second << endl; } } Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 forall(it, X) for(typeof((X).begin()) it = (X).begin(); != (X).end(); ++it) dforall(it, X) for(typeof((X).rbegin()) it = (X).rbegin it != (X).rend(); ++it) ATENCIÓN: Leer el capı́tulo del preprocesador del manual de gcc: http://gcc.gnu.org/onlinedocs/cpp/Macros.html, en especial “Macro Pitfalls”. 29 / 56 Labo de Algo III (Sabi) Mediciones Resolviendo problemas del TP 27 de Agosto de 2010 30 / 56 Mediciones Errores Hay que medir el comportamiento del algoritmo. Definición (Error de apreciación) Los errores de apreciación son los que resultan de obtener (o apreciar) el valor medido en el instrumento. Problemas propios de la medición: Preparar un experimento que permita medir el valor buscado. “Usualmente” los instrumentos digitales no tienen error de apreciación. Errores del instrumento de medición (de apreciación, sistemáticos, aleatorios, etc.). Definición (Resolución del instrumento) Resolución del instrumento La resolución del instrumento (o resolución máxima) es la mı́nima unidad que es capaz de medir el instrumento. Ejemplo: con una regla milimetrada no se puede medir mejor que 1mm. Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 31 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 32 / 56 Mediciones Mediciones Problemas de resolución Errores aleatorios Hay errores que dependen de muchos otros factores externos, y los consideramos aleatorios (interrupciones del sistema operativo, hits y misses en cache). Experimento Correremos 300 veces el mismo caso de prueba y lo mediremos todas las veces independientemente. Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 33 / 56 Labo de Algo III (Sabi) Mediciones 27 de Agosto de 2010 34 / 56 27 de Agosto de 2010 36 / 56 Mediciones Histograma Labo de Algo III (Sabi) Resolviendo problemas del TP Diagrama de caja Resolviendo problemas del TP 27 de Agosto de 2010 35 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP Mediciones Mediciones Alternativa Medir tiempo trae problemas de medición. Alternativa: “Medir” cantidad de operaciones Algorithm 2.1: factorial(n) res ← 1 inc(cont) for i ← 1 to n res ← res ∗ i do inc(cont) return (res) Resultado: Según esta medición de cantidad de operaciones factorial es O(n). ¿O(n)? ¿Seguro? Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 37 / 56 Labo de Algo III (Sabi) Mediciones Resolviendo problemas del TP 27 de Agosto de 2010 38 / 56 Mediciones Cantidad de operaciones Conclusiones Pros: Mide la cantidad de operaciones en el modelo. No hay una única forma de medir el comportamiento. No tiene errores de medición (casi). Las mediciones reales tienen error. No se puede medir cualquier cosa. Contras: Se deben contemplar los problemas de cada medición y llegar a una aproximación del valor. No permite contrastar el modelo con el comportamiento en la máquina real. No permite detectar errores en la complejidad real del algoritmo. Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 39 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 40 / 56 Gráficos Gráficos Ejemplos Ejemplos Debe tener una escala Los ejes deben tener rótulos Se deben incluir referencias claras Los ejes deben tener unidades No usar colores similares. No usar colores si se imprime en blanco y negro. Se deben distinguir las mediciones Se deben incluir referencias Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 41 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP Gráficos 27 de Agosto de 2010 42 / 56 27 de Agosto de 2010 44 / 56 Gráficos Ejemplos Gráficos Para qué sirve un gráfico: Comparar, cuantitativamente, funciones. La interpolación no siempre refleja mediciones Verificar correlación entre dos variables. Para qué NO sirve un gráfico: Se deben distinguir las mediciones Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 43 / 56 Demostrar propiedades matemáticas. Calcular complejidades. Labo de Algo III (Sabi) Resolviendo problemas del TP Gráficos Gráficos Correlación Correlación ¿Cómo se contrastan los datos con los valores teóricos? De la definición de f (n) ∈ O(g (n)): ∃k ∈ R+, n0 ∈ N : ∀n, (n0 < n) ⇒ f (n) ≤ k · g (n) Atención Los gráficos pueden ser engañosos. Podemos graficar: Las deducciones del gráfico sólo son ciertas dentro de los lı́mites del gráfico, y para los valores observados. f (n) k · g (n) y verificar que a partir de cierto n0 , f (n) está debajo de k · g (n). Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 45 / 56 Labo de Algo III (Sabi) Gráficos 27 de Agosto de 2010 46 / 56 27 de Agosto de 2010 48 / 56 Gráficos Escala lineal Labo de Algo III (Sabi) Resolviendo problemas del TP Escala logarı́tmica Resolviendo problemas del TP 27 de Agosto de 2010 47 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP Gráficos Gráficos Recordemos Ejemplos Algorithm 3.1: SlowSort(vector < Nat > v []) n ← v .size() for k ← 1 to n do for i ← 1 to n − 1 if v [i] > v [i + 1] do then swap(v [i], v [i + 1]) return Complejidad temporal en el modelo uniforme: O(n2 ) Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 49 / 56 Labo de Algo III (Sabi) Gráficos Resolviendo problemas del TP 27 de Agosto de 2010 50 / 56 27 de Agosto de 2010 52 / 56 Gráficos Constraste con lo teórico Constraste con lo teórico Debemos encontrar una constante k para que k · n2 se mantenga por encima del gráfico del algoritmo SlowSort. Se puede buscar a mano Se puede ajustar la curva (n2 ) a los datos. Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 51 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP Gráficos Gráficos Software disponible Ejemplo Algorithm 3.2: Factorizar(n) Existe mucho software para hacer gráficos y análisis de datos d ←2 res ← ∅ while n>1 while d divide a n n ← n/d do do res ← res + {d} d ←d +1 return (res) Origin Pro (propietario). Qtiplot Gnuplot Otros programas que permiten graficar funciones (Mathematica, Matlab, Microsoft Excel (propietario)). Labo de Algo III (Sabi) Resolviendo problemas del TP 27 de Agosto de 2010 53 / 56 Labo de Algo III (Sabi) Gráficos 27 de Agosto de 2010 54 / 56 27 de Agosto de 2010 56 / 56 Gráficos Factorizar Labo de Algo III (Sabi) Resolviendo problemas del TP Factorizar Resolviendo problemas del TP 27 de Agosto de 2010 55 / 56 Labo de Algo III (Sabi) Resolviendo problemas del TP