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".

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.

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.

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".

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:

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:

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 strings to ints 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:

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 .

Comments and Discussions

Well, it's good that you've waited until the end of class, but there will be future sessions, so I would not post my code, this may encourage next students to cheat.
BTW I used F# too, but not with solver foundation: I solved coloring using my own implementation of CP.

I don't think this would help anybody in the course, as I managed to solve only the first problem (out of 6) using that code. I believe there must be a smarter way of using MS Solver and that's why I wrote this article - to describe my work and start a discussion.

Well, I guess my criticism was wrong then. If you made just a simple model, like was described in the first lectures, it's OK.

Regarding why you solved only the first problem: you shouldn't go from 2 colors upwards, but rather from N colors down to 1. For example, if the optimal solution has 15 colors, the solver will most likely fail fast on 2-10 colors, but may spend a LONG time checking 13 and 14. On the other hand, going down will quickly bring you to, say, 2-5 colors above optimum, which is better then nothing

As for optimization, I see that ConstraintProgrammingDirective has members like ValueSelection and VariableSelection: haven't tried yet, but they seem to give an opportunity to break symmetry and "fail fast", which are the two methods that make a huge difference in optimization speed.

And I have a question on programming style: did you really need the Edge class? IMHO you could just leave tuples.

Thanks for the hints - I'll give them a try soon.
About the record type - I decided to create it to enhance code readability. I agree I could use tuples instead, but then this would be less clear what do the numbers denote.

There isn't just a single field of usage. F# can be used anywhere and has a lot of great features. For a brief description you can e.g. visit http://fsharpforfunandprofit.com/[^] I use it at work as the main programming language and the results are great.

At first using F# was strange to me, but now I can't imagine myself programming without some of its constructs.

Thanks for a small describe and the link as well. I have never seen F# in action, but of course it doesn't mean it's not useful lang. In the other hand, it seems like Microsoft is not paying so much attention to demonstrate F# to the developers.