<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Angel "Java" Lopez : AjAgents</title><link>http://msmvps.com/blogs/lopez/archive/tags/AjAgents/default.aspx</link><description>Tags: AjAgents</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Web Crawler usando el nuevo AjAgents</title><link>http://msmvps.com/blogs/lopez/archive/2010/11/09/web-crawler-usando-el-nuevo-ajagents.aspx</link><pubDate>Tue, 09 Nov 2010 09:35:59 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1781927</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1781927</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2010/11/09/web-crawler-usando-el-nuevo-ajagents.aspx#comments</comments><description>&lt;p&gt;Hace poco escribí una nueva implementación de &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjAgents/default.aspx"&gt;mi proyecto AjAgents&lt;/a&gt;, descripta en:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/2010/10/12/ajagents-a-new-implementation/"&gt;AjAgents: a new implementation&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2010/10/14/ajagents-una-nueva-implementaci-243-n.aspx"&gt;AjAgents: una nueva implementación&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Ahora, quiero describir una aplicación de prueba, de nuevo el Web Crawler: visitar y bajar la página desde una URL inicial, ir descubriendo enlaces al mismo sitio, y procesar el resto de las páginas. Anteriores versiones:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/2010/02/22/web-crawler-using-agents-and-ajsharp/"&gt;Web Crawler Using Agents and AjSharp&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2010/02/23/web_2D00_crawler_2D00_using_2D00_agents_2D00_and_2D00_ajsharp.aspx"&gt;Web Crawler usando AjSharp&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://ajlopez.wordpress.com/2009/03/09/distributed-web-crawler-using-ajmessages/"&gt;Distributed Web Crawler using AjMessages&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2009/03/10/web-crawler-distribuido-usando-ajmessages.aspx"&gt;Web Crawler distribuido usando AjMessages&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;La nueva versión del web crawler usa la nueva interface:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0px;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;interface&lt;/span&gt; IAgent&amp;lt;T&amp;gt;
    {
        &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Post(Action&amp;lt;T&amp;gt; action);
    }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;En vez de escribir un tipo que hereda o implementa un agente, éste es un “wrapper” aplicado a un tipo normal cualquiera de .NET. &lt;/p&gt;

&lt;p&gt;La nueva implementación de AjAgentes, y el ejemplo de web crawler (Proyecto &lt;strong&gt;AjAgents.WebCrawler&lt;/strong&gt;), puede ser bajado desde:&lt;/p&gt;

&lt;p&gt;&lt;a title="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjAgents" href="http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjAgents"&gt;http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjAgents&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En una de &lt;a href="http://msmvps.com/blogs/lopez/archive/2009/03/10/web-crawler-distribuido-usando-ajmessages.aspx"&gt;mis anteriores implementaciones&lt;/a&gt; tenía:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/webcrawler01.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Ahora, descarté el Dispatcher. Tengo tres clases:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajagentswc10.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;El Resolver recibe un enlace a bajar y procesar. Decide si lo procesa o no (puede que el enlace ya haya sido procesado, o que el link no corresponda al sitio de partida, o se alcanzó un límite en la profundidad de enlaces desde la página inicial de proceso). Si el enlace es aceptado, la inforación es enviada al Downloader. Este objeto baja el contenido de la página, y lo envía al Harvester (podría enviarlo a otros agentes, también). El Harvester examina el contenido, extrae nuevos enlaces para procesar, y a cada uno lo envía al Resolver.&lt;/p&gt;

&lt;p&gt;Estas clases son tipos .NET. Pero las referencias que mantienen entre sí son del tipo &lt;strong&gt;Agent&amp;lt;Downloader&amp;gt;&lt;/strong&gt;, &lt;strong&gt;Agent&amp;lt;Harvester&amp;gt;&lt;/strong&gt;, &lt;strong&gt;Agent&amp;lt;Resolver&amp;gt;&lt;/strong&gt;. El código que arma un grupo inicial de objetos/agentes interconectados está en &lt;strong&gt;Program.cs&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0px;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;       &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; Agent&amp;lt;Resolver&amp;gt; MakeAgent()
        {
            Resolver resolver = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Resolver();
            Harvester harvester = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Harvester();
            Downloader downloader = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Downloader();
            Agent&amp;lt;Resolver&amp;gt; aresolver = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Agent&amp;lt;Resolver&amp;gt;(resolver);
            Agent&amp;lt;Harvester&amp;gt; aharvester = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Agent&amp;lt;Harvester&amp;gt;(harvester);
            Agent&amp;lt;Downloader&amp;gt; adownloader = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Agent&amp;lt;Downloader&amp;gt;(downloader);
            resolver.Downloader = adownloader;
            harvester.Resolver = aresolver;
            downloader.Harvester = aharvester;
            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; aresolver;
        }&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;La aplicación de consola &lt;strong&gt;AjAgents.WebCrawler&lt;/strong&gt; aceptar un parámetro, con el enlace inicial:&lt;/p&gt;

&lt;p&gt;&lt;font face="Consolas"&gt;AjAgents.WebCrawler &lt;/font&gt;&lt;a title="http://ajlopez.zoomblog.com" href="http://ajlopez.zoomblog.com"&gt;&lt;font face="Consolas"&gt;http://ajlopez.zoomblog.com&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Su salida:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajagentswc11.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Este ejemplo es un “proof of concept”. Me gustaría mejorarlo:&lt;/p&gt;

&lt;p&gt;- &lt;strong&gt;Agent&amp;lt;IDownloader&amp;gt;&lt;/strong&gt;, que haga balanceo de carga con varias instancias de &lt;strong&gt;Agent&amp;lt;Downloader&amp;gt;&lt;/strong&gt;. 

  &lt;br /&gt;- &lt;strong&gt;Agent&amp;lt;T&amp;gt;&lt;/strong&gt; instanciado en diferentes máquinas, implementando así un web crawler distribuido.&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1781927" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjAgents/default.aspx">AjAgents</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Proyectos+de+C_F300_digo+Abierto/default.aspx">Proyectos de Código Abierto</category></item><item><title>AjAgents: una nueva implementación</title><link>http://msmvps.com/blogs/lopez/archive/2010/10/14/ajagents-una-nueva-implementaci-243-n.aspx</link><pubDate>Thu, 14 Oct 2010 09:34:50 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1779926</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1779926</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2010/10/14/ajagents-una-nueva-implementaci-243-n.aspx#comments</comments><description>&lt;p&gt;Hace ya un tiempo, escribí sobre &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjAgents/default.aspx" target="_blank"&gt;mi proyecto AjAgents&lt;/a&gt;, describiéndolo, implementando algoritmos genéticos y otras demos mínimas. El proyecto se basa en el envío de mensajes a “agentes” (podría llamarlos actores, o algo así). Los agentes reciben los mensajes y los procesan uno por uno. Cada instancia de un agente no necesita manejar la concurrencia: los mensajes son encolados en una cola interna por cada agente (podría más adelante, reimplementar esto usando una cola compartida entre varios agentes, o consumida por un pool de threads fijo que vaya consumiendo trabajo pendiente de esa cola, derivándo cada uno al agente destino).&lt;/p&gt;  &lt;p&gt;Pero mis anteriores implementaciones se basaban en el uso de Reflection, o, alguna vez, en la librería CCR de concurrency de Microsoft Robotics (ver mis anteriores posts para más detalles). Ahora, tomo otro camino: un agente es un wrapper alrededor de un objeto normal. El código fuente puede ser bajado desde mi&amp;#160; &lt;a href="http://code.google.com/p/ajcodekatas/" target="_blank"&gt;proyecto AjCodeKatas Google Code&lt;/a&gt;, en el directorio trunk/AjAgents.&lt;/p&gt;  &lt;p&gt;La interface principal, clave, es:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0px;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;interface&lt;/span&gt; IAgent&amp;lt;T&amp;gt;
    {
        &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Post(Action&amp;lt;T&amp;gt; action);
    }&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;La nueva idea: usar una clase genérica. T es el tipo de nuestro tipo “clásico” (que no es un agente), y Post es el método para invocar una acción sobre el objet interno: una acción que es una “rutina” que recibe un parámetro instancia de tipo T. De esta manera, le indicamos al objeto interno. Si éste tiene un método: &lt;/p&gt;

&lt;p&gt;&lt;font size="3" face="Consolas"&gt;inner.DoSomething(parameter);&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;puede ser invocado como un mensaje desde el agente como:&lt;/p&gt;

&lt;p&gt;&lt;font size="3" face="Consolas"&gt;agent.Post(x =&amp;gt; x.DoSomething(1));&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;Esta es la implementación base de agente:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0px;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Agent&amp;lt;T&amp;gt; : IAgent&amp;lt;T&amp;gt;
    {
        &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; T instance;
        &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; AgentQueue&amp;lt;T&amp;gt; queue;
        &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; running;
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Agent(T instance)
        {
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.instance = instance;
        }
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Post(Action&amp;lt;T&amp;gt; action)
        {
            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (!&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.running)
                &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Start();
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.queue.Enqueue(action);
        }
        &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Start()
        {
            &lt;span style="color:#0000ff;"&gt;lock&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;)
            {
                &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.running)
                    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;;
                &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.queue = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; AgentQueue&amp;lt;T&amp;gt;();
                Thread thread = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Thread(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ThreadStart(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Execute));
                thread.IsBackground = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;;
                thread.Start();
                &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.running = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;;
            }
        }
&lt;span style="color:#008000;"&gt;//...&lt;/span&gt;
    }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Noten que el método Post encola la acción en la cola interna del agente. El proceso de esta cola está en el método .Execute (que no se muestra arriba). La cola es una cola bloqueante (sé que hay algo así en .NET 4.0, pero escribí mi implementación para poder ejecutar todo esto en 3.x, o aún 2.x):&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0px;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; AgentQueue&amp;lt;T&amp;gt;
    {
        &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; Queue&amp;lt;Action&amp;lt;T&amp;gt;&amp;gt; queue = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Queue&amp;lt;Action&amp;lt;T&amp;gt;&amp;gt;();
        &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; maxsize;
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; AgentQueue()
            : &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;(100)
        {
        }
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; AgentQueue(&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; maxsize)
        {
            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (maxsize &amp;lt;= 0)
                &lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; InvalidOperationException(&amp;quot;&lt;span style="color:#8b0000;"&gt;AgentQueue needs a positive maxsize&lt;/span&gt;&amp;quot;);
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.maxsize = maxsize;
        }
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Enqueue(Action&amp;lt;T&amp;gt; action)
        {
            &lt;span style="color:#0000ff;"&gt;lock&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;)
            {
                &lt;span style="color:#0000ff;"&gt;while&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.queue.Count &amp;gt;= &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.maxsize)
                    Monitor.Wait(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;);
                &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.queue.Enqueue(action);
                Monitor.PulseAll(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;);
            }
        }
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Action&amp;lt;T&amp;gt; Dequeue()
        {
            &lt;span style="color:#0000ff;"&gt;lock&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;)
            {
                &lt;span style="color:#0000ff;"&gt;while&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.queue.Count == 0)
                    Monitor.Wait(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;);
                Action&amp;lt;T&amp;gt; action = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.queue.Dequeue();
                Monitor.PulseAll(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;);
                &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; action;
            }
        }
    }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Apliqué TDD para el desarrollo de todas estas clases, un ejemplo de test:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0px;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;        [TestMethod]
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; InvokeIncrement()
        {
            ManualResetEvent handle = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ManualResetEvent(&lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;);
            Counter counter = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Counter();
            Agent&amp;lt;Counter&amp;gt; agent = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Agent&amp;lt;Counter&amp;gt;(counter);
            agent.Post(c =&amp;gt; { c.Increment(); handle.Set(); });
            handle.WaitOne();
            Assert.AreEqual(1, counter.Count);
        }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Mucho del código fue derivado (bueno… casi copy and paste ;-) de mi trabajo previo con &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjSharp/default.aspx" target="_blank"&gt;AjSharp (channels, agentes, queues, goroutines… )&lt;/a&gt;&lt;a href="http://ajlopez.wordpress.com/category/ajsharp/" target="_blank"&gt;.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tengo preparada una demo “prueba de concepto” usando esta nueva implementación de AjAgents. Es mi “clásico” ejemplo de Web Crawler. Pero eso es tema para otro post.&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1779926" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjAgents/default.aspx">AjAgents</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Proyectos+de+C_F300_digo+Abierto/default.aspx">Proyectos de Código Abierto</category></item><item><title>Recursos de Grid Computing</title><link>http://msmvps.com/blogs/lopez/archive/2008/05/10/recursos-de-grid-computing.aspx</link><pubDate>Sat, 10 May 2008 08:06:13 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1618730</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1618730</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/05/10/recursos-de-grid-computing.aspx#comments</comments><description>&lt;p&gt;&lt;/p&gt; &lt;p&gt;Desde el año pasado, y más en estas últimas semanas, he estado investigando sobre Grid Computing, buscando enlaces, recursos, &amp;quot;papers&amp;quot;, implementaciones. Este post es el resultado de esa investigación.  &lt;p&gt;Como siempre, un artículo de la Wikipedia: &lt;p&gt;&lt;a title="http://en.wikipedia.org/wiki/Grid_computing" href="http://en.wikipedia.org/wiki/Grid_computing"&gt;http://en.wikipedia.org/wiki/Grid_computing&lt;/a&gt; &lt;p&gt;Si Ud. se está iniciando en el mundo de Grid Computing, estas son buenas introducciones  &lt;p&gt;&lt;a href="http://www-128.ibm.com/developerworks/grid/newto/?ca=dgr-lnxw97Grid-Coumputing" target="_blank"&gt;New to Grid Computing&lt;/a&gt;  &lt;p&gt;&lt;a href="http://www-03.ibm.com/grid/" target="_blank"&gt;Grid Computing according IBM&lt;/a&gt;  &lt;p&gt;&lt;a href="http://www-unix.globus.org/alliance/publications/papers/anatomy.pdf" target="_blank"&gt;The anatomy of the grid&lt;/a&gt;  &lt;p&gt;&lt;a href="http://www-unix.globus.org/alliance/publications/papers/ogsa.pdf" target="_blank"&gt;The physiology of the grid&lt;/a&gt;&amp;nbsp;&amp;nbsp;  &lt;p&gt;Interesante lista de lecturas para desarrolladores en Grid &lt;p&gt;&lt;a href="http://www.gridblog.com/comments.php?id=242_0_1_0_C" target="_blank"&gt;Recommended reading list for grid developers&lt;/a&gt;  &lt;p&gt;Grid Café tiene varios artículos y recursos &lt;p&gt;&lt;a href="http://gridcafe.web.cern.ch/gridcafe/gridprojects/projects.html" target="_blank"&gt;Grid Cafe Grid Projects in the world&lt;/a&gt;&amp;nbsp;&amp;nbsp;  &lt;p&gt;&lt;a href="http://gridcafe.web.cern.ch/gridcafe/"&gt;Grid Cafe The place for everybody to learn about the Grid&lt;/a&gt;&amp;nbsp;&amp;nbsp;  &lt;p&gt;&lt;a href="http://gridcafe.web.cern.ch/gridcafe/whatisgrid/dreamers.html" target="_blank"&gt;What is &amp;quot;the Grid&amp;quot;?&lt;/a&gt;&amp;nbsp;&amp;nbsp;  &lt;p&gt;&lt;a href="http://gridcafe.web.cern.ch/gridcafe/GridatCERN/gridatcern.html" target="_blank"&gt;Grid @ CERN&lt;/a&gt;&amp;nbsp;  &lt;p&gt;Sobre el estado de la industria:  &lt;p&gt;&lt;a href="http://www.gridtoday.com/"&gt;http://www.gridtoday.com/&lt;/a&gt; (un poco demasiado abarcativo, no es sólo sobre grid computing)  &lt;p&gt;&lt;a href="http://www.gridblog.com/"&gt;http://www.gridblog.com/&lt;/a&gt;  &lt;p&gt;La lista completa de enlaces que mantengo, en:  &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/gridcomputing"&gt;http://del.icio.us/ajlopez/gridcomputing&lt;/a&gt;  &lt;p&gt;Algunos productos para examinar:  &lt;p&gt;&lt;a href="http://www.gridgain.com/"&gt;http://www.gridgain.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.digipede.net/"&gt;http://www.digipede.net&lt;/a&gt;&amp;nbsp;algo más sobre Digipede en &lt;a href="http://dotnetjunkies.com/WebLog/stefandemetz/archive/2006/12/09/Free_Grid_Computing_software.aspx"&gt;http://dotnetjunkies.com/WebLog/stefandemetz/archive/2006/12/09/Free_Grid_Computing_software.aspx&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.gridgistics.net/"&gt;http://www.gridgistics.net/&lt;/a&gt;  &lt;p&gt;&lt;a href="http://sourceforge.net/projects/ngrid/"&gt;http://sourceforge.net/projects/ngrid/&lt;/a&gt;  &lt;p&gt;Algo relacionado, que comienza a &amp;quot;estar de moda&amp;quot;:  &lt;p&gt;&lt;a title="http://en.wikipedia.org/wiki/Cloud_computing" href="http://en.wikipedia.org/wiki/Cloud_computing"&gt;http://en.wikipedia.org/wiki/Cloud_computing&lt;/a&gt;&lt;/p&gt; &lt;p&gt;He escrito artículos en este blog sobre Grid Computing:  &lt;p&gt;&lt;a title="http://msmvps.com/blogs/lopez/archive/tags/Grid+Computing/default.aspx" href="http://msmvps.com/blogs/lopez/archive/tags/Grid+Computing/default.aspx"&gt;http://msmvps.com/blogs/lopez/archive/tags/Grid+Computing/default.aspx&lt;/a&gt; &lt;p&gt;y en &amp;quot;Anglish&amp;quot;, Angel&amp;#39;s English: &lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/category/grid-computing/"&gt;http://ajlopez.wordpress.com/category/grid-computing/&lt;/a&gt; &lt;/p&gt; &lt;p&gt;donde hay algunas implementaciones sencillas de ideas a seguir explorando, como &lt;a title="AjAgents" href="http://msmvps.com/blogs/lopez/archive/tags/AjAgents/default.aspx"&gt;AjAgents&lt;/a&gt;, y &lt;a title="AjMessages" href="http://msmvps.com/blogs/lopez/archive/tags/AjMessages/default.aspx"&gt;AjMessages&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Esta lista de recursos, en Anglish, desde:&lt;/p&gt; &lt;p&gt;&lt;a title="Grid Computing Resources" href="http://ajlopez.wordpress.com/2008/04/18/grid-computing-resources/"&gt;Grid Computing Resources&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1618730" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjMessages/default.aspx">AjMessages</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Grid+Computing/default.aspx">Grid Computing</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjAgents/default.aspx">AjAgents</category></item><item><title>Agentes en Grid</title><link>http://msmvps.com/blogs/lopez/archive/2008/05/08/agentes-en-grid.aspx</link><pubDate>Thu, 08 May 2008 10:14:21 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1617275</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1617275</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/05/08/agentes-en-grid.aspx#comments</comments><description>&lt;p&gt;El año pasado participé del desarrollo de una aplicación que se ejecuta en una grilla de máquinas sin disco. Este año, estoy volviendo a actualizar el proyecto, espero poder bloggear sobre el resultado dentro de un mes. Mientras, quisiera escribir sobre algunas ideas a explorar.&lt;/p&gt; &lt;p&gt;En este post, uso el término &amp;quot;agente&amp;quot;, de una forma algo libre. No definiré precisamente el concepto, quiero usarlo como término base a refinar en el futuro (llegando en algún momento a tratar el tema de agentes autónomos, que me parece más interesante). Por ahora, exploremos algunas ideas básicas (¿ingenuas?) para entender mejor los problemas relacionados con agentes y aplicaciones en grid. Algunas de las ideas acá presentadas pueden ser vistas como ingenuas, pero siento que es un ejercicio necesario, para aprehender los conceptos clave y los problemas a ser resueltos en este tipo de aplicaciones. Al final de este post, presentaré algunas sugerencias de implementación.&lt;/p&gt; &lt;p&gt;He descripto algunas aplicaciones para ejecutar en una grid en mis anteriores post:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/2007/12/03/grid-computing-programming/" target="_blank"&gt;Grid Computing Programming&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="M&amp;aacute;s programando para una grid" href="http://msmvps.com/blogs/lopez/archive/2007/11/21/m-225-s-programando-para-una-grid.aspx"&gt;Más programando para una grid&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="Programando para una Grid" href="http://msmvps.com/blogs/lopez/archive/2007/11/15/programando-para-una-grid.aspx"&gt;Programando para una Grid&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;Conceptos de Agentes&lt;/h3&gt; &lt;p&gt;En este post, un agente es una pieza de software, con conducta y estado. Se ejecuta en un host de agentes, una aplicación que provee los servicios de base para que el agente pueda &amp;quot;vivir&amp;quot; y trabajar. Representaremos al agente con esta figura:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/agentsgrid01.png" alt="" /&gt; &lt;/p&gt; &lt;h3&gt;Patrones de comunicación de agentes&lt;/h3&gt; &lt;p&gt;Hay mucha literatura sobre comunicación de agentes, desde simples técnicas hasta elaborados contratos, negociaciones, y más. Podemos tener agentes con creencias, deseos e intenciones. En este post, un agente es más simple: sólo tiene estado, puede enviar y recibir mensajes. Puede recibir estímulos de otros agentes y desde el ambiente de su host.&lt;/p&gt; &lt;p&gt;El más simple patrón de comunicación es un agente enviando un mensaje a otro agente:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/agentsgrid02.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Algunas notas:&lt;/p&gt; &lt;p&gt;-&amp;nbsp;El agente enviador conoce al agente receptor. Quiero decir, alguna forma de identidada debe ser implementada. El mensaje no es enviado a cualquiera: el que envía intenta enviar el mensaje a un determinado agente.&lt;/p&gt; &lt;p&gt;- El mensaje transporta datos, y debe ser entendido por el receptor, posiblemente procesado por uno de sus métodos de implementación.&lt;/p&gt; &lt;p&gt;- En enviador no espera por una respuesta. No está interesado en un mensaje de respuesta inmediato.&lt;/p&gt; &lt;p&gt;- Los agentes pueden residir en diferentes máquinas en la grila, y la comunicación se produce tanto local como remota.&lt;/p&gt; &lt;p&gt;Durante su vida un agente puede enviar muchos mensajes a distintos agentes, que debe conocer de alguna manera:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/agentsgrid03.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Algunas veces, el agente enviador recibirá un&amp;nbsp;mensaje desde el agente receptor, notificando algun trabajo hecho, o enviando algún dato procesado. Dependiendo de la aplicación, el mensaje de respuesta podría acarrear información para identificar al mensaje original:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/agentsgrid04.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;En este caso, el enviador original debe estar preparado para recibir la respuesta de una manera asincrónica. Esto podría ser un interesante problema a resolver: un agente puede enviar varios mensajes, y sería mejora si puede seguir ejecutando sin recibir todas las respuestas a tiempo. Por ejemplo, en una aplicación de un juego de tablero, un agente puede delegar la exploración de un árbol de jugadas a otros agentes, y, luedo de un tiempo, sería posible tomar una decisión, con sólo algunas respuestas recibidas.&lt;/p&gt; &lt;h3&gt;Nubes (&amp;quot;clouds&amp;quot;) en&amp;nbsp;el cielo de la grilla&lt;/h3&gt; &lt;p&gt;Otro caso: un agente puede estar interesado en enviar un mensaje, pero no a un receptor determinado. Al contrario, quiere enviarlo a una &amp;quot;nube&amp;quot; de agentes, así cualquiera interesado en el mensaje tendría la oportunidad de procesarlo.&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/agentsgrid05.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Esta característica puede ser implementada usando estas estrategias:&lt;/p&gt; &lt;p&gt;- Un agente envía un mensaje a un sistema de pizarra (blackboard), que otros agentes están vigilando.&lt;/p&gt; &lt;p&gt;- Una agente enviaría una mensaje a la aplicación host, indicando un tópico (como en una cola de mensajes), así cualquier agente subscripto recibirá el mensaje. Una variante: sólo algunos subscriptores reciben el mensaje, dependiendo de parámetros de aplicación.&lt;/p&gt; &lt;p&gt;- Un agente podría enviar un mensaje dirigido a alguna definición de proveedor de servicio. Un proveedor de servicio es un agente, que declara al comienzo de su vida, sus capacidades y los servicios que puede proveer.&amp;nbsp;&lt;/p&gt; &lt;p&gt;Un ejemplo, tomemos una aplicación de un juego de tablero, ajedrez o go. Un agente en esa aplicación puede enviar un mensaje reclamando resolver cierta posición de ataque. En un sistema de pizarra, publicará el pedido. En un sistema de tópicos, lo enviaría al tópico &amp;quot;ataques&amp;quot;. En una estrategia de proveedor de servicio, envía el mensaje a uno o más de los proveedores del servicio AttackResolver.&lt;/p&gt; &lt;p&gt;Como en el patrón anterior, un agente puede recibir una respuesta asincrónica, ahora desde&amp;nbsp;&amp;quot;la nube&amp;quot;:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/agentsgrid06.png" alt="" /&gt;&amp;nbsp;&lt;/p&gt; &lt;h3&gt;Duplicación de agentes&lt;/h3&gt; &lt;p&gt;Un agente tiene conducta y estado. Si el agente puede dividir su trabajo, podría tomar el camino de duplicarse a sí mismo:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/agentsgrid07.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Es algo extraño, pero podría ser útil, dependiendo de la aplicación a desarrollar.&lt;/p&gt; &lt;h3&gt;Agentes y la Grilla&lt;/h3&gt; &lt;p&gt;Cada agente puede ser albergado en un nodo de la grilla. El mecanismo de envío de mensajes debe ser capaz de enviar un mensaje a otro nodo. La aplicación host mantiene una lista de&amp;nbsp;agentes por identidad, y conoce cúal&amp;nbsp; es local o remoto. Una prueba ácida: una aplicación de grilla con agentes debe ser capaz de correr en una sola máquina, o en una grilla, sin cambiar el código o el algoritmo.&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/agentsgrid08.png" alt="" /&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Como en otras implementaciones de grilla (discutidos en los post que mencioné al principio), un servidor central está a cargo de la distribución de las tareas entre los nodos de la grilla. &amp;quot;Grid as a Service&amp;quot; es una nueva frase que podemos aplicar a esta situación.&lt;/p&gt; &lt;h3&gt;Moviendo al Agente&lt;/h3&gt; &lt;p&gt;Un agente puede iniciar sus actividades en un node. Pero en algún momento, puede decidir de continuar su trabajo en otro nodo (la aplicación host que lo alberga también puede tomar esa decisión, independientemente del agente). Entonces, su estado sería enviado de un nodo a otro (otro caso: podría querer duplicarse y que su clon siga el trabajo en otra máquina).&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/agentsgrid10.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Noten que la conducta del agente (que puede estar compilada o puede estar escrita en un lenguaje dinámico o de agente), no viaja. Pero bien podría ser que viaje, incluso, que haya agentes que vayan adaptando su conducta en el tiempo.&lt;/p&gt; &lt;h3&gt;Inyectando conducta&lt;/h3&gt; &lt;p&gt;La conducta de cada agente podría ser expresada en código compilado (archivos .jar en Java, assemblies en .NET). Otras alternativas son posibles: la conducta podría ser especificada en un lenguaje de scripting dedicado a agentes (pienso en una adaptación del AjBasic, por ejemplo).&lt;/p&gt; &lt;p&gt;Si la conducta se expresa en forma compilada, uno o varios servers puede tomar la responsabilidad de almacenar y distribuir esos componentes:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/agentsgrid09.png" alt="" /&gt; &lt;/p&gt; &lt;h3&gt;Ideas de implementación&lt;/h3&gt; &lt;p&gt;Muchas de estas ideas pueden ser implementadas en cualquier lenguaje/tecnología apropiada, como Java y .NET, que soporte múltiples threads, invocación remota, serialización de mensajes, etc... &lt;/p&gt; &lt;p&gt;En los últimos tiempos estuve trabajando en mis projectos AjMessages y AjAgents, más información enestos post:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2007/10/22/ajmessages-hacia-un-procesador-de-mensajes.aspx"&gt;&lt;/a&gt;&lt;a href="http://ajlopez.wordpress.com/2007/10/18/ajmessages-a-message-processor/"&gt;AjMessages: a message&amp;nbsp;processor &lt;/a&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2007/10/20/agentes-usando-concurrency-and-coordination-runtime-ccr.aspx"&gt;&lt;/a&gt;&lt;a href="http://ajlopez.wordpress.com/2007/10/17/agents-using-concurrency-and-coordination-runtime-ccr/"&gt;Agents using Concurrency and Coordination Runtime&amp;nbsp;(CCR) &lt;/a&gt; &lt;p&gt;&lt;a title="AjMessages- hacia un procesador de mensajes" href="http://msmvps.com/blogs/lopez/archive/2007/10/22/ajmessages-hacia-un-procesador-de-mensajes.aspx"&gt;AjMessages- hacia un procesador de mensajes&lt;/a&gt; &lt;p&gt;&lt;a title="Agentes usando Concurrency and Coordination Runtime (CCR)" href="http://msmvps.com/blogs/lopez/archive/2007/10/20/agentes-usando-concurrency-and-coordination-runtime-ccr.aspx"&gt;Agentes usando Concurrency and Coordination Runtime (CCR)&lt;/a&gt; &lt;p&gt;&lt;a title="Algoritmos Gen&amp;eacute;ticos con AjAgents y Concurrency and Coordination Runtime (CCR)" href="http://msmvps.com/blogs/lopez/archive/2008/04/13/algoritmos-gen-233-ticos-con-ajagents-y-concurrency-and-coordination-runtime-ccr.aspx"&gt;Algoritmos Genéticos con AjAgents y Concurrency and Coordination Runtime (CCR)&lt;/a&gt; &lt;p&gt;&lt;a title="Genetic Algorithms with AjAgents and Concurrency and Coordination Runtime (CCR)" href="http://ajlopez.wordpress.com/2008/04/10/genetic-algorithms-with-ajagents-and-concurrency-and-coordination-runtime-ccr/"&gt;Genetic Algorithms with AjAgents and Concurrency and Coordination Runtime (CCR)&lt;/a&gt; &lt;p&gt;(Tengo otro proyecto, AjGrid, no publicado aún). Para este post, creo que el AjAgents podría ser una implementación de esas ideas. AjMessages tiene ahora soporte de ejecución remota, pero está más orientado a un proceso tubería (&amp;quot;pipeline&amp;quot;): es más difícil de implementar en semejante sistemas las ideas de este post.&lt;/p&gt; &lt;p&gt;Estoy agregando algunas características a AjAgents (ahora, AjAgents trabaja sólo en local):&lt;/p&gt; &lt;p&gt;- &lt;strong&gt;Configuración&lt;/strong&gt;: Carga y creación de agentes en ejecución, según alguna información de configuración, ya sea al inicio o en el medio de la ejecución.&lt;/p&gt; &lt;p&gt;- &lt;strong&gt;Assembly remoto&lt;/strong&gt;: Así un nodo de grilla pueder ser inyectado con nuevos agentes.&lt;/p&gt; &lt;p&gt;- &lt;strong&gt;Identificación de Agente&lt;/strong&gt;: Para identificar al agente de manera única (un UID debería bastar).&lt;/p&gt; &lt;p&gt;- &lt;strong&gt;Transporte de mensaje&lt;/strong&gt;: Windows Communication Foundation es un candidato, otro podría ser DSSP.&lt;/p&gt; &lt;p&gt;Un posible camino es tomar Decentralized System Services (DSS) del Microsoft Robotics Developer Studio. Un agente podría ser implementado como un servicio de DSS, ejecutando en un host DSS. La comunicación entre máquinas puede ser implementada usando DSSP como protocolo.&lt;/p&gt; &lt;p&gt;&amp;quot;Stay tuned&amp;quot;, vendrá más código.&lt;/p&gt; &lt;p&gt;(Esta es una actualización y traducción de mi post en &amp;quot;Anglish&amp;quot;, Angel&amp;#39;s English:&lt;/p&gt; &lt;p&gt;&lt;a title="Agents in a Grid" href="http://ajlopez.wordpress.com/2008/01/03/agents-in-a-grid/"&gt;Agents in a Grid&lt;/a&gt;&lt;/p&gt; &lt;p&gt;)&lt;/p&gt; &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/en"&gt;http://www.ajlopez.com/en&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1617275" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjMessages/default.aspx">AjMessages</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Grid+Computing/default.aspx">Grid Computing</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjAgents/default.aspx">AjAgents</category></item><item><title>Algoritmos Genéticos con AjAgents y Concurrency and Coordination Runtime (CCR)</title><link>http://msmvps.com/blogs/lopez/archive/2008/04/13/algoritmos-gen-233-ticos-con-ajagents-y-concurrency-and-coordination-runtime-ccr.aspx</link><pubDate>Sun, 13 Apr 2008 15:03:48 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1585477</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1585477</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/04/13/algoritmos-gen-233-ticos-con-ajagents-y-concurrency-and-coordination-runtime-ccr.aspx#comments</comments><description>&lt;p&gt;El año pasado había implementado un ejemplo con AjAgents usando CCR:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2007/10/20/agentes-usando-concurrency-and-coordination-runtime-ccr.aspx" target="_blank"&gt;Agentes usando Concurrency and Coordination Runtime (CCR)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ajlopez.wordpress.com/2007/10/17/agents-using-concurrency-and-coordination-runtime-ccr/" target="_blank"&gt;Agents using Concurrency and Coordination Runtime (CCR)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Escribí en mi blog en &amp;quot;anglish&amp;quot; (Angel&amp;#39;s English) algunas ideas para explorar:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/2008/01/03/agents-in-a-grid/" target="_blank"&gt;Agents in a Grid&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Recordemos que Concurrency and Coordination Runtime es parte de Microsoft Robotics Studio, puede leer más sobre esta librería en&lt;/p&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/msdnmag/issues/06/09/ConcurrentAffairs/default.aspx" target="_blank"&gt;Concurrent Affairs: Concurrency and Coordination Runtime&lt;/a&gt;&lt;/p&gt; &lt;p&gt;y consultar mis enlaces de Delicious&lt;/p&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/ccr"&gt;http://del.icio.us/ajlopez/ccr&lt;/a&gt;&lt;br /&gt;&lt;a href="http://del.icio.us/ajlopez/msrs"&gt;http://del.icio.us/ajlopez/msrs&lt;/a&gt;&lt;/p&gt; &lt;p&gt;En estos días, extendí mi ejemplo &lt;a title="AjAgentsCCR-0.1.zip" href="http://www.ajlopez.com/downloads/AjAgentsCCR-0.1.zip"&gt;AjAgentsCCR-0.1.zip&lt;/a&gt;&amp;nbsp;con dos nuevos proyectos. Uno de consola AjAgents.Genetic01, y otro de ventanas AjAgents.WinGenetic01:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajagentsga02.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;La idea básica es ejecutar un algoritmo genético usando agentes, los elementos de AjAgents, que se envían mensajes usando ports de CCR. Cada agente procesa sus mensajes entrantes, y envía mensajes salientes a otros agentes, en paralelo. El problema que encaro es el clásico &lt;a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem" target="_blank"&gt;Travelling Salesman Problem&lt;/a&gt;. Leo en la Wikipedia:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;If a salesman starts at point A, and if the distances between every pair of points are known, what is the shortest route which visits all points and returns to point A?&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;La ventana de ejemplo es sencilla:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajagentsga01.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;La clase Genoma representa el viaje&amp;nbsp;(una lista de Points y un valor de distancia total):&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:4d8bdf80-11fc-428c-bfba-85e5d279f9c0" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Genoma
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; List&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Point&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; travel &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; List&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Point&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;();
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; value;
    }

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Point
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; x;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; y;
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Al comenzar la ejecución, los agentes son creados y conectados:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:2a22c08b-84d4-4d08-b508-f9fb3b2b8e77" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;            best &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; BestSoFar();
            evaluator &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Evaluator();
            mutator &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Mutator();
            collector &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Collector();

            evaluator.Collector &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; collector;
            collector.Mutator &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; mutator;
            collector.Evaluator &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; evaluator;
            collector.BestSoFar &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; best;
            mutator.Evaluator &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; evaluator;
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Un genoma inicial es creado:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:deb88aff-6fe9-42b9-9f78-a48ef43ef78a" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;            Genoma genoma &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Genoma();
            Random rnd &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Random();

            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; k &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;40&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k&lt;/span&gt;&lt;span style="color:#000000;"&gt;++&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
                {
                    Point pt &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Point();
                    pt.x &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; rnd.Next(&lt;/span&gt;&lt;span style="color:#000000;"&gt;12&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
                    pt.y &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; rnd.Next(&lt;/span&gt;&lt;span style="color:#000000;"&gt;12&lt;/span&gt;&lt;span style="color:#000000;"&gt;);

                    genoma.travel.Add(pt);
                }

            genoma.value &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; evaluator.CalculateValue(genoma);
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;El agente BestSoFar dispara un evento. El formulario se registra como observador de ese evento, para refrescar el mejor viaje calculado y dibujarlo. El programa envía el genoma inicial generado al agente Mutator, varias veces, para generar la primeras poblaciones:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:79e9473d-f8f8-4426-8281-75c536583015" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;            best.NewBest &lt;/span&gt;&lt;span style="color:#000000;"&gt;+=&lt;/span&gt;&lt;span style="color:#000000;"&gt; BestGenoma;

            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; k &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;60&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k&lt;/span&gt;&lt;span style="color:#000000;"&gt;++&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
            {
                mutator.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Mutate&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, genoma);
            }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Noten el uso del método Post, básico en AjAgents. Cada agente implementa ese método, que invoca&amp;nbsp;un método en el agente,&amp;nbsp;usando una puerta de CCR para invocar el método final. El método es ejecutado entonces no en el momento, sino en&amp;nbsp;forma &amp;quot;paralela&amp;quot;, en un thread&amp;nbsp;que maneja el pool de threads de CCR.&lt;/p&gt;
&lt;p&gt;Un diagrama simple para explicar la interacción entre agentes:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajagentsga03.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;El Mutator envía cada genoma al Evaluator. Este agente calcula el valor asignado a ese genoma. Lo envía a el Collector. Este implementa una nueva idea para este ejemplo: en vez de tener una clase Population o similar, el Collector recive genomas, y cuando tiene n o más genomas, determina los mejores del conjunto, envía el mejor a BestSoFar, y reenvía los mejores a Mutator, para generar una nueva lista de genomas a evaluar.&amp;nbsp;Como método típico de ejemplo, tomemos uno de la clase Collector:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:f7ff20f4-a441-44e2-86a5-ebad4bd4b4ba" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessList(List&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Genoma&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; list)
        {
            list.Sort(comparer);

            bestsofar.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Process&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,list[&lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;]);

            evaluator.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Evaluate&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,list[&lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;]);
            evaluator.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Evaluate&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,list[&lt;/span&gt;&lt;span style="color:#000000;"&gt;1&lt;/span&gt;&lt;span style="color:#000000;"&gt;]);

            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; k &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;4&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k&lt;/span&gt;&lt;span style="color:#000000;"&gt;++&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
            {
                mutator.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Mutate&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,list[k]);
                mutator.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Mutate&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,list[k]);
            }
        }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Tengo que mejorar el algoritmo genético. Ahora, sólo usa mutación, sin hacer &amp;quot;crossover&amp;quot; (cruzamiento) entre los mejores genomas. El resultado que consigue ahora, no es óptimo: puede dar como resultado un máximo local, pero no la mejor solución. La idea del ejemplo es ver ejecutando AjAgents con CCR, en una prueba de concepto.&lt;/p&gt;
&lt;h3&gt;Conclusiones&lt;/h3&gt;
&lt;p&gt;Uno puede ver cada agente como una pequeña célula u organismo, que reacciona a mensajes externos y envía mensajes a otros agentes. Cada agente está levemente acoplado a los demás. En estos ejemplos, los agentes son creados y relaciones por código, pero bien podrían ser creados y relacionados usando algún framework de inyección de dependencias, como &lt;a href="http://www.springframework.net" target="_blank"&gt;Spring.NET&lt;/a&gt; o el nuevo&amp;nbsp;&lt;a href="http://msdn2.microsoft.com/en-us/library/cc468366.aspx" target="_blank"&gt;Unity Application Block&lt;/a&gt; de Microsoft.&lt;/p&gt;
&lt;p&gt;En lugar de usar solamente ports de CCR, podría escribir los agentes como&amp;nbsp; DSS Service components (ver &lt;a href="http://www.microsoft.com/robotics" target="_blank"&gt;Microsoft Robotics Studio&lt;/a&gt; para más información sobre DSS); el algoritmo podría ser distribuido en una grilla (&amp;quot;gridified&amp;quot;) y cada agente interactuar con otros, independientemente de su ubicación..&lt;/p&gt;
&lt;p&gt;Pero eso es otra historia....;-)&lt;/p&gt;
&lt;p&gt;En esta semana, ha sido anunciada la nueva versión de Microsoft Robotics Developer Studio 2008:&lt;/p&gt;
&lt;p&gt;&lt;a title="http://blogs.msdn.com/msroboticsstudio/archive/2008/04/09/microsoft-robotics-developer-studio-2008-ctp-april-available.aspx" href="http://blogs.msdn.com/msroboticsstudio/archive/2008/04/09/microsoft-robotics-developer-studio-2008-ctp-april-available.aspx"&gt;http://blogs.msdn.com/msroboticsstudio/archive/2008/04/09/microsoft-robotics-developer-studio-2008-ctp-april-available.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;La tercera nueva característica ahí anunciada, sería muy interesante para implementar &amp;quot;miniagentes&amp;quot; distribuidos:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Support for creating applications that run on multiple DSS nodes using Visual Programming Language and DSS Manifest Editor. This makes it much simpler to create applications that run across nodes, either on the same machine or across the network. When an application containing multiple nodes is to be started, VPL creates individual deploy packages for each node and fires them up across the network.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;(este artículo es la versión en español de mi versión &amp;quot;anglish&amp;quot;:&lt;br /&gt;&lt;a href="http://ajlopez.wordpress.com/2008/04/10/genetic-algorithms-with-ajagents-and-concurrency-and-coordination-runtime-ccr/" target="_blank"&gt;Genetic Algorithms with AjAgents and Concurrency and Coordination Runtime (CCR)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1585477" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjAgents/default.aspx">AjAgents</category></item><item><title>Agentes usando Concurrency and Coordination Runtime (CCR)</title><link>http://msmvps.com/blogs/lopez/archive/2007/10/20/agentes-usando-concurrency-and-coordination-runtime-ccr.aspx</link><pubDate>Sat, 20 Oct 2007 00:24:29 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1251823</guid><dc:creator>lopez</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1251823</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2007/10/20/agentes-usando-concurrency-and-coordination-runtime-ccr.aspx#comments</comments><description>&lt;p&gt;En estos días, escribí un ejemplo mínimo, para explorar algunas ideas, usando el Concurrency and Coordination Runtime, la librería de Microsoft library&amp;nbsp;que viene en&amp;nbsp;su Robotics Studio. Más sobre CCR en el artículo:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/msdnmag/issues/06/09/ConcurrentAffairs/default.aspx" target="_blank"&gt;Concurrent Affairs: Concurrency and Coordination Runtime&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Mi idea es implementar el pase de mensajes entre componentes, de manera asincrónica. El código de ejemplo puede bajarse de &lt;a href="http://www.ajlopez.com/downloads/AjAgentsCCR-0.1.zip"&gt;AjAgentsCCR-0.1.zip&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;El agente&lt;/h3&gt; &lt;p&gt;En el ejemplo, la interfaz a implementar por cada componente, que llamamos agente, es:&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:e34cc818-2db0-4674-b32e-9afb83a6646e" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;delegate&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ReturnHandler&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;T&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(T t);

&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;interface&lt;/span&gt;&lt;span style="color:#000000;"&gt; IAgent
{
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Post(Message msg);
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Post(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; action, 
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;params&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt;[] parameters);
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Post&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;T&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; action, 
        ReturnHandler&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;T&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; handler, 
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;params&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt;[] parameters);
}
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;El agente puede recibir mensajes (que son objetos de una clase Message, ver más abajo). En el mensaje viene un texto con la Action a ejecutar (como si fuera un nombre de método) y una lista&amp;nbsp;variable de parámetros.&lt;/p&gt;
&lt;p&gt;El tercer método Post implementa un delegado, un método a ejecutar cuando el envío del mensaje produce una respuesta, un valor de retorno. Esa vuelta se produce en el futuro, no se queda esperando la respuesta. Podemos enviar un mensaje a otro agente, sin esperar la respuesta, o podemos escribir el delegado para procesar esa respuesta cuando llegue.&lt;/p&gt;
&lt;h3&gt;El mensaje&lt;/h3&gt;
&lt;p&gt;Es una clase con&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font color="#333333"&gt;&lt;strong&gt;action&lt;/strong&gt;: un nombre que identifica la acción asociada al mensaje&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#333333"&gt;&lt;strong&gt;body&lt;/strong&gt;: el contenido del mensaje&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#333333"&gt;&lt;strong&gt;response port&lt;/strong&gt;: la puerta CCR donde enviar el valor de retorno, si es necesario&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;He aquí el código de esta clase:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:6965b573-91b2-438f-98bd-aef1e84dce57" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Message
{
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; action;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; Action
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt; { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; action; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt; { action &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; value; }
    }

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; body;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; Body
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt; { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; body; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt; { body &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; value; }
    }

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; Port&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; returnport;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;internal&lt;/span&gt;&lt;span style="color:#000000;"&gt; Port&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; ReturnPort
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt; { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; returnport; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt; { returnport &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; value; }
    }
    

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Message()
    {
    }

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Message(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; action)
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.action &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; action;
    }

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Message(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; action, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; body)
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.action &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; action;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.body &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; body;
    }

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Message(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; action, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt;[] bodyvalues)
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.action &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; action;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (bodyvalues &lt;/span&gt;&lt;span style="color:#000000;"&gt;!=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color:#000000;"&gt; bodyvalues.Length &lt;/span&gt;&lt;span style="color:#000000;"&gt;==&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;1&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.body &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; bodyvalues[&lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;];
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.body &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; bodyvalues;
    }
}
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Notemos que el mensaje tiene&amp;nbsp;puede manejar un arreglo de valores en el body, y que puede enviar un objeto dentro de&amp;nbsp;su contenido.&lt;/p&gt;
&lt;h3&gt;La implementación&lt;/h3&gt;
&lt;p&gt;En este ejemplo inicial, la interfaz IAgent tiene una implementación basado en Invoke, via Reflection, que termina invocando un método en el agente, que tiene el mismo nombre que la acción recibida. Se pueden pensar otras formas de manejar el mensaje, pero esta manera permite codificar el agente como una clase más, con métodos normales.&lt;/p&gt;
&lt;p&gt;El mensaje, una vez recibido, se coloca en una puerta CCR, para que se pueda manejar de manera asincrónica. Hay un Receive arbiter de CCR para atender los mensajes entrantes, que son ruteados al correspondiente método en el objeto.&lt;/p&gt;
&lt;p&gt;Creo que es una solución interesante: se puede escribir una clase con métodos normales, y convertirla en agente, heredando de la clase Agent.&lt;/p&gt;
&lt;p&gt;Podemos enviar un mensaje con&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:b915dcf3-1163-4974-87f5-96ffeff4e3a1" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;agent1.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Decrement&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,&lt;/span&gt;&lt;span style="color:#000000;"&gt;20&lt;/span&gt;&lt;span style="color:#000000;"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Puede &amp;quot;consultar&amp;quot; algún valor con:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:263c231a-b09a-43ba-89e6-feec1f546fef" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;agent1.Post&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;GetCounter&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, PrintCounter);
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Próximos pasos&lt;/h3&gt;
&lt;p&gt;Estoy trabajando en:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Escribir un&amp;nbsp;Enviroment, o clase Host, donde los agentes &amp;quot;vivan&amp;quot;. El Host sería responsable de mantener una lista de agentes por nombre. 
&lt;li&gt;Escribir un archivo de configuración donde pueda especificar qué agentes crear y cargar a comenzar a funcionar el Environment o Host, y que los relacione usando alguna implementación de inyección de dependencias. Me imagino servidores de agentes que pueda cargar un agente remoto de assemblies que se encuentren en otros servidores de la red. 
&lt;li&gt;Usar estos agentes en forma distribuida, con&amp;nbsp;Windows Communication Foundation (WCF), o con&amp;nbsp;Decentralized System Services (DSS). En este último caso, un servicio DSS podría ser un agente o podría representar la entrada a un Environment 
&lt;li&gt;Implementar&amp;nbsp;algún&amp;nbsp;patrón Subscribe/Notify entre agentes.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1251823" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjAgents/default.aspx">AjAgents</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp.NET/default.aspx">C Sharp.NET</category></item></channel></rss>