Why Functional Programming works for the Eight Queens Problem.

At a recent Boost Conference, Bartosz Milewski [1] presented a solution to the Eight Queens problem from a functional programming perspective. The main argument is that in Functional Programming we do not modify state. We create new states by extending existing state. Regular readers of this blog (both of us) can see that this is the same principle followed in depth first game tree [3] solutions such as Sudoku, the water bucket problem or BrainVita. Indeed the code the author presented, as shown below bears an uncanny resemblance to the depth first search template [3] presented earlier:

template<class Partial, class Constraint>
std::vector<typename Partial::SolutionT> 
generate( Partial const & part, Constraint constr){
    using SolutionVec = std::vector<typename Partial::SolutionT>;

    if (part.isFinished(constr)) {
        SolutionVec result{ part.getSolution() };
        return result; //line 7
    else {
        List<Partial> partList = part.refine(constr);
        SolutionVec result;
        forEach(std::move(partList), [&](Partial const & part){
            SolutionVec lst = generate(part, constr);
            std::copy(lst.begin(), lst.end(), std::back_inserter(result)); //line 14
        return result;

Here ‘partlist’ is initialised to the next list of valid states. The main difference between this code and the game tree template is that I would have done this:

       List<Pos> positions = part.refine(constr);
        SolutionVec result;
        for(auto pos:positions)
            SolutionVec lst = generate(part+pos, constr);
            std::copy(lst.begin(), lst.end(), std::back_inserter(result));

where part+pos returns a new Partial with the pos added. Apart from following a pattern the advantage with the new code is that the new Partial is created and destroyed within the loop.

A point worthy of note is that the use of Milewski’s List as opposed to std::list means that we are not coping the part’s list of positions to create a new Partial. We are just extending part with a new position, while there is no state change to part. This is optimal both in terms of time and memory.

When does this work

When the set of states can be laid out in a tree (top-down), there is no situation where a state can be reached from two unrelated states. Put another way if A, B and C are three states then if A is the ancestor of C and B is an ancestor of C then A is an ancestor of B or vice versa. Hence while traversing the set of possible states there is no need to keep a global collection of all states reached. Implicitly though the collection of global states is maintained on the stack but the entire list is not visible from a child state. Thus Functional Programming technique of creating a tree of closures works here.

Notice that ‘generate’ returns a vector of solutions. We could just as well update a global list in line 7. The disadvantage would be that for a multi-threaded version we would need to to lock the global structure. The advantage would be that we would not need to copy as often, although we could avoid that by using Milewski’s List. The author has generously published his code[2]. The asynchronous version of this code [2] demonstrates a multi-threaded application with no explicit locks.

Finally one minor gripe, why use vectors when random access is not required? To conclude Milewski’s presentation [1] is definitely worth watching. I wish he would come up with a text version.

[1] Bartosz Milewski, “Functional Data Structures in C++,” https://www.youtube.com/watch?v=OsB09djvfl4
[2] Bartosz Milewski, “Okasaki,” https://github.com/BartoszMilewski/Okasaki
[3] Joseph Mariadassou, “Depth First Game Trees,” https://wordpress.com/post/19406938/198/

About The Sunday Programmer

Joe is an experienced C++/C# developer on Windows. Currently looking out for an opening in C/C++ on Windows or Linux.
This entry was posted in Algorithm, Software Engineering, Software Puzzle and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s