Beispiel #1
0
    def elitismSelection(self, individuals: List[Chromosome], elitesRatio = 0.1) -> Tuple[List[Chromosome], List[float], bool]:
        """
        This selection method performs elitism, here the nonElites ratio indicates that (by default), 90% of the individuals of
        the population are non-elites, or 10% of the individuals in the new population are elites.

        The algorithm starts by computing the fitness values (as usual) and store the values in tuples(indexToIndividual, fitness),
        it then selects the top X (determined by numOfElites) individuals as elites (preserved) while handing the rest to the selection
        method.
        """
        terminate = False
        retention = 0.8 - elitesRatio #TODO: we should probably encapsulate this in a class such as params
        threshold = 0.001
        numOfElites = math.ceil(elitesRatio * self.popSize)
        # 1. computes the probability (or fitness)
        maxvalue = len(self.testValues)
        aggregatedFitnesses = []
        fitnesses = []
        tuples = []
        total = 0.0
        fitness = -1
        currentIdx = 0
        for ind in individuals:
            #given that we may have couple of entries, we will get the sum of fitness in this case
            fitness = sum(v for v in ind.getProbabilities().values())
            # saves this in the chromosome
            ind.fitness = fitness
            # if the diff between the best fitness and 1.0 is close enough (threshold), we can terminate
            if(maxvalue - fitness < threshold):
                terminate = True
            # saves this in a tuplie within the fitnesses array
            tuples.append((currentIdx, fitness))
            fitnesses.append(fitness)
            #we are creating the aggregated fitness so that when we roll a random number, we just have to compare if it is <= a value in fitnesses[]
            total += fitness
            #creates the range of aggregated fitness for selection later
            aggregatedFitnesses.append(total) 
            #updates the current individual offset
            currentIdx += 1
        #sorts the tuplies
        ranked = sorted(tuples, key=lambda tup:tup[1], reverse=True)

        elites = []
        #keeps the elites
        for i in range(0, numOfElites):
            offset = ranked[i][0]
            elites.append(individuals[offset].getClone())       

        #we want to send of everything for selection
        newPop = Ga.defaultMakeSelection(self.rand, self.popSize, individuals, aggregatedFitnesses, retention = retention)
        return newPop, fitnesses, terminate, elites
Beispiel #2
0
 def rouletteWheelSelection(self, individuals: List[Chromosome], retention = 0.8) -> Tuple[List[Chromosome], List[float], bool]:
     """
     The probabilities from individuals are now based on the cases, to get the total fitness, we will sum all of the tup[1]
     """
     terminate = False
     aggregatedFitnesses = []
     fitnesses = []
     total = 0.0
     fitness = -1
     #computes the aggregated fitness
     for ind in individuals:
         probs = ind.getProbabilities()
         fitness = sum(v for v in probs.values())
         ind.fitness = fitness
         if(not terminate): #terminate should only be set to true if it's false, this prevents overwritting an otherwise true.
             terminate = self.__checkTerminateCondition(ind.fitness)
         #saves in the fitness array
         fitnesses.append(fitness)
         # updates the aggregated fitness
         total += fitness
         aggregatedFitnesses.append(total)
     return Ga.defaultMakeSelection(self.rand, self.popSize, individuals, aggregatedFitnesses, retention = retention), fitnesses, terminate
def weightedSelectionFunc(
        individuals: List[Chromosome],
        retention=0.8) -> Tuple[List[Chromosome], List[float], bool]:
    """
    This selection method performs roulette wheel selection based on a weighted fitness value:
    prob1 * value of the first binary string + prob2 * value of the 2nd binary string + ...
    """
    terminate = False
    threshold = 0.001
    #computes the probability (fitness)
    aggregatedFitnesses = []
    fitnesses = []
    total = 0.0
    fitness = -1
    maxfitness = 2**registers - 1
    for ind in individuals:
        probabilities = list(ind.getProbabilities().values())
        # we need to iterate through all of the elements in the list and compute the fitness value, given that
        # this is a binary string problem, the values are arranged in 0, 1, 2,..., 2^numRegisters - 1 so it's straightforward
        # to compute this weighted probability
        for idx, prob in enumerate(probabilities):
            if (prob > 0.0):
                fitness += prob * idx
        ind.fitness = fitness
        # we can terminate when the weighted average fitness is >= 2^numRegisters - 1
        if (maxfitness - fitness < threshold):
            terminate = True
        fitnesses.append(fitness)
        total += fitness
        aggregatedFitnesses.append(total)
        fitness = 0.0
    return Ga.defaultMakeSelection(r,
                                   popSize,
                                   individuals,
                                   aggregatedFitnesses,
                                   retention=retention), fitnesses, terminate
def main():
    # this is the "prepare" statements used by the maxone problem experiments
    hadamardPattern = ""
    # places all gates in hadamard
    for i in range(0, registers):
        hadamardPattern = hadamardPattern + "h q[" + str(i) + "];\n"

    #this is the first experiment:
    #Roulette wheel selection,
    #default multipoint crossover, mutation, and selection function is based on
    #the binary string problem and how close the value is to the intended 1111 string value.
    #1/(max value - prob of the largest binary string in the quantum experiment) where max value is 2^ num of register - 1 (the max value
    #for a binary string represented by the num of registers).
    params = GAParameters(MProb,
                          CProb,
                          totalEpochs,
                          openQASMPrepareStatement=hadamardPattern)
    try:
        ga = Ga(r,
                popSize,
                registers,
                generationFunction=QASMPrimitiveInstruction,
                minSize=minSize,
                maxSize=maxSize)
        stats = ga.evolve(totalEpochs,
                          probCrossover=CProb,
                          probMutation=MProb,
                          params=params)
    except Exception:
        traceback.print_exc()
    generateSummaries(stats=stats, experimentName="none")

    #this is the 2nd experiment:
    #Roulette wheel selection,
    #default multipoint crossover, mutation, selection function is, again, based on the binary string
    #problem, however, the fitness value is weighted based on the following formulation:
    #prob1 * value of the first binary string + prob2 * value of the 2nd binary string + ...
    params = GAParameters(MProb,
                          CProb,
                          totalEpochs,
                          openQASMPrepareStatement=hadamardPattern)

    try:
        ga = Ga(r,
                popSize,
                registers,
                generationFunction=QASMPrimitiveInstruction,
                minSize=minSize,
                maxSize=maxSize)
        stats = ga.evolve(totalEpochs,
                          selectionFunc=weightedSelectionFunc,
                          probCrossover=CProb,
                          probMutation=MProb,
                          params=params)
    except Exception:
        traceback.print_exc()
    generateSummaries(stats=stats, experimentName="W")

    #This is the start of the 3rd experiment with decreasing M and C probabilities
    #Default roulette selection method
    params = GAParameters(MProb, CProb, totalEpochs, decreaseM = True, decreaseC = True, \
                MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch, \
                openQASMPrepareStatement = hadamardPattern)
    try:
        ga = Ga(r,
                popSize,
                registers,
                generationFunction=QASMPrimitiveInstruction,
                minSize=minSize,
                maxSize=maxSize)
        stats = ga.evolve(totalEpochs,
                          probCrossover=CProb,
                          probMutation=MProb,
                          params=params)
    except Exception:
        traceback.print_exc()
    generateSummaries(stats=stats, experimentName="dMC")

    #This is the start of the 4th experiment with decreasing M and C probabilities
    #weight average selection method
    params = GAParameters(MProb, CProb, totalEpochs, decreaseM = True, decreaseC = True, \
                MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch, \
                openQASMPrepareStatement = hadamardPattern)
    try:
        ga = Ga(r,
                popSize,
                registers,
                generationFunction=QASMPrimitiveInstruction,
                minSize=minSize,
                maxSize=maxSize)
        stats = ga.evolve(totalEpochs,
                          selectionFunc=weightedSelectionFunc,
                          probCrossover=CProb,
                          probMutation=MProb,
                          params=params)
    except Exception:
        traceback.print_exc()
    generateSummaries(stats=stats, experimentName="dMCW")

    #This is the start of the 5th experiment with decreasing M and C probabilities
    #weight average selection method and delta mutation func

    params = GAParameters(MProb, CProb, totalEpochs, decreaseM = True, decreaseC = True, \
                MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch, \
                openQASMPrepareStatement = hadamardPattern)
    try:
        ga = Ga(r,
                popSize,
                registers,
                generationFunction=QASMPrimitiveInstruction,
                minSize=minSize,
                maxSize=maxSize)
        stats = ga.evolve(totalEpochs, selectionFunc = weightedSelectionFunc, probCrossover = CProb, \
            probMutation= MProb, mutationArgFunc = deltaMutationFunc, params = params)
    except Exception:
        traceback.print_exc()
    generateSummaries(stats=stats, experimentName="dMCW")

    #test code for elitism
    params = GAParameters(MProb, CProb, totalEpochs, decreaseM = True, decreaseC = True, \
                MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch, \
                eliteRatio=eliteRatio , openQASMPrepareStatement = hadamardPattern)
    try:
        ga = Ga(r,
                popSize,
                registers,
                generationFunction=QASMPrimitiveInstruction,
                minSize=minSize,
                maxSize=maxSize)
        stats = ga.evolve(totalEpochs, selectionFunc = elitismDefaultSelectionFunc, probCrossover = CProb, \
            probMutation= MProb, mutationArgFunc = deltaMutationFunc, params = params)
    except Exception:
        traceback.print_exc()
    generateSummaries(stats=stats, experimentName="edMCW")
    input("Press [enter] to continue.")
def elitismDefaultSelectionFunc(
    individuals: List[Chromosome],
    elitesRatio=0.1
) -> Tuple[List[Chromosome], List[float], bool, List[Chromosome]]:
    """
    This selection method performs elitism, here the nonElites ratio indicates that (by default), 90% of the individuals of
    the population are non-elites, or 10% of the individuals in the new population are elites.

    The algorithm starts by computing the fitness values (as usual) and store the values in tuples(indexToIndividual, fitness),
    it then selects the top X (determined by numOfElites) individuals as elites (preserved) while handing the rest to the selection
    method.
    """
    terminate = False
    retention = 0.8 - elitesRatio  #TODO: we should probably encapsulate this in a class such as params
    threshold = 0.001
    numOfElites = ceil(elitesRatio * popSize)
    # 1. computes the probability (or fitness)
    maxvalue = 2**registers - 1
    aggregatedFitnesses = []
    fitnesses = []
    tuples = []
    total = 0.0
    fitness = -1
    currentIdx = 0
    for ind in individuals:
        probabilities = list(ind.getProbabilities().values())
        largest = 0
        # gets the prob of the last non 0 prob entry in the list. This is only applicable for the max binary string problem
        # since the largest value is the one with all 1111...
        for i in range(maxvalue, -1, -1):
            if (probabilities[i] > 0.0):
                # i is the corresponding value translate from binary since:
                # for 5 registers: 11111 = 31 and the largest offset is 31 in the array
                largest = i
                break

        # the fitness value is the probability * value (state vector) for the state string that's closest to the max
        # value that can be represented by the qubits. For instance: given a 3 qubit problem, the max value is "111", so
        # if we obtained {000: 0.1, .... 100: 0.5, 101:0, 110:0, 111:0}, the fitness value is going to be int(100) * 0.5.
        fitness = probabilities[largest] * i

        # saves this in the chromosome
        ind.fitness = fitness

        # if the diff between the best fitness and 1.0 is close enough (threshold), we can terminate
        if (maxvalue - fitness < threshold):
            terminate = True

        # saves this in a tuplie within the fitnesses array
        tuples.append((currentIdx, fitness))
        fitnesses.append(fitness)
        #we are creating the aggregated fitness so that when we roll a random number, we just have to compare if it is <= a value in fitnesses[]
        total += fitness
        #creates the range of aggregated fitness for selection later
        aggregatedFitnesses.append(total)
        #updates the current individual offset
        currentIdx += 1

    #sorts the tuplies
    ranked = sorted(tuples, key=lambda tup: tup[1], reverse=True)

    elites = []
    #keeps the elites
    for i in range(0, numOfElites):
        offset = ranked[i][0]
        elites.append(individuals[offset].getClone())

    #we want to send of everything for selection
    newPop = Ga.defaultMakeSelection(r,
                                     popSize,
                                     individuals,
                                     aggregatedFitnesses,
                                     retention=retention)

    return newPop, fitnesses, terminate, elites
def decrementExperiment():
    """ 
    This is the main method for the decrement problem 
    This problem is phrased as follows:
    given a set of registers, we will create a prepare statement corresponding to a value in superposition, such as 
    0x4, the decrement op should output 50% for 0 and 5 correspondingly
    
    We will implement the experiment for 5 qubits (+1 qubit as scratch): 
    the first qubit is the min value within the circuit initially: x a[0] 
    (as in the prepareStatement)
    So the values in the lookup table are : 
    h a[1] (2^1) - {'00000': 0.5, '00010': 0.5}
    h a[2] (2^2) - {'00000': 0.5, '00100': 0.5}
    h a[3] (2^3) - {'00000': 0.5, '01000': 0.5}
    h a[4] (2^4) - {'00000': 0.5, '10000': 0.5}

    """
    #sets up entries in the lookup table
    lookupTable = [
        ('00000', '00010', "x q[0];\nh q[1];\nrz(0.785398163397448) q[1];\n"),
        ('00000', '00100', "x q[0];\nh q[2];\nrz(0.785398163397448) q[2];\n"),
        ('00000', '01000', "x q[0];\nh q[3];\nrz(0.785398163397448) q[3];\n"),
        ('00000', '10000', "x q[0];\nh q[4];\nrz(0.785398163397448) q[4];\n"),
    ]

    #this array makes it easy to control which experiment is to run by the sim
    enabledExperiments = [False, False, True, False]
    #default params
    params = GAParameters(MProb, CProb, totalEpochs)
    incDecExp = IncDecExperiment(registers, lookupTable, r, popSize)

    if (enabledExperiments[0]):
        # the default roulette wheel selection with a constant CProb, MProb, 80% retention rate
        try:
            ga = Ga(r,
                    popSize,
                    registers,
                    generationFunction=QASMPrimitiveInstruction,
                    minSize=minSize,
                    maxSize=maxSize)
            stats = ga.evolve(totalEpochs, probCrossover = CProb, probMutation= MProb, \
                        evaluationFunc = incDecExp.evaluationFunction, selectionFunc= incDecExp.rouletteWheelSelection, \
                        params = params)
        except Exception:
            traceback.print_exc()
        generateSummaries(stats=stats, experimentName="dec-none")

    if (enabledExperiments[1]):
        # decreasing CProb, MProb with default roulette wheel selection
        try:
            params = GAParameters(MProb, CProb, totalEpochs, decreaseM = True, decreaseC = True, \
                        MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch)
            ga = Ga(r,
                    popSize,
                    registers,
                    generationFunction=QASMPrimitiveInstruction,
                    minSize=minSize,
                    maxSize=maxSize)
            stats = ga.evolve(totalEpochs, probCrossover = CProb, probMutation= MProb, \
                        evaluationFunc = incDecExp.evaluationFunction, selectionFunc= incDecExp.rouletteWheelSelection, \
                        params = params)
        except Exception:
            traceback.print_exc()
        generateSummaries(stats=stats, experimentName="dec-MC")

    if (enabledExperiments[2]):
        try:
            # decreasing CProb, MProb with default roulette wheel selection but delta mutation func
            #params = GAParameters(MProb, CProb, totalEpochs, decreaseM = True, decreaseC = True, \
            #           MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch)

            #constant CProb, MProb with default roulette wheel selection but delta mutation func
            params = GAParameters(MProb, CProb, totalEpochs, decreaseM = False, decreaseC = False, \
                MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch)
            ga = Ga(r,
                    popSize,
                    registers,
                    generationFunction=QASMPrimitiveInstruction,
                    minSize=minSize,
                    maxSize=maxSize)
            stats = ga.evolve(totalEpochs, probCrossover = CProb, probMutation= MProb, \
                        evaluationFunc = incDecExp.evaluationFunction, selectionFunc= incDecExp.rouletteWheelSelection, \
                        mutationArgFunc = deltaMutationFunc, params = params)
        except Exception:
            traceback.print_exc()
        generateSummaries(stats=stats, experimentName="dec-rw")

    if (enabledExperiments[3]):
        try:
            # decreasing CProb, MProb with default roulette wheel selection but detal mutation func
            #params = GAParameters(MProb, CProb, totalEpochs, decreaseM = True, decreaseC = True, \
            # MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch, \
            # eliteRatio=eliteRatio)
            params = GAParameters(MProb, CProb, totalEpochs, decreaseM = False, decreaseC = False, \
                MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch, \
                eliteRatio=eliteRatio)
            ga = Ga(r,
                    popSize,
                    registers,
                    generationFunction=QASMPrimitiveInstruction,
                    minSize=minSize,
                    maxSize=maxSize)
            stats = ga.evolve(totalEpochs, probCrossover = CProb, probMutation= MProb, \
                        evaluationFunc = incDecExp.evaluationFunction, selectionFunc= incDecExp.elitismSelection, \
                        mutationArgFunc = deltaMutationFunc, params = params)
        except Exception:
            traceback.print_exc()
        generateSummaries(stats=stats, experimentName="dec-e")
    input("Press [enter] to continue.")
def incrementExperiment():
    """ 
    This is the main method for the increment problem 
    This problem is phrased as follows:
    given a set of registers, we will create a prepare statement corresponding to a value in superposition, such as 
    4, the increment op should output 50% for 1 and 5 correspondingly
    
    The setup is the same as what's depicted in : https://oreilly-qc.github.io/# (increment & decrement)
    but we will use a[5] instead of a[4] and scratch[1] in the preparestatement. Thus, wherever there's a scratch[0], 
    we will have a[4] instead. If you look at the test code in OpenQASMTest.py, the output should be the same.

    We will implement the experiment for 5 qubits (+1 qubit as scratch): 
    the first qubit is the min value within the circuit: x a[0] 
    (as in the prepareStatement)
    So the values in the lookup table are : 
    h a[1] (2^1) - {'00010': 0.5, '00100': 0.5}
    h a[2] (2^2) - {'00010': 0.5, '00110': 0.5}
    h a[3] (2^3) - {'00010': 0.5, '01010': 0.5}
    h a[4] (2^4) - {'00010': 0.5, '10010': 0.5}
    Note that the lowest value is 00010 = 2 because we wrote a value of 1 in x q[0].

    """
    #sets up entries in the lookup table
    lookupTable = [
        ('00010', '00100', "x q[0];\nh q[1];\nrz(0.785398163397448) q[1];\n"),
        ('00010', '00110', "x q[0];\nh q[2];\nrz(0.785398163397448) q[2];\n"),
        ('00010', '01010', "x q[0];\nh q[3];\nrz(0.785398163397448) q[3];\n"),
        ('00010', '10010', "x q[0];\nh q[4];\nrz(0.785398163397448) q[4];\n"),
    ]

    #this array makes it easy to control which experiment is to run by the sim
    enabledExperiments = [False, False, False, True]
    #default params
    params = GAParameters(MProb, CProb, totalEpochs)

    incDecExp = IncDecExperiment(registers, lookupTable, r, popSize)

    if (enabledExperiments[0]):
        # the default roulette wheel selection with a constant CProb, MProb, 80% retention rate
        try:
            ga = Ga(r,
                    popSize,
                    registers,
                    generationFunction=QASMPrimitiveInstruction,
                    minSize=minSize,
                    maxSize=maxSize)
            stats = ga.evolve(totalEpochs, probCrossover = CProb, probMutation= MProb, \
                        evaluationFunc = incDecExp.evaluationFunction, selectionFunc= incDecExp.rouletteWheelSelection, \
                        params = params)
        except Exception:
            traceback.print_exc()
        generateSummaries(stats=stats, experimentName="inc-none")

    if (enabledExperiments[1]):

        try:
            # decreasing CProb, MProb with default roulette wheel selection

            # params = GAParameters(MProb, CProb, totalEpochs, decreaseM = True, decreaseC = True, \
            #            MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch)

            #constant CProb, MProb with default roulette wheel selection
            params = GAParameters(MProb, CProb, totalEpochs, decreaseM = False, decreaseC = False, \
                        MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch)
            ga = Ga(r,
                    popSize,
                    registers,
                    generationFunction=QASMPrimitiveInstruction,
                    minSize=minSize,
                    maxSize=maxSize)
            stats = ga.evolve(totalEpochs, probCrossover = CProb, probMutation= MProb, \
                        evaluationFunc = incDecExp.evaluationFunction, selectionFunc= incDecExp.rouletteWheelSelection, \
                        params = params)
        except Exception:
            traceback.print_exc()
        generateSummaries(stats=stats, experimentName="inc-MC")

    if (enabledExperiments[2]):

        try:
            # decreasing CProb, MProb with default roulette wheel selection but delta mutation func
            #params = GAParameters(MProb, CProb, totalEpochs, decreaseM = True, decreaseC = True, \
            #            MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch)

            #constant cprob, mprob with default roulette wheel but delta mutation func
            params = GAParameters(MProb, CProb, totalEpochs, decreaseM = False, decreaseC = False, \
                        MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch)
            ga = Ga(r,
                    popSize,
                    registers,
                    generationFunction=QASMPrimitiveInstruction,
                    minSize=minSize,
                    maxSize=maxSize)
            stats = ga.evolve(totalEpochs, probCrossover = CProb, probMutation= MProb, \
                        evaluationFunc = incDecExp.evaluationFunction, selectionFunc= incDecExp.rouletteWheelSelection, \
                        mutationArgFunc = deltaMutationFunc, params = params)
        except Exception:
            traceback.print_exc()
        generateSummaries(stats=stats, experimentName="inc-rw")

    if (enabledExperiments[3]):

        try:
            # decreasing CProb, MProb with elitism selection but delta mutation func
            # params = GAParameters(MProb, CProb, totalEpochs, decreaseM = True, decreaseC = True, \
            # MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch, \
            # eliteRatio=eliteRatio)

            # constant CProb, MProb with elitism selection but delta mutation func
            params = GAParameters(MProb, CProb, totalEpochs, decreaseM = False, decreaseC = False, \
             MStartEpoch = mStartEpoch, MEndEpoch = mEndEpoch, CStartEpoch = cStartEpoch, CEndEpoch = cEndEpoch, \
             eliteRatio=eliteRatio)
            ga = Ga(r,
                    popSize,
                    registers,
                    generationFunction=QASMPrimitiveInstruction,
                    minSize=minSize,
                    maxSize=maxSize)
            stats = ga.evolve(totalEpochs, probCrossover = CProb, probMutation= MProb, \
                        evaluationFunc = incDecExp.evaluationFunction, selectionFunc= incDecExp.elitismSelection, \
                        mutationArgFunc = deltaMutationFunc, params = params)
        except Exception:
            traceback.print_exc()
        generateSummaries(stats=stats, experimentName="inc-e")
    input("Press [enter] to continue.")