def solve(self, rand, problem): comm = problem.comm() n = problem.numVariables assert n < 63 numPotentialSolutions = 2**n binaryAssignments = MpiCollection.makeRange(comm, numPotentialSolutions) currentAssignment = MpiKsatAssignment.emptyMpiKsatAssignment(problem.comm(), n) currentLocalAssignment = currentAssignment.localAssignment() #FIXME: collectEverywhere() probably should return a list, not an iterable. allClauses = list(problem.distributedClauses().values().collectEverywhere()) if comm.rank == 0: print allClauses def checkBinaryAssignment(binaryAssignment): MpiKsatAssignment.unpackTo(binaryAssignment, currentLocalAssignment, n) return currentLocalAssignment.satisfiesClauses(allClauses) satisfyingBinaryAssignments = binaryAssignments.filter(checkBinaryAssignment) resultStatistics = (satisfyingBinaryAssignments .map(lambda elt: (1, elt)) .reduce((0, -1), lambda countAndMaxA, countAndMaxB: (countAndMaxA[0] + countAndMaxB[0], max(countAndMaxA[1], countAndMaxB[1])))) def buildSolution(): numSatisfyingAssignments, arbitrarySatisfyingAssignment = resultStatistics print "%d out of %d satisfying assignments." % (numSatisfyingAssignments, numPotentialSolutions) if arbitrarySatisfyingAssignment > -1: return KsatSolution.success(MpiKsatAssignment.unpack(arbitrarySatisfyingAssignment, n)) else: return KsatSolution.failure() return onMaster(problem.comm(), buildSolution)
def solve(self, rand, problem): comm = problem.comm() n = problem.numVariables numSamples = self.numSamples processorRand = MpiUtils.reseed(comm, rand) startingSeed = Utils.randLargeInt(rand) allClauses = list(problem.distributedClauses().values().collectEverywhere()) satisfyingAssignments = (MpiCollection.makeRange(comm, numSamples) .map(lambda idx: MpiKsatAssignment.uniformRandomKsatAssignment(processorRand, n)) .filter(lambda assignment: assignment.satisfiesClauses(allClauses))) #if comm.rank == 0: #print allClauses def reduceResultStatistics(countAndArbitraryElementA, countAndArbitraryElementB): newCount = countAndArbitraryElementA[0] + countAndArbitraryElementB[0] newArbitraryElement = countAndArbitraryElementA[1] if countAndArbitraryElementB[1] is None else countAndArbitraryElementB[1] return (newCount, newArbitraryElement) resultStatistics = (satisfyingAssignments .map(lambda elt: (1, elt)) .reduce((0, None), reduceResultStatistics)) def buildSolution(): numSatisfyingAssignments, arbitrarySatisfyingAssignment = resultStatistics #print "%d out of %d satisfying assignments." % (numSatisfyingAssignments, numSamples) #if numSatisfyingAssignments*1.0/numSamples <= 0.0002 and numSatisfyingAssignments != 0: print "problem difficulty = " + str(numSatisfyingAssignments*1.0/numSamples) if arbitrarySatisfyingAssignment > -1: return KsatSolution.success(arbitrarySatisfyingAssignment) else: return KsatSolution.failure() return onMaster(problem.comm(), buildSolution)
def collectAndCombineLocalAssignments(comm, locallySatisfyingAssignments): allLocalAssignments = locallySatisfyingAssignments.collect() def findGloballySatisfyingAssignments(): satisfyingAssignments = set(allLocalAssignments[0]) for procAssignments in allLocalAssignments: satisfyingAssignments &= frozenset(procAssignments) return satisfyingAssignments return onMaster(comm, findGloballySatisfyingAssignments)
def solve(self, rand, problem): comm = problem.comm() allClauses = problem.distributedClauses().values().collectEverywhere() if comm.rank == 0: print list(allClauses) n = problem.numVariables assert n < 63 numPotentialSolutions = 2**n locallySatisfyingAssignments = MpiChunks(problem.comm(), []) assignment = MpiKsatAssignment.emptyMpiKsatAssignment( problem.comm(), n) localAssignment = assignment.localAssignment() assignmentsSinceLastCommunication = 0 satisfyingAssignment = None numSatisfyingAssignments = 0 if comm.rank == 0: satisfyingAssignments = set() for binaryAssignment in xrange(numPotentialSolutions): MpiKsatAssignment.unpackTo(binaryAssignment, localAssignment, n) if localAssignment.satisfiesClauses(problem.localClauses()): locallySatisfyingAssignments.localData().append( binaryAssignment) assignmentsSinceLastCommunication += 1 if assignmentsSinceLastCommunication >= self.communicationFrequency or binaryAssignment == numPotentialSolutions - 1: newSatisfyingAssignments = collectAndCombineLocalAssignments( comm, locallySatisfyingAssignments) if comm.rank == 0: numSatisfyingAssignments += len(newSatisfyingAssignments) if len(newSatisfyingAssignments ) > 0 and satisfyingAssignment is None: satisfyingAssignment = MpiKsatAssignment.unpack( list(newSatisfyingAssignments)[0], n) locallySatisfyingAssignments = MpiChunks(comm, []) assignmentsSinceLastCommunication = 0 def buildSolution(): print "%d out of %d satisfying assignments." % ( numSatisfyingAssignments, numPotentialSolutions) if satisfyingAssignment is not None: return KsatSolution.success(satisfyingAssignment) else: return KsatSolution.failure() return onMaster(comm, buildSolution)
def solve(self, rand, problem): comm = problem.comm() n = problem.numVariables numSamples = self.numSamples processorRand = MpiUtils.reseed(comm, rand) startingSeed = Utils.randLargeInt(rand) allClauses = list( problem.distributedClauses().values().collectEverywhere()) satisfyingAssignments = ( MpiCollection.makeRange( comm, numSamples).map(lambda idx: MpiKsatAssignment. uniformRandomKsatAssignment(processorRand, n)). filter(lambda assignment: assignment.satisfiesClauses(allClauses))) #if comm.rank == 0: #print allClauses def reduceResultStatistics(countAndArbitraryElementA, countAndArbitraryElementB): newCount = countAndArbitraryElementA[ 0] + countAndArbitraryElementB[0] newArbitraryElement = countAndArbitraryElementA[ 1] if countAndArbitraryElementB[ 1] is None else countAndArbitraryElementB[1] return (newCount, newArbitraryElement) resultStatistics = ( satisfyingAssignments.map(lambda elt: (1, elt)).reduce( (0, None), reduceResultStatistics)) def buildSolution(): numSatisfyingAssignments, arbitrarySatisfyingAssignment = resultStatistics #print "%d out of %d satisfying assignments." % (numSatisfyingAssignments, numSamples) #if numSatisfyingAssignments*1.0/numSamples <= 0.0002 and numSatisfyingAssignments != 0: print "problem difficulty = " + str( numSatisfyingAssignments * 1.0 / numSamples) if arbitrarySatisfyingAssignment > -1: return KsatSolution.success(arbitrarySatisfyingAssignment) else: return KsatSolution.failure() return onMaster(problem.comm(), buildSolution)
def solve(self, rand, problem): comm = problem.comm() allClauses = problem.distributedClauses().values().collectEverywhere() if comm.rank == 0: print list(allClauses) n = problem.numVariables assert n < 63 numPotentialSolutions = 2**n locallySatisfyingAssignments = MpiChunks(problem.comm(), []) assignment = MpiKsatAssignment.emptyMpiKsatAssignment(problem.comm(), n) localAssignment = assignment.localAssignment() assignmentsSinceLastCommunication = 0 satisfyingAssignment = None numSatisfyingAssignments = 0 if comm.rank == 0: satisfyingAssignments = set() for binaryAssignment in xrange(numPotentialSolutions): MpiKsatAssignment.unpackTo(binaryAssignment, localAssignment, n) if localAssignment.satisfiesClauses(problem.localClauses()): locallySatisfyingAssignments.localData().append(binaryAssignment) assignmentsSinceLastCommunication += 1 if assignmentsSinceLastCommunication >= self.communicationFrequency or binaryAssignment == numPotentialSolutions-1: newSatisfyingAssignments = collectAndCombineLocalAssignments(comm, locallySatisfyingAssignments) if comm.rank == 0: numSatisfyingAssignments += len(newSatisfyingAssignments) if len(newSatisfyingAssignments) > 0 and satisfyingAssignment is None: satisfyingAssignment = MpiKsatAssignment.unpack(list(newSatisfyingAssignments)[0], n) locallySatisfyingAssignments = MpiChunks(comm, []) assignmentsSinceLastCommunication = 0 def buildSolution(): print "%d out of %d satisfying assignments." % (numSatisfyingAssignments, numPotentialSolutions) if satisfyingAssignment is not None: return KsatSolution.success(satisfyingAssignment) else: return KsatSolution.failure() return onMaster(comm, buildSolution)
def solve(self, rand, problem): comm = problem.comm() n = problem.numVariables assert n < 63 numPotentialSolutions = 2**n binaryAssignments = MpiCollection.makeRange(comm, numPotentialSolutions) currentAssignment = MpiKsatAssignment.emptyMpiKsatAssignment( problem.comm(), n) currentLocalAssignment = currentAssignment.localAssignment() #FIXME: collectEverywhere() probably should return a list, not an iterable. allClauses = list( problem.distributedClauses().values().collectEverywhere()) if comm.rank == 0: print allClauses def checkBinaryAssignment(binaryAssignment): MpiKsatAssignment.unpackTo(binaryAssignment, currentLocalAssignment, n) return currentLocalAssignment.satisfiesClauses(allClauses) satisfyingBinaryAssignments = binaryAssignments.filter( checkBinaryAssignment) resultStatistics = ( satisfyingBinaryAssignments.map(lambda elt: (1, elt)).reduce( (0, -1), lambda countAndMaxA, countAndMaxB: (countAndMaxA[0] + countAndMaxB[0], max(countAndMaxA[1], countAndMaxB[1])))) def buildSolution(): numSatisfyingAssignments, arbitrarySatisfyingAssignment = resultStatistics print "%d out of %d satisfying assignments." % ( numSatisfyingAssignments, numPotentialSolutions) if arbitrarySatisfyingAssignment > -1: return KsatSolution.success( MpiKsatAssignment.unpack(arbitrarySatisfyingAssignment, n)) else: return KsatSolution.failure() return onMaster(problem.comm(), buildSolution)
def reduce(self, zero, plus): collectedValue = self.collect() return onMaster(self.comm, lambda : reduce(plus, collectedValue, zero))
def reduce(self, zero, plus): collectedValue = self.collect() return onMaster(self.comm, lambda: reduce(plus, collectedValue, zero))
def size(self): numElements = self.mapChunks(_chunkLen).reduce(0, operator.add) return onMaster(self.comm(), lambda : numElements)
def collect(self): collectedChunks = self.distributedChunks.collect() return onMaster(self.comm(), lambda : itertools.chain.from_iterable(collectedChunks))
def collect(self): dicts = self.dictChunks.collect() return onMaster(self.comm(), lambda : addAll_update(dicts))
def solve(self, rand, problem): comm = problem.comm() n = problem.numVariables #broadcastStartTime = now() broadcastStartTime = datetime.datetime.now() broadcastProblem = problem.toBroadcast() broadcastEndTime = datetime.datetime.now() #graphCreationStartTime = now() graphCreationStartTime = datetime.datetime.now() graph = broadcastProblem.toDependencyGraph(comm) graphCreationEndTime = datetime.datetime.now() currentAssignment = MpiKsatAssignment.uniformRandomMpiKsatAssignment( comm, rand, n) maxNumIterations = self.independentSetFinder.calculateNumIterations( problem, graph) if comm.rank == 0: print "Solving problem with %s iterations." % maxNumIterations #initialMarkingsStartTime = now() initialMarkingsStartTime = datetime.datetime.now() independentSetFunc = self.independentSetFinder.buildFinderFunc( rand, graph) initialMarkingsEndTime = datetime.datetime.now() findIndependentSetAndResampleTotalTime = datetime.timedelta() broadcastModifiedVariablesTotalTime = datetime.timedelta() for i in xrange(maxNumIterations): # At the beginning of each iteration of this loop, @currentAssignment # is consistent across processors. localAssignment = currentAssignment.localAssignment() unsatSubgraph = graph.filter( lambda clauseIdx: not localAssignment.satisfiesClause( broadcastProblem.clausesByIdx[clauseIdx])) # print "%d unsatisfied clauses on iteration %d on machine %d: %s." % (CollectionUtils.iterlen(unsatSubgraph.nodesIterator().localElements()), i, comm.rank, {clauseIdx: broadcastProblem.clausesByIdx[clauseIdx] for clauseIdx in unsatSubgraph.nodesIterator().localElements()}) localIndependentSet = independentSetFunc(unsatSubgraph) locallyModifiedVariables = MpiCollection.dictFromLocal(comm, {}) #FIXME localIndependentSetSize = 0 #findIndependentSetAndResampleStartTime = now() findIndependentSetAndResampleStartTime = datetime.datetime.now() for clauseIdx in localIndependentSet.localElements(): clause = broadcastProblem.clausesByIdx[clauseIdx] #TODO: Only communicate modified variables to machines that need them. # For now we assume all machines need to see all modified variables, # which is true when m*k/p >> n (i.e. when the number of literals per # machine is large). updates = { variable: Utils.randBit(rand) for variable in clause.literals } locallyModifiedVariables.localDict().update(updates) localIndependentSetSize += 1 findIndependentSetAndResampleTotalTime += datetime.datetime.now( ) - findIndependentSetAndResampleStartTime # print "Using an independent set of size %d on iteration %d on machine %d." % (localIndependentSetSize, i, comm.rank) #TODO: Probably inefficient serialization here. Should serialize as # a list of ints and a list of bools. #broadcastModifiedVariablesStartTime = now() broadcastModifiedVariablesStartTime = datetime.datetime.now() allModifiedVariables = locallyModifiedVariables.collectEverywhere() broadcastModifiedVariablesTotalTime += datetime.datetime.now( ) - broadcastModifiedVariablesStartTime if len(allModifiedVariables) == 0: if comm.rank == 0: print "\nBroadcast time = " + str( (broadcastEndTime - broadcastStartTime).total_seconds()) print "Graph creation time = " + str( (graphCreationEndTime - graphCreationStartTime).total_seconds()) print "Initial markings time = " + str( (initialMarkingsEndTime - initialMarkingsStartTime).total_seconds()) print "Find independentSet and resample time = " + str( findIndependentSetAndResampleTotalTime.total_seconds()) print "Boardcast modified variables time = " + str( broadcastModifiedVariablesTotalTime.total_seconds()) print "\n" print "Finished after %d iterations." % i return onMaster(comm, lambda: KsatSolution.success(localAssignment)) # Update modified variables from everywhere. for var, value in allModifiedVariables.items(): localAssignment.values[var] = value return onMaster(comm, lambda: KsatSolution.failure())