• No results found

Prioritizing options for multi-objective agricultural development through the

El algoritmo Twitter Followee Recommender (Armentano et al., 2011), especificado en la Sec- ción 2.3.2 del Capítulo 2, realiza un recorrido exploratorio del grafo que rodea a un usuario objetivo, seleccionando usuarios a recomendar.

En el contexto de la red social Twitter, un usuario tiene un grupo de seguidores ofollowers (bordes salientes) y seguidos ofollowees(bordes entrantes). El algoritmo se puede dividir en dos etapas. En primer lugar, explora la redfollowee/followerdel usuario objetivo (es decir, el usuario que recibe las sugerencias) para seleccionar un conjunto de usuarios potenciales para recomendar. A continuación, los candidatos se filtran y se clasifican de acuerdo a diferentes cri- terios, como el número de amigos comunes con el usuario de destino o la similitud de sus perfiles basados en contenidos. En esta tesis, el objetivo es proporcionar un soporte distribuido para la exploración de grafos, y por lo tanto, el análisis se centra en la primera etapa del algoritmo.

La exploración de la red de followees/followers en este algoritmo se basa en la caracteri- zación de los usuarios de Twitter realizados en varios estudios (Java et al., 2007; Krishnamurthy et al., 2008) y el hecho de que las redes sociales en línea se han convertido fuentes de informa- ción en tiempo real y medios de comunicación de difusión, además de fomentar la formación de los lazos sociales (Kwak et al., 2010). Desde un punto de vista centrado en la información, los usuarios se dividen principalmente en dos categorías: fuentes de información y buscadores de información. Los usuarios que se comportan como fuentes de información tienden a acumu- lar un gran número de seguidores, ya que publican información útil o de noticias, mientras que los buscadores de información siguen a varios usuarios para obtener información, pero rara vez publicar un tweet por sí mismos.

Elrationalede la etapa de recorrido del grafo del algoritmo de TFR se basa en la catego- rización de los usuarios en buscadores de información o fuentes de información. Por lo tanto, se

1 g r a p h l y . v ( t a r g e t ). s a v e (" t a r g e t ") 2 . out (). s a v e (" f o l l o w e e s ")

3 . c o u n t I n (). f i l t e r (" f o l l o w e e s ", " t a r g e t ") 4 . c o u n t O u t (). f i l t e r (" f o l l o w e e s ", " t a r g e t ") 5 . top ( n );

Listado de código 5.1: TFR implementada utilizando la API de recorridos.

supone que el usuario de destino es un buscador de información que ya ha identificado algunos usuarios interesantes de Twitter en calidad de fuentes de información (es decir, sus seguidores). Otras personas que también siguen a estas personas (es decir, los seguidores de los seguidos del usuario) es probable que compartan algunos intereses con el usuario de destino y podrían haber descubierto otras fuentes de información relevante sobre los mismos temas (es decir, sus segui- dos). Este último grupo se compone entonces de los posibles candidatos para ser propuesto al usuario objetivo como futuros usuarios a seguir.

En forma matricial, se puede observar que el algoritmo lleva a cabo una serie de recorridos a partir de un usuario de destinou: primero, uno en la direcciónOU T (es decir, obtener los seguidores deu), a continuación otro en la dirección IN y, por último, un recorrido final en la direcciónOU T. En cada paso, el usuariouy susfolloweesse quitan de los sub-resultados. Por otra parte, el algoritmo debe contar el número de apariciones de cada vértice con el fin de ordenar aquellos que serán recomendados por el número de caminos que se originan enu. La Figura 5.1 muestra un ejemplo sencillo de un recorrido realizado por TFR. El conjunto inicial (es decir,u y sus seguidos) aparece en rojo y sus vértices se filtran del conjunto de segundo y tercer nivel. vértices de segundo nivel aparecen en azul y se utilizan para encontrar los vértices resultado, que se muestran en verde. Debido al hecho de que los vértices de segundo nivel pueden ser parte del conjunto de resultados, algunos de estos vértices se muestran en verde y azul. Algunos bordes se ignoran porque apuntan al conjunto de partida. Es importante tener en cuenta que los bordes azules no se usan nunca en la etapa final (es decir, el paso que utiliza bordes verdes), ya que siempre apuntan a la configuración inicial.

Implementación Fork-Join del Algoritmo TFR TFR se puede dividir en tareas FJ bien definidos, cada uno de los cuales depende de un resultado de una tarea anterior. La primera parte del algoritmo obtiene los vecinos en la direcciónOU T, i.e. los seguidores del usuario. La lista followee resultante se pasa luego al algoritmo de recuento que se deben obtener los seguidores de esta lista y agregar las ocurrencias de cada seguidor. Finalmente, el mismo algoritmo se aplica a los seguidores contar, pero contando la aparición de sus seguidores. Es importante señalar que los recuentos anteriores deben ser distribuidos entre los de aquellos que siguen de la última etapa. Por ejemplo, si un usuario con ID 1 aparece 10 veces comofolloweren el paso 2 y susfollowees son2,3,4, entonces 2,3,4 recibirán un valor de 10 cada uno, significando que hay 10 caminos desde el usuario objetivo hasta los usuarios 2, 3 y 4. Por el otro lado, si el usuario 5 aparece 3

1 p u b l i c c l a s s C o u n t S t e p i m p l e m e n t s S t e p { 2 p u b l i c T r a v e r s a l R e s u l t ex e c ( T r a v e r s a l R e s u l t b e f o r e ) { 3 F J R e s u l t res = g r a p h l y 4 . fj () 5 . t a s k (new T a sk (){ 6 // The c o u n t t a s k e m i t s a c o u n t for e a c h n e i g h b o r . 7 p u b l i c v o i d c o m p u t e ( L i s t v e r t i c e s , 8 T r a v e r s a l R e s u l t p r e v i o u s ){ 9 for (l o n g vID : v e r t i c e s ) 10 for (l o n g n e i g h b o r : g e t G r a p h (). g e t N e i g h b o r s ( vID )) 11 e m i t ( n e i g h bo r , p r e v i o u s . g e t C o u n t ( vID )); 12 } 13 })

14 // The m e r g e r s i m p l y s u m s two c o u n t s for the s a m e v e r t e x .

15 . m e r g e r (new R e s u l t M e r g e r (){

16 p u b l i c F l o a t m e r g e ( F l o a t a , F l o a t b ){ 17 r e t u r n a + b ;

18 }

19 })

20 // E x e c u t e u s i n g the m a p p i n g s t r a t e g y and the p r e v i o u s c o u n t s .

21 . run ( m a p p i n g _ s t r a t e g y , b e f o r e ); 22 r e t u r n new C o u n t R e s u l t ( res . v a l u e ( ) ) ;

23 }

24 }

Listado de código 5.2: Implementación en Graphly del algoritmo Count.

veces y susfolloweesson 3,4,7, la cuenta resultante será 2→10,3→13,4→13,7→3. Uti- lizando la API de Traversals, este acople de cuentas de caminos y filtros se puede expresar como se ve en el Listado 5.1.

El código representado muestra cómo la API de Traversals oculta toda la funcionalidad con respecto a la distribución de tareas y el procesamiento de los resultados detrás de una API fácil de usar. Como se ha mencionado en el Capítulo 4, Sección 4.5, la API de recorridos proporciona un DSL (Lenguaje Específico de dominio) para recorrer y procesar el grafo. En este caso, la función Count se utiliza para contar el número de caminos entre el usuario de destino y los usuarios recomendados. En cada paso, el grupo de seguidores y el usuario de destino se eliminan de los sub-resultados. Por último, los mejoresN vértices se obtienen y se presentan al usuario como usuarios potenciales para comenzar a seguir.

Las funciones que requieren agrupar los resultados del clúster se implementan utilizando el modelo FJ proporcionado por Graphly. En este caso, la funciónOU T y ambas funcionesCount (CountInyCountOut) se implementan bajo FJ y están integrados en Graphly. No obstante, el usuario puede crear nuevas funciones personalizadas, a través de la API mediante la ampliación de la interfazCustomStep, como se explicará más adelante en este capítulo.

Naturalmente, la operación principal y, también, la que más tiempo consume en el programa del Listado 5.1 es la función Count. La razón es que el conteo debe agregar todas los con- tadores de rutas para un conjunto de vértices que crecen exponencialmente en cada paso. La

clase CountStep, que implementa la funcionalidad de recuento, se muestra en el Listado 5.2. Cuando se ejecuta, CountStep crea un trabajo FJ mediante la API de modelos. En este caso, la clase CountTask es responsable de distribuir el recuento actual de recorridos entre cada vecino (representado por la operaciónprevious.getCount(vID)). Se debe tener en cuenta que el recuento de inicial es 1. Los sub-resultados emitidos son luego fusionados en la etapa de combinación utilizando una clase Combiner, que suma la cuenta de recorridos por cada vértice.

Implementación Pregel del Algoritmo TFR La versión Pregel del algoritmo TFR requiere un cambio paradigmático en términos del diseño de algoritmos. El recuento de los vértices es, ahora, llevado a cabo desde un punto de vista centrado en el vértice, lo que complica algunas de las operaciones que eran simples de realizar en FJ, tales como pasar los resultados de una etapa a la siguiente o el filtrado de vértices.

La implementación del algoritmo se muestra en el Listado 5.3. Como se puede ver, el de- sarrollador debe programar las tres etapas en la misma función utilizando el enfoque de pro- gramación centrada en el vértice. Por otra parte, el código de usuario debe utilizar el número de superetapa para decidir qué operación se debe realizar. Por ejemplo, las dos primeras su- peretapas (paso 0 y 1) marcan los vértices como parte del conjunto de destino (implementa- dos como set("TYPE", "TARGET_SET")), y para el resto de pasos si el vértice es parte del objetivo conjunto (es decir,get("TYPE") == "TARGET_SET"), la función retorna sin realizar ninguna operación, efectivamente filtrando los vértices iniciales. Una vez que los vértices se filtran o se marcan, el recuento de rutas se calcula mediante la suma de los conteos de ruta entrantes. Es importante notar que los vértices en el primer paso envían una longitud de 1. De- bido a que el algoritmo alterna la dirección a la que se envía el recuento de rutas, la función

isEven(getSuperStep())ayuda a decidir si se realiza el envío a vértices salientes o entrantes. Dadas las restricciones impuestas por el modelo de programación de Pregel, el código resul- tante es más difícil de comprender que la alternativa integrada en la API de recorrido, hecha en FJ. Sin embargo, a diferencia del FJ donde el número de caminos se fusiona en un solo nodo, Pregel propaga la cuenta de caminos a lo largo de todo el clúster (utilizando el métodosenden el código que se muestra en el Listado 5.3, Línea 21) y, como resultado, la fusión de sub-resultados se distribuye.

Implementación DPM de TFR Motivado por el problema del cuello de botella identificado en el modelo FJ, DPM tiene un enfoque FJ para distribuir las tareas, pero utilizando un enfoque Pregel (o enfoque de MapReduce) para la distribución de los sub-resultados. En virtud de este nuevo modelo, el algoritmo Count DPM obtiene la longitud de los caminos actuales a partir del grafo en lugar de pasar los resultados de un trabajo a otro, como sucede en FJ. Los recuentos parciales de las rutas se distribuyen y almacenan en todo el clúster, equilibrando la fusión de resultados. El Listado 5.4 muestra la implementación Count DPM, que es un elemento esencial

1 p u b l i c c l a s s TFR i m p l e m e n t s V e r t e x F u n c t i o n { 2 p u b l i c v o i d e x e c u t e (l o n g v , M e s s a g e L i s t m s g s ){ 3 if ( g e t S u p e r S t e p () == 0 || g e t S u p e r S t e p () == 1) 4 set (" T Y P E ", " T A R G E T _ S E T "); 5 el s e if ( get (" T Y PE ") == " T A R G E T _ S E T ") 6 r e t u r n; 7 f l o a t p a t h C o u n t = 0 f ; 8 if ( g e t S u p e r S t e p () > 0){ 9 for ( M e s s a g e msg : m s g s ) 10 p a t h C o u n t += msg . v a l u e (); 11 if ( g e t S u p e r S t e p () == 3) 12 set (" R E S U L T ", p a t h C o u n t ); 13 }e l s e 14 p a t h C o u n t = 1 f ; 15 L o n g S e t u s e r L i s t = i s E v e n ( g e t S u p e r S t e p ()) ? g e t G r a p h (). out ( v ) 16 : g e t G r a p h (). in ( v ); 17 for (l o n g n e i g h b o r : u s e r L i s t ) 18 s e n d ( n e i g h b o r , p a t h C o u n t ); 19 } 20 } 21 p u b l i c c l a s s P r e g e l C o u n t i m p l e m e n t s S t e p { 22 p u b l i c T r a v e r s a l R e s u l t e x e c ( T r a v e r s a l R e s u l t b e f o r e ) { 23 P r e g e l R e s u l t res = g r a p h l y . p r e g e l () 24 . vf (new TFR ()) 25 . run ( m a p p i n g _ s t r a t e g y , b e f o r e ); 26 r e t u r n new P r e g e l T r a v e r s a l R e s u l t ( res ); 27 } 28 }

Listado de código 5.3: Implementación Pregel del algoritmo TFR.

1 p u b l i c c l a s s D P M C o u n t i m p l e m e n t s S t e p { 2 p u b l i c T r a v e r s a l R e s u l t ex e c ( T r a v e r s a l R e s u l t b e f o r e ) { 3 D P M R e s u l t res = g r a p h l y 4 . dpm () 5 . t a s k (new D P M T a s k (){ 6 p u b l i c v o i d c o m p u t e ( L i s t v e r t i c e s ){ 7 for (l o n g vID : v e r t i c e s ) 8 for (l o n g n e i g h b o r : g e t N e i g h b o r s ( vID )) 9 e m i t ( vID , g e t O r D e f a u l t ( vID , 1 ) ); 10 } 11 }) 12 . c o m b i n e r (new C o m b i n e r (){ 13 p u b l i c F l o a t c o m b i n e ( F l o a t a , F l o a t b ){ 14 r e t u r n a + b ; 15 } 16 }) 17 . run ( m a p p i n g _ s t r a t e g y , b e f o r e ); 18 r e t u r n new D P M T r a v e r s a l R e s u l t ( res ); 19 } 20 }

1 p u b l i c c l a s s B e t a C o u n t i m p l e m e n t s S t e p { 2 p u b l i c T r a v e r s a l R e s u l t e x e c u t e ( B e t a R e s u l t prev , T r a v e r s a l tr ){ 3 int p a t h _ l e n g t h = g e t C u r r e n t L e n g t h (); 4 F J R e s u l t res = g r a p h l y 5 . fj () 6 . t a s k (new T a sk (){ 7 p u b l i c v o i d c o m p u t e ( L i s t v e r t i c e s , B e t a R e s u l t p r e v ){ 8 for (l o n g vID : v e r t i c e s ) 9 for (l o n g n e i g h b o r : g e t G r a p h (). g e t N e i g h b o r s ( vID )) 10 e m i t (" P A T H ", vID , p r e v . g e t C o u n t ( vID )); 11 } 12 }) 13 . m e r g e r (/* sum v a l u e s */) 14 . r e s u l t _ e m i t t e r (new E m i t t e r (){ 15 p u b l i c v o i d c o m p u t e ( L o n g vid , I n t e g e r paths , B e t a R e s u l t p r e v ){ 16 e mi t (" B E T A ", vid , p r e v . g e t B e t a ( vid )+ b e ta . a p p l y ( p a t h _ l e n g t h )* p a t h s ); 17 } 18 }) 19 . run ( m a p p i n g _ s t r a t e g y , b e f o r e ); 20

21 r e t u r n new B e t a T r a v e r s a l R e s u l t ( res . v a l u e (" P A T H ") , res . v a l u e (" B E T A "));

22 }

23 }

Listado de código 5.5: Algoritmo Count en FJ utilizando un Beta personalizable.

para implementar TFR en DPM.

En lugar de obtener la cuenta de rutas de una etapa anterior como FJ, estas longitudes se registran en el almacén de grafos y se obtienen utilizando la función get(v)(ogetOrDefault). Luego, la longitud de caminos hasta el vértice actual se emite de manera que los recuentos de caminos se distribuyan y se fusionen en todo el clúster. Naturalmente, como se explica en el Capítulo 4, Sección 4.8, los recuentos de rutas distribuidos deben ser almacenados en una memoria auxiliar para evitar lecturas inconsistentes en otros nodos que aún se encuentran procesando rutas. Cuando todos los nodos completan la ejecución, los resultados auxiliares se persisten en el almacén y se utilizan como entrada para el siguiente paso.