<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-15964854</id><updated>2011-11-28T00:53:16.080+01:00</updated><category term='Coding'/><category term='Python'/><category term='Reading'/><category term='MSR'/><category term='Logtalk'/><category term='GCD'/><category term='NLP'/><category term='ProjectEuler'/><category term='CCR'/><category term='SourceControl'/><category term='Prime'/><category term='lists'/><category term='F#'/><category term='Robotics'/><category term='Prolog'/><category term='Prolog environments'/><category term='MRS'/><category term='C#'/><category term='Terrarium'/><category term='3D'/><category term='General'/><category term='AI'/><category term='VPL'/><category term='Terrarium2'/><category term='Link'/><category term='Lectures'/><category term='DSS'/><category term='.NET'/><category term='Fibonacci'/><title type='text'>Bittis Blog - ramblings of a (half) bitter mind</title><subtitle type='html'>Musings on the beauty of computer science - (AI, ML, NLP, CG) - stumbled upon using Prolog, F# and other exotics</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>46</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-15964854.post-5664585249898991737</id><published>2009-12-18T01:44:00.011+01:00</published><updated>2009-12-18T05:18:13.238+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Logtalk'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><title type='text'>Logtalk - Hello World</title><content type='html'>According to the SWI-Prolog Mailing List, ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;Logtalk is an object-oriented logic programming language that can use most&lt;br /&gt;Prolog implementations as a back-end compiler. As a multi-paradigm language, it includes support for both prototypes and classes, protocols (interfaces), component-based programming through category-based composition, event-driven programming, and high-level multi-threading programming.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/blockquote&gt;For this, it seems worth trying Logtalk in order to lift Prolog programming to a different level (more contained). As usually, the first program show-casing some programming language is the famous "hello world" program. Unlike, other programming languages the Prolog version of "hello world" is a family relation.&lt;br /&gt;&lt;br /&gt;Since this post is merely to maintain flow, I will present a "hello world" in Logtalk. Logtalk helps decomposing program logic by offering the well known concept of object and interface (including visibility of object members).&lt;br /&gt;&lt;br /&gt;Behold .. the magic "hello world":&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;:- object(first_program).&lt;br /&gt;  :- public(main/1).&lt;br /&gt;&lt;br /&gt;  hello_world(Text) :- write(Text), nl.&lt;br /&gt;&lt;br /&gt;  main(Text) :-&lt;br /&gt;    hello_world(Text).&lt;br /&gt;&lt;br /&gt;:- end_object.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;As can be guessed, the program is quite simple. An object called &lt;span style="font-family:courier new;"&gt;first program&lt;/span&gt; is declared,&lt;br /&gt;offering a publicly visible method called &lt;span style="font-family:courier new;"&gt;main&lt;/span&gt;. &lt;span style="font-family:courier new;"&gt;main&lt;/span&gt; passes one argument, i.e. some text to print, to the famous &lt;span style="font-family:courier new;"&gt;hello_world&lt;/span&gt; procedure. &lt;span style="font-family:courier new;"&gt;hello_world&lt;/span&gt; calls Prolog's &lt;span style="font-family:courier new;"&gt;write&lt;/span&gt; function to write the passed text on some line, adding a newline at the end of the text.&lt;br /&gt;&lt;br /&gt;After consulting the program, one may call &lt;span style="font-family:courier new;"&gt;main&lt;/span&gt; using&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;first_program::main('Hello World').&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-5664585249898991737?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://logtalk.org' title='Logtalk - Hello World'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/5664585249898991737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=5664585249898991737' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/5664585249898991737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/5664585249898991737'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/12/logtalk-hello-world.html' title='Logtalk - Hello World'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-1626021026301262411</id><published>2009-10-04T12:35:00.001+02:00</published><updated>2009-10-04T12:35:21.727+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='General'/><title type='text'>Prolog – Mindstorms (I)</title><content type='html'>&lt;p&gt;The last friday, I received my Lego Mindstorms NXT 2.0 – THANKS! Unfortunately, I lack the necessary power supply in form of 6AA batteries. Clearly, I went to my favorite retailer – Amazon – and ordered a couple of rechargeable ones (including the recharger). &lt;/p&gt;  &lt;p&gt;Since my mind is somehow attached to Prolog, I asked myself would it be possible to do the mind-storming in Prolog … so I fired up the information retrieval engine of the day … and hit:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;[English] New Mexico State University: &lt;strong&gt;Building and Programming Robots&lt;/strong&gt;       &lt;br /&gt;&lt;a title="http://www.cs.nmsu.edu/~tson/classes/fall03-579/schedule.htm" href="http://www.cs.nmsu.edu/~tson/classes/fall03-579/schedule.htm"&gt;http://www.cs.nmsu.edu/~tson/classes/fall03-579/schedule.htm&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;[German] University of Potsdam: &lt;strong&gt;Programmieren in Prolog&lt;/strong&gt;       &lt;br /&gt;&lt;a title="http://www.cs.uni-potsdam.de/wv/03SS/aktuell.html#SECTION00051000000000000000" href="http://www.cs.uni-potsdam.de/wv/03SS/aktuell.html#SECTION00051000000000000000"&gt;http://www.cs.uni-potsdam.de/wv/03SS/aktuell.html#SECTION00051000000000000000&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;[German] Toni Gläser: &lt;strong&gt;LEGOLOG - Lego Mindstorms und ein Golog-Planer Eine Einführung und ein Überblick über das Konzept und die        &lt;br /&gt;Programmierung sowie die Implementation von Aufgaben für         &lt;br /&gt;den Roboter&lt;/strong&gt;       &lt;br /&gt;&lt;a title="http://www.kbs.uni-hannover.de/~brase/Paper/studienarbeit_Prolog.pdf" href="http://www.kbs.uni-hannover.de/~brase/Paper/studienarbeit_Prolog.pdf"&gt;http://www.kbs.uni-hannover.de/~brase/Paper/studienarbeit_Prolog.pdf&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;[English] Fermé and Gaspar: &lt;strong&gt;RCX+PROLOG        &lt;br /&gt;A platform to use Lego Mindstorms™ Robots in         &lt;br /&gt;Artificial Intelligence courses&lt;/strong&gt;       &lt;br /&gt;&lt;a title="http://dme.uma.pt/ferme/Papers/Ferme-Gaspar07.pdf" href="http://dme.uma.pt/ferme/Papers/Ferme-Gaspar07.pdf"&gt;http://dme.uma.pt/ferme/Papers/Ferme-Gaspar07.pdf&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;[English] University of Toronto: &lt;strong&gt;Cognitive Robotics&lt;/strong&gt;       &lt;br /&gt;&lt;a title="http://www.cs.toronto.edu/cogrobo/main/systems/index.html" href="http://www.cs.toronto.edu/cogrobo/main/systems/index.html"&gt;http://www.cs.toronto.edu/cogrobo/main/systems/index.html&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;[English] Nalepa: &lt;strong&gt;Prototype Prolog API for Mindstorms NXT        &lt;br /&gt;&lt;a title="http://www.springerlink.com/content/9r47108w18835742/" href="http://www.springerlink.com/content/9r47108w18835742/"&gt;http://www.springerlink.com/content/9r47108w18835742/&lt;/a&gt;&lt;/strong&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Clearly, I will inspect some of these resources soon to see what’s in the Lego Prolog toolbox. Until then happy robot-building.&lt;/strong&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-1626021026301262411?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/1626021026301262411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=1626021026301262411' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/1626021026301262411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/1626021026301262411'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/10/prolog-mindstorms-i.html' title='Prolog – Mindstorms (I)'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-3404064180069882845</id><published>2009-09-12T11:24:00.002+02:00</published><updated>2009-09-12T11:29:00.154+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Reading'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='NLP'/><title type='text'>Adventures In Prolog - General Reading (2)</title><content type='html'>Since I have not posted anything for while, I thought I keep the flow running, by pointing to &lt;a href="http://www.wollie.pwp.blueyonder.co.uk/docs/Document%20Analysis%20Experiment%20-%20Final.htm"&gt;Boehm's "Document Analysis Experiment"&lt;/a&gt;  - applied NLP using Prolog.&lt;br /&gt;&lt;br /&gt;Taken from the Overview section:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;The main purpose of this document analysis program is to count the number of useful words in the document in various ways, and to use NLP to (hopefully)&lt;br /&gt;improve the analysis.&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;You may find his project useful and interesting - so happy reading. &lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-3404064180069882845?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.wollie.pwp.blueyonder.co.uk/docs/Document%20Analysis%20Experiment%20-%20Final.htm' title='Adventures In Prolog - General Reading (2)'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/3404064180069882845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=3404064180069882845' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/3404064180069882845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/3404064180069882845'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/09/adventures-in-prolog-general-reading-2.html' title='Adventures In Prolog - General Reading (2)'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-8177164262876832325</id><published>2009-08-18T23:44:00.005+02:00</published><updated>2009-08-19T00:11:00.638+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ProjectEuler'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><title type='text'>Adventures In Prolog - ProjectEuler20</title><content type='html'>Continuing with the Euler Quest, a simple and straight-forward solution to Project Euler's problem 20 is presented.&lt;br /&gt;&lt;br /&gt;The problem statement reads:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Find the sum of the digits in the number 100!&lt;/blockquote&gt; Where ! denotes the faculty operator.&lt;br /&gt;&lt;br /&gt;One (simple) way to solve the problem goes as follows:&lt;br /&gt;&lt;br /&gt;Firstly, calculate the value of 100!. Secondly, convert the value into a list of digits. Thirdly, sum each digit. Lastly, output the cumulative result.&lt;br /&gt;&lt;br /&gt;A translation of this solution may read like:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;euler_20_1(F, Out) :-&lt;br /&gt;  fac(F, Fac),&lt;br /&gt;  string_to_list(Fac, CList),&lt;br /&gt;  euler_20_1_t(CList, 0, Out), !.&lt;br /&gt;&lt;br /&gt;euler_20_1_t([], Current, Current).&lt;br /&gt;&lt;br /&gt;euler_20_1_t([X|Y], Current, Out) :-&lt;br /&gt;  number_chars(N, [X]),&lt;br /&gt;  NewCurrent is Current + N,&lt;br /&gt;  euler_20_1_t(Y, NewCurrent, Out).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The fac predicate computes the faculty of some positive integer number. string_to_list is a built-in predicate converting a string into its character list representation and number chars converts between ascii character code and number. Building only on these relatively few predicates the code should be straight-forward.&lt;br /&gt;&lt;br /&gt;Please note, that this solution is not the most efficient, in fact it may not work for very large numbers. To reduce the complexity of the faculty operation, we might additional knowledge like:&lt;br /&gt;&lt;br /&gt;multiplying a number n by a multiply of 10 (n mod 10 = 0), does not change the value of the sum of the digits of the result. For example&lt;br /&gt;&lt;br /&gt;3*4*10 = 120 but sum_digit(3*4*10) = sum_digit(3*4*100) = sum_digit(3*4) = 3&lt;br /&gt;&lt;br /&gt;Now building on such knowledge, one might cut all numbers that multiplied together yield a multiply of 10 from the faculty operation. This approach will be covered in a future post.&lt;br /&gt;&lt;br /&gt;On a different side node, a Prolog implementation of the Porter stemming algorithm can be found &lt;a href="http://tartarus.org/~martin/PorterStemmer/prolog.txt"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-8177164262876832325?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://projecteuler.net' title='Adventures In Prolog - ProjectEuler20'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/8177164262876832325/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=8177164262876832325' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/8177164262876832325'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/8177164262876832325'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/08/adventures-in-prolog-projecteuler20.html' title='Adventures In Prolog - ProjectEuler20'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-8867802811088661172</id><published>2009-08-18T10:06:00.005+02:00</published><updated>2009-08-19T00:12:03.876+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Prime'/><category scheme='http://www.blogger.com/atom/ns#' term='ProjectEuler'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><title type='text'>Adventures In Prolog - Euler7 and the Nth Prime</title><content type='html'>Building on our previous prime-related posts, today's post will cover a solution to Project Euler's 7th Problem, i.e. finding the 10001st prime. Now, the solution to this problem can be easily expressed in thought and then converted to some programming language …&lt;br /&gt;&lt;br /&gt;Starting with the lowest and first prime – 2 - , we check each subsequent number j &gt; i, for primality. Whenever we find a j such that j is prime, we increment a prime counter c by one and continue testing numbers k &gt; j. This is done until c reaches the number 10001.&lt;br /&gt;&lt;br /&gt;The Prolog code below is an expression of this idea, added with some prime numbers found during the process of finding the 10001st prime. This means, given the border of some prime interval, i.e. 100th prime = i and 200th prime = j, we may start looking for the 150th prime within the number interval [i,j], instead of starting at 2 and checking each number until the prime counter reaches 150. Also, we might have defined the euler_7 predicate to be dynamic, i.e. updatable, such that whenever we find some kth prime, it will be stored in the fact database.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;%EULER7 the 10001 prime&lt;br /&gt;euler_7(4409, 600) :- !.&lt;br /&gt;&lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  Xth &lt; 600, !,&lt;br /&gt;  euler_7_t(2, 1, Xth, Out).&lt;br /&gt;&lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  Xth &lt; 700, !,&lt;br /&gt;  euler_7_t(4409, 600, Xth, Out).&lt;br /&gt;&lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  Xth &lt; 1000, !,&lt;br /&gt;  euler_7_t(5279, 700, Xth, Out).&lt;br /&gt;&lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  Xth &lt; 1100, !,&lt;br /&gt;  euler_7_t(7917, 1000, Xth, Out).&lt;br /&gt;&lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  Xth &lt; 1200, !,&lt;br /&gt;  euler_7_t(8831, 1100, Xth, Out).&lt;br /&gt;&lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  Xth &lt; 1500, !,&lt;br /&gt;  euler_7_t(9733, 1200, Xth, Out).&lt;br /&gt;&lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  Xth &lt; 2000, !,&lt;br /&gt;  euler_7_t(12553, 1500, Xth, Out).&lt;br /&gt;&lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  Xth &lt; 3000, !,&lt;br /&gt;  euler_7_t(17389, 2000, Xth, Out).&lt;br /&gt;&lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  Xth &lt; 4000, !,&lt;br /&gt;  euler_7_t(27449, 3000, Xth, Out).&lt;br /&gt;  &lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  Xth &lt; 5000, !,&lt;br /&gt;  euler_7_t(37813, 4000, Xth, Out).&lt;br /&gt;&lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  Xth &lt; 7000,&lt;br /&gt;  euler_7_t(48611, 5000, Xth, Out), !.&lt;br /&gt;&lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  Xth &lt; 10001,&lt;br /&gt;  euler_7_t(70657, 7000, Xth, Out), !.&lt;br /&gt;&lt;br /&gt;euler_7(Out, Xth) :-&lt;br /&gt;  euler_7_t(104743, 10001, Xth, Out), !.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;euler_7_t(P, Xth, Xth, P) :-&lt;br /&gt;  is_prime(P), !.&lt;br /&gt;  &lt;br /&gt;euler_7_t(NP, Xth, Xth, P) :-&lt;br /&gt;  NewPrime is NP + 1,&lt;br /&gt;  euler_7_t(NewPrime, Xth, Xth, P), !.&lt;br /&gt;&lt;br /&gt;euler_7_t(X, Xth, Gth, Prime) :-&lt;br /&gt;  is_prime(X),&lt;br /&gt;  Y is X + 1,&lt;br /&gt;  Yth is Xth + 1,&lt;br /&gt;  euler_7_t(Y, Yth, Gth, Prime), !.&lt;br /&gt;&lt;br /&gt;euler_7_t(X, Xth, Gth, Prime) :-&lt;br /&gt;  Y is X + 1,&lt;br /&gt;  euler_7_t(Y, Xth, Gth, Prime).&lt;br /&gt;%EULER7 the 10001 prime&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-8867802811088661172?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://projecteuler.net' title='Adventures In Prolog - Euler7 and the Nth Prime'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/8867802811088661172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=8867802811088661172' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/8867802811088661172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/8867802811088661172'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/08/adventures-in-prolog-euler7-and-nth.html' title='Adventures In Prolog - Euler7 and the Nth Prime'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-3343913557530516043</id><published>2009-07-09T10:10:00.012+02:00</published><updated>2009-07-09T13:16:38.513+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prime'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='GCD'/><title type='text'>Adventures in Prolog - Some more Primes</title><content type='html'>Again, we are going to tackle some problems mentioned in the list of 99-Prolog problems. Today's post builds upon the gcd predicate defined last time to attack problems:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;P31 = is_prime&lt;/li&gt;&lt;br /&gt;&lt;li&gt;P35 = prime_factors&lt;/li&gt;&lt;br /&gt;&lt;li&gt;P36 = prime_factors_mult&lt;/li&gt;&lt;br /&gt;&lt;li&gt;P39 = prime_list&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;Now, building on the previously defined gcd predicate, on may define a prime inductively:&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;a prime is a number which is only (divisible by one and itself) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;the smallest prime is 2&lt;/li&gt;&lt;br /&gt;&lt;li&gt;any number greater than 2 is either composite or prime&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;Building on this definition we may translate the smallest prime into a Prolog predicate quite easily. To determine the primeness/composibility of any number greater than 2, one may use the gcd predicate. Recalling that a prime p is a number which cannot be divided by any number in ]1, p[, the following predicate may be given:&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;is_prime(2) :- !.&lt;br /&gt;is_prime(3) :- !.&lt;br /&gt;is_prime(X) :-&lt;br /&gt;  X &gt;= 2,&lt;br /&gt;  UpperBound is round(sqrt(X)) + 1,&lt;br /&gt;  is_prime_t(X, 2, UpperBound), !.&lt;br /&gt;&lt;br /&gt;is_prime_t(_, UpperBound, UpperBound).&lt;br /&gt;is_prime_t(X, CurrentFactor, UpperBound) :-&lt;br /&gt;  gcd(X, CurrentFactor, GCD),&lt;br /&gt;  GCD = 1, !,&lt;br /&gt;  NewFactor is CurrentFactor + 1,&lt;br /&gt;  is_prime_t(X, NewFactor, UpperBound).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As can be seen above, two elementary cases (2 and 3) are given and any number not 2 or 3 is checked for primeness. Instead of checking composibility of a prime p for any number in ]1, p[, one may use any number in ]1, square_root(p)]. The reason why I used the rounded value of the square root + 1 is the case of checking 4 which would be determined as a prime because of:&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;is_prime_t(4, 2, 2).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Instead of the + 1, we might also a check on whether some number is even. Since we know that 2 is not only the smallest prime but also the only even prime number, such a check might greatly enhance the solution search.&lt;br /&gt;&lt;br /&gt;Using this definition of is_prime, we might define the prime_list predicate quite easily. A prime list is generated from any number within some interval [a, b], which is prime. We might differentiate three cases (where the last is for convenience) in the definition of prime_list:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;the interval is [a,b] where a=b&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the interval is [a,b] where a&amp;lt;b&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the interval is [a,b] where b&amp;lt;a&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;Case one results in a list containing one prime if a is itself a prime number. Case 3 will be mapped to case 2 where a and b are switched. This results in a possible prime_predicate as follows:&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;prime_list(X, X, [X]) :-&lt;br /&gt;  is_prime(X), !.&lt;br /&gt;&lt;br /&gt;prime_list(X, X, []) :- !.&lt;br /&gt;&lt;br /&gt;prime_list(X, Y, L) :-&lt;br /&gt;  X &gt; Y,&lt;br /&gt;  prime_list_t(Y, X, [], L), !.&lt;br /&gt; &lt;br /&gt;prime_list(X, Y, L) :-&lt;br /&gt;  prime_list_t(X, Y, [], L), !.&lt;br /&gt; &lt;br /&gt;prime_list_t(X, X, CurrentPrimes, OutPrimes) :-&lt;br /&gt;  is_prime(X), !,&lt;br /&gt;  append(CurrentPrimes, [X], OutPrimes);&lt;br /&gt;  OutPrimes = CurrentPrimes.&lt;br /&gt;&lt;br /&gt;prime_list_t(X, Y, CurrentPrimes, OutPrimes) :-&lt;br /&gt;  is_prime(X), !,&lt;br /&gt;  append(CurrentPrimes, [X], NewPrimes),&lt;br /&gt;  Z is X + 1,&lt;br /&gt;  prime_list_t(Z, Y, NewPrimes, OutPrimes).&lt;br /&gt; &lt;br /&gt;prime_list_t(X, Y, CurrentPrimes, OutPrimes) :-&lt;br /&gt;  Z is X + 1,&lt;br /&gt;  prime_list_t(Z, Y, CurrentPrimes, OutPrimes).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The last problem to cover is the prime factorization of some given number. This problem is handled by the two predicates prime_factors and prime_factors_mult. Where  the first contains each (possibly duplicate) prime factor and prime_factors_mult delivers a power representation of the prime factors of some given number. The approach taken is quite simple, again the factorization of a prime number contains itself (and one which is not included). Also, any composite number can be represented uniquely by a product of prime factors. For example, 4 = 2 * 2 or 12 = 2 * 2 * 3. Now, provided this property of a natural number we may define our two predicates like this:&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;prime_factors(0, []) :- !.&lt;br /&gt;prime_factors(1, []) :- !.&lt;br /&gt;prime_factors(X, [X]) :- is_prime(X), !.&lt;br /&gt;prime_factors(X, Out) :-&lt;br /&gt;  prime_factors_t(X, 2, [], Out), !.&lt;br /&gt;  &lt;br /&gt;prime_factors_t(1, _, Out, Out).&lt;br /&gt;&lt;br /&gt;prime_factors_t(X, TestFactor, CurrentFactors, Out) :-&lt;br /&gt;  gcd(X, TestFactor, GCD),&lt;br /&gt;  GCD \== 1, !,&lt;br /&gt;  append(CurrentFactors, [GCD], NewFactors),&lt;br /&gt;  Z is X / TestFactor,&lt;br /&gt;  prime_factors_t(Z, TestFactor, NewFactors, Out).&lt;br /&gt;  &lt;br /&gt;prime_factors_t(X, TestFactor, CurrentFactors, Out) :-&lt;br /&gt;  NewTestFactor is TestFactor + 1,&lt;br /&gt;  prime_factors_t(X, NewTestFactor, CurrentFactors, Out).&lt;br /&gt;  &lt;br /&gt;prime_factors_mult(0, []) :- !.&lt;br /&gt;prime_factors_mult(1, []) :- !.&lt;br /&gt;prime_factors_mult(X, [X]) :- is_prime(X), !.&lt;br /&gt;prime_factors_mult(X, Out) :-&lt;br /&gt;  prime_factors_mult_t(X, 2, 0, [], Out), !.&lt;br /&gt;&lt;br /&gt;prime_factors_mult_t(1, _, _, Out, Out).&lt;br /&gt;prime_factors_mult_t(X, X, CurrentPower, CurrentFactors, Out) :-&lt;br /&gt;  Power is CurrentPower + 1,&lt;br /&gt;  append(CurrentFactors, [[X, Power]], Out).&lt;br /&gt;&lt;br /&gt;prime_factors_mult_t(X, TestFactor, Power, CurrentFactors, Out) :-&lt;br /&gt;  gcd(X, TestFactor, GCD),&lt;br /&gt;  GCD \== 1, !,&lt;br /&gt;  NewPower is Power + 1,&lt;br /&gt;  Z is X / TestFactor,&lt;br /&gt;  prime_factors_mult_t(Z, TestFactor, NewPower, CurrentFactors, Out).&lt;br /&gt;&lt;br /&gt;prime_factors_mult_t(X, TestFactor, Power, CurrentFactors, Out) :-&lt;br /&gt;  Power &gt;= 1,&lt;br /&gt;  append(CurrentFactors, [[TestFactor, Power]], NewFactors),&lt;br /&gt;  NewTestFactor is TestFactor + 1,&lt;br /&gt;  prime_factors_mult_t(X, NewTestFactor, 0, NewFactors, Out).&lt;br /&gt;&lt;br /&gt;prime_factors_mult_t(X, TestFactor, Power, CurrentFactors, Out) :-&lt;br /&gt;  Power = 0,&lt;br /&gt;  NewTestFactor is TestFactor + 1,&lt;br /&gt;  prime_factors_mult_t(X, NewTestFactor, 0, CurrentFactors, Out).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Essentially, prime_factors_mult performs the same steps as prime_factors. However, instead of creating a list for some prime factor right from the beginning, the power of that prime factor is accumulated and stored at last.&lt;br /&gt;&lt;br /&gt;Happy, Prolog-ing and if you find any errors/typos please report them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-3343913557530516043?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99' title='Adventures in Prolog - Some more Primes'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/3343913557530516043/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=3343913557530516043' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/3343913557530516043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/3343913557530516043'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/07/adventures-in-prolog-some-more-primes.html' title='Adventures in Prolog - Some more Primes'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-1868761824395284909</id><published>2009-07-07T22:51:00.005+02:00</published><updated>2009-07-07T23:05:06.981+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='GCD'/><title type='text'>Adventures in Prolog - GCD and Coprime</title><content type='html'>Today's post follows the tradition of the my last post, i.e. it continues with another problem stated in the list of 99 Prolog problems. Today, we are going to have a look at problem 32 and 33.&lt;br /&gt;&lt;br /&gt;Problem 32 concerns the implementation of a greatest common divisor predicate (gcd). In an earlier post, I implemented a gcd routine in &lt;a href="http://bitterman-page.blogspot.com/2007/09/i-finally-found-my-way-to-iron-python12.html"&gt;Python&lt;/a&gt;. We are going to reuse this definition of gcd here, using a ternary predicate/relation.&lt;br /&gt;&lt;br /&gt;The Prolog definition of gcd makes use of gcd's recursive definition, which are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;the gcd of two numbers x and y is equal to the gcd of x - y and y for y &lt;&gt; &lt;li&gt;the gcd of some number and 0 is the number&lt;/li&gt;&lt;li&gt;the gcd of some number and 1 is 1&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Now, given the above properties (and some more) a possible gcd predicate might look like this:&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;gcd(A, 0, A) :- !. %includes gcd(0,0)&lt;br /&gt;gcd(1, _, 1) :- !.&lt;br /&gt;gcd(A, A, A) :- !.&lt;br /&gt;&lt;br /&gt;gcd(A, B, GCD) :-&lt;br /&gt;  A &lt; B, !,&lt;br /&gt;  X is B - A,&lt;br /&gt;  gcd(X, A, GCD).&lt;br /&gt;&lt;br /&gt;gcd(A, B, GCD) :-&lt;br /&gt;  X is A - B,&lt;br /&gt;  gcd(X, B, GCD).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Provided the above definition of gcd, the solution to problem P33 is given within the problem statement. For this, a predicate to determine coprimality may be defined as is:&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;coprime(X, X) :- fail.&lt;br /&gt;coprime(X, Y) :- gcd(X, Y, 1).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Clearly, we could add more clause to avoid a computation of gcd when it is obviously not necessary. However this was omitted here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-1868761824395284909?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/' title='Adventures in Prolog - GCD and Coprime'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/1868761824395284909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=1868761824395284909' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/1868761824395284909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/1868761824395284909'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/07/adventures-in-prolog-gcd-and-coprime.html' title='Adventures in Prolog - GCD and Coprime'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-4993733943492147372</id><published>2009-07-03T17:36:00.005+02:00</published><updated>2009-07-03T17:45:55.658+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='lists'/><title type='text'>Adventures In Prolog - Duplicate List Members</title><content type='html'>&lt;div&gt;Today's post is about problem 14 from the list of 99 Prolog problems (see &lt;a href="https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/"&gt;here&lt;/a&gt;):&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;(*) Duplicate the elements of a list.&lt;br /&gt;Example:&lt;br /&gt;?- dupli([a,b,c,c,d],X).&lt;br /&gt;X = [a,a,b,b,c,c,c,c,d,d]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Since the problem is marked with one star, a solution should be within reach. Now, to duplicate each element of the list, we do the following:&lt;/div&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;We traverse the list element by element until we reach the last element, i.e. the empty list.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;For each element (excluding the empty list), the element is added twice to a newly built output list.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;Given the above solution statement, a possible translation to Prolog code might look like this:&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;dupli([], []).&lt;br /&gt;dupli(L, O) :-  dupli_t(L, [], O).&lt;br /&gt;&lt;br /&gt;dupli_t([], Current, Current).&lt;br /&gt;dupli_t([H|T], CList, OutList) :-  &lt;br /&gt;  append(CList, [H, H], IntermediateList),  &lt;br /&gt;  dupli_t(T, IntermediateList, OutList).&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-4993733943492147372?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/4993733943492147372/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=4993733943492147372' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/4993733943492147372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/4993733943492147372'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/07/adventures-in-prolog-duplicate-list.html' title='Adventures In Prolog - Duplicate List Members'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-8566536790570179486</id><published>2009-06-28T14:16:00.009+02:00</published><updated>2009-06-28T14:30:51.269+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='NLP'/><title type='text'>Adventures in Prolog – A Simple Tokenizer</title><content type='html'>Today’s post is concerned with presenting a simple tokenizer that I have written during the last couple of weeks (not full-time off course). The tokenizer’s goal is to – off course – tokenize a provided sentence or input sequence of characters. For example, the following sentence:&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;“This is my world!”&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Should be split up into individual descriptors/ tokens of the respective string part they cover, such as:&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;Word(This), Space(5), Word(is), Space(8), Word(my), Space(11), Word(world), EndOfSentence(!)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, given that the position of a space between characters can be computed by taking the length of the character sequence and adding one to it, we might not need to store the Space explicitly. Also, to avoid verbose representation of tokens we might shorten the name of individual tokens a bit. Since Prolog reserves upper case characters for variables, we might change the casing of tokens too. For example, the above token stream might be collapsed to:&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;w(This), w(is), w(my), w(world), eos(!)&lt;/pre&gt;&lt;br /&gt;Now, what difference does it make whether this is written with a capital t or not? Clearly, this is at the beginning of a sentence, but since we now that it is at the beginning of the sentence we might change casing here. Also transforming to lower case characters simplifies the implementation of the tokenizer somewhat, since we don’t need to deal with specific representations of a single character. For this, all characters will be transformed to lower case characters and the above sequence of tokens reduces too:&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;w(this), w(is), w(my), w(world), eos(!)&lt;/pre&gt;&lt;p&gt;&lt;br /&gt;Adding a complement to the end of sentence indicator, i.e. beginning of sentence, marks each distinct sentence, such that the above token stream looks like:&lt;br /&gt;bos(i), w(this), w(is), w(my), w(world), eos(!)&lt;br /&gt;i in the bos() token identifies the ith sentence in a set of sentences. As you may see from the above example there are a few situations one wants to deal with in order to tokenize real-world sentences. For this, the tokenizer is spread across several Prolog files, each covering a separate aspect or token. Tokens covered are: &lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;&lt;em&gt;Words&lt;/em&gt;&lt;br /&gt;&lt;/strong&gt;Description: A sequence of letters, possibly containing “-“ (bar), or “’” (apostrophe).&lt;br /&gt;Example: Hello, world, top-down, Mike’s, Andreas’, don’t &lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;em&gt;Simple Numbers (integer, float)&lt;br /&gt;&lt;/em&gt;&lt;/strong&gt;Description: A sequence of digits, possibly containing a “.” (dot)&lt;br /&gt;Example: 1234, 12.343 &lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;em&gt;Names, Quantities and Abbreviations&lt;/em&gt;&lt;/strong&gt;&lt;br /&gt;Description: special words, stored in a name, quantity, abbreviation map&lt;br /&gt;Example: 5m (five meter), MS (Microsoft) &lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;em&gt;Unknown and unrecognized character streams&lt;/em&gt;&lt;/strong&gt;&lt;br /&gt;Description: A sequence of arbitrary characters closed by a “ “ (space)&lt;br /&gt;Example: 34sd=+&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Please note that in order to identify a sentence, a sentence must be properly terminated with one of the following: ‘.’ (Dot), ‘?’ (Question mark) or ‘!’ (Exclamation mark). Other types of (sub)sentence termination , such as the ‘-‘ (bar), ‘;’, (Semicolon), ‘,’ (comma) are handled as sentence fragment terminators. If you want to use the tokenizer, you may either tokenize a file containing sentences or a string. For this, you may use either of the following predicates:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;tokenize_string(+InString, -OutTokenList)&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;tokenize_file(+InFile, -OutTokenList)&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;For example, you might ask:&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;3 ?- tokenize_string("this is my world!", X).&lt;br /&gt;X = [[bos(0), w(this), w(is), w(my), w(world), eos(!)]].&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Or you might ask:&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;tokenize_file(‘Path to file’, X).&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The Prolog source code of the tokenizer can be found &lt;a href="http://cid-aecaa12b1d66e6ec.skydrive.live.com/self.aspx/.Public/CBTokenizer.zip"&gt;here&lt;/a&gt;. It is stored as a zip container. You will find the following inside the zip-file:&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Prolog source files (extension pl) &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Directory “Corpora” with two text files containing some text to test the tokenizer on.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;Please note that I do not claim its robustness or coverage of 99% of the possible sentences. Also, performance has not been a major concern for me. For this you will not find the use of difference lists or optimized database access. This might be a future task as well. In fact, this is one of the many open points. However, in case that you do have found a bug, error or recommendation, please do contact me. Currently, I try to add features to the tokenizer and make it more stable. Also, documentation and code cleanup is a item on the to-do list. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-8566536790570179486?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://cid-aecaa12b1d66e6ec.skydrive.live.com/self.aspx/.Public/CBTokenizer.zip' title='Adventures in Prolog – A Simple Tokenizer'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/8566536790570179486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=8566536790570179486' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/8566536790570179486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/8566536790570179486'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/06/adventures-in-prolog-simple-tokenizer.html' title='Adventures in Prolog – A Simple Tokenizer'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-6121927657961759711</id><published>2009-06-07T19:45:00.003+02:00</published><updated>2009-06-07T19:52:02.975+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='Link'/><title type='text'>Adventures in Prolog - LinkList (2)</title><content type='html'>Some time ago, I have done a small tokenizer, which I will present in one of the upcoming posts. However, this post is another link to some Prolog tutorials:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.intranet.csupomona.edu/~jrfisher/www/prolog_tutorial/intro.html"&gt;http://www.intranet.csupomona.edu/~jrfisher/www/prolog_tutorial/intro.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;All posted links and links that I will post in the future, will be collected on my Prolog link site at:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://sites.google.com/site/bittermanpage/Home/prolog-links"&gt;http://sites.google.com/site/bittermanpage/Home/prolog-links&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This link will be available in the side bar as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-6121927657961759711?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/6121927657961759711/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=6121927657961759711' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6121927657961759711'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6121927657961759711'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/06/adventures-in-prolog-linklist-2.html' title='Adventures in Prolog - LinkList (2)'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-1332288026420532100</id><published>2009-06-04T13:20:00.001+02:00</published><updated>2009-06-04T13:22:04.502+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='Link'/><title type='text'>Adventures in Prolog - LinkList</title><content type='html'>Here is a link to the Prolog directory of CMU's AI group:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cs.cmu.edu/Groups/AI/lang/prolog/"&gt;http://www.cs.cmu.edu/Groups/AI/lang/prolog/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-1332288026420532100?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/1332288026420532100/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=1332288026420532100' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/1332288026420532100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/1332288026420532100'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/06/adventures-in-prolog-linklist.html' title='Adventures in Prolog - LinkList'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-5856631963632740841</id><published>2009-05-25T11:40:00.005+02:00</published><updated>2009-09-12T11:24:47.117+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Reading'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog environments'/><title type='text'>Adventures in Prolog - General Reading (1)</title><content type='html'>Today's post is merely the advertisement of a dissertation thesis that might be an interesting read:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;&lt;br /&gt;Can Logic Programming Execute as Fast as Imperative Programming?&lt;br /&gt;Peter Lodewijk Van Roy&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;ABSTRACT&lt;/strong&gt;&lt;br /&gt;The purpose of this dissertation is to provide constructive proof that the logic programming language Prolog can be implemented an order of magnitude more efficiently than the best previous systems, so that its speed approaches imperative languages such as C for a significant class of problems. The driving force in the design is to encode each occurrence of a general feature of Prolog as simply as possible. The resulting system, Aquarius Prolog, is about five times faster than Quintus Prolog, a high performance commercial system, on a set of representative programs. The design is based on the following ideas:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Reduce instruction granularity.&lt;/strong&gt; Use an execution model, the Berkeley Abstract Machine (BAM), that retains the good features of the Warren Abstract Machine (WAM), a standard execution model for Prolog, but is more easily optimized and closer to a real machine.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Exploit determinism.&lt;/strong&gt; Compile deterministic programs with efficient conditional branches. Most predicates written by human programmers are deterministic, yet previous systems often compile them in an inefficient manner by simulating conditional branching with backtracking.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Specialize unification.&lt;/strong&gt; Compile unification to the simplest possible code. Unification is a general pattern-matching operation that can do many things in the implementation: pass parameters, assign values to variables, allocate memory, and do conditional branching.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Dataflow analysis.&lt;/strong&gt; Derive type information by global dataflow analysis to support these ideas. &lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;br /&gt;The thesis can be found &lt;a href="http://www.info.ucl.ac.be/~pvr/Peter.thesis/Peter.thesis.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;On that note I would like to mention a paper going for a similar direction, actually I found the thesis because of the paper.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Optimizing Prolog for Small Devices: A Case Study&lt;br /&gt;M. Carro, J. Morales, Henk L. Muller, G. Puebla, M. Hermenegildo&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Abstract&lt;br /&gt;&lt;/strong&gt;In this paper we present the design and implementation of a wearable application in Prolog. The application program is a “sound spatializer.” Given an audio signal and real time data from a head-mounted compass, a signal is generated for stereo headphones that will appear to come from a position in space. We describe high-level and low-level optimizations and transformations that have been applied in order to fit this application on the wearable device. The end application operates comfortably in real-time on a wearable computer, and has a memory foot print that remains constant over time enabling it to run on continuous audio streams. Comparison with a version hand-written in C shows that the C version is no more than 20-40% faster; a small price to pay for a high level description.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The paper can be found &lt;a href="http://clip.dia.fi.upm.es/papers/carro06:stream-interpreter-TR.pdf"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The reason why posting these documents, is my thinking of maybe porting or reusing an existing Prolog implementation for the Nintendo DS. Unfortunately, I have not made great progress. But with some time, there may be something out there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-5856631963632740841?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/5856631963632740841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=5856631963632740841' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/5856631963632740841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/5856631963632740841'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/05/adventures-in-prolog-general-reading-1.html' title='Adventures in Prolog - General Reading (1)'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-440208478927936943</id><published>2009-05-16T22:17:00.004+02:00</published><updated>2009-05-16T22:23:09.366+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><title type='text'>Adventures in Prolog - Simplify Sum (4)</title><content type='html'>Last post was concerned with implementing the simplification of an additive (compound) term. The proposed solution consists of three elementary steps (sorting, simplifying and reducing). Although the proposed solution is quite flexible, i.e. works on any atom not specifically a single character,&lt;br /&gt;the sorting of characters decreases performance somewhat. For this, this post is concerned with a more targeted approach to the introduced problem.&lt;br /&gt;&lt;br /&gt;Given an additive (compound) term containing numbers and (unitary) variable symbols (e.g., a, b, x, y, z), we wish to obtain a reduced form of this term, which simplifies the same variables and sums multiple numbers to one single number.&lt;br /&gt;&lt;br /&gt;The following solution makes use of:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The (German and English) alphabet contains only 26 elementary characters (variable symbols) &lt;/li&gt;&lt;li&gt;Character symbols can be ordered according to their occurence within the alphabet. &lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Instead of operating on additive compound term, the proposed solution operates on a character array , i.e. array indexing individual variable characters. The following solution consists of two main steps: &lt;/p&gt;&lt;ol&gt;&lt;li&gt;Simplification of additive (compound) term &lt;/li&gt;&lt;li&gt;Computing a reduced printable form (string) of the simplified term. &lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Now, given the perimeters of the proposed approach, this is what it looks like:&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;map_index(a, 1).&lt;br /&gt;map_index(b, 2).&lt;br /&gt;map_index(c, 3).&lt;br /&gt;map_index(d, 4).&lt;br /&gt;map_index(e, 5).&lt;br /&gt;map_index(f, 6).&lt;br /&gt;map_index(g, 7).&lt;br /&gt;map_index(h, 8).&lt;br /&gt;map_index(i, 9).&lt;br /&gt;map_index(j, 10).&lt;br /&gt;map_index(k, 11).&lt;br /&gt;map_index(l, 12).&lt;br /&gt;map_index(m, 13).&lt;br /&gt;map_index(n, 14).&lt;br /&gt;map_index(o, 15).&lt;br /&gt;map_index(p, 16).&lt;br /&gt;map_index(q, 17).&lt;br /&gt;map_index(r, 18).&lt;br /&gt;map_index(s, 19).&lt;br /&gt;map_index(t, 20).&lt;br /&gt;map_index(u, 21).&lt;br /&gt;map_index(v, 22).&lt;br /&gt;map_index(w, 23).&lt;br /&gt;map_index(x, 24).&lt;br /&gt;map_index(y, 25).&lt;br /&gt;map_index(z, 26).&lt;br /&gt;map_index(V, 27) :- number(V).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;map_index defines the array index of each variable symbol. index 27 is reserved as the computation cell for numbers.&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;increment(1, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A1, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- A1 is A + 1.&lt;br /&gt;increment(2, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B1, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- B1 is B + 1.&lt;br /&gt;increment(3, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C1, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- C1 is C + 1.&lt;br /&gt;increment(4, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D1, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- D1 is D + 1.&lt;br /&gt;increment(5, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E1, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- E1 is E + 1.&lt;br /&gt;increment(6, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F1, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- F1 is F + 1.&lt;br /&gt;increment(7, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G1, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- G1 is G + 1.&lt;br /&gt;increment(8, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H1, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- H1 is H + 1.&lt;br /&gt;increment(9, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I1, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- I1 is I + 1.&lt;br /&gt;increment(10, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J1, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- J1 is J + 1.&lt;br /&gt;increment(11, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K1, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- K1 is K + 1.&lt;br /&gt;increment(12, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L1, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- L1 is L + 1.&lt;br /&gt;increment(13, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M1, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- M1 is M + 1.&lt;br /&gt;increment(14, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N1, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- N1 is N + 1.&lt;br /&gt;increment(15, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O1, P, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- O1 is O + 1.&lt;br /&gt;increment(16, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P1, Q, R, S, T, U, V, W, X, Y, Z, NN]) :- P1 is P + 1.&lt;br /&gt;increment(17, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q1, R, S, T, U, V, W, X, Y, Z, NN]) :- Q1 is Q + 1.&lt;br /&gt;increment(18, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R1, S, T, U, V, W, X, Y, Z, NN]) :- R1 is R + 1.&lt;br /&gt;increment(19, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S1, T, U, V, W, X, Y, Z, NN]) :- S1 is S + 1.&lt;br /&gt;increment(20, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T1, U, V, W, X, Y, Z, NN]) :- T1 is T + 1.&lt;br /&gt;increment(21, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U1, V, W, X, Y, Z, NN]) :- U1 is U + 1.&lt;br /&gt;increment(22, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V1, W, X, Y, Z, NN]) :- V1 is V + 1.&lt;br /&gt;increment(23, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W1, X, Y, Z, NN]) :- W1 is W + 1.&lt;br /&gt;increment(24, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X1, Y, Z, NN]) :- X1 is X + 1.&lt;br /&gt;increment(25, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y1, Z, NN]) :- Y1 is Y + 1.&lt;br /&gt;increment(26, _, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z1, NN]) :- Z1 is Z + 1.&lt;br /&gt;&lt;br /&gt;increment(27, Inc, [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN],&lt;br /&gt;[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, NN1]) :- NN1 is NN + Inc.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;increment uses an index and updates the respective variable or number cell. Note that, variables may only be&lt;br /&gt;incremented by one, whereas numbers can be incremented by any other number (adding two numbers).&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;simplify(In) :-&lt;br /&gt;simplify_a(In, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], OutMap),&lt;br /&gt;print_simplified(OutMap), !.&lt;br /&gt;&lt;br /&gt;simplify(_).&lt;br /&gt;&lt;br /&gt;simplify_a(X, InMap, OutMap) :-&lt;br /&gt;  atomic(X),&lt;br /&gt;  map_index(X, I),&lt;br /&gt;  print('Index: '), print(I), nl,&lt;br /&gt;  increment(I, X, InMap, OutMap), !.&lt;br /&gt;&lt;br /&gt;simplify_a(A + B, InMap, OutMap) :-&lt;br /&gt;  atomic(A),&lt;br /&gt;  atomic(B),&lt;br /&gt;  map_index(A, I1),&lt;br /&gt;  map_index(B, I2),&lt;br /&gt;  increment(I1, A, InMap, TMap),&lt;br /&gt;  increment(I2, B, TMap, OutMap), !.&lt;br /&gt;&lt;br /&gt;simplify_a(A + B, InMap, OutMap) :-&lt;br /&gt;  compound(A),&lt;br /&gt;  atomic(B),&lt;br /&gt;  map_index(B, I),&lt;br /&gt;  increment(I, B, InMap, TMap),&lt;br /&gt;  simplify_a(A, TMap, OutMap), !.&lt;br /&gt;&lt;br /&gt;simplify_a(_, InMap, InMap).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;simplify calls simplify_a, which is responsible for obtaining a simplified representation from some additive term.&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;print_simplified(In) :-&lt;br /&gt;  print('Result:'), nl,&lt;br /&gt;  str_simplified_t(In, 1, '', OutStr),&lt;br /&gt;  print(OutStr), nl, !.&lt;br /&gt;&lt;br /&gt;get_no(_, 0, '').&lt;br /&gt;get_no(Char, 1, Char).&lt;br /&gt;get_no(Char, X, X*Char).&lt;br /&gt;&lt;br /&gt;str_simplified_t([0|Rest], Index, TStr, RStr) :-&lt;br /&gt;  Index1 is Index + 1,&lt;br /&gt;  str_simplified_t(Rest, Index1, TStr, RStr), !.&lt;br /&gt;&lt;br /&gt;str_simplified_t([X, 0], 26, TStr, RStr) :-&lt;br /&gt;  map_index(Char, 26),&lt;br /&gt;  RStr = TStr + X*Char, !.&lt;br /&gt;&lt;br /&gt;str_simplified_t([X, N], 26, TStr, RStr) :-&lt;br /&gt;  map_index(Char, 26),&lt;br /&gt;  get_no(Char, X, XStr),&lt;br /&gt;  RStr = TStr + XStr + N, !.&lt;br /&gt;&lt;br /&gt;str_simplified_t([X|R], 1, _, RStr) :-&lt;br /&gt;  map_index(Char, Loop),&lt;br /&gt;  get_no(Char, X, AStr),&lt;br /&gt;  I1 is Loop + 1,&lt;br /&gt;  str_simplified_t(R, I1, AStr, RStr), !.&lt;br /&gt;&lt;br /&gt;str_simplified_t([X|R], Loop, TStr, RStr) :-&lt;br /&gt;  map_index(Char, Loop),&lt;br /&gt;  get_no(Char, X, XStr),&lt;br /&gt;  AStr = TStr + XStr,&lt;br /&gt;  I1 is Loop + 1,&lt;br /&gt;  str_simplified_t(R, I1, AStr, RStr).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;print_simplified calls str_simplified_t to compute the reduced string representing a simplified additive term of the initial additive term.&lt;br /&gt;&lt;br /&gt;As one can see this solution is somewhat less complex and more performant than the previous solution. Most of the code is responsible for computing array indices or updating an array cell. For this, further (code length) optimizations may be identified. The array approach completely avoids the sort predicate thereby reducing run-time overhead. On the downside, this approach works with single characters instead of any atom.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-440208478927936943?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/440208478927936943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=440208478927936943' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/440208478927936943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/440208478927936943'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/05/adventures-in-prolog-simplify-sum-4.html' title='Adventures in Prolog - Simplify Sum (4)'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-6859271430539211588</id><published>2009-05-12T13:17:00.044+02:00</published><updated>2009-05-13T15:09:48.235+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><title type='text'>Adventures in Prolog - Simplify Sum (3)</title><content type='html'>&lt;span style="font-family:arial;"&gt;In an earlier installment the simplify_sum predicate was discussed. However it was not really a feature complete solution to the initially motivated problem. For this, this post is concerned with providing a newer version, which actually solves the following problem.&lt;br /&gt;&lt;br /&gt;Given some additive formulae, such as:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;1&lt;br /&gt;a&lt;br /&gt;1 + a&lt;br /&gt;a + a&lt;br /&gt;1 + a + 9 + b + a + b + c&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;we wish to obtain the following results:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;1&lt;br /&gt;1*a (or a)&lt;br /&gt;1*a + 1 (or a + 1)&lt;br /&gt;2*a&lt;br /&gt;2*a + 2*b + 1*c + 10 (or 2*a + 2*b + c + 10)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;The proposed solution will consist of three parts:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1.&lt;/strong&gt;&lt;br /&gt;order all parts of an additive equation according to letters and numbers.&lt;br /&gt;place letters in order of the alphabet and summarize numbers, such that at most one number is present.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2.&lt;/strong&gt;&lt;br /&gt;summarize all variables. this leads to the transformation of x into 1*x&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;3.&lt;br /&gt;&lt;/strong&gt;reduce all variables from 1*x to x.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:arial;"&gt;Translating the above sequence of steps into a Prolog program, leads to the following definition of the simplify_sum predicate: &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;simplify_sum(In, Final) :-&lt;br /&gt;  sort_sum(In, SortedOut),&lt;br /&gt;  simplify(SortedOut, Result),&lt;br /&gt;  strip_sum(Result, Final), !.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;A first naive implementation of sort_sum, checks whether some parameter is an atom or a number and arranges the output accordingly. The high level predicate sort_sum makes use of the acutal predicate called sort_sum_t. sort_sum_t implements a bubble sort approach to arrange numbers and atoms. If two numbers are encountered they are reduced to their sum.Elementary cases are only one number, one atom, two atoms, two numbers and atom and number. Compound cases split the input argument into simpler forms until input is elementary.&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;%sort_sum_t&lt;br /&gt;sort_sum_t(X + Y, X + Y) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  number(Y), !.&lt;br /&gt;&lt;br /&gt;sort_sum_t(X + Y, X + Y) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  atom(Y),&lt;br /&gt;  char_code(X, CX),&lt;br /&gt;  char_code(Y, CY),&lt;br /&gt;  CX =&lt; CY, !.&lt;br /&gt;&lt;br /&gt;sort_sum_t(X + Y, Y + X) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  atom(Y), !.&lt;br /&gt;&lt;br /&gt;sort_sum_t(X + Y, Y + X) :-&lt;br /&gt;  number(X),&lt;br /&gt;  atom(Y), !.&lt;br /&gt;&lt;br /&gt;sort_sum_t(X + Y, Res) :-&lt;br /&gt;  number(X),&lt;br /&gt;  number(Y),&lt;br /&gt;  Res is X + Y, !.&lt;br /&gt;&lt;br /&gt;%compounds&lt;br /&gt;sort_sum_t(C + X, Res) :-&lt;br /&gt;  sort_sum_t(C, R1),&lt;br /&gt;  number(R1),&lt;br /&gt;  number(X),&lt;br /&gt;  Res is X + R1, !.&lt;br /&gt;&lt;br /&gt;sort_sum_t(C + X, X + R1) :-&lt;br /&gt;  sort_sum_t(C, R1),&lt;br /&gt;  number(R1),&lt;br /&gt;  atom(X), !.&lt;br /&gt;&lt;br /&gt;sort_sum_t(C + X, A + Res) :-&lt;br /&gt;  sort_sum_t(C, A + B),&lt;br /&gt;  number(B),&lt;br /&gt;  number(X),&lt;br /&gt;  Res is B + X, !.&lt;br /&gt;&lt;br /&gt;sort_sum_t(C + X, A + B + X) :-&lt;br /&gt;  sort_sum_t(C, A + B),&lt;br /&gt;  atom(B),&lt;br /&gt;  number(X), !.&lt;br /&gt;&lt;br /&gt;sort_sum_t(C + X, Res + B) :-&lt;br /&gt;  sort_sum_t(C, A + B),&lt;br /&gt;  number(B),&lt;br /&gt;  atom(X),&lt;br /&gt;  sort_sum_t(A + X, Res), !.&lt;br /&gt;&lt;br /&gt;sort_sum_t(C + X, Res + B) :-&lt;br /&gt;  sort_sum_t(C, A + B),&lt;br /&gt;  atom(B),&lt;br /&gt;  atom(X),&lt;br /&gt;  char_code(B, CB),&lt;br /&gt;  char_code(X, CX),&lt;br /&gt;  CX =&lt; CB,&lt;br /&gt;  sort_sum_t(A + X, Res), !.&lt;br /&gt;&lt;br /&gt;sort_sum_t(C + X, A + B + X) :-&lt;br /&gt;  sort_sum_t(C, A + B),&lt;br /&gt;  atom(B),&lt;br /&gt;  atom(X), !.&lt;br /&gt;&lt;br /&gt;sort_sum(X, X) :- atom(X), !.&lt;br /&gt;sort_sum(X, X) :- number(X), !.&lt;br /&gt;&lt;br /&gt;sort_sum(In, Out) :- sort_sum_t(In, Out), !.&lt;br /&gt;&lt;br /&gt;sort_sum(_, _).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Now that an input additive term is sorted according to variables and numbers, it may be processed. This processing, i.e. summing equal atoms and numbers is handled by the simplify predicate, which in turn calls simplify_t to summarize some additive input term. special cases correspond to those identified for the sort_sum predicate. However, simplify_t can make use of the following: (1) there is only one number in the input term, which is at the right most position and (2) an atom follows another atom which is either equal to itself (only having higher quantity) or is a smaller atom.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;simplify_t(X, 1*X) :- atom(X), !.&lt;br /&gt;&lt;br /&gt;simplify_t(A*X, A*X) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  number(A), !.&lt;br /&gt;&lt;br /&gt;simplify_t(X*A, A*X) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  number(A), !.&lt;br /&gt;&lt;br /&gt;simplify_t(X, X) :- number(X), !.&lt;br /&gt;&lt;br /&gt;simplify_t(X + Y, 1*X + Y) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  number(Y), !.&lt;br /&gt;&lt;br /&gt;simplify_t(X + Y, 1*X + 1*Y) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  atom(Y),&lt;br /&gt;  X \= Y, !.&lt;br /&gt;&lt;br /&gt;simplify_t(X + X, 2*X) :- atom(X), !.&lt;br /&gt;&lt;br /&gt;simplify_t(X + I*X, J*X) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  number(I),&lt;br /&gt;  J is I + 1, !.&lt;br /&gt;&lt;br /&gt;simplify_t(X + X*I, J*X) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  number(I),&lt;br /&gt;  J is I + 1, !.&lt;br /&gt;&lt;br /&gt;simplify_t(I*X + X, J*X) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  number(I),&lt;br /&gt;  J is I + 1, !.&lt;br /&gt;&lt;br /&gt;simplify_t(X*I + Y, I*X + Y) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  atom(Y),&lt;br /&gt;  number(I), !.&lt;br /&gt;&lt;br /&gt;simplify_t(I*X + Y, I*X + Y) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  atom(Y),&lt;br /&gt;  number(I), !.&lt;br /&gt;&lt;br /&gt;simplify_t(X + Y*I, X + I*Y) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  atom(Y),&lt;br /&gt;  number(I), !.&lt;br /&gt;&lt;br /&gt;simplify_t(X + I*Y, X + I*Y) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  atom(Y),&lt;br /&gt;  number(I), !.&lt;br /&gt;&lt;br /&gt;simplify_t(A*X + B*X, C*X) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  number(A),&lt;br /&gt;  number(B),&lt;br /&gt;  C is A + B, !.&lt;br /&gt;&lt;br /&gt;simplify_t(X + Y, X + Y) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  atom(Y), !.&lt;br /&gt;&lt;br /&gt;simplify_t(A*X + B*Y, U + V) :-&lt;br /&gt;  simplify_t(A*X, U),&lt;br /&gt;  simplify_t(B*Y, V), !.&lt;br /&gt;&lt;br /&gt;%compounds&lt;br /&gt;simplify_t(C + X, R + X) :-&lt;br /&gt;  number(X),&lt;br /&gt;  simplify_t(C, R), !.&lt;br /&gt;&lt;br /&gt;simplify_t(A + B, R*X) :-&lt;br /&gt;  simplify_t(A, M*X),&lt;br /&gt;  simplify_t(B, N*X),&lt;br /&gt;  atom(X),&lt;br /&gt;  R is M + N, !.&lt;br /&gt;&lt;br /&gt;simplify_t(A + B, M*X + N*Y) :-&lt;br /&gt;  simplify_t(A, M*X),&lt;br /&gt;  simplify_t(B, N*Y),&lt;br /&gt;  atom(X),&lt;br /&gt;  atom(Y),&lt;br /&gt;  X \= Y, !.&lt;br /&gt;&lt;br /&gt;simplify_t(A + B, M + R*X) :-&lt;br /&gt;  simplify_t(A, M + N*X),&lt;br /&gt;  simplify_t(B, S*X),&lt;br /&gt;  atom(X),&lt;br /&gt;  R is N + S, !.&lt;br /&gt;&lt;br /&gt;simplify_t(A + B, M + N + SX) :-&lt;br /&gt;  simplify_t(A, M + N),&lt;br /&gt;  simplify_t(B, SX), !.&lt;br /&gt;&lt;br /&gt;simplify(In, Out) :- simplify_t(In, Out), !.&lt;br /&gt;&lt;br /&gt;simplify(_, _).&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Now that an additive term is transformed to its reduced form, the only thing left is to remove any unnecessary 1. That is reduce each 1*x to x. Again the compound case is reduced to atomic cases, which are 1*x = x, n*x = n*x, number = number.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;strip_sum(X, X) :- number(X), !.&lt;br /&gt;&lt;br /&gt;strip_sum(1*X, X) :- atom(X), !.&lt;br /&gt;&lt;br /&gt;strip_sum(N*X, N*X) :-&lt;br /&gt;  atom(X),&lt;br /&gt;  number(N), !.&lt;br /&gt;&lt;br /&gt;strip_sum(A + B, A1 + B1) :-&lt;br /&gt;  strip_sum(A, A1),&lt;br /&gt;  strip_sum(B, B1), !.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;running the following example:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: plain; ruler: true; first-line: 1"&gt;&lt;br /&gt;simplify_sum(a + b + c + d + a + c + 70 + a+ a + 50, X).&lt;br /&gt;X = 4*a+b+2*c+d+120.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;shows the correct working of simplify_sum.&lt;br /&gt;&lt;br /&gt;As mentioned sort_sum makes use of a bubble sort approach, which clearly is less than optimal. For this, the next post is concerned with using a different sort_sum approach to speed simplify_sum up.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-6859271430539211588?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/6859271430539211588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=6859271430539211588' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6859271430539211588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6859271430539211588'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/05/adventures-in-prolog-simplify-sum-3.html' title='Adventures in Prolog - Simplify Sum (3)'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-3895915019827918095</id><published>2009-04-17T18:55:00.003+02:00</published><updated>2009-04-17T19:08:43.873+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><title type='text'>Adventures in Prolog - Computations with lists VII</title><content type='html'>&lt;span style="font-family:arial;"&gt;Again, as I am quite busy these days, I will present some not recent predicates, just to keep the flow going. Quite recently, I have seen the world of depth, breadth and intelligent search in Prolog. For this, I am working on an implementation of the 8-queens problem. Unfortunately, this is nothing to show off at the moment. But probably in 2 weeks or so, I will be able to show present it here and demonstrate how elegantly one may solve problems using Prolog.&lt;br /&gt;&lt;br /&gt;Today's post is about the detection of a palindrome using Prolog. A palindrome is defined as some word that can be read from start to end or end to start and it will not change. For example, the word ANNA is a palindrome.&lt;br /&gt;&lt;br /&gt;Now, using the idea that a palindromic word is a word that can be read back and forth and does not change, we come with the following ...&lt;br /&gt;&lt;br /&gt;Let X be some word. If X is the empty word then it is a palindrome. If X is not the empty word then let Y be the reverse of X. If Y equals X, X is a palindromic word. Instead of focussing on words, we focus on lists.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;%palin/1 X is a palindrome&lt;br /&gt;&lt;strong&gt;palin&lt;/strong&gt;([]).&lt;br /&gt;&lt;strong&gt;palin&lt;/strong&gt;(X) :- &lt;strong&gt;revList&lt;/strong&gt;(X, Y), X = Y.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;A more succinct version of the above would avoid the additional test of equality, i.e. lead to the following predicate:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;palin&lt;/strong&gt;(X) :- &lt;strong&gt;revList&lt;/strong&gt;(X, X).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Which clearly is the the same, i.e. if reversing X leads to X, then clearly, X has to be palindromic. &lt;span style="font-family:courier new;"&gt;revList&lt;/span&gt; is a  binary predicate that takes a list as input and outputs the reverse list.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-3895915019827918095?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/3895915019827918095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=3895915019827918095' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/3895915019827918095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/3895915019827918095'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/04/adventures-in-prolog-computations-with_17.html' title='Adventures in Prolog - Computations with lists VII'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-2426395130256362497</id><published>2009-04-06T08:49:00.002+02:00</published><updated>2009-04-06T08:56:58.301+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><title type='text'>Adventures in Prolog - Computations with lists VI</title><content type='html'>Today's post is merely to get the flow going and the blog updated. That is it is about the simple concatenation of two lists. Just like the append predicate appends some element at the end of a list, &lt;span style="font-family:courier new;"&gt;concatenate_list&lt;/span&gt; joins two lists by recursively reducing one list until it is the empty list.&lt;br /&gt;&lt;br /&gt;%concatenate_list/3&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;concatenate_list&lt;/strong&gt;([], List, List).&lt;br /&gt;&lt;strong&gt;concatenate_list&lt;/strong&gt;([H1¦T1], [H2¦T2], [H1¦T3]) :- &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;concatenate_list&lt;/strong&gt;(T1, [H2¦T2], T3).&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-2426395130256362497?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/2426395130256362497/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=2426395130256362497' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/2426395130256362497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/2426395130256362497'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/04/adventures-in-prolog-computations-with.html' title='Adventures in Prolog - Computations with lists VI'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-853063960225754051</id><published>2009-03-30T17:05:00.003+02:00</published><updated>2009-03-30T17:10:58.859+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='Link'/><title type='text'>Adventures in Prolog - Link List I</title><content type='html'>Today's post is merely a compilation of interesting resources on Prolog.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://cs.union.edu/~striegnk/learn-prolog-now/lpnpage.php?pageid=top"&gt;Learn Prolog Now&lt;/a&gt; - An online (and paperback) book to learn Prolog&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cotilliongroup.com/man/aspects/aspects-man.html"&gt;Aspect-Oriented Programming Prolog&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amzi.com/AdventureInProlog/index.htm"&gt;Adventures in Prolog &lt;/a&gt;- another online book to learn Prolog&lt;br /&gt;&lt;br /&gt;&lt;a href="https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/"&gt;P99-Ninety-Nine Prolog Problems &lt;/a&gt;- a set of Prolog challenges organized into different degree of difficulty and domains&lt;br /&gt;&lt;br /&gt;So happy reading and solving problems :D&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-853063960225754051?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/853063960225754051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=853063960225754051' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/853063960225754051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/853063960225754051'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/03/adventures-in-prolog-link-list-i.html' title='Adventures in Prolog - Link List I'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-1051673063142340403</id><published>2009-03-17T11:29:00.002+01:00</published><updated>2009-03-17T11:36:52.738+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='lists'/><title type='text'>Adventures in Prolog - computations with Lists V</title><content type='html'>&lt;p&gt;Today's post presents a predicate defined for lists that is as simple as yesterdays &lt;span style="font-family:courier new;"&gt;&lt;strong&gt;rem_dups/2&lt;/strong&gt;&lt;/span&gt;. &lt;span style="font-family:courier new;"&gt;&lt;strong&gt;flatten/2&lt;/strong&gt;&lt;/span&gt; is concerned with flattening an arbitrary list to a one-dimensional list/array.The idea behind flatten is pretty simple, i.e. if a list is non-flat we lower its dimensionality by taking theinner of that list and process it further until we reach a one-dimensional list.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;%flatten/2&lt;br /&gt;&lt;strong&gt;flatten&lt;/strong&gt;([], []).&lt;br /&gt;&lt;strong&gt;flatten&lt;/strong&gt;([[]], []).&lt;br /&gt;&lt;strong&gt;flatten&lt;/strong&gt;([[HT]], X) :- &lt;strong&gt;flatten&lt;/strong&gt;([HT], X).&lt;br /&gt;&lt;strong&gt;flatten&lt;/strong&gt;([[H]T], X) :- &lt;strong&gt;flatten&lt;/strong&gt;([HT], X).&lt;br /&gt;&lt;strong&gt;flatten&lt;/strong&gt;([H[T]], X) :- &lt;strong&gt;flatten&lt;/strong&gt;([HT], X).&lt;br /&gt;&lt;strong&gt;flatten&lt;/strong&gt;([HT], X) :-&lt;br /&gt;  &lt;strong&gt;flatten&lt;/strong&gt;(T, Y),&lt;br /&gt;  &lt;strong&gt;append&lt;/strong&gt;([H], Y, X).&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-1051673063142340403?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/1051673063142340403/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=1051673063142340403' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/1051673063142340403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/1051673063142340403'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/03/adventures-in-prolog-computations-with_17.html' title='Adventures in Prolog - computations with Lists V'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-5436992683040021620</id><published>2009-03-16T14:55:00.003+01:00</published><updated>2009-03-16T15:25:07.572+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='lists'/><title type='text'>Adventures in Prolog - computations with lists IV</title><content type='html'>Today's post is merely a modification to yesterdays post, i.e. the remove duplicate functions will be streamlined. &lt;span style="font-family:courier new;"&gt;&lt;strong&gt;rem_dups2/2&lt;/strong&gt;&lt;/span&gt; is a replication of &lt;span style="font-family:courier new;"&gt;&lt;strong&gt;rem_dups/2&lt;/strong&gt;&lt;/span&gt; with less dependencies, i.e. it does not use the &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;remove/3&lt;/span&gt;&lt;/strong&gt; predicate thereby improving performance. A drawback is that &lt;span style="font-family:courier new;"&gt;&lt;strong&gt;rem_dups2&lt;/strong&gt;&lt;/span&gt; does not preserve order of list elements when producing output, i.e. the last occurence of a duplicate list element will be preserved in the output list.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;rem_dups2&lt;/strong&gt;([X[]], [X]).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;rem_dups2&lt;/strong&gt;([HT], X) :- &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;strong&gt;member&lt;/strong&gt;(H, T), &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  !, &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;strong&gt;rem_dups2&lt;/strong&gt;(T, X); &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;strong&gt;rem_dups2&lt;/strong&gt;(T, Y), &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;strong&gt;append&lt;/strong&gt;([H], Y, X).&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-5436992683040021620?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/5436992683040021620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=5436992683040021620' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/5436992683040021620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/5436992683040021620'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/03/adventures-in-prolog-computations-with_16.html' title='Adventures in Prolog - computations with lists IV'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-8591261234192384148</id><published>2009-03-15T19:42:00.002+01:00</published><updated>2009-03-15T19:56:10.500+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='lists'/><title type='text'>Adventures in Prolog - Computations with lists III</title><content type='html'>&lt;span style="font-family:arial;"&gt;This week's post is concerned with another operation on lists, i.e. how to compute a set given a list. This means that given a list containing any values, we wish to remove duplicates from this list to obtain a set containing unique members. The predicate &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;rem_dups/2&lt;/span&gt;&lt;/strong&gt; does exactly this.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;rem_dups&lt;/strong&gt;([X[]], [X]).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;rem_dups&lt;/strong&gt;([HT], X) :- &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;strong&gt;member&lt;/strong&gt;(H, T), &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  !, &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;strong&gt;remove&lt;/strong&gt;(H, T, Y), &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;strong&gt;rem_dup&lt;/strong&gt;([HY], X); &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;strong&gt;rem_dup&lt;/strong&gt;(T, Y), &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;strong&gt;append&lt;/strong&gt;([H], Y, X).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;The problem forumulation basically says that if the head of a list is contained within the tail of the list it is a duplicate. Consequently, this duplicate (and any further duplicate of H) is removed from T. Since we want to retain H, we need to connect it with the list that does not contain any instance of H, i.e. X. This procedure is followed for all elements of the list. If a list element does not have a duplicate it is not removed from the list.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;rem_dup&lt;/strong&gt;&lt;/span&gt; makes use of auxiliary predicates like &lt;span style="font-family:courier new;"&gt;&lt;strong&gt;remove/3, append/3 and member/2. member/2&lt;/strong&gt;&lt;/span&gt; checks whether some X is element of some list L. &lt;span style="font-family:courier new;"&gt;&lt;strong&gt;remove/3&lt;/strong&gt;&lt;/span&gt; removes some X from list L1 yielding the result list L2. &lt;span style="font-family:courier new;"&gt;&lt;strong&gt;append/3&lt;/strong&gt;&lt;/span&gt; does the opposite it appends some X to an existing list L1 yielding L2.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-8591261234192384148?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/8591261234192384148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=8591261234192384148' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/8591261234192384148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/8591261234192384148'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/03/adventures-in-prolog-computations-with.html' title='Adventures in Prolog - Computations with lists III'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-6678073599296705645</id><published>2009-03-05T21:55:00.003+01:00</published><updated>2009-03-05T21:57:48.963+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='Link'/><title type='text'>Adventures in Prolog - Link</title><content type='html'>Since I am quite occupied these days, I will only post a link to some intellectual stimulus today.&lt;br /&gt;&lt;br /&gt;If you follow this &lt;a href="http://www.cs.kuleuven.be/~dtai/ppcbook/ppcbook.pdf"&gt;link&lt;/a&gt; you will be taken to "The First 10 Prolog Programming Contests". So indulge some brain food.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-6678073599296705645?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/6678073599296705645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=6678073599296705645' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6678073599296705645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6678073599296705645'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/03/adventures-in-prolog-link.html' title='Adventures in Prolog - Link'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-6816840852597284379</id><published>2009-02-25T21:31:00.003+01:00</published><updated>2009-02-25T21:36:49.752+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><title type='text'>Adventures in Prolog - Simplify Sum (2)</title><content type='html'>The last post showed how to compute simple addition expressions. To provide a more structured approach to the problem at hand, I decided to write a small Prolog program that actually recognizes such addition expressions. This program basically represents a Prolog conversion of the grammar underlying such addition expressions. Because Prolog notation and grammer are so close, I will not comment on the following Prolog clauses.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;addition_expression&lt;/strong&gt;(A) :- &lt;strong&gt;sum_term&lt;/strong&gt;(A).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;addition_expression&lt;/strong&gt;(A) :- &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  A = X + Y, &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;strong&gt;addition_expression&lt;/strong&gt;(X), &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;strong&gt;sum_term&lt;/strong&gt;(Y).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;sum_term&lt;/strong&gt;(X) :- &lt;strong&gt;number&lt;/strong&gt;(X).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;sum_term&lt;/strong&gt;(X) :- &lt;strong&gt;atom&lt;/strong&gt;(X).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;sum_term&lt;/strong&gt;(X) :- &lt;strong&gt;prod_term&lt;/strong&gt;(X).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;prod_term&lt;/strong&gt;(X) :- X = A * B, &lt;strong&gt;number&lt;/strong&gt;(A), &lt;strong&gt;atom&lt;/strong&gt;(B).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;prod_term&lt;/strong&gt;(X) :- X = A * B, &lt;strong&gt;atom&lt;/strong&gt;(A), &lt;strong&gt;number&lt;/strong&gt;(B).&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-6816840852597284379?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/6816840852597284379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=6816840852597284379' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6816840852597284379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6816840852597284379'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/02/adventures-in-prolog-simplify-sum-2.html' title='Adventures in Prolog - Simplify Sum (2)'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-6331656038010093348</id><published>2009-02-22T20:24:00.002+01:00</published><updated>2009-02-22T20:55:10.404+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><title type='text'>Adventures in Prolog - Simplify Sum (1)</title><content type='html'>&lt;span style="font-family:arial;"&gt;Today's post is concerned with (the first part of) an example task from the book "Prolog Programming For Artificial Intelligence" - it is a about the simplification of additive terms using Prolog's facilities to reason about the type of some symbol.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;For example, Prolog offers the following (and more) built-in predicates:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;number&lt;/strong&gt;&lt;/span&gt;/1 - is the argumet passed, a number, e.g. number(1) returns true&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;atom&lt;/strong&gt;&lt;/span&gt;/1 - is the passed argument an atom, e.g. atom(x) returns true&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;compound&lt;/strong&gt;&lt;/span&gt;/1 - is the passed argument a compound term, e.g. compound(X+Y) returns true&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;Now, that we know how to inspect the type of some Prolog symbol, we may take a look onto today's task. Given some summation, the task is to simplify this summation, using some predicate called &lt;span style="font-family:courier new;"&gt;&lt;strong&gt;simplify_sum&lt;/strong&gt;&lt;/span&gt; or &lt;span style="font-family:courier new;"&gt;&lt;strong&gt;simp_sum&lt;/strong&gt;&lt;/span&gt; (for short).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;For example:&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;1 +2 +3 = 6&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;1 +a = a +1&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;a + b + 1 + c = a+ b +c + 1&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;a + 1 +2 + b = a + b + 3&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;So in short, the summation should be ordered with atoms first and aggregated numbers last. The original task by Bratko is concerned with the aggration of atoms as well, such as x +x = 2*x, but I will keep this for the next post.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;So based on the above statement of the problem, we must consider some elementary cases, such as: &lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;number + atom = atom + number&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;number + number = number&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;atom1 + atom2 = atom1 + atom2&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;atom + number = atom + number&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;These cases will act as the recursion anchor in our simp_sum clauses. Based on this reduction to the simplest form of the problem (please note, that we do not consider a case where only one atom or one number is passed to simp_sum), we identify more advanced incarnations of the problem.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;We must consider the following:&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;some compound term + number&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Arial;"&gt;some compound term + atom&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;cases as well. The reason for compound term occuring only on the left-hand side is the associativity of the + operator. For example. 3 + 4 + 5 is (3 + 4) + 5 and consuequently we have 3+ 4 +5 = compound + number where compound = number + number. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;Putting together all this information we might come up with the following ... &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;simp_sum&lt;/strong&gt;(X + Y, R) :- &lt;strong&gt;number&lt;/strong&gt;(X), &lt;strong&gt;number&lt;/strong&gt;(Y), R &lt;strong&gt;is&lt;/strong&gt; X + Y.&lt;br /&gt;&lt;strong&gt;simp_sum&lt;/strong&gt;(X + Y, X + Y) :-  &lt;strong&gt;atom&lt;/strong&gt;(X),  &lt;strong&gt;number&lt;/strong&gt;(Y).&lt;br /&gt;&lt;strong&gt;simp_sum&lt;/strong&gt;(X + Y, Y + X) :-  &lt;strong&gt;atom&lt;/strong&gt;(Y),  &lt;strong&gt;number&lt;/strong&gt;(X).&lt;br /&gt;&lt;strong&gt;simp_sum&lt;/strong&gt;(X + Y, X + Y) :-  &lt;strong&gt;atom&lt;/strong&gt;(X),  &lt;strong&gt;atom&lt;/strong&gt;(Y), X \== Y.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;%Result of simpsum is not compound&lt;br /&gt;&lt;strong&gt;simp_sum&lt;/strong&gt;(X + Y, Z) :-&lt;br /&gt;  &lt;strong&gt;simp_sum&lt;/strong&gt;(X, X0), &lt;strong&gt;number&lt;/strong&gt;(X0), &lt;strong&gt;number&lt;/strong&gt;(Y), Z &lt;strong&gt;is&lt;/strong&gt; X0 + Y.&lt;br /&gt;&lt;strong&gt;simp_sum&lt;/strong&gt;(X + Y, Y + X0) :-&lt;br /&gt;  &lt;strong&gt;simp_sum&lt;/strong&gt;(X, X0), &lt;strong&gt;number&lt;/strong&gt;(X0), &lt;strong&gt;atom&lt;/strong&gt;(Y).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;%Result of simpsum is compound&lt;br /&gt;&lt;strong&gt;simp_sum&lt;/strong&gt;(X + Y, A + Y0) :-&lt;br /&gt;  &lt;strong&gt;simp_sum&lt;/strong&gt;(X, X0), &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;number&lt;/strong&gt;(Y), X0 = A + B,&lt;br /&gt;  &lt;strong&gt;number&lt;/strong&gt;(B), &lt;strong&gt;simp_sum&lt;/strong&gt;(B+Y, Y0).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;simp_sum&lt;/strong&gt;(X + Y, A + B + Y) :-&lt;br /&gt;  &lt;strong&gt;simp_sum&lt;/strong&gt;(X, X0), &lt;strong&gt;number&lt;/strong&gt;(Y), X0 = A + B, &lt;strong&gt;atom&lt;/strong&gt;(B).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;simp_sum&lt;/strong&gt;(X + Y, A + Y + B) :-&lt;br /&gt;  &lt;strong&gt;simp_sum&lt;/strong&gt;(X, X0), &lt;strong&gt;atom&lt;/strong&gt;(Y), X0 = A + B, &lt;strong&gt;number&lt;/strong&gt;(B).&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;strong&gt;simp_sum&lt;/strong&gt;(X + Y, A + B + Y) :-&lt;br /&gt;  &lt;strong&gt;simp_sum&lt;/strong&gt;(X, X0), &lt;strong&gt;atom&lt;/strong&gt;(Y), X0 = A + B, &lt;strong&gt;atom&lt;/strong&gt;(B).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;When Prolog is asked:&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;simp_sum(1 + b + 2 + c + a + 4 + d + 39 + e+ f + 122, X).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;It answers correctly:&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;X = b+c+a+d+e+f+168 .&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-6331656038010093348?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/6331656038010093348/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=6331656038010093348' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6331656038010093348'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6331656038010093348'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/02/adventures-in-prolog-simplify-sum-1.html' title='Adventures in Prolog - Simplify Sum (1)'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-7011913943603456906</id><published>2009-02-19T19:43:00.004+01:00</published><updated>2009-02-19T20:10:13.643+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='lists'/><title type='text'>Adventures in Prolog - Computations with lists II</title><content type='html'>&lt;span style="font-family:times new roman;"&gt;&lt;span style="font-family:arial;"&gt;As mentioned in my last post, this post is concerned with building some abstraction when computing with lists. For this, I will abstract the the&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;addList&lt;/span&gt;&lt;/strong&gt; &lt;span style="font-family:arial;"&gt;and&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;mulList&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:arial;"&gt; prodecures into one more general processList procedure. &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;processList&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:arial;"&gt; will iterate over a list and process it according to some user-defined function. Users of F# might recognize this from F#'s map function offered by a list object.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;At first we define the processList function. processList takes 4 input parameters - a list, a processing function some identity element and the result.&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;processList&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:arial;"&gt; processes some input list according to the provided processing function. The identity&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;strong&gt;Identity&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-family:arial;"&gt; element is used to process the empty list. The result of this operation is placed into the variable &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;Res&lt;/strong&gt;&lt;/span&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;%processList/4&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;processList&lt;/strong&gt;([], F, Identity, Identity) :- &lt;strong&gt;functor&lt;/strong&gt;(_, F, 3).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;processList&lt;/strong&gt;([HT], F, Identity, Res) :- &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;functor&lt;/strong&gt;(_, F, 2), &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;processList&lt;/strong&gt;(T, F, Identity, L1), &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;apply&lt;/strong&gt;(F, [H, L1, Res]).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:times new roman;"&gt;&lt;span style="font-family:arial;"&gt;The&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;functor&lt;/span&gt;&lt;/strong&gt; &lt;span style="font-family:arial;"&gt;procedure checks whether the user supplied processing function F is indeed a function accepting 3 Variables (F/3).&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;processList&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:arial;"&gt; is similar to&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;mulList&lt;/span&gt;&lt;/strong&gt; &lt;span style="font-family:arial;"&gt;or&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;addList&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:arial;"&gt;, in that it uses the recursive definition of a list to process each list element.&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;apply&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-family:arial;"&gt; is used to call the user-supplied procedure F with submitted input variables.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:Times New Roman;"&gt;&lt;span style="font-family:arial;"&gt;By itself&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;processList&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:arial;"&gt; does not do much, it is merely the skeleton to enable abstract computation on lists. To make use of it, we have to define some processing function F.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Times New Roman;"&gt;&lt;span style="font-family:arial;"&gt;As mentioned, I want to use&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;processList&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:arial;"&gt; to abstract&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;addList&lt;/span&gt;&lt;/strong&gt; &lt;span style="font-family:arial;"&gt;and&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;mulList&lt;/span&gt;&lt;/strong&gt;.&lt;span style="font-family:arial;"&gt; For this, let's define two ternary relations &lt;strong&gt;add&lt;/strong&gt; and &lt;strong&gt;mul&lt;/strong&gt;.&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;add&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:arial;"&gt; is used to realize &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;addList&lt;/span&gt;&lt;/strong&gt; &lt;span style="font-family:arial;"&gt;and&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;mul&lt;/span&gt;&lt;/strong&gt; is &lt;span style="font-family:arial;"&gt;given to realize&lt;/span&gt; &lt;strong&gt;&lt;span style="font-family:courier new;"&gt;mulList&lt;/span&gt;&lt;/strong&gt;.&lt;span style="font-family:arial;"&gt; Their definition is straightforward and presented in the following&lt;/span&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;%test ops&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;add&lt;/strong&gt;(X, 0, X).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;add&lt;/strong&gt;(0, _, 0).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;add&lt;/strong&gt;(X, Y, Z) :- Z is X + Y.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;mul&lt;/strong&gt;(_, 0, 0).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;mul&lt;/strong&gt;(0, _, 0).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;mul&lt;/strong&gt;(X, 1, X).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;mul&lt;/strong&gt;(1, X, X).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;mul&lt;/strong&gt;(X, Y, Z) :- Z is X*Y.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Given the above definitions, we may ask Prolog now:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;?- &lt;strong&gt;processList&lt;/strong&gt;([1, 2, 3, 4, 5], &lt;strong&gt;add&lt;/strong&gt;, 0, R).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;, which yields:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;R = 15&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;span style="font-family:times new roman;"&gt;&lt;span style="font-family:arial;"&gt;Clearly&lt;/span&gt;,&lt;/span&gt; &lt;strong&gt;add&lt;/strong&gt;&lt;span style="font-family:times new roman;"&gt; &lt;span style="font-family:arial;"&gt;and&lt;/span&gt; &lt;/span&gt;&lt;strong&gt;mul&lt;/strong&gt;&lt;span style="font-family:times new roman;"&gt;&lt;span style="font-family:arial;"&gt; are simple examples but more powerful processing functions can be implemented and passed to&lt;/span&gt; &lt;/span&gt;&lt;strong&gt;processList&lt;/strong&gt;.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-7011913943603456906?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/7011913943603456906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=7011913943603456906' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/7011913943603456906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/7011913943603456906'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/02/adventures-in-prolog-computations-with_19.html' title='Adventures in Prolog - Computations with lists II'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-5477249394271927572</id><published>2009-02-18T21:29:00.003+01:00</published><updated>2009-02-18T22:13:48.473+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='lists'/><title type='text'>Adventures in Prolog - Computations with lists</title><content type='html'>My last post was concerned with basic computations in Prolog using the powerful technique - recursion. Today's post is concerned with recursion as well, but this time recursion is applied to Prolog's main data structure - the list.&lt;br /&gt;&lt;br /&gt;A list in Prolog is a recursive data structure itself. Why? Because a list can be built by remembering the following ...&lt;br /&gt;&lt;br /&gt;1. the empty list [] is a list&lt;br /&gt;2. a list can be built by appending any list T to an item H, which yields [HT]&lt;br /&gt;&lt;br /&gt;Using this definition we can see that the list [1, 2, 3, 4] is indeed a list with H = 1 and T = [2, 3, 4]. Consequently, a list cannot only be built from points 1. and 2. but also decomposed according to 1. and 2. Therefore 1. and 2. form the underlying principle when computing with lists in Prolog.&lt;br /&gt;&lt;br /&gt;Now that we have covered the basic principle underlying a list. I will present two operations on lists - the addition of elements of a list (sumList) and the multiplication of elements of a list (mulList).&lt;br /&gt;&lt;br /&gt;Both operations make use of the presented recursive structure of a list. The needed recursion anchor is the processing of the empty list. This maps to the identity operation in addition and multiplication. Identity in addition is performed using the zero element thus - a + 0 = 0 + a = a. Identity in multiplication is done by multiplying with the one element thus a * 1 = 1 * a = a.&lt;br /&gt;&lt;br /&gt;Employing both identities, the definition of sumList and mulList become straightforward. A list is peeled down until it is stripped to the empty list, in this case the identity operation is performed. While peeling the list each element is either added or multiplied with the result obtained by performing the operation on the remaining unpeeled list (the list's tail T).&lt;br /&gt;&lt;br /&gt;%sumList/2 sum list elements%&lt;br /&gt;&lt;strong&gt;sumList&lt;/strong&gt;([], 0).&lt;br /&gt;&lt;strong&gt;sumList&lt;/strong&gt;([HT], L) :-&lt;br /&gt;&lt;strong&gt;  sumList&lt;/strong&gt;(T, L1),&lt;br /&gt;  L &lt;strong&gt;is&lt;/strong&gt; H + L1.&lt;br /&gt;&lt;br /&gt;%mul list elements%&lt;br /&gt;&lt;strong&gt;mulList&lt;/strong&gt;([], 1).&lt;br /&gt;&lt;strong&gt;mulList&lt;/strong&gt;([HT], L) :-&lt;br /&gt;&lt;strong&gt;  mulList&lt;/strong&gt;(T, L1),&lt;br /&gt;  L &lt;strong&gt;is&lt;/strong&gt; H * L1.&lt;br /&gt;&lt;br /&gt;In my next post, I will cover the abstraction from special computations on lists to defining a general operation on a list, which executes a special function on each list item. This is similar to F#'s list-map function.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-5477249394271927572?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/5477249394271927572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=5477249394271927572' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/5477249394271927572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/5477249394271927572'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/02/adventures-in-prolog-computations-with.html' title='Adventures in Prolog - Computations with lists'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-8055196223701481398</id><published>2009-02-15T19:15:00.004+01:00</published><updated>2009-02-15T19:24:12.454+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><title type='text'>Adventures in Prolog - Simple computations</title><content type='html'>This time I present a way to calculate the ith power of some integer j (i is also an integer number). Clearly, this is nothing too sophisticated but it will be helpful for some other program, I want to show later on.&lt;br /&gt;&lt;br /&gt;Power is implemented as a simple ternary relation, which uses recursion. The base cases for power are of course the 0th and 1st power of some integer number. All other powers will be dependant on this anchor. The ith power of j means that j is multiplied with itself i times. For instance, the 3rd power of 2 is eigth, which is 2 * 2 * 2 = 8. This is used to implement the recursive core of power, which is ith power of j is the j * (i-1)th power of j.&lt;br /&gt;&lt;br /&gt;After the basic power relation, power10 and power2 show how to use existing relations to implement some simple abstractions.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;%power/3&lt;br /&gt;&lt;strong&gt;power&lt;/strong&gt;(X, 0, 1).&lt;br /&gt;&lt;strong&gt;power&lt;/strong&gt;(X, 1, X).&lt;br /&gt;&lt;strong&gt;power&lt;/strong&gt;(X, Y, Z) :-&lt;br /&gt;  Y1 &lt;strong&gt;is&lt;/strong&gt; Y - 1,&lt;br /&gt;  &lt;strong&gt;power&lt;/strong&gt;(X, Y1, Z1),&lt;br /&gt;  Z &lt;strong&gt;is&lt;/strong&gt; X * Z1.&lt;br /&gt;&lt;br /&gt;%power10/2&lt;br /&gt;&lt;strong&gt;power10&lt;/strong&gt;(P, R) :- &lt;strong&gt;power&lt;/strong&gt;(10, P, R).&lt;br /&gt;%power2/2&lt;br /&gt;&lt;strong&gt;power2&lt;/strong&gt;(P, R) :- &lt;strong&gt;power&lt;/strong&gt;(2, P, R).&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/code&gt;&lt;code&gt;&lt;code&gt;&lt;/code&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-8055196223701481398?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/8055196223701481398/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=8055196223701481398' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/8055196223701481398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/8055196223701481398'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/02/adventures-in-prolog-simple.html' title='Adventures in Prolog - Simple computations'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-5209301454830113542</id><published>2009-02-15T10:52:00.000+01:00</published><updated>2009-02-15T12:15:08.338+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='Fibonacci'/><title type='text'>Adventures in Prolog - Fibonacci</title><content type='html'>&lt;span style="font-family:times new roman;"&gt;As I have played around with Prolog lately, I wanted to share some enriching moments with my new favourite pet. We start of with the famous Fibonnaci numbers and their computation in Prolog. To spice things up, I used the dynamic clause, which enables one to add clauses to an existing database.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;:- &lt;strong&gt;dynamic&lt;/strong&gt;(fib/2).&lt;br /&gt;&lt;strong&gt;fib&lt;/strong&gt;(0, 1).&lt;br /&gt;&lt;strong&gt;fib&lt;/strong&gt;(1, 1).&lt;br /&gt;&lt;strong&gt;fib&lt;/strong&gt;(F, X) :-&lt;br /&gt;  F1 &lt;strong&gt;is&lt;/strong&gt; F-1,&lt;br /&gt;  F2 &lt;strong&gt;is&lt;/strong&gt; F-2,&lt;br /&gt;&lt;strong&gt;  fib&lt;/strong&gt;(F1, X1),&lt;br /&gt;&lt;strong&gt;  fib&lt;/strong&gt;(F2, X2),&lt;br /&gt;  X &lt;strong&gt;is&lt;/strong&gt; X1 + X2,&lt;br /&gt;&lt;strong&gt;  asserta&lt;/strong&gt;(fib(F, X)).&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;&lt;/p&gt;&lt;br /&gt;&lt;span style="font-family:times new roman;"&gt;So what does this listing do? Clearly, it computes the ith value of the Fibonacci sequence using recoursion. Therefore, the recoursion anchor - 1st and 0th value - of the sequence is established first. After that the definition of the sequence is given in its known form. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:times new roman;"&gt;By making the predicate fib/2 dynamic, we can add facts to the list of clauses covering &lt;span style="font-family:courier new;"&gt;fib/2&lt;/span&gt;. Dynamic has to be executed upon loading the fib database. That is why we write &lt;span style="font-family:courier new;"&gt;:- dynamic(fib/2).&lt;/span&gt; .&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:times new roman;"&gt;Now new knowledge about the Fibonnaci values can be added to the database. This is what is done later one with the &lt;span style="font-family:courier new;"&gt;asserta&lt;/span&gt; statement - asserta adds new clauses at the beginning of the database (&lt;span style="font-family:courier new;"&gt;assertz&lt;/span&gt; at the end). The value of the computation of the jth Fibonacci sequence value (&lt;span style="font-family:courier new;"&gt;fib(J, X)&lt;/span&gt;) is added as a fact to the database, thereby speeding up future computations of the same Fibonacci sequence value.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:times new roman;"&gt;&lt;/span&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-5209301454830113542?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/5209301454830113542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=5209301454830113542' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/5209301454830113542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/5209301454830113542'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2009/02/adventures-in-prolog-fibonacci.html' title='Adventures in Prolog - Fibonacci'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-1551825444373521738</id><published>2008-08-23T21:07:00.000+02:00</published><updated>2008-08-24T11:26:53.784+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MSR'/><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='Terrarium2'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><title type='text'>Adventures in F# - A port of the simplest Herbivore</title><content type='html'>Following the past of my previous post, this time I present a barebones stripped-down version of  the Herbivore that ships with the Terrarium SDK. The code is will equip you with a compilable herbivore, which however does nothing but sit in your terrarium. Just like in the previous post, I did not strip out some of the inline comments, which may be helpful to some of us.&lt;br /&gt;&lt;br /&gt;So here comes the code ...&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;code&gt;&lt;strong&gt;namespace&lt;/strong&gt;&lt;/code&gt;&lt;code&gt; CBHerbivore&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;#light&lt;br /&gt;#r "E:\\Development\\my fsharp\\Terrarium\\Terrarium\\OrganismBase.dll"&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;open&lt;/strong&gt; System;;&lt;br /&gt;&lt;strong&gt;open&lt;/strong&gt; System.Drawing;;&lt;br /&gt;&lt;strong&gt;open&lt;/strong&gt; System.Collections;;&lt;br /&gt;&lt;strong&gt;open&lt;/strong&gt; System.IO;;&lt;br /&gt;&lt;strong&gt;open&lt;/strong&gt; OrganismBase;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;//Sample Herbivore&lt;br /&gt;//The following Assembly attributes must be applied to each&lt;br /&gt;//Organism Assembly&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;[&amp;lt;assembly: OrganismClass("CBHerbivore.CBHerbivore")&amp;gt;]&lt;br /&gt;//The class that derives from Animal&lt;br /&gt;[&amp;lt;assembly: AuthorInformation("Christian Bitter", "x@y.z")&amp;gt;]&lt;br /&gt;//It's an herbivore&lt;br /&gt;[&amp;lt;CarnivoreAttribute(false)&amp;gt;]&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;span style="font-size:85%;"&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;//This value must be between 24 and 48, 24 means faster&lt;br /&gt;//reproduction&lt;br /&gt;//while 48 would give more defense and attack power&lt;br /&gt;//Make it smaller for reproduction&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;[&amp;lt;MatureSize(26)&amp;gt;]&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;span style="font-size:85%;"&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;//AnimalSkin = AnimalSkinFamilyEnum.Beetle, you can be a Beetle&lt;br /&gt;//an Ant, a Scorpion, an Inchworm, or a Spider&lt;br /&gt;//MarkingColor = KnownColor.Red, you can choose to mark your&lt;br /&gt;//creature with a color.&lt;br /&gt;//This does not affect appearance in the game.&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;[&amp;lt;AnimalSkin(AnimalSkinFamily.Beetle)&amp;gt;]&lt;br /&gt;[&amp;lt;MarkingColor(KnownColor.Red)&amp;gt;]&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;span style="font-size:85%;"&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;//You get 100 points to distribute among these attributes to define&lt;br /&gt;//what your organism can do.  &lt;br /&gt;//Choose them based on the strategy your organism will use.&lt;br /&gt;//This organism hides and has good eyesight to find plants.&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;[&amp;lt;MaximumEnergyPoints(0)&amp;gt;]&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;//Don't need to increase this as it just sits next to plants&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;[&amp;lt;EatingSpeedPoints(0)&amp;gt;] //Ditto&lt;br /&gt;[&amp;lt;AttackDamagePoints(0)&amp;gt;] //Doesn't ever attack&lt;br /&gt;[&amp;lt;DefendDamagePoints(0)&amp;gt;]&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;span style="font-size:85%;"&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;//This attribute changes the skin of our herbivore, &lt;br /&gt;//which is now going to be a beetle.&lt;br /&gt;//Point Based Attributes&lt;br /&gt;//Doesn't even defend&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;[&amp;lt;MaximumSpeedPoints(0)&amp;gt;] //Doesn't need to move quickly&lt;br /&gt;[&amp;lt;CamouflagePoints(50)&amp;gt;] //Try to remain hidden&lt;br /&gt;[&amp;lt;EyesightPoints(50)&amp;gt;] &lt;span style="font-size:85%;"&gt;//Need this to find plants better&lt;/span&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;type&lt;/strong&gt; CBHerbivore () =   &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;  &lt;strong&gt;inherit&lt;/strong&gt; Animal()  &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;  &lt;strong&gt;override&lt;/strong&gt; sh.Initialize() = ()  &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;  &lt;strong&gt;override&lt;/strong&gt; sh.SerializeAnimal (m:MemoryStream) = ()  &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;override&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; sh.DeserializeAnimal (m:MemoryStream) = ()&lt;/span&gt;&lt;p&gt;&lt;span style="font-family:arial;"&gt;As you may see, the main difference between this herbivore and the previous plant, is the base type our herbivore type needs to implement, and some attributes declared on our animal. In this case the abstract Animal class, declares 3 abstract members (Initialize, SerializeAnimal, DesirializeAnimal), which need to be implemented by our herbivor. Attributes control some of the properties of our herbivore, such as its moving speed, etc. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:arial;"&gt;Again, if you compile this type and introduce it to your terrarium, do not be surprised, to see, that the animal is stiff and not moving like an animal during hibernation. This is due to not implemented event handlers. These event handlers are responsible for your animal's interaction with its environment.&lt;/span&gt;&lt;/p&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-1551825444373521738?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/1551825444373521738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=1551825444373521738' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/1551825444373521738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/1551825444373521738'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2008/08/adventures-in-f-port-of-simplest.html' title='Adventures in F# - A port of the simplest Herbivore'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-7186445262302631716</id><published>2008-08-23T14:08:00.000+02:00</published><updated>2008-08-23T14:38:26.680+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MSR'/><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='Terrarium2'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><title type='text'>Adventures in F# - A Plant for Terrarium 2</title><content type='html'>&lt;p&gt;Recently, my beloved Terrarium-game has reappeared from the neatherworlds of software. As some of you may know, Terrarium's intend was to showcase the back then rather new and exciting .NET platform version 1.x (not that it is not still exciting). Although from a gamer's perspective, the graphics weren't all to great, from a technology standpoint, it featured great things, such as Webservices, Reflection, etc.&lt;/p&gt;&lt;p&gt;At some point Terrarium ceased to exist, which was a shame, since the community was quite active developing plants, herbivores and carnivores for the virtual ecosystem that Terrarium simulates. I for myself, developed some simple creatures too (a simple decision-based/state-based agent), as part of a project I did during university for my AI course. More advanced (in comparison to my creature) could be imported showcasing great AI stuff such as A*, neural networks, planning, etc.&lt;/p&gt;&lt;p&gt;However, in an community effort, Terrarium was relaunched lately on codeplex and will hopefully see great new additions, such as a port to a more current version of the .NET platform and DirectX.&lt;/p&gt;&lt;p&gt;In a small attempt I tried to put my superficial F#  skills to work, and decided to port a plant organism to F#. My attempt can be seen in the following lines of code. For a C# version, see the codeplex discussion &lt;a href="http://www.codeplex.com/terrarium2/Thread/View.aspx?ThreadId=32598"&gt;here&lt;/a&gt;. I decided to leave the comments from the discussion as is.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;namespace&lt;/strong&gt; CBPlant&lt;/p&gt;&lt;p&gt;We open a namespace for the plant organism&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;#light&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;#r&lt;/strong&gt; "E:\\Path to OrganismBase.dll\\OrganismBase.dll"&lt;/code&gt;&lt;/span&gt;&lt;/code&gt;&lt;p&gt;We set the environment to lightweight and reference the OrganismBase.dll, which contains all the Terrarium2 stuff.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;open&lt;/strong&gt; System;;&lt;br /&gt;&lt;strong&gt;open&lt;/strong&gt; System.Drawing;;&lt;br /&gt;&lt;strong&gt;open&lt;/strong&gt; System.Collections;;&lt;br /&gt;&lt;strong&gt;open&lt;/strong&gt; System.IO;;&lt;br /&gt;&lt;strong&gt;open&lt;/strong&gt; OrganismBase;;&lt;/p&gt;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;p&gt;We open some namespaces, which we are going to use later and dive right into the code.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;// Sample Herbivore&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;p&gt;&lt;/p&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;//Strategy&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;//This animal moves until it finds a food source and &lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;//then stays there&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;// The following Assembly attributes must be applied to each &lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;&lt;span style="font-family:courier new;"&gt;//Organism Assembly&lt;br /&gt;[&amp;lt;assembly: OrganismClass("CBPlant.CBPlant")&amp;gt;&lt;assembly:&gt;]    // The class that derives from Animal&lt;br /&gt;[&amp;lt;assembly: AuthorInformation("XYZ", "x@y.z")&amp;gt;&lt;assembly:&gt;] // Provide Author Information&lt;br /&gt;&lt;strong&gt;do&lt;/strong&gt;()&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;&lt;assembly:&gt;&lt;assembly:&gt;&lt;/p&gt;&lt;p&gt;Assembly-level attributes have to be declared via a global do() statement. See the discussion &lt;a href="http://cs.hubfs.net/forums/post/3722.aspx"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;//3.2 Plants &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;//The definition of a plant is relatively easy since plants do not have to have any sort of movement defined to allow them to locate sources of food. &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;//Each plant has three basic functions: &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;//1. Grow &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;//2. Reproduce by spreading seeds &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;//3. Be eaten by herbivores &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;//A plant organism does not need to contain any methods, it just has three properties that define how a plant functions. &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;//4 &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;//1. The “MaximumEnergyPoints” property allows the developer to state how many energy points a herbivore will gain by consuming this plant. The maximum allowed is 10. &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;//2. The “MatureSize” property which must be a number between 24 and 48 states the maximum size a plant can grow to when it has survived for some amount of time without being consumed. The smaller a plant is, the faster it will be able to reproduce. As a plant gets larger it will become easier for herbivores to see and will more likely be consumed. &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;//3. The “SeedSpreadDistanceAttribute” states the maximum distance a plant can spread seeds from its current location. The maximum allowed is 100. These three properties alone are enough to define a functioning plant for the Terrarium game. &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;// This value must be between 26 and 48, 26 means faster reproduction &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;// while 48 would give more defense and attack power &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;// Make it smaller for reproduction*) &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;[&amp;lt;MatureSize(26)&amp;amp;gt&lt;maturesize&gt;;] &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;[&amp;lt;SeedSpreadDistance(100)&amp;gt;&lt;seedspreaddistance&gt;] &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;// Point Based Attributes &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;// You get 100 points to distribute among these attributes to define &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;// what your organism can do.&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;Choose them based on the strategy your organism &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;// will use. This organism hides and has good eyesight to find plants&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;[&lt;maximumenergypoints&gt;&amp;lt;MaximumEnergyPoints(10)&amp;gt;] &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;type&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; CBPlant () = &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;inherit&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; Plant ()&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;override&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; cb.SerializePlant (m:MemoryStream) = ()&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;override&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; cb.DeserializePlant (m:MemoryStream) = ()&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;;;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;We define a new plant type, called CBPlant (full CBPlant.CBPlant). This type is a subclass of the abstract class Plant. We have to implement Plant's two abstract members, which according to the example is just an empty method body. If we compile this by invoking &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;fsc OrganismBase.dll CBPlant.fs -a&lt;/span&gt;&lt;/p&gt;&lt;p&gt;A new library will be created, containing just this simple type.&lt;/p&gt;&lt;p&gt;Hopefully, I will get to play some more with F# and Terrarium doing some other stuff, like porting the Herbivore, Carnivore and start to add some real behaviour. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-7186445262302631716?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.codeplex.com/terrarium2' title='Adventures in F# - A Plant for Terrarium 2'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/7186445262302631716/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=7186445262302631716' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/7186445262302631716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/7186445262302631716'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2008/08/adventures-in-f-plant-for-terrarium-2.html' title='Adventures in F# - A Plant for Terrarium 2'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-2511451633965454426</id><published>2008-08-23T11:43:00.000+02:00</published><updated>2008-08-23T12:25:03.855+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><title type='text'>Adventures in F# - F# and ADO.NET</title><content type='html'>&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;Today's post is rather simplistic in what it does, but it illustrates some key language elements of F#, such as exception handling. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;The task to accomplish is quite it easy, nameley, to connect to a SQL Server 2005 database called "TestDB" on my local machine, using ADO.NET to pull out some rows of the "Person" table having the following schema:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;Person (&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;  PersonID: &lt;strong&gt;int&lt;/strong&gt;; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;  FirstName &lt;strong&gt;nvarchar&lt;/strong&gt;(50); &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;  LastName &lt;strong&gt;nvarchar&lt;/strong&gt; (50); &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;  Street &lt;strong&gt;nvarchar&lt;/strong&gt;(50); &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;  City &lt;strong&gt;nvarchar&lt;/strong&gt;(50); &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;  ZIP &lt;strong&gt;int&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;The code we use in F# is a rather straightforward conversion of some typical C# code, and as such is probably not the best way to do things, but it gets the task done, and may illustate the point.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;#light&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;We use the lightweight syntax option.&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-size:100%;"&gt;&lt;strong&gt;open&lt;/strong&gt; System.Data;&lt;br /&gt;&lt;strong&gt;open&lt;/strong&gt; System;&lt;br /&gt;&lt;strong&gt;open&lt;/strong&gt; System.Data.SqlClient;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;As a next step, we have to open the correct namespaces.&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-size:100%;"&gt;&lt;strong&gt;let&lt;/strong&gt; ADONetTest = &lt;br /&gt;  &lt;strong&gt;let&lt;/strong&gt; conStringBuilder = &lt;strong&gt;new&lt;/strong&gt; SqlConnectionStringBuilder()&lt;br /&gt;  conStringBuilder.IntegratedSecurity &lt;- true&lt;br /&gt;  conStringBuilder.["Data Source"] &lt;- "localhost"&lt;br /&gt;  conStringBuilder.InitialCatalog &lt;- "TestDB"&lt;br /&gt;  &lt;strong&gt;let&lt;/strong&gt; con = &lt;strong&gt;new&lt;/strong&gt; SqlConnection(conStringBuilder.ConnectionString)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;These lines create the connection to the SQL Server 2005 database "TestDB" on my local machine. As you may see I use a mixture of passing values to properties (IntegratedSecurity, InitialCatalog) and the indexer (["Data Source"]) that is defined on the SqlConnectionStringBuilder type.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;try&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;      con.Open()&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;      &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;let&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; cmdString = "SELECT * FROM [dbo].[Person]"&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;      &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;let&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; cmd = &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;new&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; SqlCommand(cmdString, con)&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;      cmd.CommandType &lt;- CommandType.Text&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;      &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;using&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; (cmd.ExecuteReader()) (&lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;fun&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; reader -&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;          &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;if&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; (reader.HasRows) &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;then&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;              (&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                  printfn "Queried: %s" cmdString&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                  &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;while&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; (reader.Read()) &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;do&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                      (&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                          &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;let&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; id = reader.GetInt32(0)&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                          &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;let&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; firstName = reader.GetString(1)&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                          &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;let&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; lastName = reader.GetString(2)&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                          &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;let&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; street = reader.GetString(3)&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                          &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;let&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; city = reader.GetString(4)&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                          &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;let&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; zip = reader.GetInt32(5) &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                          printfn "%d %s %s %s %s %d" id firstName lastName street city zip&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                      )&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;                  &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;done&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;              )&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;          &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;else&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; (printfn "Empty result")&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;      )&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;      con.Close()&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;with&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;      | :? System.Data.SqlClient.SqlException &lt;/span&gt;&lt;strong&gt;&lt;span style="font-family:courier new;"&gt;as&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family:courier new;"&gt; sqlEx -&gt; printfn "%A" sqlEx.Message&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;      | _ -&gt; printfn "Unknown Exception"&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:courier new;"&gt;  (con :&gt; IDisposable).Dispose ()&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;;;&lt;/span&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;This part is responsible for the main functionality. We open the previously specified connection. We do this in a &lt;strong&gt;try-with&lt;/strong&gt; block, to be prepared in case of exceptions. We actually try to handle one exceptio, the SqlExceptio. In the &lt;strong&gt;with&lt;/strong&gt; block, we use type/pattern matching rule (|:? SqlException) to catch this particular exception. Since we do not have a handling strategy in place, a printf command is issued.The next with rule gets executed on whatever type not matching SqlException. We indicate that we do not even care about what it is (| _) using an anonymous rule. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;Inside our &lt;strong&gt;try&lt;/strong&gt; block, we &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;declare a SqlCommand and pass in the Sql query stored in the cmdString. variable. This command encapsulates a &lt;strong&gt;Select-From-Where&lt;/strong&gt; SQL-query. We execute the query, using one of F#'s equivalent's of the C# using statement - the &lt;strong&gt;using&lt;/strong&gt; statement (the other one would be &lt;strong&gt;use&lt;/strong&gt;).&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;The &lt;strong&gt;using&lt;/strong&gt; keeps track for us, that in the case of an exception the "Dispose" method of the object used in the &lt;strong&gt;using&lt;/strong&gt; statement is called - in this case it would be the Dispose declared by the result of  SqlCommand.ExecuteReader() - a DataReader object.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;Inside the using block, it is asked whether the result of the query (DataReader) actually has rows that were returned by our particular query. This is done by &lt;strong&gt;if&lt;/strong&gt; (reader.HasRows) &lt;strong&gt;then&lt;/strong&gt; () &lt;strong&gt;else&lt;/strong&gt; ().In case rows were returned by that query,they are enumerated by the &lt;strong&gt;while&lt;/strong&gt; &lt;strong&gt;do&lt;/strong&gt; () &lt;strong&gt;done&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt; loop. This loop does nothing but print each row present in the DataReader.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;The last statement to mention is the  (con :&gt; IDisposable).Dispose (). This statement casts the connection object into the IDisposable and calls the Dispose method on it. This has to be done, since it is not automatically called by a try-with block, and we have to ensure that all used objects are properly disposed of - espacially those that abstract native resources, such as database or file connections.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-2511451633965454426?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/2511451633965454426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=2511451633965454426' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/2511451633965454426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/2511451633965454426'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2008/08/adventures-in-f-f-and-adonet.html' title='Adventures in F# - F# and ADO.NET'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-7856178921254289460</id><published>2008-08-20T11:01:00.000+02:00</published><updated>2008-08-21T16:30:36.716+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SourceControl'/><category scheme='http://www.blogger.com/atom/ns#' term='Coding'/><title type='text'>Small one - SourceSafe via command line</title><content type='html'>Yes, I haven't been blogging for quite a bit and this small post is not going to change that but at least it is a little somethin'. I've been digging into F# and have had some great learning experience but this is nothing to really present now.&lt;br /&gt;&lt;br /&gt;Today I show a little snippet that let's you load some project ("XYZ") from SourceSafe into a specific folder (&amp;ltTarget Directory&amp;gt). This may come in handy in some sort of automatic build invironment.&lt;br /&gt;&lt;br /&gt;At first you need to define, i.e. set as environment variables: &lt;br /&gt;1. SourceSafe User Account, supplied with sufficient privileges to actually access the project you want to retrieve&lt;br /&gt;2. The account's password&lt;br /&gt;3. The path to the SourceSafe DB's SourceSafe configuration file (srcsafe.ini)&lt;br /&gt;&lt;br /&gt;Next you ask SourceSafe to change the working directory for the project, you are going to load. You do this via "ss Workfold". &lt;br /&gt;The last step is to load/get the actual project into the working directory.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;SET SSUSER=&amp;ltyour SourceSafe Account&amp;gt&lt;br /&gt;SET SSPWD=&amp;ltyour SourceSafe Account's Password&amp;gt&lt;br /&gt;SET SSDIR=&amp;ltthe path to your SourceSafe DB&amp;gt&lt;br /&gt;&lt;br /&gt;"SOURCESAFEDIR\ss.exe" Workfold $/&amp;ltPath to XYZ&amp;gt/XYZ "&amp;ltTarget Directory&amp;gt"&lt;br /&gt;"SOURCESAFEDIR\ss.exe" get $/&amp;ltPath to XYZ&amp;gt/XYZ -R&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The only problem with this solution is, that SourceSafe is going to ask you, whether the intended working folder is the correct one. To fix this we include a change of the current directory into the &amp;ltTarget Directory&amp;gt and everything will be fine.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;SET SSUSER=&amp;ltyour SourceSafe Account&amp;gt&lt;br /&gt;SET SSPWD=&amp;ltyour SourceSafe Account's Password&amp;gt&lt;br /&gt;SET SSDIR=&amp;ltthe path to your SourceSafe DB&amp;gt&lt;br /&gt;&lt;br /&gt;cd "&amp;ltTarget Directory&amp;gt"&lt;br /&gt;&lt;br /&gt;"SOURCESAFEDIR\ss.exe" Workfold $/&amp;ltPath to XYZ&amp;gt/XYZ "&amp;ltTarget Directory&amp;gt"&lt;br /&gt;"SOURCESAFEDIR\ss.exe" get $/&amp;ltPath to XYZ&amp;gt/XYZ -R&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Another way to accomplish this sort of automatic build environment is by the use of SourceSafe initialization variables. These let one configure the SourceSafe environment. By specifying a custom SourceSafe initialization file, one may configure all aspects to one's needs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-7856178921254289460?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/7856178921254289460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=7856178921254289460' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/7856178921254289460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/7856178921254289460'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2008/08/small-one-sourcesafe-via-command-line.html' title='Small one - SourceSafe via command line'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-6991585970284207783</id><published>2008-05-02T00:14:00.000+02:00</published><updated>2009-02-15T12:16:47.490+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MSR'/><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><category scheme='http://www.blogger.com/atom/ns#' term='Fibonacci'/><title type='text'>Aventures in F# - Fibs</title><content type='html'>Today's post is about the famous Fibbonaci sequence: 0, 1, 1, 2, 3, 5, 8, ...&lt;br /&gt;&lt;br /&gt;I will present a recursive and an iterative F# approach to generating the sequence.&lt;br /&gt;&lt;br /&gt;The Fibbonaci number n = Fib(n) is generated as follows:&lt;br /&gt;&lt;br /&gt;Fib(n) = Fib(n-2) + Fib(n-1) where Fib(0) = 0 and Fib(1) = 1&lt;br /&gt;&lt;br /&gt;The condition Fib(0) and Fib(1) are the anchor to end the recursion and otherwise it is dug into the recursion. Consequently, ...&lt;br /&gt;&lt;br /&gt;1. &lt;b&gt;Recursive Approach&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;strong&gt;let rec&lt;/strong&gt; FibRec n =&lt;br /&gt;&lt;strong&gt;if&lt;/strong&gt; n = 0 &lt;strong&gt;then&lt;/strong&gt; 0&lt;br /&gt;&lt;strong&gt;else&lt;/strong&gt; &lt;strong&gt;if&lt;/strong&gt; n = 1 &lt;strong&gt;then&lt;/strong&gt; 1&lt;br /&gt;&lt;strong&gt;else&lt;/strong&gt; (FibRec (n-2) + FibRec(n-1))&lt;br /&gt;;;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;As you can see the function is rather straightforward and follows the definition closely. However, its recursive nature make it rather unsuiting for large values of n - you will notice that for large values of n the recursion slows the process down.&lt;br /&gt;&lt;br /&gt;2. &lt;b&gt;Iterative approach&lt;/b&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;strong&gt;let&lt;/strong&gt; FibIt n =&lt;br /&gt;&lt;strong&gt;if&lt;/strong&gt; n = 0 &lt;strong&gt;then&lt;/strong&gt; 0&lt;br /&gt;&lt;strong&gt;else if&lt;/strong&gt; n = 1 &lt;strong&gt;then&lt;/strong&gt; 1&lt;br /&gt;&lt;strong&gt;else&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;let&lt;/strong&gt; fibA = Array.create (n+1) 0&lt;br /&gt;fibA.[0] &lt;- 0 fibA.[1] &lt;- 1 &lt;strong&gt;for&lt;/strong&gt; i = 2 &lt;strong&gt;to&lt;/strong&gt; n &lt;strong&gt;do&lt;/strong&gt;&lt;br /&gt;fibA.[i] &lt;- fibA.[i-2] + fibA.[i-1] fibA.[n] ;; &lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family:georgia;"&gt;As you can see the iterative approach employs Fib(0) and Fib(1) equally as anchors. However, it uses a for loop starting at two to fill an array at index i with the Fibbonaci number Fib(i).&lt;/span&gt;&lt;/span&gt; Clearly, we do not need the array but it will come in handy at a later stage.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family:Georgia;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family:Georgia;"&gt;Although being faster, i.e. compare the recursive approach with the iterative approach for Fib(40) and you will notice some time difference, both approaches suffer data overflow. This means that Fib(48) displays correctly but Fib(49) wraps around the integer boarder and becomes a negative number. Therefore we have to find a way around this problem - probably the next time.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family:Georgia;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family:Georgia;"&gt;I have come around some valuable resources with respect to F# &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family:Georgia;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Marius Bancila's Blog: &lt;a href="http://mariusbancila.ro/blog/"&gt;http://mariusbancila.ro/blog/&lt;/a&gt;&lt;br /&gt;Robert Pickering's Strange Blog: &lt;a href="http://strangelights.com/blog/"&gt;http://strangelights.com/blog/&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family:Georgia;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-6991585970284207783?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://research.microsoft.com/fsharp' title='Aventures in F# - Fibs'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/6991585970284207783/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=6991585970284207783' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6991585970284207783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6991585970284207783'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2008/05/aventures-in-f-fibs.html' title='Aventures in F# - Fibs'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-3771577294647308998</id><published>2008-04-29T09:27:00.000+02:00</published><updated>2008-04-29T10:03:23.385+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><title type='text'>Aventures in F# - words is all you need</title><content type='html'>&lt;span style="font-family:times new roman;"&gt;F# let's you specify the same thing in different styles - depending on your likings (clarity, purity, style, compactness, problem-domain-specific) you my choose the appropriate expression.&lt;br /&gt;&lt;br /&gt;For example: Assume we have a list of numbers and want to transform them in a certain way, e.g. we want to square them.&lt;br /&gt;&lt;br /&gt;1. generate a list of numbers&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;let&lt;/strong&gt; numbers = [&lt;strong&gt;for&lt;/strong&gt; i &lt;strong&gt;in&lt;/strong&gt; 1..10 -&gt; i];;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:times new roman;"&gt;Now we have different options to reach our goal, i.e. transforming the elements of the list to be equal to their respective square, i.e. i -&gt; i * i&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:times new roman;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Times New Roman;"&gt;The first way to do this is to generate the set with squared numbers.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;let sqnumbers = [&lt;strong&gt;for &lt;/strong&gt;i &lt;strong&gt;in&lt;/strong&gt; 1..10 -&gt; i * i];;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;While it solves the problem, it was not exactly what I was looking for.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So we define a function that takes an integer list as input and generates the appropriate output list by taking each element squaring it and appending it to the output list.&lt;br /&gt;Let sqfunc be this function.&lt;br /&gt;&lt;br /&gt;One way of calling sqfunc is: &lt;span style="font-family:courier new;"&gt;sqfunc numbers;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But we could also use F#'s incredible pipelining operator &gt;&lt;br /&gt;which would result in: numbers &gt; sqfunc;;&lt;br /&gt;The operator matches perfectly the way of reading it, i.e. "put numbers into the pipeline component sqfunc" - Nice&lt;br /&gt;So If we were to compute the fourth power of our numbers list we could write:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;numbers &gt; xfunc &gt; xfunc;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The pipeline operator is nothing but syntatctic suggar, being defined as:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;strong&gt;let&lt;/strong&gt; (&gt;) x f = f x&lt;/span&gt;&lt;br /&gt;where x is the input to apply the function f on.&lt;br /&gt;&lt;br /&gt;Since we work on lists, we may also use the map function defined on list types. The map function takes as input a function that transforms elements of an input list. Therefore we may write&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;List.map (fun x -&gt; x * x) numbers;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This exhibits F#'s anonymous function values - so much like a C# delegate type as an input parameter to a function List.map.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-3771577294647308998?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://research.microsoft.com/fsharp' title='Aventures in F# - words is all you need'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/3771577294647308998/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=3771577294647308998' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/3771577294647308998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/3771577294647308998'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2008/04/aventures-in-f-words-is-all-you-need.html' title='Aventures in F# - words is all you need'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-3669434713634794727</id><published>2008-04-24T12:50:00.000+02:00</published><updated>2008-04-24T13:05:45.134+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='MSR'/><category scheme='http://www.blogger.com/atom/ns#' term='F#'/><title type='text'>Adventures in F#</title><content type='html'>Adventure 1: Reversing an integer list&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;strong&gt;let rec&lt;/strong&gt; ReverseList (l: &lt;strong&gt;int list&lt;/strong&gt;) =&lt;br /&gt;&amp;nbsp;&lt;strong&gt;match&lt;/strong&gt; l &lt;strong&gt;with&lt;/strong&gt;&lt;br /&gt;&amp;nbsp;&amp;brvbar;&amp;nbsp;H::T -&gt; (ReverseList T) &lt;strong&gt;@&lt;/strong&gt; [H]&lt;br /&gt;&amp;nbsp;&amp;brvbar;&amp;nbsp;[] -&gt; []&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The code is quite simple. It does the following:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;define a recoursive function (&lt;strong&gt;rec&lt;/strong&gt; keyword) on integer list argument&lt;/li&gt;&lt;li&gt;use pattern matching (&lt;strong&gt;match with&lt;/strong&gt;) on the argument l to decompose l into a head and a tail. The head is the head (first) element of l and tail is the remainder of l.&lt;/li&gt;&lt;li&gt;use this knowledge to call itself recoursively&lt;/li&gt;&lt;li&gt;It is checked whether l consists of a head H and a tail T, if yes, then ReverseList calls itself with T (the list consisting of the tail of l, i.e. l without the head element) and concatenates (&lt;strong&gt;@&lt;/strong&gt; operator) the result with the list consisting of the headelement ([H])&lt;/li&gt;&lt;li&gt;if the input argument l is the empty list ([]), then ReverseList exits by returning the empty list.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/code&gt;&lt;code&gt;&lt;code&gt;&lt;/code&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-3669434713634794727?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://research.microsoft.com/fsharp' title='Adventures in F#'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/3669434713634794727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=3669434713634794727' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/3669434713634794727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/3669434713634794727'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2008/04/adventures-in-f.html' title='Adventures in F#'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-588720546911730206</id><published>2007-12-06T10:55:00.000+01:00</published><updated>2007-12-06T11:07:07.285+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='3D'/><category scheme='http://www.blogger.com/atom/ns#' term='General'/><title type='text'>3D Engine Design</title><content type='html'>During the past weeks, I haven't been able to come up with something new and/or meaningful. But for those interested in building a 3D engine, I came across the &lt;a href="http://lightfeather.de/"&gt;Lightfeather 3D engine&lt;/a&gt;. And the guys over there describe (in a high level manner - functional point of view) the design of their engine. So an experienced graphics developer might use this information to design a "copy" or get inspired by the Lightfeather engine.&lt;br /&gt;&lt;br /&gt;Following is the "table of contents" of the Lightfeather 3D engine design:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://lightfeather.de/e107_plugins/wet_wiki/index.php?page=EngineDesignIntroduction"&gt;Introduction&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://lightfeather.de/e107_plugins/wet_wiki/index.php?page=EngineDesignScene"&gt;Geometry&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://lightfeather.de/e107_plugins/wet_wiki/index.php?page=EngineDesignScene"&gt;Scene&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://lightfeather.de/e107_plugins/wet_wiki/index.php?page=EngineDesignPortals"&gt;Portals&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://lightfeather.de/e107_plugins/wet_wiki/index.php?page=EngineDesignRendering"&gt;Rendering&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-588720546911730206?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://lightfeather.de/e107_plugins/wet_wiki/index.php?page=EngineDesignIntroduction' title='3D Engine Design'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/588720546911730206/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=588720546911730206' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/588720546911730206'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/588720546911730206'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2007/12/3d-engine-design.html' title='3D Engine Design'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-21640191928773183</id><published>2007-11-28T13:45:00.000+01:00</published><updated>2007-11-28T16:09:37.958+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AI'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Terrarium'/><title type='text'>Talk like an animal, walk like an animal ...</title><content type='html'>Well, after some time has passed, it seems that Microsoft's Terrarium is at least surfacing again. I have played around with Terrarium while doing some AI in the university. Official links are not working but googling a bit has popped a Microsoft site about some Canadian Terrarium contest. Look here &lt;a href="http://msdn.microsoft.com/canada/terrarium/"&gt;http://msdn.microsoft.com/canada/terrarium/&lt;/a&gt; in the bottom of the page you may even download some video made at the contest but it is not working.&lt;br /&gt;&lt;br /&gt;The new download link on windowsclient.net is this one &lt;a href="https://windowsclient.net/downloads/folders/starterkits/entry1269.aspx"&gt;https://windowsclient.net/downloads/folders/starterkits/entry1269.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Browsing through MSDN has surfaced that Tom Anderson did a VB.NET port of Terrarium from .NET framework version 1.x to 2.0. You will find the respective MSDN post here&lt;br /&gt;&lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=373738&amp;amp;SiteID=1"&gt;http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=373738&amp;amp;SiteID=1&lt;/a&gt;&lt;br /&gt;Unfortunately, he has stopped working on the project and there is no visible link to me where one can grab the .NET 2.0 port of Terrarium.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Maybe there is some time left to play around a bit ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-21640191928773183?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/21640191928773183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=21640191928773183' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/21640191928773183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/21640191928773183'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2007/11/talk-like-animal-walk-like-animal.html' title='Talk like an animal, walk like an animal ...'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-6310892185134334032</id><published>2007-10-06T23:00:00.001+02:00</published><updated>2007-10-06T23:08:24.774+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MRS'/><category scheme='http://www.blogger.com/atom/ns#' term='CCR'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Newbie on the CCR Road</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;This post is about the CCR part of MRS, in particular I am going to do some simple examples about ports and a simple arbiter the Receiver.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;CCR components use ports to communicate with each other. Just like a human being uses speech, verbal speech, or mimicry to communicate, so do CCR components use ports to communicate with each other. Ports are used to&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Send a message to a particular receiver.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Receive a message from a particular sender.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In terms of CCR port, we have to define how the message, looks like that our port is going to receive. For this, we have to define the message's underlying data type or more precisely we have to create a port, which receives a message with some particular data type.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;&lt;span style="font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Port&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt; stringPort = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Port&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt;();&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This creates a new port, which is able to send and receive message of type string. Now, that we have defined our port, how are do we send a message? Nothing simpler than that, the port offers an instance method Post. This method accepts a formal parameter item of type string. So the canonical "Hello World" example looks like this&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;stringPort.Post(&lt;span style="color:#a31515;"&gt;"Hello World"&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This passes the item of type string with value "Hello World" to our stringPort, where it waits to be taken from the port for whatever one wants to do with it. To illustrate that the sent item is really "sitting" on the stringPort, we could simply do the following:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt; (inputPort.ItemCount &amp;gt; 0)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;string&lt;/span&gt; item = inputPort.Test() &lt;span style="color:blue;"&gt;as &lt;/span&gt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt; (!&lt;span style="color:blue;"&gt;string&lt;/span&gt;.IsNullOrEmpty(item))&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;"Item: "&lt;/span&gt; + item);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:10;"&gt;This shows two things. The first (1) being, that you may query the number of items waiting on some port by the ports field ItemCount and the second (2) being that you may test the port for the presence of items. If there is one ore more items on the port, then Test will return this item as an object and remove it from the queue of available items. Fortunately, the removal of an item is an atomic process, so that we won't going to race condition hell.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:10;"&gt;At times you may want to be able to send and receive more than just one item on some port. Therefore, the CCR offers a so called PortSet, which is just that a set of Ports. For example, to create a PortSet accepting a string and DateTime message, we would do the following:&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;PortSet&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;, &lt;span style="color:#2b91af;"&gt;DateTime&lt;/span&gt;&amp;gt; messageDateTimePort = &lt;span style="color:blue;"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2b91af;"&gt;PortSet&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;, &lt;span style="color:#2b91af;"&gt;DateTime&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:10;"&gt;To avoid passing ports around in some program and taking individual items of some port, the CCR offers arbiters. Arbiters coordinate incoming messages passed between ports. In order to not manually call the Test method on the stringPort, we are going to declare a so called Receiver, which will be active whenever an item is waiting on a port matching the Receiver's signature. For example,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Receiver&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt; stringReceiver = &lt;span style="color:blue;"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2b91af;"&gt;Receiver&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt;(&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;true&lt;/span&gt;,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;stringPort,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;null&lt;/span&gt;,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2b91af;"&gt;IterativeTask&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt;(MessageHandler));&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:10;"&gt;this creates a Receiver, which accepts string items waiting on stringPort. The first parameter with value true sets persistence to true for this receiver. This means that the Receiver continues to receive string items even after it has received one string item. The null value is passed to the constraints formal parameter and the last parameter wires up a message handler, which actually takes care of string items incoming from stringPort. The MessageHandler function is nothing special (of course, you are free to add your own logic to it) and looks like this&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2b91af;"&gt;IEnumerator&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;ITask&lt;/span&gt;&amp;gt; MessageHandler(&lt;span style="color:blue;"&gt;string&lt;/span&gt; message)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;"Received Message: "&lt;/span&gt; + message);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;yield&lt;/span&gt; &lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:10;"&gt;To make things complete, a small sample illustrates the previous things. The example creates a simple string port, which is used by a secondary thread to to send the current time to. This message is received by a Receiver arbiter and printed out to the console. The program terminates if the user presses any key. In this case we stop the secondary thread and simple exit the program.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Text;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Threading;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; Microsoft.Ccr.Core;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;namespace&lt;/span&gt; CCRTest5&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Program&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;{&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;private static&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; running = &lt;span style="color:blue;"&gt;false&lt;/span&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; Main(&lt;span style="color:blue;"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;"CCRTest5 - send to a message port and use arbiter to receive"&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Port&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt; stringPort = &lt;span style="color:blue;"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2b91af;"&gt;Port&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;"Created Port&amp;lt;string&amp;gt;"&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Thread&lt;/span&gt; messageThread = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Thread&lt;/span&gt;(&lt;span style="color:blue;"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2b91af;"&gt;ParameterizedThreadStart&lt;/span&gt;(AddItemFunc));&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Receiver&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt; stringReceiver = &lt;span style="color:blue;"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2b91af;"&gt;Receiver&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt;(&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 108pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;true&lt;/span&gt;,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 108pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;stringPort,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 108pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;null&lt;/span&gt;,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 108pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2b91af;"&gt;IterativeTask&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt;(MessageHandler));&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;"Created Receiver"&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;"Starting Arbiter"&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Arbiter&lt;/span&gt;.Activate(&lt;span style="color:blue;"&gt;new&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2b91af;"&gt;DispatcherQueue&lt;/span&gt;(), stringReceiver);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;"Starting AddItem Thread"&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;messageThread.Start(stringPort);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;"Press key to exit"&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.ReadLine();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;color:green;"&gt;//abort&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;running = &lt;span style="color:blue;"&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Thread&lt;/span&gt;.Sleep(500);&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt; (messageThread.ThreadState == &lt;span style="color:#2b91af;"&gt;ThreadState&lt;/span&gt;.Running)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 108pt"&gt;&lt;span style="font-family:Courier New;font-size:10;color:blue;"&gt;try&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 108pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 144pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;messageThread.Abort();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 108pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 108pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;catch&lt;/span&gt; { }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2b91af;"&gt;IEnumerator&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;ITask&lt;/span&gt;&amp;gt; MessageHandler(&lt;span style="color:blue;"&gt;string&lt;/span&gt; message)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;"Received Message: "&lt;/span&gt; + message);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;yield&lt;/span&gt; &lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; AddItemFunc(&lt;span style="color:blue;"&gt;object&lt;/span&gt; port)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;running = &lt;span style="color:blue;"&gt;true&lt;/span&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Port&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt; messagePort = port &lt;span style="color:blue;"&gt;as&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2b91af;"&gt;Port&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt;;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:blue;"&gt;while&lt;/span&gt;(running)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 108pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;messagePort.Post(&lt;span style="color:#2b91af;"&gt;DateTime&lt;/span&gt;.Now.ToString());&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 108pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;&lt;span style="color:#2b91af;"&gt;Thread&lt;/span&gt;.Sleep(500);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 72pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;font-size:10;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:10;"&gt;More on arbiters and CCR in the next post.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-6310892185134334032?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/6310892185134334032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=6310892185134334032' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6310892185134334032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6310892185134334032'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2007/10/newbie-on-ccr-road.html' title='Newbie on the CCR Road'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-6848208988624833449</id><published>2007-09-27T08:43:00.000+02:00</published><updated>2007-09-30T12:24:47.585+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DSS'/><category scheme='http://www.blogger.com/atom/ns#' term='MRS'/><category scheme='http://www.blogger.com/atom/ns#' term='Robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>A simple GreatestCommonDivisor service in C# - Part2</title><content type='html'>What if we wanted to consume our previously built GCD Service by a web browser, such as Internet Explorer? ... Nothing easier than that. In fact, with minimal effort we can implement this functionality.&lt;br /&gt;Firstly, we have to (1) declare that our service supports the HTTPQuery operation, secondly we have to (2) implement a handler for this HTTPQuery request, and thirdly we may (3) test the service with a browser.&lt;br /&gt;&lt;br /&gt;1.&lt;br /&gt;Just add the HTTPQuery port to the GCD service's port set, which is defined in GCDTypes.cs (assuming that your service is named GCD).&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[ServicePort()]&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; &lt;strong&gt;class&lt;/strong&gt; GCDOperations : PortSet&lt;..., HttpQuery, ...&gt;&lt;br /&gt;{}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;So now that we have declared that our service is capable of understanding a HttpQuery action, we need to implement a routine, which handles such HttpQuery requests - a HTTPQueryGCDHandler.&lt;br /&gt;&lt;br /&gt;2. Add the following lines to the GCD.cs&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[ServiceHandler(ServiceHandlerBehavior.Concurrent)]&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; &lt;strong&gt;virtual&lt;/strong&gt; IEnumerator&lt;itask&gt; HTTPQueryGCDHandler(HttpQuery httpQuery) {&lt;br /&gt;&lt;strong&gt;if&lt;/strong&gt; (!&lt;strong&gt;string&lt;/strong&gt;.IsNullOrEmpty(httpQuery.Body.Query["Action"]) &amp;amp;&amp;amp;&lt;br /&gt;httpQuery.Body.Query["Action"] == "GCD")&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;string&lt;/strong&gt; _M = httpQuery.Body.Query["M"];&lt;br /&gt;&lt;strong&gt;string&lt;/strong&gt; _N = httpQuery.Body.Query["N"];&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;int&lt;/strong&gt; _intM = 1;&lt;br /&gt;&lt;strong&gt;int&lt;/strong&gt; _intN = 1;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;if&lt;/strong&gt; (!Int32.TryParse(_M, &lt;strong&gt;out&lt;/strong&gt; _intM))&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;.LogError("Failed to parse M");&lt;br /&gt;httpQuery.ResponsePort.Post(&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;strong&gt;new&lt;/strong&gt; HttpResponseType(&lt;strong&gt;new&lt;/strong&gt; GcdtestState(-1)));&lt;br /&gt;&lt;strong&gt;yield&lt;/strong&gt; &lt;strong&gt;break&lt;/strong&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;if&lt;/strong&gt; (!Int32.TryParse(_N, &lt;strong&gt;out&lt;/strong&gt; _intN))&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;.LogError("Failed to parse N");&lt;br /&gt;httpQuery.ResponsePort.Post(&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;strong&gt;new&lt;/strong&gt; HttpResponseType(&lt;strong&gt;new&lt;/strong&gt; GcdtestState(-1)));&lt;br /&gt;&lt;strong&gt;yield&lt;/strong&gt; &lt;strong&gt;break&lt;/strong&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;int&lt;/strong&gt; _GDC = &lt;strong&gt;this&lt;/strong&gt;.ComputeGCD(_intM, _intN);&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;.LogError("GDC = " + _GDC);&lt;br /&gt;&lt;br /&gt;httpQuery.ResponsePort.Post(&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;strong&gt;new&lt;/strong&gt; HttpResponseType(&lt;strong&gt;new&lt;/strong&gt; GcdtestState(_GCD)));&lt;br /&gt;}&lt;br /&gt;&lt;strong&gt;else&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;.LogError("Action is not GDC");&lt;br /&gt;httpQuery.ResponsePort.Post(&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;strong&gt;new&lt;/strong&gt; HttpResponseType(&lt;strong&gt;new&lt;/strong&gt; GcdtestState(-1)));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;yield&lt;/strong&gt; &lt;strong&gt;break&lt;/strong&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Besides computing the greatest common divisor and returning it as a http response, this handler does not do too much. It analyses whether the passed Action equals GCD and if so it tries to take the (hopefully) supplied parameters M and N. The service uses M and N to compute their GCD and if successful, passes the result back. If an error occurs, this service returns -1. The handler does not update the service's internal GCD state because of the following recommendation from the MRS help :&lt;br /&gt;&lt;br /&gt;&lt;cite&gt;"As both GET and QUERY requests are defined by DSSP as not having any&lt;br /&gt;side-effects, GET and QUERY handlers should be marked as&lt;br /&gt;ServiceHandlerBehavior.Concurrent using the ServiceHandler attribute so that the&lt;br /&gt;infrastructure knows that these handlers can run concurrently. "&lt;/cite&gt;&lt;br /&gt;&lt;br /&gt;3.With the handler in place, we may test our service. So we execute it by opening a browser and typing in the following URL&lt;br /&gt;&lt;code&gt;&lt;br /&gt;http://localhost:50000/GCD?Action=GCD&amp;amp;M=15&amp;amp;N=3&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;and this will return the correct result of 3. Note, that depending on you configuration the port and service name might be different. In fact, in the previous tutorial the service's name was GCDService, so you might want to take this into consideratio.&lt;br /&gt;&lt;br /&gt;Although this was only a minor sample, I am trying to do something more meaningful with DSS and I hope to provide another small tutorial soon. So read you soon.&lt;br /&gt;&lt;br /&gt;Christian&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-6848208988624833449?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/6848208988624833449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=6848208988624833449' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6848208988624833449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/6848208988624833449'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2007/09/allowing-to-query-gcd-service-via.html' title='A simple GreatestCommonDivisor service in C# - Part2'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-554465700428308897</id><published>2007-09-15T17:58:00.000+02:00</published><updated>2007-09-30T12:24:18.079+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MRS'/><category scheme='http://www.blogger.com/atom/ns#' term='Robotics'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>A simple GreatestCommonDivisor service in C# - Part 1</title><content type='html'>I was finally able to get the GCD service up and running. Essentially it does nothing different than my previously posted GCD service, which is implemented in VPL. So to recall, this service computes the greatest common divisor of two positive integer numbers (inputx, inputy) and outputs the result as greatestcommondivisor.&lt;br /&gt;&lt;br /&gt;Based on this description of what the service does, the remainder of this post will guide you through the process of how I built such a rather simple DSS service using the MRS object model and C# as implementation language (as mentioned you could also choose VB.NET, C++).&lt;br /&gt;&lt;br /&gt;This kind of tutorial is divided into distinct steps beginning at creating a new service project to the final result being the service we want.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Create new DSS Service&lt;/strong&gt;&lt;br /&gt;The first thing one has to do in order to set up a basic GreatestCommonDivisor service is to create a new DSS service.We will do so by creating a new Visual Studio 2005 Project. More specifically it is a "Simple DSS Service (1.5)" project (it is assumed that you have MRS 1.5 installed). Select the mentioned project type and name it as you please (e.g., "GCDService") (see &lt;a href="http://picasaweb.google.de/lh/viewPhoto?uname=Christian.Bitter&amp;amp;aid=5107878398546974753&amp;amp;iid=5110531791456198930"&gt;here&lt;/a&gt; for more detail). This will create a file for the service (e.g., GCDService.cs) a manifest file (e.g., *.manifest.xml) and a file for the types used by the service (e.g., GCDServiceTypes.cs).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Define what is the objective of the service&lt;br /&gt;&lt;/strong&gt;The service should do nothing special, just compute the greatest common divisor of two non-negative integer numbers m and n.This can be easily accomplished via euclids algorithm. In a previous post about python, I gave a recoursive implementation for this algorith, which is why I won't do it here again. So let us assume we have built a function, which implements euclids algorithm. The function's signature might look like this&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;strong&gt;public&lt;/strong&gt; &lt;strong&gt;static&lt;/strong&gt; &lt;strong&gt;int&lt;/strong&gt; ComputeGreatestCommonDivisor(&lt;strong&gt;int&lt;/strong&gt; m, int &lt;strong&gt;n&lt;/strong&gt;)&lt;br /&gt;{/*function's implementation not shown*/}&lt;/code&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Define the input message&lt;/strong&gt;&lt;br /&gt;A DSS Service accepts input messages of some form coming from some input port, handles these messages and sends some output message as a response to its ouput port. For example, to get information about the state of a DSS service, this service has to handle a &lt;strong&gt;Get&lt;/strong&gt; request, i.e. a "Get" message sent to the input port of this service. The DSS service receives the "Get" message does something and might respond to this message by sending "Hello World" as answer to its output port.&lt;br /&gt;Similarly, our "GreatestCommonDivisor" service might get a request to compute the greatest common divisor (GCD) of two non-negative integer numbers n and m. Therefore, such a request might incorporate the n, and m sent to our service and the expected response might be the GCD of m and n. Consequently, we have to define such a request or how such a GCD message must look like to be accepted as GCD message by our service and to be handled appropriately. The following lines of code, which we add to the types source code file (e.g., GCDServiceTypes.cs), define such a GCD request&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[DataContract(Name="ComputeGreatestCommonDivisor")]&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; &lt;strong&gt;class&lt;/strong&gt; ComputeGCDRequest&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;private&lt;/strong&gt; &lt;strong&gt;int&lt;/strong&gt; _inputX;&lt;br /&gt;&lt;br /&gt;[DataMember(IsRequired = &lt;strong&gt;true&lt;/strong&gt;, Name = "InputX")]&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; &lt;strong&gt;int&lt;/strong&gt; InputX&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;get&lt;/strong&gt; { &lt;strong&gt;return&lt;/strong&gt; (&lt;strong&gt;this&lt;/strong&gt;._inputX); }&lt;br /&gt;&lt;strong&gt;set&lt;/strong&gt; { &lt;strong&gt;this&lt;/strong&gt;._inputX = value; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;private&lt;/strong&gt; &lt;strong&gt;int&lt;/strong&gt; _inputY;&lt;br /&gt;&lt;br /&gt;[DataMember(IsRequired = &lt;strong&gt;true&lt;/strong&gt;, Name = "InputY")]&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; &lt;strong&gt;int&lt;/strong&gt; InputY&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;get&lt;/strong&gt; { &lt;strong&gt;return&lt;/strong&gt; (&lt;strong&gt;this&lt;/strong&gt;._inputY); }&lt;br /&gt;&lt;strong&gt;set&lt;/strong&gt; { &lt;strong&gt;this&lt;/strong&gt;._inputY = value; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; ComputeGCDRequest()&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;.InputX = 1;&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;.InputY = 1;&lt;br /&gt;}&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; ComputeGCDRequest(&lt;strong&gt;int&lt;/strong&gt; x, &lt;strong&gt;int&lt;/strong&gt; y)&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;._inputX = x;&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;._inputY = y;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The ComputeGCDRequest defines how a request to our service has to look like. It defines m and n (InputX, InputY). Each request has to be marked with the DataContractAttribute attribute, so DSS can wire things up for us. Fields we want to incorporate in our request have to be marked with DataMemberAttribute attribute (those fields are part of the message serialization process when the ComputeGCDRequest message is serialized over some channel). These two attributes take some optional arguments such as "Name" and "IsRequired".&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Define a message handler for the input message&lt;/strong&gt;&lt;br /&gt;The sheer presence of such a GCD request message type won't bring us far. We have to do define a GCD request (I), and add this GCD request to list of requests understood by our service (II). Afterwards we have to set up a mechanism that whenever a GCD request is issued to our service, takes the message, which abstracts this request and acts accordingly (III). So defining a GCD request serive, involves defining what the incoming GCD request message body looks like and defining what the result of processing a GCD request is, may it be success or failure. The following lines of source code, added to the GCDServiceTypes.cs, define a ComputeGCD request type ...&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; &lt;strong&gt;class&lt;/strong&gt; ComputeGCD :&lt;br /&gt;Query&amp;lt;ComputeGCDRequest, PortSet&amp;lt;GCDState, Fault&amp;gt;&amp;gt;{&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; ComputeGCD(&lt;strong&gt;int&lt;/strong&gt; m, &lt;strong&gt;int&lt;/strong&gt; n) :&lt;br /&gt;&lt;strong&gt;base&lt;/strong&gt;(&lt;strong&gt;new&lt;/strong&gt; ComputeGCDRequest(m, n))&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;.Body.InputX = m;&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;.Body.InputY = n;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; ComputeGCD() :&lt;br /&gt;&lt;strong&gt;base&lt;/strong&gt;()&lt;br /&gt;{ }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The ComputeGCD request type, subclasses the Query&lt;&gt; type, and defines the incoming message to be our previously declared ComputeGCDRequest message and the result will be a GCDState on success and the pre-defined Fault on failure. A Portset is a collection of ports (a set of ports) and a port is just an abstraction that allows services to communicate with each other. So to signal that our GCDService actually understands the ComputeGCD type, we have to add this type to the GCDService service's operations port set, which is defined in the GCDServiceTypes.cs file.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[ServicePort()]&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; &lt;strong&gt;class&lt;/strong&gt; GCDServiceOperations :&lt;br /&gt;PortSet&amp;lt;DsspDefaultLookup, DsspDefaultDrop, Get, ComputeGCD&amp;gt;&lt;br /&gt;{}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Now that our GCDService declares being able to understand GCD requests, we have to make him do so. More specifically we have to set up a message handler that jumps in whenever a GCDRequest is sent to our GCDService. The following lines of code, added to the GCDService.cs will be in charge of this.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[ServiceHandler(ServiceHandlerBehavior.Exclusive)]&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; &lt;strong&gt;virtual&lt;/strong&gt; IEnumerator&lt;itask&gt; ComputeGCDHandler(ComputeGCD computeGCD)&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;int&lt;/strong&gt; M = computeGCD.Body.InputX;&lt;br /&gt;&lt;strong&gt;int&lt;/strong&gt; N = computeGCD.Body.InputY;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;int&lt;/strong&gt; gcd = ComputeGreatestCommonDivisor(M, N);&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;._state.GCD = gcd;&lt;br /&gt;&lt;br /&gt;LogInfo("=========\r\nGcdTest\r\n=========");&lt;br /&gt;LogInfo(string.Format("M = {0}\r\nN = {1}\r\nGCD= {2}",&lt;br /&gt;computeGCD.Body.InputX,&lt;br /&gt;computeGCD.Body.InputY,&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;._state.GCD));&lt;br /&gt;&lt;br /&gt;computeGCD.ResponsePort.Post(&lt;strong&gt;new&lt;/strong&gt; GCDState(gcd));&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;yield&lt;/strong&gt; &lt;strong&gt;break&lt;/strong&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;The ComputeGCDHandler handler takes the ComputeGCD request as input and unwraps the necessary InputX and InputY fields from message's body. It then uses these two numbers as input to our ComputeGreatestCommonDivisor method, which computes the greatest common divisor and stores it in the gcd parameter. This gcd parameter is stored into the state of the service, which is of type GCDState. This GCDState encapsulates the state of the service, which is the greatest common divisor computed by the service. Actually the state is not really necessary, because we don't do much with it. At last, the message handler outputs the result of the operation to the output port for success, which was of type GCDState. The LogInfo calls are merely for debugging. Since this service alters its internal state, we have to make sure that this happens in an exclusive fashion, i.e. while updating the state no access to the state is granted. This is what the&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[ServiceHandler(ServiceHandlerBehavior.Exclusive)]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Attribute declaration is for. It ensures that no race condition can occur by exclusively granting access to the internals our service.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Define the GCDState type&lt;br /&gt;&lt;/strong&gt;What is left, is to define what the state of our GCDService looks like. As mentioned, our service doesn't need to have a state but I have to decided to give it one (mainly for learning purposes). The GCDState type is define in the GCDServiceTypes.cd and can be modified like this&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[DataContract()]&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; &lt;strong&gt;class&lt;/strong&gt; GCDState&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;private&lt;/strong&gt; int _GCD;&lt;br /&gt;&lt;br /&gt;[DataMember(IsRequired=&lt;strong&gt;true&lt;/strong&gt;, Name = "GreatestCommonDivisor")]&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; &lt;strong&gt;int&lt;/strong&gt; GCD&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;get&lt;/strong&gt; { &lt;strong&gt;return&lt;/strong&gt; (&lt;strong&gt;this&lt;/strong&gt;._GCD); }&lt;br /&gt;&lt;strong&gt;set&lt;/strong&gt; { &lt;strong&gt;this&lt;/strong&gt;._GCD = &lt;strong&gt;value&lt;/strong&gt;; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; GCDState()&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;._GCD = 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; GCDState(&lt;strong&gt;int&lt;/strong&gt; gcd)&lt;br /&gt;{&lt;br /&gt;&lt;strong&gt;this&lt;/strong&gt;._GCD = gcd;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Let's test&lt;/strong&gt;&lt;br /&gt;Now that we have set things up. We are ready to build the service and test it. Therefore compile everything. Open the MRS Visual Programming Language to build a new test service using our GCDService. I have done that and the test service can be seen &lt;a href="http://lh3.google.de/Christian.Bitter/Ru1B62sWYSI/AAAAAAAAACw/3kOJ7hW71aM/usingGCD.JPG"&gt;here &lt;/a&gt;(my GCDService is named "GreatestCommonDivisor"). &lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;br /&gt;I hope you enjoyed building this service as much as I did and I hope to have something ready for you asap.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Christian&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-554465700428308897?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/554465700428308897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=554465700428308897' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/554465700428308897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/554465700428308897'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2007/09/simple-greatestcommondivisor-service-in.html' title='A simple GreatestCommonDivisor service in C# - Part 1'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-1706357640388605122</id><published>2007-09-13T14:25:00.000+02:00</published><updated>2007-10-01T20:43:12.585+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lectures'/><category scheme='http://www.blogger.com/atom/ns#' term='General'/><title type='text'>Online Lectures</title><content type='html'>&lt;p&gt;Hi folks,&lt;br /&gt;&lt;br /&gt;I found this link about online learning in video form on another blog and thought I could repost it here&lt;br /&gt;&lt;br /&gt;&lt;a href="http://videolectures.net/"&gt;http://videolectures.net/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;so thanks goes out to&lt;br /&gt;&lt;br /&gt;&lt;a href="http://smart-machines.blogspot.com/"&gt;http://smart-machines.blogspot.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Both links are available in the sidebar.&lt;br /&gt;&lt;br /&gt;Other online lectures&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.researchchannel.org/prog/displayinst.aspx?fID=880"&gt;http://www.researchchannel.org/prog/displayinst.aspx?fID=880&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;Christian&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-1706357640388605122?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://videolectures.net/' title='Online Lectures'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/1706357640388605122/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=1706357640388605122' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/1706357640388605122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/1706357640388605122'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2007/09/hi-folks-i-found-this-link-about-online.html' title='Online Lectures'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-39010479104272886</id><published>2007-09-08T18:16:00.000+02:00</published><updated>2007-09-30T12:20:59.949+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MRS'/><category scheme='http://www.blogger.com/atom/ns#' term='VPL'/><title type='text'>Microsoft Robotics Studio - First Sight</title><content type='html'>&lt;div align="left"&gt;Microsoft Robotics Studio (MRS)&lt;br /&gt;&lt;br /&gt;I have recently come accross this great piece of new technology, offered for free by big MS [1]. MRS allows to program robots and other external devices via a visual programming language (VPL) or your prefered .NET programming language, such as VB.NET or C#. MRS main abstraction is a service.&lt;/div&gt;&lt;div align="left"&gt; &lt;/div&gt;&lt;div align="left"&gt;Assuming you use VPL, a service is graphically represented as a box. Services exist in their own space and can be combined via message passing. In fact, services communicate via a SOAP-like protocol. This communication act is graphically represented by wires between services. Where such a wire connects the output of one service to the input of another. It is up to the developer of a service to decide what a service does, i.e. what kind kind of messages a service understands and what output a service produces. Therefore one can develop rather simple services such as a NoOP service, which does nothing, to a more complex service that for example takes a picture from a webcam. The great news is that MS ships MRS with a bunch of pre-built services, such as a Text-to-Speech service. This service takes some input message and renders it as its audio representive.&lt;/div&gt;&lt;div align="left"&gt; &lt;/div&gt;&lt;div align="left"&gt;Since I have been able to play around with MRS, I wanted to share my first project, which calculates the greatest common divisor of two positive integer number m and n. Currently it is assumed that m is greater than n. The main routine that computes the gcd of m and n can be seen below &lt;a href="http://picasaweb.google.com/lh/viewPhoto?uname=Christian.Bitter&amp;aid=5107878398546974753&amp;iid=5107878505921157170"&gt;here&lt;/a&gt;. As in yesterdays post, we make use of the fact that gcd (m, n) = gcd (n, r) where n = m % n and % is defined as the modulus of m and n. At the moment there is no swapping of m and n, in case n is greater than m (gcd (m,n) = gcd(n,m)). A possible example setting can be seen &lt;a href="http://picasaweb.google.com/lh/viewPhoto?uname=Christian.Bitter&amp;aid=5107878398546974753&amp;iid=5107879626907621442"&gt;here&lt;/a&gt;. This example simply takes 10 and 5 as input and produces the expected output 5. I hope that this simple service will be one of many to come on my road to do cool stuff with MRS.&lt;br /&gt;&lt;br /&gt;[1] Microsoft Robotics Studio: &lt;a href="http://msdn2.microsoft.com/de-de/robotics/bb625969.aspx"&gt;http://msdn2.microsoft.com/de-de/robotics/bb625969.aspx&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-39010479104272886?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://msdn2.microsoft.com/en-us/robotics/default.aspx' title='Microsoft Robotics Studio - First Sight'/><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/39010479104272886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=39010479104272886' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/39010479104272886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/39010479104272886'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2007/09/microsoft-robotics-studio-mrs-i-have.html' title='Microsoft Robotics Studio - First Sight'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-3849617070981904113</id><published>2007-09-07T08:32:00.001+02:00</published><updated>2007-09-23T12:04:16.328+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Working the Snake - Python</title><content type='html'>I finally found my way to (Iron) Python[1][2] - well I did some Python in the beginning of my studies but lost focus after some time. The experience was quite impressive, since development time is greatly reduced by such a dynamic language. I managed to get some small programs running in less then 1 hour and of course I want to share them with you - precious audience. Since these are my first scripts, I assume that they are  not quite correct/stable/... - they are simple and not very error-safe (no checking of arguments ) ...&lt;br /&gt;&lt;br /&gt;The first is some simple factorial program, which tries to find the greatest common divisor (&lt;strong&gt;gcd&lt;/strong&gt;)of two numbers by employing the fact that gcd (x, y) = gcd (y, r) where r = x mod y. Since I do not know how a scope for loops can be created (scoping a while/for loop) I did the routine recoursively. The second function builds on the first and is allows to ask whether some number x is a prime number by using the simple strategy of finding a gcd within the range of 1..root(x)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;strong&gt;import&lt;/strong&gt; System&lt;br /&gt;&lt;strong&gt;def&lt;/strong&gt; gcd(x,y):&lt;br /&gt;    &lt;strong&gt;if&lt;/strong&gt; y == 1 : &lt;strong&gt;return&lt;/strong&gt; 1&lt;br /&gt;    &lt;strong&gt;elif&lt;/strong&gt; y == 0: &lt;strong&gt;return&lt;/strong&gt; y&lt;br /&gt;    &lt;strong&gt;elif&lt;/strong&gt; x == y : &lt;strong&gt;return&lt;/strong&gt; y&lt;br /&gt;    &lt;strong&gt;elif&lt;/strong&gt; x &lt;strong&gt;return&lt;/strong&gt; gdc(y,x)&lt;br /&gt;    n = x % y&lt;br /&gt;&lt;strong&gt;   if&lt;/strong&gt; n == 0: &lt;strong&gt;return&lt;/strong&gt; y&lt;br /&gt;&lt;strong&gt;   return&lt;/strong&gt; gcd(y, n)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;def&lt;/strong&gt; IsPrime(x):&lt;br /&gt;&lt;strong&gt;   if&lt;/strong&gt; x == 1 : &lt;strong&gt;return&lt;/strong&gt; 1&lt;br /&gt;&lt;strong&gt;   elif&lt;/strong&gt; x == 2 : &lt;strong&gt;return&lt;/strong&gt; 1&lt;br /&gt;&lt;strong&gt;   elif&lt;/strong&gt; x == 3 : &lt;strong&gt;return&lt;/strong&gt; 1&lt;br /&gt;  tempsqrt = System.Math.Sqrt(x)&lt;br /&gt;  tempsqrt = System.Convert.ToInt32(tempsqrt)&lt;br /&gt;&lt;strong&gt;   for&lt;/strong&gt; i &lt;strong&gt;in&lt;/strong&gt; &lt;strong&gt;range&lt;/strong&gt;(tempsqrt) :&lt;br /&gt;    j = i + 1&lt;br /&gt;    divisor = gcd(x,j)&lt;br /&gt;&lt;strong&gt;   if&lt;/strong&gt; divisor != 1 : &lt;strong&gt;return&lt;/strong&gt; 0&lt;br /&gt;&lt;strong&gt;   return&lt;/strong&gt; 1&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The second program is about the all time recursion favorite - the fibonaci numbers ...&lt;br /&gt;&lt;br /&gt;the Fibonaci (Fib ) numbers are defined as follows&lt;br /&gt;&lt;br /&gt;Fib(0) = 0&lt;br /&gt;Fib(1) = 1&lt;br /&gt;Fib(n) = Fib(n-2) + Fib(n-1)&lt;br /&gt;&lt;br /&gt;example&lt;br /&gt;&lt;br /&gt;n             0  1  2  3  4  5 6&lt;br /&gt;Fib (n)   0  1  1  2  3  5  8&lt;br /&gt;and here is the program - putting python suggar just around the exemplified formulae&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;import&lt;/strong&gt; System&lt;br /&gt;&lt;strong&gt;def&lt;/strong&gt; Fibonaci(n):&lt;br /&gt;&lt;strong&gt;   if&lt;/strong&gt; n &lt;= 0: &lt;strong&gt;return&lt;/strong&gt; 0&lt;br /&gt;&lt;strong&gt;   if&lt;/strong&gt; n == 1: &lt;strong&gt;return&lt;/strong&gt; 1&lt;br /&gt;&lt;strong&gt;   return&lt;/strong&gt; Fibonaci(n-2) + Fibonaci(n-1)&lt;br /&gt;&lt;br /&gt;References:&lt;br /&gt;&lt;br /&gt;[1] IronPython - &lt;a href="http://www.codeplex.com/IronPython"&gt;www.codeplex.com/IronPython&lt;/a&gt;&lt;br /&gt;[2] Python - &lt;a href="http://www.python.org/"&gt;www.python.org&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-3849617070981904113?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/3849617070981904113/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=3849617070981904113' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/3849617070981904113'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/3849617070981904113'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2007/09/i-finally-found-my-way-to-iron-python12.html' title='Working the Snake - Python'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-8619711158139054251</id><published>2007-03-22T21:31:00.000+01:00</published><updated>2007-12-06T11:07:42.026+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='3D'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'></title><content type='html'>Well not much happened today. I was able to implement a triangle filling routine and read a bit on .NET remoting. I thought about how to implement a Z-Buffer for my small system and thought about homogenous clipping as well.&lt;br /&gt;&lt;br /&gt;The problems I have right now are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;I want to implement basic triangle 2D screen-space clipping. Which itself is not a big deal but I do not want to implement a polygon filling scan-line algorithm. A polygon may be the outcome of a triangle clipped against a rectangular clip window. So what is there to do ? Either clip a triangle which produces a polygon and implement a "simple" scanline algorithm to fill that polygon. The other option is of course to split the triangle into a series of triangles. Either way has its intricacies.&lt;/li&gt;&lt;li&gt;As mentioned in yesterday's I want to implement homogenous clipping for triangles. Which makes things even more complicated then a simple 2D clipper. The reason is that not only a triangle can be split into a series of triangles during the clipping process but also extra state is necessary. Remember, we do not only clip the triangle and generate new triangles that form the clipped triangle but we have to generate appropriate values for associated color, texture and normal data.&lt;/li&gt;&lt;li&gt;I want the filling of the z-buffer and the filling of the framebuffer to be separate. Although expensive, I want to maintain this separation for flexibility.&lt;/li&gt;&lt;/ol&gt;With these "basic" things I should be busy for some days :D ...&lt;br /&gt;&lt;br /&gt;For all the people who want to do some graphics stuff I recommend the following books. At least they served my understanding quite well.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://www.amazon.de/Practical-Linear-Algebra-Geometry-Toolbox/dp/1568812345/ref=cm_lmf_tit_3/302-3887307-7188858"&gt;&lt;span class="small" id="lm_asinlink95" style="LINE-HEIGHT: 14px"&gt;&lt;strong&gt;Practical Linear Algebra: A Geometry Toolbox&lt;/strong&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="small" id="lm_asinlink95" style="LINE-HEIGHT: 14px"&gt;&lt;a href="http://www.amazon.de/Computer-Graphics-Principles-Addison-Wesley-Programming/dp/0201848406/ref=sr_1_1/302-3887307-7188858?ie=UTF8&amp;amp;s=books-intl-de&amp;amp;qid=1174596428&amp;amp;sr=1-1"&gt;Computer Graphics: Principles and Practise&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="small" id="lm_asinlink95" style="LINE-HEIGHT: 14px"&gt;&lt;a href="http://www.amazon.de/Real-Time-Rendering-Tomas-Akenine-M%C3%B6ller/dp/1568811829/ref=sr_1_1/302-3887307-7188858?ie=UTF8&amp;amp;s=books-intl-de&amp;amp;qid=1174596499&amp;amp;sr=1-1"&gt;Real-time Rendering&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="small" id="lm_asinlink95" style="LINE-HEIGHT: 14px"&gt;&lt;a href="http://www.amazon.de/Programming-Computer-Graphics-Charles-Development/dp/1584502770/ref=sr_1_1/302-3887307-7188858?ie=UTF8&amp;amp;s=books-intl-de&amp;amp;qid=1174596576&amp;amp;sr=1-1"&gt;Math for 3D Game Programming &amp;amp; Computer Graphics&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;a web reference on the topic&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://www.mactech.com/articles/mactech/Vol.15/15.06/3DGraphicEngineEssentials/index.html"&gt;3D Graphic Engine Essentials&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.devmaster.net/articles/software-rendering/part1.php"&gt;Software Rendering School&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;Happy reading&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-8619711158139054251?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/8619711158139054251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=8619711158139054251' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/8619711158139054251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/8619711158139054251'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2007/03/well-not-much-happened-today.html' title=''/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-7658121090284677184</id><published>2007-03-21T13:26:00.000+01:00</published><updated>2007-03-21T13:36:06.279+01:00</updated><title type='text'></title><content type='html'>In reference to yesterday's post I continued a bit and implemented the following&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Line drawing via DDA and Bresenham&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Basic Cohen-Southerland Clipping in 2D&lt;/li&gt;&lt;/ol&gt;These routines may not be the fastet but this actually not the point since the code is written in managed C# and makes no use of any optimizations. It's sole purpose is learning. The next things that need to be done are&lt;br /&gt;&lt;ul&gt;&lt;li&gt;drawing of triangles (including basic fill)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;a Z-Buffer (at least I have already set up the basics)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;clipping in homogenous clip space&lt;/li&gt;&lt;li&gt;simple scene-graph&lt;/li&gt;&lt;/ul&gt;If anyone is interested in some sources - I can either post them here or put them online on my website. I also thought about making the whole engine a bit more flexible. So I thought I could&lt;br /&gt;divide all the pipeline elements into pipeline stages. Each stage has access to some renderstate and does only execute on some defined input. As a consequence one would get something similar to vertex and fragment programs and a non-fixed function pipeline. But of course this is only some thinking and I should better get things set up before reasoning about making it most flexible.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-7658121090284677184?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/7658121090284677184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=7658121090284677184' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/7658121090284677184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/7658121090284677184'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2007/03/in-reference-to-yesterdays-post-i.html' title=''/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-342493615124972879</id><published>2007-03-20T10:48:00.000+01:00</published><updated>2007-03-20T11:08:51.889+01:00</updated><title type='text'></title><content type='html'>I have been quite busy these days writing my own small 3d engine. I did some small stuff with OpenGL in the past and to understand at least a bit better what is going on behind the scenes, I decided to do my own small renderer. I know, why write another software renderer if there is so much available. But at least for me I can say, that what I implement I do understand a little better.&lt;br /&gt;&lt;br /&gt;Of course, it takes some time to get the basics running. Until know it does only little (only perspective projection is covered), such as the transformation from an object's local space to actual screen space. But many things are left to do such as homogenous clipping, 2D clipping, painting ...&lt;br /&gt;&lt;br /&gt;The things I want to implement as a next step are&lt;br /&gt;&lt;ul&gt;&lt;li&gt;rasterization (lines via bresenham, basic filling - flat shading)&lt;/li&gt;&lt;li&gt;homogenous clipping&lt;/li&gt;&lt;li&gt;2d clipping&lt;br /&gt;&lt;/li&gt;&lt;li&gt;a primitive scene graph&lt;/li&gt;&lt;/ul&gt;Since basic rasterization often produces flicker, I looked for a basic method to do double-buffering with windows forms and .NET and these are some of my findings:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Enable double buffering for a control (e.g., Form) via setting a control's property &lt;span style="font-weight: bold;"&gt;DoubleBuffered = true&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Set a control's style via calling&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt; Control.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;This gives you basic double-buffering in an instant. But sometimes one wants to have a bit more control over the actual double-buffering process and therefore, the .NET framework provides several new classes in the &lt;span style="font-weight: bold;"&gt;System.Drawing&lt;/span&gt; namespace, such as:&lt;br /&gt;&lt;ul&gt;&lt;li style="font-weight: bold;"&gt;BufferedGraphics&lt;/li&gt;&lt;li style="font-weight: bold;"&gt;BufferedGraphicsContext&lt;/li&gt;&lt;li style="font-weight: bold;"&gt;BufferedGraphicsManager&lt;/li&gt;&lt;/ul&gt;You can obtain an AppDomain's main &lt;span style="font-weight: bold;"&gt;BufferedGraphicsContext&lt;/span&gt; by using the &lt;span style="font-weight: bold;"&gt;Current&lt;/span&gt; property of the &lt;span style="font-weight: bold;"&gt;BufferedGraphicsManager&lt;/span&gt; or you may create your own &lt;span style="font-weight: bold;"&gt;BufferedGraphicsContext&lt;/span&gt;. A &lt;span style="font-weight: bold;"&gt;BufferedGraphicsContext&lt;/span&gt; can be used to create a &lt;span style="font-weight: bold;"&gt;BufferedGraphics&lt;/span&gt; object (the Off-screen buffer you want to use for drawing) and associate this object to an output device (e.g. display).&lt;br /&gt;Use a &lt;span style="font-weight: bold;"&gt;BufferedGraphicsContext.Allocate&lt;/span&gt; method to create a &lt;span style="font-weight: bold;"&gt;BufferedGraphics&lt;/span&gt; object and to render the contents of such a &lt;span style="font-weight: bold;"&gt;BufferedGraphics&lt;/span&gt; object to an output device use the &lt;span style="font-weight: bold;"&gt;BufferedGraphics.Render&lt;/span&gt; method, which allows you to set the desired output device or use the one supplied to the &lt;span style="font-weight: bold;"&gt;BufferedGraphics.Allocate&lt;/span&gt; method. Drawing to such an off-screen buffer is easily done via a &lt;span style="font-weight: bold;"&gt;BufferedGraphics.Graphics&lt;/span&gt; property.&lt;br /&gt;&lt;br /&gt;Of course, if this is not what you want you may still use a Bitmap object to do all off-screen drawing and draw that bitmap to the display.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-342493615124972879?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/342493615124972879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=342493615124972879' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/342493615124972879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/342493615124972879'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2007/03/i-have-been-quite-busy-these-days.html' title=''/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15964854.post-7014495419950365859</id><published>2007-03-11T00:17:00.000+01:00</published><updated>2007-09-30T12:19:25.464+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General'/><title type='text'>Back again :D</title><content type='html'>A long time ago ... in this galaxy :D ...&lt;br /&gt;&lt;br /&gt;Well, it has been a while since I wrote the last post. But since I was finally able to conclude my studies this thursday, the 8th of march, I hope to be around more often. I will probably start my first work on april the 2nd. My new employer will be Avanade Deutschland GmbH (german office of Avanade Inc.). And I am quite happy about that since I expect a great learning experience - well but let's see ...&lt;br /&gt;&lt;br /&gt;Since I am not too busy these days I will try to have a look onto several things such as SQL Server 2005 and maybe I get my hands dirty with Phoenix again.&lt;br /&gt;&lt;br /&gt;Best regards&lt;br /&gt;&lt;br /&gt;Christian&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15964854-7014495419950365859?l=bitterman-page.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bitterman-page.blogspot.com/feeds/7014495419950365859/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15964854&amp;postID=7014495419950365859' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/7014495419950365859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15964854/posts/default/7014495419950365859'/><link rel='alternate' type='text/html' href='http://bitterman-page.blogspot.com/2007/03/long-time-ago.html' title='Back again :D'/><author><name>Bittis Blog</name><uri>http://www.blogger.com/profile/13146191397538056989</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
