13,900,451 members
Tip/Trick
alternative version

#### Stats

17.7K views
2 bookmarked
Posted 29 Aug 2013
Licenced CPOL

# Learning F# - Graph Coloring using Microsoft Solver Foundation

, 29 Aug 2013
As MSDN doesn't provide an example in F#, I decided to translate one of the examples from C#.

## Introduction

As many people know, programmers are typically lazy. I'm not an exception to that rule, so instead of implementing from scratch a solution for my problem (see the section "Background"), I searched for a library that could do this for me. It turned out that Microsoft Solver Foundation was the right choice. However, it didn't provide a clear, suitable for beginners example in F#. I found a nice C# one here and decided to translate it to F#. The main point of this tip is to let you know about some tricky points I found.

## Background

The background for this project is a bit complicated and can be expressed as "a series of coincidences".

1. Not so long time ago, I started learning F#. After few first bad impressions ("My God - why is that so much immutable ??!"), I started getting on well with this language so that now I can't even imagine how could I live (i.e. "do programming" - in other languages like C++) without some features.
2. For some time, I've been playing with Project Euler - this thing can really blow somebody's mind up, can't it? One day, I got stuck solving a Sudoku problem. I knew there must a more elegant solution than brute force, but didn't know that at that moment.
3. You know coursera.org, don't you? There's a really cool course called Discrete Optimisation. I learnt a lot of great stuff there. Also - the professor mentioned some CSP (Constraint Programming) methods and the course resources contained a link to some useful libraries. "Cool" - I thought - "This will surely come in handy with my PE problem".
4. Searching for the most appropriate tool, I found MS Solver Foundation. As always, I wanted to kill two birds with a one stone and decided to give it a try using F#. The problem was I couldn't find an example in that language, so I had to translate one written in C#. However, there were some problems.

## Using the Code

The project I attached to the tip was created using Visual Studio 2012. Moreover, you need to download Microsoft Solver Foundation (e.g. from here) and add a reference to your project (important: this requires your project to use .NET 4.0). Last but no least, I set a default cmd argument in project properties, so you can easily run the code from VS. You can also build it and run from command line, specifying your own file.

## Part I: Translating

When I started translating, I thought "Naah, big deal - it's enough to replace definitions with `let`-bindings". As a result, when I saw a piece of code in C#:

`Model model = context.CreateModel();`

I replaced this with an F#-equivalent.

`let model = context.CreateModel()`

However - As you might expected, life was more brutal than it initially seemed to be. The first problem arose with the sequence:

```Domain colors = Domain.Enum("red", "green", "blue", "yellow");
Decision be = new Decision(colors, "belgium");
Decision de = new Decision(colors, "germany");
Decision fr = new Decision(colors, "france");
Decision nl = new Decision(colors, "netherlands");

be != de, be != fr, be != nl, de != fr, de != nl);```

Literate translation caused the compilator to complain:

No good, but what could I do? I started searching on MSDN. The argument required by `AddConstraints` method should be of type `Term`. A quick look at the reference guide here and everything started to make sense. There is an implicit conversion from `bool` to `Term`...

... but F# DOESN'T support implicit conversions! So I had to make this "more explicit". There are several ways of doing so, but I think that defining an operator is the most convenient one.

`let (!=) (d1 : Decision) (d2 : Decision) = Term.op_Inequality(d1, d2)`

## Part II: Extending the Code

That was enough to run the code. However, in the current version application was only able to tell you that it is possible to color the given map with 4 colors. That's far too little! I had my file with a graph and expected the application to read this and tell me if e.g. this can be colored with a given number of colors. The format of an external file was pretty straightforward:

```N E
V1 U1
V2 U2
...
VE UE```

where

• N - number of vertices
• E - number of edges
• Vi Ui - an edge from Vith to Uith vertex

An example of this would be:

```4 3
0 1
1 2
1 3```

I decided to pass the file's name as an application parameter instead of hardcoding it in the source. Also, I needed an additional data structure, but defining such in F# is ridiculously simple:

```type Edge =
{
V1 : int
V2 : int
}```

The code that parses data from a file is an example of what I love F# for:

```let header, items =
|> Seq.map parseToTuple
|> Seq.toList
|> function
| h::t -> h, t
| _    -> failwith "Wrong data format"

let Edges = List.map (fun (v1,v2) -> { V1 = v1 ; V2 = v2 } ) items |> Array.ofList```

An equivalent code in C# would take at least twice as much space, wouldn't it?

Anyway - the next step was to do something about the `Domain` object. I'm a man, so I know only 8 colors. I believe there are graphs that require more of them, so I decided to change `string`s to `int`s in a `Domain`'s definition. Luckily, it offers `IntegerRange` method. However, when I tried an obvious way of using it:

Deja vu ? Again - quick check on MSDN. `Rational` class supports implicit conversions from `int`. Fortunately, I know how to deal with the problem:

```let rat (i : int) = Rational.op_Implicit i
let colors = Domain.IntegerRange(rat 1, rat maxNum)```

Much better now. And the whole application is much more flexible now.

## Part III - Going crazy!

After all of that, I decided to go crazy and extend the application even further. I wanted it to let me know the MINIMAL number of colors necessary for a given graph. However, with F#, this turned out to be trivial. I simply moved my whole solution to a function called `solveUsingGivenSet` which takes a number of colors available. Then I used F#-`seq`:

`seq { 2 .. N } |> Seq.pick solveUsingGivenSet |> printfn "%s"`

`Seq.pick` iterates through the elements of a given `seq`, applying a function to each of then. If the function returns "`None`", then the next item is evaluated. If the result of the evaluation is "`Some x`", then the iteration is stopped and "`x`" gets returned.

Pfeeew... that's it. "A little bit" of work ;).

## Points of Interest

The most important thing I learnt is that F# doesn't support implicit conversions. I found one post on SO explaining this. Also, I found it nice to use Microsoft Solver. I've never seen such a library before and the opportunities it gives seem to be awesome!

Last thing - I believe there's a better way of using Microsoft SF in F# than a naive code translation, but couldn't find any example that would be simple enough to learn something without much pain. Moreover - the code itself isn't too efficient. Works fine for small problems, but not for larger ones. If you see any ways of improving it - feel free to shout! ...

... but - since I mentioned I'm lazy - this may take me a while to respond ;).

## Share

 Software Developer Poland
No Biography provided

## You may also be interested in...

 Pro Pro

 First Prev Next
 coursera code of honor IMil4229-Aug-13 21:41 IMil42 29-Aug-13 21:41
 Re: coursera code of honor Alojzy Leszcz30-Aug-13 2:50 Alojzy Leszcz 30-Aug-13 2:50
 Re: coursera code of honor IMil423-Sep-13 22:35 IMil42 3-Sep-13 22:35
 Re: coursera code of honor Alojzy Leszcz5-Sep-13 10:39 Alojzy Leszcz 5-Sep-13 10:39
 My vote of 5 GregoryW29-Aug-13 20:30 GregoryW 29-Aug-13 20:30
 Re: My vote of 5 Alojzy Leszcz30-Aug-13 2:55 Alojzy Leszcz 30-Aug-13 2:55
 Re: My vote of 5 GregoryW30-Aug-13 2:58 GregoryW 30-Aug-13 2:58
 Re: My vote of 5 Alojzy Leszcz30-Aug-13 3:28 Alojzy Leszcz 30-Aug-13 3:28
 Re: My vote of 5 GregoryW30-Aug-13 6:46 GregoryW 30-Aug-13 6:46
 Last Visit: 23-Mar-19 16:45     Last Update: 23-Mar-19 16:45 Refresh 1

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Web01 | 2.8.190306.1 | Last Updated 29 Aug 2013
Article Copyright 2013 by Alojzy Leszcz