Jeff Ferguson

Irritating other people since 1967

  Home  |   Contact  |   Syndication    |   Login
  41 Posts | 0 Stories | 49 Comments | 0 Trackbacks

News

I am a Principal Consultant with Magenic (www.magenic.com).

Twitter












Archives

Monday, February 28, 2011 #

Axum, as a distinct language, is most likely not going to happen. Instead, its features will most likely be folded into features of C# and VB. Read all about it here.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Sunday, October 24, 2010 #

Note: The code below applies to version 0.3 of Microsoft Axum. If you are not using this version of Axum, then your code may differ from that shown here.

I have just solved Problem 2 of Project Euler using Microsoft Axum. The problem statement is as follows:

Find the sum of all the even-valued terms in the Fibonacci sequence which do not exceed four million..

Solution

My Axum-based solution is as follows:

   1: using System;
   2: using Microsoft.Axum;
   3: using System.Concurrency.Messaging;
   4:  
   5: namespace Problem002
   6: {
   7:     // http://projecteuler.net/index.php?section=problems&id=2
   8:     //
   9:     // Each new term in the Fibonacci sequence is generated by adding the previous two terms.
  10:     // By starting with 1 and 2, the first 10 terms will be:
  11:     // 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
  12:     // Find the sum of all the even-valued terms in the sequence which do not exceed four million.
  13:     
  14:     channel Problem002Channel
  15:     {
  16:         input long Maximum;
  17:         output long Sum;
  18:     }
  19:     
  20:     agent Problem002Agent : channel Problem002Channel
  21:     {
  22:         long CalculatedSum = 0;
  23:         bool ContinueCalculation = true;
  24:         long Max = 0;
  25:         
  26:         public Problem002Agent()
  27:         {
  28:             Max = receive(PrimaryChannel::Maximum);
  29:             long InputValue = 1;
  30:             while(ContinueCalculation)
  31:             {
  32:                 long Result;
  33:                 
  34:                 if(InputValue % 3 == 0)
  35:                 {
  36:                     Result = Fibonacci(InputValue);
  37:                     if(Result > Max)
  38:                     {
  39:                         ContinueCalculation = false;
  40:                         continue;
  41:                     }
  42:                     CalculatedSum += Result;
  43:                 }
  44:                 InputValue++;
  45:             }
  46:             PrimaryChannel::Sum <-- CalculatedSum;
  47:         }
  48:         
  49:         function long Fibonacci(long n)
  50:         {
  51:             if(n <= 1)
  52:                 return n;
  53:             return Fibonacci(n - 1) + Fibonacci(n - 2);
  54:         }
  55:     }
  56:     
  57:     agent MainAgent : channel Application
  58:     {
  59:         public MainAgent()
  60:         {
  61:             var AgentInstance = Problem002Agent.CreateInNewDomain();
  62:             AgentInstance::Maximum <-- (long)4000000;
  63:             var Sum = receive(AgentInstance::Sum); // should be 4613732
  64:             Console.Write("The sum of all the even-valued terms in the sequence which do not exceed 4,000,000 is ");
  65:             Console.Write(Sum);
  66:             Console.WriteLine(".");
  67:             Console.ReadLine();
  68:             PrimaryChannel::ExitCode <-- 0;
  69:         }
  70:     }
  71: }

This is a very simple Axum design, with a main Application-based agent called MainAgent and a second agent called Problem002Agent that performs the actual calculation. The input to the Problem002Agent is the calculation maximum, which in this case is 400000 and the output is the calculated sum of the even terms. Most of the work is performed in the constructor of the Problem002Agent, which also contains a recursive Fibonacci function.

You may be curious as to why the Problem002Agent constructor calls the Fibonacci function only once every three times in lines 34-44. This is a mathematical optimization that we can take advantage of thanks to the problem statement. The problem statement notes that only even-valued Fibonacci terms are to be added up. A careful study of the Fibonacci sequence shows that only every third term in the sequence is an even-numbered term. The first few terms in the sequence are:

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, …

The pattern with respect to odd and even terms are:

odd, odd, even, odd, odd, even, odd, odd, even, odd, odd, even, odd, odd, even, …

Given this fact, and the fact that the problem domain asks that only even terms be calculated, only every third term needs to be computed. This also explains why there is no check to make sure that the calculated output of the Fibonacci function is an even number, because we know it to be even since only every third term is used as input. Calculating the Fibonacci number for every term is certainly possible, but, given the problem statement, would simply be a waste of computing.

Failed Attempts

In one of my earlier attempts to solve this problem using Axum, I had a pipeline built that started with an ordered list of integers, and a pipeline that looked something like this:

   1: numbers ==> Fibonacci ==> EvenTerm ==> CalculateSum

The EvenTerm() function was designed to take in the output of a Fibonacci term and send it into a function that would return the value if it was an even number and zero otherwise:

   1: function long EvenTerm(long Input)
   2: {
   3:     if(Input % 2 == 0)
   4:         return Input;
   5:     return 0;
   6: }

That output would be fed into code that would keep track of the sum:

   1: long CalculatedSum = 0;
   2:  
   3: void CalculateSum(long Input)
   4: {
   5:     CalculatedSum += Input;
   6: }

With this approach, all Fibonacci terms would be calculated, but the odd terms would be weeded out by the EvenTerm() pipeline function which would effectively turn them into zeros when added to the sum.

The problem that I had with the pipeline approach is that I didn’t know how to stop the pipeline once the Fibonacci terms exceeded 4,000,000. I would need to write something like this:

   1: var numbers = new OrderedInteractionList<int>();
   2: var PipelineInput = 1;
   3: while(Fibonacci terms have not exceeded the max)
   4:     numbers <-- PipelineInput++;

I don’t (yet) know how to write line 3 in terms of Axum given its multiple-thread model. I like the pipeline approach, because it would make the code feel more like Axum and less like C#, but the Axum threading model would have the code filling the numbers list in one thread and calculating in another thread, possibly causing too many items to be added the the list. Perhaps I can find a more “Axum-like” solution for this problem as Axum matures.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Saturday, October 23, 2010 #

I will be presenting the Microsoft Axum language for the third time this year at the Iowa Code Camp on Sat Nov 06 2010. The event is free, so, if you’re in the area, feel free to come enjoy the day. The list of speakers and topics is here; the attendee registration form is here. I hope to see you there!

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Sunday, October 10, 2010 #

Thank you to all who attended my “A First Look At Axum” presentation during Twin Cities Code Camp 9! I have zipped up the Axum code samples that I presented and have made it available online; you can download your copy here. Enjoy!

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Tuesday, October 05, 2010 #

Last month, I presented an overview of the Microsoft Axum language for the Twin Cities Languages User Group. I will be giving the same talk on Sun Oct 10 2010 at The Twin Cities Code Camp. Visit the Twin Cities Code Camp site for more information about this free event. Don’t forget to register for the Code Camp; the registration form is here. The Code Camp will be held over two days; the full schedule is here. See you there!

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Tuesday, September 14, 2010 #

Last week, while presenting Axum at the Twin Cities Languages User Group, I presented this application:

   1: using System;
   2: using Microsoft.Axum;
   3: using System.Concurrency.Messaging;
   4:  
   5: namespace Project06
   6: {
   7:     schema Pair
   8:     {
   9:         required int Num1;
  10:         required int Num2;
  11:     }
  12:     
  13:     channel Adder
  14:     {
  15:         input Pair Nums : int;
  16:     }
  17:     
  18:     agent AdderAgent : channel Adder
  19:     {
  20:         public AdderAgent()
  21:         {
  22:             while(true)
  23:             {
  24:                 var result = receive(PrimaryChannel::Nums);
  25:                 result <-- result.RequestValue.Num1 + result.RequestValue.Num2;
  26:             }
  27:         }
  28:     }
  29:  
  30:     agent MainAgent : channel Microsoft.Axum.Application
  31:     {
  32:         public MainAgent()
  33:         {
  34:             var adder = AdderAgent.CreateInNewDomain();
  35:             var correlator1 = adder::Nums <-- new Pair { Num1=10, Num2=20 };
  36:             var correlator2 = adder::Nums <-- new Pair { Num1=30, Num2=40 };
  37:             var sum1 = receive(correlator1);
  38:             Console.WriteLine(sum1);
  39:             var sum2 = receive(correlator2);
  40:             Console.WriteLine(sum2);
  41:             PrimaryChannel::ExitCode <-- 0;
  42:         }
  43:     }
  44: }

Someone asked about the “int” keyword that follows the colon on line 15 and how that related to the definition of a channel in Axum. Basically, this is a more concise definition of the type for an output channel port. A more explicit definition for the channel would be this:

   1: channel Adder
   2: {
   3:     input Pair Add;
   4:     output int OutputPortName;
   5: }

Using the original channel definition, the “int” says that the channel will output data of type “int” on an unnamed port. This unnamed port is intrinsically tied to the input “Add” port and allows specific replies to be correlated with specific requests. Note that, on lines 35 and 36, the code is sending new Pair data values to the “adder::Nums” port, and a correlator is returned. This correlator is like a “job ticket”. Lines 37 and 39 receive the data that responds to the correlator, and the returned data is of type “int”, since that’s what appears after the colon on line 15.

All in all, the code is doing this:

  • Line 35 sends a new pair of integers (10 and 20) to the “Nums” input port on the “Adder” channel, and gets a ticket back. We’ll call this ticket “correlator1”.
  • Line 36 sends a new pair of integers (30 and 40) to the “Nums” input port on the “Adder” channel, and gets another ticket back. We’ll call this ticket “correlator2”.
  • Line 37 receives whatever output data corresponds to the input data specified by the “correlator1” variable. This is the input data on line 35. A value of 30 will be returned as an “int”. Note that we didn’t have to name the output port, since it’s built-in to the channel definition.
  • Line 39 receives whatever output data corresponds to the input data specified by the “correlator2” variable. This is the input data on line 36. A value of 70 will be returned as an “int”. Note that we didn’t have to name the output port, since it’s built-in to the channel definition.
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, September 09, 2010 #

I’ve just returned from presenting Axum to the Twin Cities Languages User Group. Thank you to all who attended! The meeting went well, and everyone participated in an active discussion as we took a look at Axum’s actor/channel based programming model. Some good questions arose during the presentation and I hope to more fully answer the questions in future blog posts. Many thanks to Jason Bock for allowing me to speak at the meeting, and to Jon Stonecash for his warm introduction.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, August 19, 2010 #

I will be presenting an overview of the Microsoft Axum language at the Sep 09 2010 meeting of the Twin Cities Languages User Group. If you’re in the area, drop on by! Visit the Twin Cities Languages User Group Web site for more information.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Wednesday, June 23, 2010 #

Despite the publication of the TUIO specification, relatively little information is available regarding some of its implementation details. One such area in which documentation seems to be lacking related to the TUIO coordinate system. Keep the following in mind when working with the TUIO coordinate system:

  • The coordinate system for a TUIO surface has a boundary of (0,0) to (1,1).
  • The (0, 0) origin is at the top left of the surface, and the (1, 1) point is at the lower right of the surface.
  • The X coordinate moves from X=0 at the left side of the surface to X=1 at the right side of the surface.
  • The Y coordinate moves from Y=0 at the top of the surface to Y=1 at the bottom of the surface.
  • Points in between are represented as a decimal value between 0 and 1. This means that the center of the surface is at TUIO point (0.5, 0.5).
  • TUIO coordinates are always relative to the entire display surface and are never relative to a user interface element. If a window, for example, fills a portion of a TUIO-enabled surface, then the (0, 0) coordinate is still at the upper left corner of the entire display surface, not at the upper left corner of the window. TUIO coordinates are, in effect, hardware coordinates.
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, June 14, 2010 #

WPF measures all elements in device independent pixels (DIPs). These DIPs equate to device pixels if the current display monitor is set to the default of 96 DPI. However, for monitors set to a DPI setting that is different than 96 DPI, then WPF DIPs will not correspond directly to monitor pixels.

Consider, for example, the WPF properties SystemParameters.PrimaryScreenHeight and SystemParameters.PrimaryScreenWidth. If your monitor resolution is set to 1024 pixels wide by 768 pixels high, and your monitor is set to 96 DPI, then WPF will report the value of SystemParameters.PrimaryScreenHeight as 768 and the value of SystemParameters.PrimaryScreenWidth as 1024. No problem. This aligns nicely because the WPF device independent pixel value (96) matches your monitor's DPI setting (96).

However, if your monitor is not set to display pixels at 96 DPI, then SystemParameters.PrimaryScreenHeight and SystemParameters.PrimaryScreenWidth will not return what you expect. The values returned by these properties may be greater than or less than what you expect, depending on whether or not your monitor's DPI value is less than or greater than 96. Since the SystemParameters.PrimaryScreenHeight and SystemParameters.PrimaryScreenWidth properties are WPF properties, their values are measured in WPF DIPs, rather than taking monitor DPI into effect. Once again: WPF measures all elements in device independent pixels (DIPs).

To combat this issue, you must take your monitor's DPI settings into effect if you're looking for the monitor's width and height using the monitor's DPI settings. The handy code block below will help you calculate these values regardless of the DPI setting on your monitor:

Window MainWindow = Application.Current.MainWindow;
PresentationSource MainWindowPresentationSource = PresentationSource.FromVisual(MainWindow);
Matrix m = MainWindowPresentationSource.CompositionTarget.TransformToDevice;
DpiWidthFactor = m.M11;
DpiHeightFactor = m.M22;
double ScreenHeight = SystemParameters.PrimaryScreenHeight * DpiHeightFactor;
double ScreenWidth = SystemParameters.PrimaryScreenWidth * DpiWidthFactor;

The values of ScreenHeight and ScreenWidth should, after this code is executed, match the resolution that you see in the display's Properties window.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati