pmaple.py 5.8 KB

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