From: Maurice D. <md...@fr...> - 2007-09-14 21:02:31
|
Bonjour =E0 tous, Sorry for the late response, but this oeply was stic in my todo box! Le 6 juin 07 =E0 14:10, Sciss a =E9crit : > last, i'm interested to know if anyone is using choco in a scripting > environment on top of java, like groovy or jython. About this question, I've done some successfull try (with groovy) and =20= with jruby. The advantage of (J)Ruby is that it is a full object language (in fact, groovy is quite ruby like, but only for java) One can add new method to existing java class (e.g. for adding utilities to the Problem class of choco (see the example) Here is a full (french) commented exemple (and a little eavy because it show some feature or ryby syntax) (Re)Tested with the last jruby-1.0: jruby -v ruby 1.8.5 (2007-08-23 rev 4201) [ppc-jruby1.0.1] -- Maurice #!/usr/bin/env jruby # interpr=E9teur choco : idem jruby apres avoir ajout=E9 choco.jar dans = =20 CLASSPATH # interpr=E9teur corlab : idem jruby apres avoir ajout=E9 plein de jar =20= pour la # recherche op=E9rationnelle (dont choco) #!/usr/bin/env choco #!/usr/bin/env corlab # =3D=3D=3D=3D Variables du carre magique de taille 4 =3D=3D=3D=3D # 1 2 15 16 # 12 14 3 5 # 13 7 10 4 # 8 11 6 9 # Somme de chaque ligne/col/diag : sumVar=3D34 # Ajout dynamique d'un fichier jar dans le CLASSPATH require ENV['CHOCO_TEST_JAR'] require "java" require "pp" # Pour debug # Diff=E9rentes mani=E8res d'afficher des infos sur l'environnement # cp =3D java.lang.System.getProperty("java.class.path") puts "Affichage du java.class.path :\n #{cp.split(":").join("\n =20= ")}" # display the special rubypath variable (i.e. classpath for ruby libs) puts "Affichage du rubypath \n #{$:.join("\n ")}" # display one environment variable (onluy if exists!) puts "ENV['CLASSPATH'] =3D " << ENV['CLASSPATH'] unless = !ENV['CLASSPATH'] # display all environment variables calling java method # java.lang.System.getenv.each { |k,v| p k; p v; puts "--" } # # # require "choco" include_class "choco.integer.IntDomainVar" include_class "choco.Problem" include_class "choco.Constraint" class MagicSquare # Pour cr=E9er des accesseurs pour ces attributs (sinon private =20 par d=E9faut) # attr_accessor :n, :vers, :sumars, :pb # @xxxx : instance attribut xxxx need not to be declared (just =20 lisibility) @n =3D nil @vars =3D nil @sumVar =3D nil @pb =3D nil SOLVE_ALL =3D false =20 ########################################################################=20= #### def initialize argl @pb =3D Problem.new self.parseArgs argl self.buildVariables self.buildConstraints self.solve self.printStats end =20 ########################################################################=20= #### def parseArgs argl puts argl.join(", ") @n =3D 4 if argl.length >=3D 1 @n =3D argl[0].to_i end end =20 ########################################################################=20= #### def buildVariables @vars =3D [] puts "n=3D" + @n.to_s for i in 0...@n for j in 0...@n # pb.makeEnumIntVar serait moins bien pour ce probl=E8me @vars << @pb.makeBoundIntVar("C_#{i}_#{j}", 1, @n*@n) end end puts "Construction des variables de d=E9cision principales =20 faite." # Calcul de la somme de chaque ligne/col =3D 1/n * sommeTotale =20= (de 1..n^2) @sumVal =3D @n * (@n*@n + 1) / 2 @sumVar =3D @pb.makeBoundIntVar("S", @sumVal, @sumVal) puts "Construction de la variable auxiliaire sumVar faite." puts "" printVars end =20 ########################################################################=20= #### def buildConstraints # # Toutes les cellules doivent contenir une variable diff=E9rente # # Bug jruby 1.0 ?? : IntDomainVar non reconnu # @pb.post(@pb.allDifferent( @vars.to_java(IntDomainVar) )) @pb.post(@pb.allDifferent(@vars.to_java=20 ("choco.integer.IntDomainVar") )) puts "Construction de la contrainte allDifferent faite." # # Contraintes de la forme "somme de toute ligne est =E9gale =E0 = =20 sumVar" # for i in 0...@n # 1 - first solution : one create and fill a typed java =20 array # row =3D IntDomainVar[@n].new # Fill java array with choco variable for j in 0...@n row[j] =3D @vars[i*@n+j] end # With ruby operator overloading, the folowing could be # writable as: # constraint =3D (@pb.sum(row) =3D=3D @sumVar) # but choco need some work to make this easier ! constraint =3D @pb.eq(@pb.sum(row), @sumVar) @pb.post constraint # # 2 - Second solution : play with ruby list, then convert # # it to the java array befor passing to choco method. # # # row =3D [] # for j in 0...@n # row << @vars[i*@n+j] # end # jrow =3D row.to_java("choco.integer.IntDomainVar") # c =3D @pb.eq(@pb.sum(jrow), @sumVar) # @pb.post c end puts "Construction des contraintes de lignes faite." # Contraintes de la forme "somme de toute colonne est =E9gale =20= =E0 sumVar" # for j in 0...@n col =3D [] for i in 0...@n col << @vars[i*@n+j] end @pb.post(@pb.eq(@pb.sum( col.to_java("choco.integer.IntDomainVar")), =20 @sumVar)) end puts "Construction des contraintes de colonnes faite." # # Egalit=E9 de la somme des deux diagonales # - diag1 : diagonale directe # - diag2 : diagonale inverse diag1 =3D [] diag2 =3D [] for i in 0...@n diag1 << @vars[i*@n+i]; diag2 << @vars[i*@n+(@n-1-i)]; end chocoIntDomVar =3D "choco.integer.IntDomainVar" @pb.post(@pb.eq(@pb.sum(diag1.to_java(chocoIntDomVar)), =20 @sumVar)) @pb.post(@pb.eq(@pb.sum(diag2.to_java(chocoIntDomVar)), =20 @sumVar)) puts "Construction des contraintes des diagonales faite." end def solve puts "Before propagate" # printVars vars begin @pb.propagate rescue # puts "Erreur lors de la propag. initiale" puts "Error while initial propagation" exit end puts "After propagate" # printVars vars puts "Before solve" if SOLVE_ALL @pb.solveAll else @pb.solve end puts "After solve" end def printVars # print "=3D=3D=3D=3D Variables du carre magique de taille = #{@n} =3D=3D=3D=3D" print "=3D=3D=3D=3D Variables of magic squar of size #{@n} = =3D=3D=3D=3D" for i in 0...@vars.length if (i % @n =3D=3D 0) print "\n" end if @vars[i].isInstantiated printf "%4d ", @vars[i].val else printf "%10s ", @vars[i].pretty end end puts "" # print "Somme de chaque ligne/col/diag : sumVar=3D" print "Sum of each line/col/diag : sumVar=3D" if @sumVar.isInstantiated print @sumVar.val else print @sumVar.pretty end puts "" end def printStats if SOLVE_ALL print " (nbSol found: #{@pb.nbSol})\n" print "Last found solution:\n" else print "First found solution:\n" end printVars print "n=3D#{@n} =3D> nbNodes=3D#{@pb.nbNodes} en = #{@pb.nbMillis/=20 1000.0} s." end end # With ruby, one can add methods to existing choco java class class Problem def nbSol getSolver().getNbSolutions() # can be call as : solver.nbSolution end def nbMillis # jruby accepte la conversion implicite de m=E9thode =20 "getSearchSolver()" # en attribut virtuel "searchSolver" # getSolver.getSearchSolver.limits.get(0).getNbTot solver.searchSolver.limits.get(0).nbTot end def nbNodes # getSolver.getSearchSolver.limits.get(1).getNbTot solver.searchSolver.limits.get(1).nbTot end end # ARGV est la liste des arguments transmis au programme MagicSquare.new ARGV puts "FIN" # ./ |