pmaple.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. # -*- coding: utf-8 -*-
  2. # reasonLS
  3. # authors
  4. #
  5. # runs n instances of reasonLS in parallel (script code based on code of Norbert Manthey 2014)
  6. #
  7. # used libraries
  8. import os, signal, subprocess, time
  9. import sys, shutil, random, re
  10. def check_pid(pid):
  11. """ Check For the existence of a unix pid. """
  12. try:
  13. os.kill(pid, 0)
  14. except OSError:
  15. return False
  16. else:
  17. return True
  18. def kill_pid(pid):
  19. """ Check For the existence of a unix pid. """
  20. try:
  21. os.kill(pid, 15)
  22. except OSError:
  23. return False
  24. else:
  25. return True
  26. #
  27. # usage and current PID
  28. #
  29. print ("c reasonLS SC18")
  30. print ("c authors")
  31. print ("c runs n instances of reasonLS in parallel")
  32. if (len(sys.argv) < 4):
  33. print ("c usage: python pmapple.py <input.cnf> <seed> <numCores> [<proofFile>] [<tmpDirectory>]" ) #n is the number of instances to start
  34. sys.exit(0)
  35. print ("c running with PID " + str(os.getpid()))
  36. #
  37. # Handle parameters
  38. #
  39. # get input file
  40. #
  41. inputFile = sys.argv[1]
  42. seed = int(sys.argv[2])
  43. numCores = int(sys.argv[3])
  44. if (numCores == 1):
  45. print ("c does not make sense, please start reasonLS directly")
  46. sys.exit(0)
  47. # set proof file
  48. if (len(sys.argv) > 4):
  49. tmpProofz = sys.argv[4]
  50. path_proof = tmpProofz[tmpProofz.find('drup-file=')+10:]
  51. pathz = os.path.dirname(path_proof)
  52. proof = os.path.basename(path_proof)
  53. else:
  54. proof = "/dev/null"
  55. #
  56. # setup tmp files
  57. #
  58. tmpDir = "/tmp/"
  59. print ("c found " + str(len(sys.argv)) + " parameters")
  60. if (len(sys.argv) > 5):
  61. tmpDir = sys.argv[5]
  62. if (tmpDir[-1:] != '/'):
  63. tmpDir = tmpDir + "/"
  64. #construction of temporary files for output
  65. # let user know that everything has been read correctly
  66. print ("c starting " + str(numCores) + " instances of reasonLS with seed " + str(
  67. seed) + " on instance " + str(
  68. inputFile) + " \nc writing temp files to " + tmpDir)
  69. #
  70. # start the two solvers, each in its private process group
  71. #
  72. random.seed(seed)
  73. pids = set()
  74. pidsseed = set()
  75. seeds = set()
  76. # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  77. confl = [0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.9, 0.7, 0.5, 0.9, 0.7, 0.5, 1, 1]
  78. area = [1.01, 1.01, 1.01, 1.01, 1.01, 1.01, 1.01, 1.01, 1, 1, 1, 1, 1, 1, 1, 1, 1.01, 1.05, 1.1, 1.01, 1.05, 1.1, 1.01, 1.01]
  79. maxflip = [600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 600, 500, 600, 600, 600, 600]
  80. initflip = [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 50, 50, 50, 50, 50, 50, 100, 100]
  81. raiseflip = [1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02, 1.02]
  82. switch = [2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 0, 0, 0, 0, 2500]
  83. time = [0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 0.35, 0.45, 0.55, 0.35, 0.45, 0.55, 0.35, 0.35]
  84. aspiration = [1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
  85. threshold = [50, 50, 300, 300, 50, 50, 300, 300, 50, 50, 300, 300, 50, 50, 300, 300, 50, 50, 50, 50, 50, 50, 50, 50]
  86. q = [0, 0.7, 0, 0.7, 0, 0.7, 0, 0.7, 0, 0.7, 0, 0.7, 0, 0.7, 0, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7]
  87. tmpBassename = os.path.basename(inputFile)
  88. for i in range(0, numCores):
  89. seed=random.randint(0,2147483647)
  90. tmpFile = tmpDir + tmpBassename + "reasonLS_" + str(seed)
  91. print ("c starting instance " + str(
  92. i) + " of reasonLS started with seed " + str(seed))
  93. print ("c writing to files " + tmpFile + ".out .err")
  94. # start reasonLS
  95. if (proof != "/dev/null"):
  96. tmpProof = tmpDir + tmpBassename + proof + "reasonLS_" + str(seed)
  97. else:
  98. tmpProof = proof
  99. reasonLSCallString = "./ReasonLS " + inputFile + " -drup-file=" + tmpProof # add CNF file and tmp directory
  100. reasonLSCallString = reasonLSCallString + " -conflRatio=" + str(confl[i]) + " -areaRatio=" + str(area[i])
  101. reasonLSCallString = reasonLSCallString + " -maxFlipRatio=" + str(maxflip[i]) + " -initFlipRatio=" + str(initflip[i]) + " -raiseFlipRatio=" + str(raiseflip[i])
  102. reasonLSCallString = reasonLSCallString + " -timeRatio=" + str(time[i]) + " -switchMode=" +str(switch[i])
  103. reasonLSCallString = reasonLSCallString + " -swt_q=" + str(q[i]) + " -swt_threshold="+ str(threshold[i]) + " -aspiration=" +str(aspiration[i])
  104. args = reasonLSCallString.split()
  105. # split the actual command line
  106. print ("c calling reasonLS with " + str(args))
  107. reasonLSProcess = subprocess.Popen(
  108. args,
  109. stdout=open(tmpFile + ".out", "w"),
  110. stderr=open(tmpFile + ".err", "w"),
  111. preexec_fn=os.setpgrp)
  112. pidsseed.add((reasonLSProcess.pid, seed))
  113. pids.add(reasonLSProcess.pid)
  114. seeds.add(seed)
  115. print ("c started reasonLS instance with PID" + str(reasonLSProcess.pid))
  116. # wait until the first solver returns
  117. winner = ""
  118. winnerCode = 0
  119. while pids:
  120. pid, retval = os.wait()
  121. print ("c finished " + str(pid) + " with return value " + str(retval))
  122. pids.remove(pid)
  123. # extract the exit code
  124. signal = retval & 255
  125. exitCode = (retval >> 8) & 255
  126. print ("c signal: " + str(signal) + " exit code: " + str(exitCode))
  127. # if exit code is nice, select the winner
  128. winnerseed = -1
  129. if signal == 0 and (exitCode == 10 or exitCode == 20):
  130. winnerCode = exitCode # get exit code
  131. for i in range(numCores):
  132. proc = pidsseed.pop()
  133. if proc[0] == pid:
  134. winnerseed = proc[1]
  135. break # do not wait for the other process as well, if a solution has been found!
  136. if winnerseed != -1:
  137. break
  138. #
  139. # output the result
  140. #
  141. if winnerCode != 0:
  142. print ("c winner seed: " + str(winnerseed))
  143. tmpFile = tmpDir + tmpBassename + "reasonLS_" + str(winnerseed)
  144. # for more recent python versions:
  145. # with open(tmpFile + ".out", "r") as f:
  146. # for the competition 2014 version:
  147. f = open(tmpFile + ".out", "r")
  148. if f:
  149. shutil.copyfileobj(f, sys.stdout)
  150. if (proof != "/dev/null"):
  151. tmpProof = tmpBassename + proof + "reasonLS_" + str(winnerseed)
  152. if( not os.path.exists(pathz) ):
  153. os.mkdir(pathz)
  154. if( os.path.exists(tmpDir+tmpProof)):
  155. os.system("cp " + tmpDir + tmpProof + " " + pathz + '/' +proof)
  156. else:
  157. print ("s UNKNOWN")
  158. # kill the other process, and its child processes
  159. for p in pids:
  160. kill_pid(p)
  161. # clean up the temporary files
  162. for i in range(numCores):
  163. seed = seeds.pop()
  164. tmpFile = tmpDir + tmpBassename + "reasonLS_" + str(seed)
  165. if(os.path.exists(tmpFile + ".err")):
  166. os.unlink(tmpFile + ".err")
  167. if(os.path.exists(tmpFile + ".out")):
  168. os.unlink(tmpFile + ".out")
  169. if(proof != "/dev/null"):
  170. tmpProof = tmpDir + tmpBassename + proof + "reasonLS_" + str(seed)
  171. #if(os.path.exists(tmpProof)):
  172. os.unlink(tmpProof)
  173. # exit with the correct exit code
  174. sys.exit(winnerCode)