示例#1
0
 def __init__(self, s,  metrics_variables, metrics_objective_direction, decision_variables=[], options=GuidedImprovementAlgorithmOptions()):
     self.s = s
     self.metrics_variables = metrics_variables
     self.metrics_objective_direction = metrics_objective_direction
     self.decision_variables = decision_variables
     self.options = options
     self.verbosity = self.options.verbosity
     self.GIALogger = GIALogging(self.options, self.metrics_variables, self.decision_variables)
示例#2
0
class GuidedImprovementAlgorithm(object):
    def __init__(self, s,  metrics_variables, metrics_objective_direction, decision_variables=[], options=GuidedImprovementAlgorithmOptions()):
        self.s = s
        self.metrics_variables = metrics_variables
        self.metrics_objective_direction = metrics_objective_direction
        self.decision_variables = decision_variables
        self.options = options
        self.verbosity = self.options.verbosity
        self.GIALogger = GIALogging(self.options, self.metrics_variables, self.decision_variables)

    def _setAndLogZ3RandomSeeds(self):
        """ 
        Will set random seeds for z3 and store them on the file
        """
        random.seed()
        z3_random_seed_val = random.randint(0, 500000000)
        z3_arith_random_seed_val = random.randint(0, 500000000)        
        set_option(random_seed=z3_random_seed_val)
        set_option(arith_random_seed=z3_arith_random_seed_val)
        
        self.options.randomSeedsFil =  open(self.options.writeRandomSeedsFilename, "a")            
        self.options.randomSeedsFil.write("%s, %s, %s\n" % \
          ( self.options.writeLogFilename ,"random_seed", z3_random_seed_val ))
        self.options.randomSeedsFil.write("%s, %s, %s\n" % \
          ( self.options.writeLogFilename ,"arith_random_seed", z3_arith_random_seed_val ))
        
        self.options.randomSeedsFil.close()
          
        
    def ExecuteGuidedImprovementAlgorithm(self, outfilename, recordpointfile=""):
        """ 
        Ran the Guided Improvement Algorithm.
        """
        self._setAndLogZ3RandomSeeds()
        count_paretoPoints = 0
        ParetoFront = []
        initial_start_time = time()
        start_time = time()
        count_sat_calls = 0
        count_unsat_calls = 0
        #self.GIALogger.logStartCall()
        if self.s.check() == sat:
            count_sat_calls += 1
            prev_solution = self.s.model()
            #self.GIALogger.logEndCall(True, model=prev_solution, statistics = self.s.statistics())            
            self.s.push()
            FirstParetoPoint, local_count_sat_calls, local_count_unsat_calls = self.ranToParetoFront(prev_solution)
            end_time = time()
            count_sat_calls += local_count_sat_calls
            count_unsat_calls += local_count_unsat_calls
            count_paretoPoints += 1
            ParetoFront.append(FirstParetoPoint)
            # RecordPoint
            strNextParetoPoint = list((d.name(), str(FirstParetoPoint[d])) for d in FirstParetoPoint.decls())
            if RECORDPOINT:
                outputFile = open(recordpointfile, 'a')
                try:
                    outputFile.writelines(str(count_paretoPoints) + ',' +
                                          str(count_sat_calls) + ',' +
                                          str(end_time - start_time) + ',' +
                                          str(strNextParetoPoint) + ',' +
                                          '\n')
                finally:
                    outputFile.close()
                ##    
                    
            self.s.pop()
            #self.s.add(self.edstest)
            tmpNotDominatedByFirstParetoPoint = self.ConstraintNotDominatedByX(FirstParetoPoint)
#             self.GIALogger.logStartCall(tmpNotDominatedByFirstParetoPoint)
            self.s.add(tmpNotDominatedByFirstParetoPoint)
            start_time = time()
            while(self.s.check() == sat):
                count_sat_calls += 1
#                 self.GIALogger.logEndCall(True, model = self.s.model(), statistics = self.s.statistics())                              
                prev_solution = self.s.model()
                self.s.push()
                NextParetoPoint, local_count_sat_calls, local_count_unsat_calls = self.ranToParetoFront(prev_solution)
                end_time = time()
                count_sat_calls += local_count_sat_calls
                count_unsat_calls += local_count_unsat_calls
                count_paretoPoints += 1
                ParetoFront.append(NextParetoPoint)
                # RecordPoint
                strNextParetoPoint = list((d.name(), str(FirstParetoPoint[d])) for d in FirstParetoPoint.decls())
                if RECORDPOINT:
                    outputFile = open(recordpointfile, 'a')
                    try:
                        outputFile.writelines(str(count_paretoPoints) + ',' +
                                              str(count_sat_calls) + ',' +
                                              str(end_time - start_time) + ',' +
                                              str(strNextParetoPoint) + ',' +
                                              '\n')
                    finally:
                        outputFile.close()
                ##    
                self.s.pop()
                #self.s.add(self.edstest)
#                 ParetoFront.append(NextParetoPoint)
#                 if self.options.incrementallyprintparetopoints == True:
#                     self.print_solution(NextParetoPoint)
                tmpNotDominatedByNextParetoPoint = self.ConstraintNotDominatedByX(NextParetoPoint)
#                 self.GIALogger.logStartCall(tmpNotDominatedByNextParetoPoint)
                self.s.add(tmpNotDominatedByNextParetoPoint)
                start_time = time()
#             self.GIALogger.logEndCall(False, statistics = self.s.statistics())                
#         else :
        count_unsat_calls += 1
            #self.GIALogger.logEndCall(False, statistics = self.s.statistics())            
            
        end_time = time()
#         if OUTPUT_PARETO_FRONT:
#             #         print count_paretoPoints, count_sat_calls, count_sat_calls, end_time - start_time
#             outputFile2 = open("ERS_ParetoFront.csv", 'a')
#             ParetoPointsList2 = []
#             try:
#                 for paretopoint in ParetoFront:
#                     strParetoPoint = list((d.name(), str(paretopoint[d])) for d in paretopoint.decls())
#                     dict = {}
#                     for item in strParetoPoint:
#                         if( item[0] == 'total_batteryusage' or item[0] == 'total_cost' or item[0] == 'total_deploymenttime' or
#                             item[0] == 'total_developmenttime' or item[0] == 'total_rampuptime' or item[0] == 'total_reliability' or
#                             item[0] == 'total_responsetime' ):
#                             # print item
#                             outputFile2.writelines(str(item) + ';')
#                             dict[str(item[0])] = str(item[1])
#                     ParetoPointsList2.append(dict)
#                     outputFile2.writelines('\n')
#             finally:
#                 outputFile2.close()
            
#             totalpoints = count_paretoPoints
#             for i in xrange(len(ParetoPointsList2)):
#                 isDominated = False
#                 for j in xrange(i+1, len(ParetoPointsList2)):
#                         strlist1 = ParetoPointsList2[i]['total_reliability'].split("/")
#                         #print strlist1
#                         strlist2 = ParetoPointsList2[j]['total_reliability'].split("/")
#                         #print strlist2
#                         if (int(ParetoPointsList2[i]['total_cost']) >= int(ParetoPointsList2[j]['total_cost']) and 
#                             int(ParetoPointsList2[i]['total_responsetime']) >= int(ParetoPointsList2[j]['total_responsetime']) and
#                             int(ParetoPointsList2[i]['total_batteryusage']) >= int(ParetoPointsList2[j]['total_batteryusage']) and 
#                             int(ParetoPointsList2[i]['total_deploymenttime']) >= int(ParetoPointsList2[j]['total_deploymenttime']) and 
#                             int(ParetoPointsList2[i]['total_developmenttime']) >= int(ParetoPointsList2[j]['total_developmenttime']) and
#                             int(ParetoPointsList2[i]['total_rampuptime']) >= int(ParetoPointsList2[j]['total_rampuptime']) and
#                             # precision of reliability is 1/1000 
#                             round(float(strlist1[0])/float(strlist1[1]),12) >= round(float(strlist2[0])/float(strlist2[1]), 12)):
#                             isDominated = True
#         #                     print str(i) + " dominated by " + str(j)
#         #                     print str(int(ParetoPointsList2[i]['total_cost'])) + " cost >=" + str(int(ParetoPointsList2[j]['total_cost']))
#         #                     print str(int(ParetoPointsList2[i]['total_responsetime'])) + "response >=" + str(int(ParetoPointsList2[j]['total_responsetime']))
#         #                     print str(int(ParetoPointsList2[i]['total_batteryusage'])) + "battery >=" + str(int(ParetoPointsList2[j]['total_batteryusage']))
#         #                     print str(int(ParetoPointsList2[i]['total_deploymenttime'])) + "deploy >=" + str(int(ParetoPointsList2[j]['total_deploymenttime']))
#         #                     print str(int(ParetoPointsList2[i]['total_developmenttime'])) + "develp >=" + str(int(ParetoPointsList2[j]['total_developmenttime']))
#         #                     print str(int(ParetoPointsList2[i]['total_rampuptime'])) + "rampup >=" + str(int(ParetoPointsList2[j]['total_rampuptime']))
#         #                     print str(strlist1[0]) + "/" + str(strlist1[1])  + "reliability >=" + str(strlist2[0]) + "/" + str(strlist2[1])
#         #                     print str(round(float(strlist1[0])/float(strlist1[1]),3)) +"reliability >=" + str(round(float(strlist2[0])/float(strlist2[1]), 3))
#                             break;
#                 if isDominated == True: 
#                     totalpoints -= 1   
#             print totalpoints
        
        
        
#         print count_paretoPoints, count_sat_calls, count_sat_calls, end_time - start_time
        outputFile = open(outfilename, 'a')
        try:
            outputFile.writelines(str(count_paretoPoints) + ',' +
                                  str(count_sat_calls) + ',' +
                                  str(count_unsat_calls) + ',' +
                                  str(end_time - initial_start_time) + ',' +
                                  '\n')
        finally:
            outputFile.close()
        
#         TotalUniqueParetoFront = len(ParetoFront)
#         print TotalUniqueParetoFront
#         ParetoPointsList = []
#         for i in xrange(len(ParetoFront)):
#             point = ParetoFront[i]
#             strPoint = list((d.name(), str(point[d])) for d in point.decls())
#             dict = {}
#             for item in strPoint:
#                 dict[str(item[0])] = str(item[1])
#             ParetoPointsList.append(dict)
#             
#         for i in xrange(len(ParetoPointsList)):
#             isDominated = False
#             for j in xrange(i+1, len(ParetoPointsList)):
#                     strlist1 = ParetoPointsList[i]['total_reliability'].split("/")
#                     #print strlist1
#                     strlist2 = ParetoPointsList[j]['total_reliability'].split("/")
#                     #print strlist2
#                     if (int(ParetoPointsList[i]['total_cost']) < int(ParetoPointsList[j]['total_cost']) and 
#                         int(ParetoPointsList[i]['total_responsetime']) < int(ParetoPointsList[j]['total_responsetime']) and
#                         int(ParetoPointsList[i]['total_batteryusage']) < int(ParetoPointsList[j]['total_batteryusage']) and 
#                         int(ParetoPointsList[i]['total_deploymenttime']) < int(ParetoPointsList[j]['total_deploymenttime']) and 
#                         int(ParetoPointsList[i]['total_developmenttime']) < int(ParetoPointsList[j]['total_developmenttime']) and
#                         int(ParetoPointsList[i]['total_rampuptime']) < int(ParetoPointsList[j]['total_rampuptime']) and 
#                         float(int(strlist1[0])/int(strlist1[1])) < float(int(strlist2[0])/int(strlist2[1]))):
#                         isDominated = True
#             if isDominated == True: 
#                 TotalUniqueParetoFront = TotalUniqueParetoFront - 1
#         print TotalUniqueParetoFront

             
#         if self.verbosity > consts.VERBOSE_NONE:
#             print "ParetoFront has size of %s " % len(ParetoFront)
#             print "Time taken is %s " % (end_time - start_time)
#         
#             for ParetoPoint in ParetoFront:
#                 self.print_solution(ParetoPoint)
#        
#         if  self.options.useSummaryStatsFile == True:        
#             self.print_stats_info(end_time, start_time, ParetoFront)
# 
#         self.options.timefilelog =  open(self.options.writeTotalTimeFilename, "a")            
#         self.options.timefilelog.write("%s, %s\n" %  ( self.options.writeLogFilename , (end_time - start_time)))
#         self.options.timefilelog.close()
        
        #for entry in self.GIALogger.getLog():
        #    print entry.statistics

        
    def print_stats_info(self, end_time, start_time, ParetoFront):
        statsfile_fd = open(self.args.statsfile, "a")   
        self.print_header_if_file_is_empty(statsfile_fd)   
        statsfile_fd.write( "%s, %s,%s\n" % (self.optimizationmodelname , (end_time - start_time), len(ParetoFront)))
        statsfile_fd.close()
        
    def print_header_if_file_is_empty(self, statsfile_fd):
        if statsfile_fd.tell() == 0:
            statsfile_fd.write("%s, %s, %s\n" % ('model name' , 'time to compute pareto front', 'length of pareto front'))
                
    def print_solution(self, solution):
        """
        Prints the objective value for the solution in one line, followed by the decision variables in the next line.
        """        
        SolutionSpacePoint = []
        for metric in self.metrics_variables:
            SolutionSpacePoint.append(solution[metric])
        print SolutionSpacePoint
                
        DecisionSpacePoint = []
        for instVariable in solution.decls()  :
            if instVariable.name() not in self.exclude_variables_in_printout:
                DecisionSpacePoint.append("%s=%s" % (instVariable.name(),  solution[instVariable]))
        print DecisionSpacePoint
    
    
    def ranToParetoFront(self, prev_solution):
        """
        It iterates getting close and closer to the pareto front.
        """
#         if self.verbosity > consts.VERBOSE_NONE:
#             self.print_solution(prev_solution)

        local_count_sat_calls = 0
        local_count_unsat_calls = 0
        tmpConstraintMustDominateX= self.ConstraintMustDominatesX(prev_solution)
#         self.GIALogger.logStartCall(tmpConstraintMustDominateX)
        self.s.add(tmpConstraintMustDominateX)
        while (self.s.check() == sat):
            local_count_sat_calls += 1
#             self.GIALogger.logEndCall(True, model = self.s.model(), statistics = self.s.statistics())              
#             if self.verbosity > consts.VERBOSE_NONE:
#                 self.print_solution(prev_solution)
            prev_solution = self.s.model()     
            tmpConstraintMustDominateX = self.ConstraintMustDominatesX(prev_solution)      
            self.s.add(tmpConstraintMustDominateX)
            self.GIALogger.logStartCall(tmpConstraintMustDominateX)
        local_count_unsat_calls += 1
        #    self.edstest= self.edstestExtension(prev_solution)
#         self.GIALogger.logEndCall(False, statistics = self.s.statistics())  
#         if self.verbosity > consts.VERBOSE_NONE:
#             self.print_solution(prev_solution)
        return prev_solution, local_count_sat_calls, local_count_unsat_calls

    def ConstraintNotDominatedByX(self, model):
        """
        Returns a Constraint that a  new instance, can't be dominated by the instance represented by model. 
        (it can't be worst in any objective).
        """
        DisjunctionOrLessMetrics  = list()
        for i in range(len(self.metrics_variables)):
            if self.metrics_objective_direction[i] == consts.METRICS_MAXIMIZE:
                DisjunctionOrLessMetrics.append(self.metrics_variables[i] >  model[self.metrics_variables[i]])
            else :
                DisjunctionOrLessMetrics.append(self.metrics_variables[i] <  model[self.metrics_variables[i]])
        return Or(DisjunctionOrLessMetrics)

    # add for EPOAL

    def EtractConstraintListNotDominatedByX(self, model):
        """
        Returns a Constraint that a  new instance, can't be dominated by the instance represented by model. 
        (it can't be worst in any objective).
        """
        DisjunctionOrLessMetrics  = list()
        for i in range(len(self.metrics_variables)):
            if self.metrics_objective_direction[i] == consts.METRICS_MAXIMIZE:
                DisjunctionOrLessMetrics.append(self.metrics_variables[i] >  model[self.metrics_variables[i]])
            else :
                DisjunctionOrLessMetrics.append(self.metrics_variables[i] <  model[self.metrics_variables[i]])
        return DisjunctionOrLessMetrics
    
    def edstestExtension(self, model):
        '''seeing if this extra constraint improves performance.'''
        dominationConjunction = []
        i = 0
        for dominatedByMetric in self.metrics_variables:        
            if  self.metrics_objective_direction[i] == consts.METRICS_MAXIMIZE :
                dominationConjunction.append(dominatedByMetric > model[dominatedByMetric])             
            else:
                dominationConjunction.append(dominatedByMetric < model[dominatedByMetric]) 
            i = 1 + i          
        constraintDominateX = Not(And(dominationConjunction))
        return constraintDominateX
    
    def ConstraintMustDominatesX(self, model):
        """
        Returns a constraint that a new instance has to be better than the instance represented by model in at least one dimension, 
        and better or equal in all the other ones.
        """
        dominationDisjunction= []
        i = 0
        for dominatedByMetric in self.metrics_variables:        
            dominationConjunction = []
            j = 0
            if  self.metrics_objective_direction[i] == consts.METRICS_MAXIMIZE :
                dominationConjunction.append(dominatedByMetric > model[dominatedByMetric])             
            else:
                dominationConjunction.append(dominatedByMetric < model[dominatedByMetric]) 
            for AtLeastEqualInOtherMetric in self.metrics_variables:
                if j != i:
                    if self.metrics_objective_direction[j] == consts.METRICS_MAXIMIZE:
                        dominationConjunction.append(AtLeastEqualInOtherMetric >= model[AtLeastEqualInOtherMetric])
                    else:
                        dominationConjunction.append(AtLeastEqualInOtherMetric <= model[AtLeastEqualInOtherMetric])                    
                j = 1 + j
            i = 1 + i    
            dominationDisjunction.append(And(dominationConjunction))         
        constraintDominateX = Or(dominationDisjunction)
        return constraintDominateX