Current section

Files

Jump to
fixpoint lib examples hakank all_interval.ex
Raw

lib/examples/hakank/all_interval.ex

#
# All interval problem in Elixir.
#
# CSPLib problem number 7
# http://www.cs.st-andrews.ac.uk/~ianm/CSPLib/prob/prob007/index.html
# """
# Given the twelve standard pitch-classes (c, c , d, ...), represented by
# numbers 0,1,...,11, find a series in which each pitch-class occurs exactly
# once and in which the musical intervals between neighbouring notes cover
# the full set of intervals from the minor second (1 semitone) to the major
# seventh (11 semitones). That is, for each of the intervals, there is a
# pair of neigbhouring pitch-classes in the series, between which this
# interval appears. The problem of finding such a series can be easily
# formulated as an instance of a more general arithmetic problem on Z_n,
# the set of integer residues modulo n. Given n in N, find a vector
# s = (s_1, ..., s_n), such that (i) s is a permutation of
# Z_n = {0,1,...,n-1}; and (ii) the interval vector
# v = (|s_2-s_1|, |s_3-s_2|, ... |s_n-s_{n-1}|) is a permutation of
# Z_n-{0} = {1,2,...,n-1}. A vector v satisfying these conditions is
# called an all-interval series of size n; the problem of finding such
# a series is the all-interval series problem of size n. We may also be
# interested in finding all possible series of a given size.
# """
#
# NOPE: I need an abs/2 constraint!
#
# This program was created by Hakan Kjellerstrand, hakank@gmail.com
# See also my Elixir page: http://www.hakank.org/elxir/
#
defmodule AllInterval do
alias CPSolver.IntVariable
alias CPSolver.Constraint.AllDifferent.FWC, as: AllDifferent
# alias CPSolver.Constraint.Sum
alias CPSolver.Constraint.LessOrEqual
alias CPSolver.Constraint.Absolute
alias CPSolver.Model
# alias CPSolver.Objective
import CPSolver.Constraint.Factory
# import CPSolver.Variable.View.Factory
def main() do
n = 8
x =
for i <- 0..(n - 1) do
IntVariable.new(1..n, name: "x[#{i}]")
end
diffs =
for i <- 0..(n - 2) do
IntVariable.new(1..(n - 1), name: "diffs[#{i}]")
end
constraints =
for k <- 0..(n - 2) do
{difference_var, difference_constraint} = subtract(Enum.at(x, k + 1), Enum.at(x, k))
## |dirrerence_var| = diffs[k]
[Absolute.new(difference_var, Enum.at(diffs, k)), difference_constraint]
end
|> List.flatten()
model =
Model.new(
x ++ diffs,
constraints ++
[
AllDifferent.new(x),
AllDifferent.new(diffs),
# symmetry breaking
LessOrEqual.new(Enum.at(x, 0), Enum.at(x, n - 1)),
# symmetry breaking
LessOrEqual.new(Enum.at(diffs, 0), Enum.at(diffs, 1))
]
)
Logger.configure(level: :info)
opts = [
# search: {:first_fail, :indomain_min},
search: {:input_order, :indomain_random},
# search: {:first_fail, :indomain_random},
space_threads: 12,
timeout: :timer.minutes(5)
# stop_on: {:max_solutions, 2},
]
{:ok, _res} =
CPSolver.solve_sync(
model,
opts
)
# IO.inspect(res.statistics)
# res.solutions
# |> Enum.map(fn solution -> Enum.take(solution, 15) end)
end
end