jmitchell

jmitchell

Introducing Backtrex: solve discrete problems by brute force

I mentioned the project in “Logging: a silent performance killer”, but I’d like to formally present it. Backtrex is a behaviour that makes it easy to brute force any discrete problem.

The project currently includes a sample Sudoku solver, though it will probably get pulled out into a separate project later.

These callbacks are all Backtrex needs to get to work.

defmodule SudokuSolver do
  use Backtrex

  def unknowns(puzzle) do
    SudokuPuzzle.empty_cells(puzzle)
  end

  def values(_puzzle, _cell), do: 1..9

  def assign(puzzle, cell, value) do
    SudokuPuzzle.put_cell(puzzle, cell, value)
  end

  def valid?(puzzle) do
    SudokuPuzzle.valid?(puzzle)
  end
end

Since this is my first published package I’d sincerely appreciate feedback on its design. Cheers.

Most Liked

michalmuskala

michalmuskala

This does look interesting. How does it compare to prolog? From what I saw, this is in some ways similar to working with clpfd (“Constraint Logic Programming over Finite Domains”).

There’s an erlang implementation of prolog, https://github.com/rvirding/erlog, but it does not come with a clpfd library. I think this would also be an interesting area to explore.

jmitchell

jmitchell

AFAIK Backtrex could be used as the basis for a Prolog engine or other unification systems. I’ve made toy projects in Prolog to solve constraint satisfaction problems like Sudoku, but I can’t claim to understand all its semantics. For example, it has impure features to prematurely stop searching part of the tree (known as a “cut”), but I don’t have any experience using it. Backtrex’s API would allow somebody to prematurely prune the search; they could simply stop returning as many unknowns and values. It’s not a recommended use case, but could be worth exploring, and I don’t know if this maps well to the “cut” semantics.

A while back I studied *kanren languages and implemented microKanren in Idris (may not compile anymore since Idris has changed a bit). Kanrens are small logic programming languages, most focusing on purity and determinism. The original authors prefer the term relational programming to emphasize that unification isn’t biased in a particular direction. For instance, “the head of a list” is a relation that could produce the single element at the front of a list or an infinite stream of lists where a given element is at the front (or even simply the set of all non-empty lists along with the first element of each). They’re fascinating languages. Anyone interested in learning more should work through The Reasoned Schemer and read the first few chapters of William E. Byrd’s PhD dissertation where the Core miniKanren language introduced and implemented in Scheme.

I’m not familiar with it. I’ll definitely check it out. Could inspire some fun demo applications and test the limits of the current API.

I recently heard about this, but haven’t had a chance to try it out yet. Looking at the README it’s not clear whether there’s been any focus on parallelism and distributed computing.

Part of why I’m excited about Backtrex is the massive scaling potential provided almost out of the box by the BEAM, and the opportunity to learn how to do that well.

jmitchell

jmitchell

Yup, no sweat compared to all the potential bottlenecks in the backtracking algorithm and callback implementations. I’m working on generating flexible profiler reports now so I can identify bottlenecks and compare multiple implementations.

OvermindDL1

OvermindDL1

I’m not really sure what backtrex does yet (I’ve not looked at the docs yet, I’m on my phone ^.^), but what kind of scaling do you need? Is it serialized? Trivially distributable? Do you need one central information store? Is there no shared information?

jmitchell

jmitchell

It implements a generic backtracking algorithm to solve problems amenable to brute force. After implementing a few simple callbacks specific to your problem domain, you get a Backtrex.solve/1 function in return that will find a solution (eventually a stream of all solutions).

Backtracking is a step up from naive brute force. For example, the most naive way to solve a Sudoku puzzle is taking the N blank cells and enumerating all possible 9^N ways to fill them with number 1-9. A significant ratio of those solutions aren’t worth exploring, though, because as soon as a fraction of those cells are in an invalid state you know no possible values for the remaining blank cells could possibly yield a solution. Backtracking actively prunes the search space by checking whether a provisional set of assignments are valid.

Concurrency is a natural fit for a problem like this. Rather than having one process do a depth first search of the space on its own, you could, for instance, assign half the possible values for the first blank cell to one process and the other half to a second process.

As in needing everything to happen in a sequential order? No, not for this API, but I intend to offer a non-concurrent API for cases where users want solutions to arrive in a deterministic order.

Yes, every problem can be broken in many subproblems, each of which can be delegated to another process/node. And in turn, those subproblems may be broken in sub-subproblems, which lends well to a tree of workers and supervisors.

It would be nice to support work stealing when there are unoccupied nodes and worker processes, but that requires more coordination traffic in this work tree.

Solutions discovered by individual workers must be reported back up the tree to the root so they can be appended to a stream which is fed on demand to the Backtrex client.

Not in the sense of a database, no. That would be the Backtrex user’s job. If you mean processes responsible for coordinating other processes, yes, especially if the problem is repeatedly divided into the large tree structure described above. And again, more will be required of these coordinating processes if work stealing is supported (which I’d like).

At this stage, nope, not any more than what’s introduced by the coordination problem. However, a potential optimization may benefit from a way to broadcast information from one worker to all workers, probably by reporting up the tree to the root and then back down.

Where Next?

Popular in Libraries Top

josevalim
Hi everyone, We would like to announce that Plataformatec is working on a new MySQL driver called MyXQL. Our goal is to eventually integ...
New
kip
Image is an image processing library for Elixir. It is based upon the fabulous vix library that provides a libvips wrapper for Elixir. I...
574 16576 179
New
hpopp
After just over two years in development, this latest version of Pigeon is what I finally consider done in regards to my original vision ...
New
praveenperera
FastRSS Parse RSS feeds very quickly: This is rust NIF built using rustler Uses the RSS rust crate to do the actual RSS parsing Speed...
New
cjen07
parameterized pipe in elixir: |n> edit: negative index in |n> and mixed usage with |> are supported example: use ParamP...
New
michalmuskala
Hello everybody. I have just released Jason - a new JSON library. You might be wondering, why do we need a new library? The primary foc...
New
bryanjos
Hi, I just published version 0.23.0 of Elixirscript. Most of the changes are around JavaScript interop now that Elixirscript uses the ...
New
OvermindDL1
I created a new library (rather I pulled out a couple files from my big project), it manages an operating system PID file for the BEAM. ...
New
Hal9000
Here is my first stab at this. README pasted below. https://github.com/Hal9000/elixir_random Comments and critiques are welcome. Th...
New
maltoe
Hello! Came here to announce ChromicPDF, a pet project PDF generator I’ve been working on for the past few months. Why another PDF gener...
New

Other popular topics Top

yurko
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New

Sub Categories:

We're in Beta

About us Mission Statement