1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | /******************************************************************************* * OscaR is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 2.1 of the License, or * (at your option) any later version. * * OscaR is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with OscaR. * If not, see http://www.gnu.org/licenses/lgpl-3.0.en.html ******************************************************************************/ package oscar.examples.cp.hakank import oscar.cp.modeling. _ import oscar.cp.core. _ import scala.io.Source. _ import scala.math. _ import Array. _ /* Golomb Golomb ruler in Oscar. CSPLib problem 6 http://www.cs.st-andrews.ac.uk/~ianm/CSPLib/prob/prob006/index.html """ These problems are said to have many practical applications including sensor placements for x-ray crystallography and radio astronomy. A Golomb ruler may be defined as a set of m integers 0 = a_1 < a_2 < ... < a_m such that the m(m-1)/2 differences a_j - a_i, 1 <= i < j <= m are distinct. Such a ruler is said to contain m marks and is of length a_m. The objective is to find optimal (minimum length) or near optimal rulers. Note that a symmetry can be removed by adding the constraint that a_2 - a_1 < a_m - a_{m-1}, the first difference is less than the last. """ Also see: @author Hakan Kjellerstrand hakank@gmail.com */ object GolombRuler { def increasing(cp : CPSolver, y : Array[CPIntVar]) = { for (i <- 1 until y.length) { cp.add(y(i- 1 ) < = y(i), Strong) } } def main(args : Array[String]) { val cp = CPSolver() // // data // var m = 8 if (args.length > 0 ) { m = args( 0 ).toInt } val n = m*m // // variables // val mark = Array.fill(m)(CPIntVar( 0 to n)(cp)) val differences = for {i <- 0 until m; j <- i+ 1 until m} yield mark(j)-mark(i) // // constraints // var numSols = 0 cp.minimize(mark(m- 1 )) subjectTo { cp.add(allDifferent(mark), Strong) cp.add(allDifferent(differences), Strong) increasing(cp, mark) // symmetry breaking cp.add(mark( 0 ) == 0 ) cp.add(mark( 1 )-mark( 0 ) < mark(m- 1 ) - mark(m- 2 )) // ensure positive differences // (Cred to Pierre Schaus.) differences.foreach(d = > cp.add(d > 0 )) } search { binaryStatic(mark) // 756 backtracks for m=8 } onSolution { println( "\nSolution:" ) print( "mark: " + mark.mkString( "" )) println( "\ndifferences: " + differences.mkString( "" )) println() numSols + = 1 } println(cp.start()) } } |