예제 #1
0
    def __init__(self, num_reads=None, num_trials=None):

        self.domain = ['4', '6', '8', '10', '12', '14', '16', '18', '20']
        objective_functions = []
        for size in self.domain:
            objective_functions.append(
                QAPObjectiveFunction(dat_file='had' + size + '.dat'))
        if num_reads:
            self.num_reads = num_reads
        else:
            self.num_reads = 100

        sampler_kwargs = {'num_reads': self.num_reads}

        if num_trials:
            num_trials = num_trials
        else:
            num_trials = 100

        dwave_solver = TabuSampler()

        self.data = {
            'average': [],
            'standard deviation': [],
            'domain': self.domain,
            'domain with QUBO size': []
        }
        for objective_function in objective_functions:
            n_qap = objective_function.n
            s = SortingNetwork(n_qap)
            p = PermutationNetwork(n_qap)
            if s.depth <= p.depth:
                network = s
            else:
                network = p
            self.data['domain with QUBO size'].append('{} ({})'.format(
                n_qap, network.depth))
            unique_bin_val = []
            for trial in range(num_trials):
                binary_vals = []

                q = np.random.randint(0, 2, size=network.depth)
                qubo = LQUBO(objective_function=objective_function,
                             switch_network=network,
                             num_activation_vectors=network.depth)
                formed_qubo = qubo.form_lqubo(q=q)[0]

                response = dwave_solver.sample_qubo(formed_qubo,
                                                    **sampler_kwargs)
                reads = response.record
                for read in reads:
                    for num_occurrence in range(read[2]):
                        binary_vals.append(read[0])

                num_unique_binary = 0
                while len(binary_vals) != 0:
                    num_unique_binary += 1
                    delta_q = binary_vals[0]
                    binary_vals = remove_redundant_binaries(
                        binary_list=binary_vals, delta_switch=delta_q)

                unique_bin_val.append(num_unique_binary)

            self.data['average'].append(stat.mean(unique_bin_val))
            self.data['standard deviation'].append(stat.stdev(unique_bin_val))
예제 #2
0
class LocalQUBOIterativeSolver(Solver):
    """
    The Local-QUBO Solver uses a switch/permutation network to encode the QAP permutation
    in a bitstring.
    """
    def __init__(self,
                 objective_function=None,
                 dwave_sampler=None,
                 dwave_sampler_kwargs=None,
                 num_activation_vectors=None,
                 activation_vec_hamming_dist=1,
                 max_hd=None,
                 parse_samples=True,
                 experiment_type=None,
                 num_reads=None,
                 num_iters=None,
                 network_type='minimum'):
        super().__init__(objective_function=objective_function)

        # Initialize switch network:
        # The default behavior here is to choose the smaller of either permutation or
        # sorting networks for the given input size.
        self.n_obj = self.objective_function.n
        if network_type == 'sorting':
            self.network = SortingNetwork(self.n_obj)
        elif network_type == 'permutation':
            self.network = PermutationNetwork(self.n_obj)
        elif network_type == 'minimum':
            s = SortingNetwork(self.n_obj)
            p = PermutationNetwork(self.n_obj)
            if s.depth <= p.depth:
                self.network = s
            else:
                self.network = p
        else:
            raise TypeError('Network type {} not recognized'.format(str(network_type)))
        self.n_qubo = self.network.depth
        self.dwave_solver = None
        self.sampler_kwargs = None
        self.qpu = False

        # Initialize dwave sampler:
        if dwave_sampler == 'QPU':
            self.dwave_solver = EmbeddingComposite(DWaveSampler())
            self.qpu = True
            if dwave_sampler_kwargs:
                self.sampler_kwargs = dwave_sampler_kwargs
            else:
                self.sampler_kwargs = dict()
        elif dwave_sampler == 'SA':
            self.dwave_solver = SimulatedAnnealingSampler()
            if num_reads:
                self.sampler_kwargs = {
                    'num_reads': num_reads
                }
            else:
                self.sampler_kwargs = {
                    'num_reads': 25
                }
        elif dwave_sampler == 'Tabu':
            self.dwave_solver = TabuSampler()
            if num_reads:
                self.sampler_kwargs = {
                    'num_reads': num_reads
                }
            else:
                self.sampler_kwargs = {
                    'num_reads': 250
                }

        self.stopwatch = 0

        # Initialize type of experiment
        # When running a timed experiment there is a high number of iterations and a 30 sec wall clock
        # When running a iteration experiment there is a iteration limit of 30 and no wall clock
        if experiment_type == 'time_lim':
            self.n_iters = 1000
            self.time_limit = 30

        if experiment_type == 'iter_lim' and num_iters:
            self.n_iters = num_iters
            self.time_limit = False
        else:
            self.n_iters = 50
            self.time_limit = False

        if max_hd:
            self.max_hd = max_hd
        else:
            self.max_hd = 0

        if num_activation_vectors:
            self.num_activation_vec = num_activation_vectors
        else:
            self.num_activation_vec = self.n_qubo

        self.form_qubo = LQUBO(objective_function=self.objective_function,
                               switch_network=self.network,
                               max_hamming_dist=self.max_hd,
                               num_activation_vectors=self.num_activation_vec,
                               activation_vec_hamming_dist=activation_vec_hamming_dist)

        self.solution = self.objective_function.min_v

        if parse_samples:
            self.selection = CheckAndSelect
        else:
            self.selection = Select

    def minimize_objective(self):
        start_code = time.time()

        q = np.random.randint(0, 2, size=self.n_qubo)
        p = self.network.permute(q)
        v = self.objective_function(p)
        delta_q = None

        data_dict = dict()
        data_dict['q_vec'] = [q]
        data_dict['p_vec'] = [p]
        data_dict['v_vec'] = [v]
        data_dict['delta_q_vec'] = [['random switch setting']]

        # Initialize bitstring

        begin_loop = time.time()
        self.stopwatch = begin_loop - start_code
        for iteration in range(self.n_iters):

            # If there is a timing limit and the stopwatch is greater than the timing limit then break
            if self.time_limit and self.time_limit <= self.stopwatch:
                break
            start_iteration = time.time()

            # Build the Local QUBO by creating all delta_q's that are hamming distance 2
            # from the current q.  For each of those, the new q gives a permutation (via
            # the network encoding) and hence a new objective function value.  The deltas
            # in the objective function values are what populate the qubo.
            qubo = self.form_qubo.form_lqubo(q=q)[0]
            delta_q_basis = self.form_qubo.form_lqubo(q=q)[1]

            # Solve the QUBO for delta_q
            if self.qpu:
                self.sampler_kwargs.update({
                    'chain_strength': 1.5*abs(max(qubo.values(), key=abs)),
                    'num_reads': 1000
                })

            retries = 10
            while retries > 0:
                try:
                    response = self.dwave_solver.sample_qubo(qubo, **self.sampler_kwargs)
                    select_response = self.selection(objective_function=self.objective_function,
                                                     switch_network=self.network,
                                                     response_record=response.record,
                                                     delta_q_basis=delta_q_basis,
                                                     data_dict_qvecs=data_dict['q_vec'],
                                                     current_q=q).select()
                    q = select_response[0]
                    p = select_response[1]
                    v = select_response[2]
                    delta_q = select_response[3]
                    break
                except ValueError:
                    print('retrying QUBO...')
                    retries -= 1

            if retries == 0:
                q = np.random.randint(0, 2, size=self.n_qubo)
                p = self.network.permute(q)
                v = self.objective_function(p)
                delta_q = None

                data_dict['q_vec'] = [q]
                data_dict['p_vec'] = [p]
                data_dict['v_vec'] = [v]
                data_dict['delta_q_vec'] = [['random switch setting']]

            data_dict['q_vec'].append(q)
            data_dict['p_vec'].append(p)
            data_dict['v_vec'].append(v)
            data_dict['delta_q_vec'].append(delta_q)

            end_iteration = time.time()
            self.stopwatch += end_iteration - start_iteration

        end_code = time.time()
        timing_code = end_code - start_code

        lqubo_ans = min(data_dict['v_vec'])
        num_iters = len(data_dict['v_vec']) - 1

        if lqubo_ans == self.solution:
            obtain_optimal = 1
            percent_error = 0
        else:
            percent_error = abs(self.solution - lqubo_ans) / self.solution * 100
            obtain_optimal = 0

        return lqubo_ans, percent_error, obtain_optimal, timing_code, num_iters, data_dict, data_dict['v_vec']
예제 #3
0
class PopulationLQUBOSolver(Solver):
    """
    The Local-QUBO Solver uses a switch/permutation network to encode the QAP permutation
    in a bitstring.
    """
    def __init__(self,
                 objective_function=None,
                 dwave_sampler=None,
                 dwave_sampler_kwargs=None,
                 experiment_type=None,
                 population_size=1,
                 num_reads=1,
                 num_iters=None):
        super().__init__(objective_function=objective_function)

        self.n_obj = self.objective_function.n

        self.n_qubo = self.n_obj - 1
        self.dwave_solver = None
        self.sampler_kwargs = None
        self.qpu = False
        self.population_size = population_size
        self.num_reads = num_reads

        # Initialize dwave sampler:
        if dwave_sampler == 'QPU':
            self.dwave_solver = EmbeddingComposite(DWaveSampler())
            self.qpu = True
            if dwave_sampler_kwargs:
                self.sampler_kwargs = dwave_sampler_kwargs
            else:
                self.sampler_kwargs = dict()
        elif dwave_sampler == 'SA':
            self.dwave_solver = SimulatedAnnealingSampler()
            if num_reads:
                self.sampler_kwargs = {'num_reads': num_reads}
            else:
                self.sampler_kwargs = {'num_reads': 25}
        elif dwave_sampler == 'Tabu':
            self.dwave_solver = TabuSampler()
            if num_reads:
                self.sampler_kwargs = {'num_reads': num_reads}
            else:
                self.sampler_kwargs = {'num_reads': 250}

        self.stopwatch = 0

        if experiment_type == 'time_lim':
            self.n_iters = 1000
            self.time_limit = 30

        if experiment_type == 'iter_lim' and num_iters:
            self.n_iters = num_iters
            self.time_limit = False
        else:
            self.n_iters = 50
            self.time_limit = False

        self.form_qubo = NewLQUBO(objective_function=self.objective_function)

        self.solution = self.objective_function.min_v

    def minimize_objective(self):
        start_code = time.time()

        population = initialize_population(
            population_size=self.population_size, n_obj=self.n_obj)
        evaluated_fitness = evaluate_fitness(
            population=population, objective_function=self.objective_function)
        max_fit = max_fitness(fitness_array=evaluated_fitness)
        min_fit = min_fitness(fitness_array=evaluated_fitness)
        avg_fit = avg_fitness(fitness_array=evaluated_fitness)

        data_dict = dict()
        data_dict['max_fitness'] = [max_fit]
        data_dict['min_fitness'] = [min_fit]
        data_dict['avg_fitness'] = [avg_fit]
        data_dict['population'] = [population]

        form_lqubo_timing = []
        solve_lqubo_timing = []

        # Initialize bitstring

        begin_loop = time.time()
        self.stopwatch = begin_loop - start_code
        for iteration in range(self.n_iters):

            # If there is a timing limit and the stopwatch is greater than the timing limit then break
            if self.time_limit and self.time_limit <= self.stopwatch:
                break
            start_iteration = time.time()

            total_lqubo_population = []
            for perm in population:
                start_form_lqubo = time.time()
                lqubo = self.form_qubo.form_lqubo(p=perm)
                end_form_lqubo = time.time()
                form_lqubo_timing.append(end_form_lqubo - start_form_lqubo)

                # Solve the LQUBO for new permutations
                if self.qpu:
                    self.sampler_kwargs.update({
                        'chain_strength':
                        1.5 * abs(max(lqubo.values(), key=abs)),
                        'num_reads':
                        1000
                    })

                start_solve_lqubo = time.time()
                response = self.dwave_solver.sample_qubo(
                    lqubo, **self.sampler_kwargs)
                end_solve_lqubo = time.time()
                solve_lqubo_timing.append(end_solve_lqubo - start_solve_lqubo)

                lqubo_population = CollectLQUBOPopulation(
                    objective_function=self.objective_function,
                    response_record=response.record,
                    current_perm=perm).collect_population()
                total_lqubo_population += lqubo_population

            tournament_selection = BestFitPopulation(
                final_population_size=self.population_size,
                lqubo_population=total_lqubo_population,
                previous_population=population,
                objective_function=self.objective_function)

            # Compile new population from tournament selection
            population = tournament_selection.return_population()
            evaluated_fitness = evaluate_fitness(
                population=population,
                objective_function=self.objective_function)
            max_fit = max_fitness(fitness_array=evaluated_fitness)
            min_fit = min_fitness(fitness_array=evaluated_fitness)
            avg_fit = avg_fitness(fitness_array=evaluated_fitness)

            data_dict['max_fitness'].append(max_fit)
            data_dict['min_fitness'].append(min_fit)
            data_dict['avg_fitness'].append(avg_fit)
            data_dict['population'].append(population)

            end_iteration = time.time()
            self.stopwatch += end_iteration - start_iteration

        end_code = time.time()
        timing_code = end_code - start_code
        average_form_lqubo = np.average(form_lqubo_timing)
        average_solve_lqubo = np.average(solve_lqubo_timing)

        lqubo_ans = min(data_dict['max_fitness'])
        num_iters = len(data_dict['max_fitness']) - 1

        if lqubo_ans == self.solution:
            obtain_optimal = 1
            percent_error = 0
        else:
            percent_error = abs(self.solution -
                                lqubo_ans) / self.solution * 100
            obtain_optimal = 0

        return lqubo_ans, percent_error, obtain_optimal, timing_code, num_iters, data_dict, data_dict['max_fitness'], \
               average_form_lqubo, average_solve_lqubo, data_dict, data_dict['avg_fitness'], data_dict['min_fitness']