Some ideas on AI and ML.

I do strange and interesting things with python...

Generally with qiskit, numpy, scipy, etc.. I really like to use matplotlib for visualizations here and there.

I research the intersections of quantum computing and artifical intelligence. Riding the dimensional barriers with my code, and inferring probability.

I have been programming since mid 1980. BASIC, 6502 assembly, on and on. Until it all became a blurr and I find myself writing programs in C, adding processor specific assembly, maybe throwing in some other stuff here and there for added randomness. Made my first OS, this one for the Apple ][gs in the 80s. It was a horrible kludge of assembler, too many subroutines. I'm amazed it worked with all the cycles it used unnecessarily.

After a while, all the languages tend to blend together. Syntaxes become similar, you index man pages in your mind. "Oh, I know where to find my notes on that.." And so on. 

A side effect of coding a lot is that you end up having dreams about it. Trying to find your keyboard in your sleep, strange and awkward conversations that you don't remember in the middle of the night, restlessness.. And then suddenly waking up and just having to write that bit of code because it's the solution to a problem you've been thinking about for the last day or so.

Or even weirder, you wake up and have to write this code because it came to you in a dream...

You run the code and it does some weird stuff. But, then it becomes relevant to the thing you've been working on for years, and managed to make some strides in recently. 

Strange things are afoot at the Circle K...  

Lately, I've been trying to work towards figuring out P=NP.

Some success there, but, if you're into python like I am, you want to do more.

However, I am learning one thing above all else:

If people don't know you have that special piece of paper, your opinion means nothing. 

Nothing at all.

    qi[4] = -N1_x1 + N3_x1

    qi[2] = -N1_t + N2_t

    qi[1] = -N1_x1 + N2_x1

    qi[10] = qi[2] * qi[7] - qi[1] * qi[8]

    qi[11] = -(qi[2] * qi[4]) + qi[1] * qi[8]

    qi[18] = qi[0] * qi[9] + qi[3] * qi[10] * qi[6]

    qi[19] = 1 / qi[18]

    qi[12] = qi[5] * qi[6] - qi[3] * qi[8]

    qi[21] = qi[12] * qi[19]

    qi[15] = -(qi[4] * qi[6]) + qi[3] * qi[7]

    qi[22] = qi[15] * qi[19]

    qi[23] = qi[10] * qi[19]

    qi[13] = -(qi[2] * qi[6]) + qi[0] * qi[8]

    qi[24] = qi[13] * qi[19]

    qi[16] = qi[1] * qi[6] - qi[0] * qi[7]

    qi[25] = qi[16] * qi[19]

    qi[26] = qi[11] * qi[19]

    qi[14] = qi[2] * qi[3] - qi[0] * qi[5]

    qi[27] = qi[14] * qi[19]

    qi[17] = -(qi[1] * qi[3]) + qi[0] * qi[4]

    qi[28] = qi[17] * qi[19]

    qi[29] = -qi[20] - qi[23] - qi[26]

    qi[30] = -qi[21] - qi[24] - qi[27]

    qi[31] = -qi[22] - qi[25] - qi[28]


You could literally be as smart as Tony Stark, build an Iron Man suit in Real Life, and once they find out you don't have a doctorate in something. You're suddenly a thief, a fake, a hack, a plagiarist, etc. 

I mean, of course, I don't have that fancy degree yet, how could I *possibly* understand ANYTHING at all?

So many things in our society exclude very talented people. People who may not fit into whatever mold you want them to be in. You don't put a finished product into a mold, your fancy schooling should have told you that, but apparently your education failed you there.

Some random P=NP exploratory code:

from qiskit import Aer, QuantumCircuit, transpile

from qiskit.providers.aer import AerSimulator

from qiskit_algorithms.amplitude_amplifiers import AmplificationProblem, Grover

from concurrent.futures import ThreadPoolExecutor

import random

import math


def distance(city1, city2):

    return ((city1[0] - city2[0]) ** 2 + (city1[1] - city2[1]) ** 2) ** 0.5


def total_distance(path):

    distance_sum = 0

    for i in range(len(path)):

        base_distance = distance(cities[path[i]], cities[path[i - 1]])

        if weather_conditions[path[i]] == "storms":

            base_distance *= 1.2

        elif weather_conditions[path[i]] == "cloudy":

            base_distance *= 1.1

        if traffic_conditions[path[i]] == "heavy":

            base_distance *= 1.3

        elif traffic_conditions[path[i]] == "light":

            base_distance *= 1.1

        distance_sum += base_distance

    fuel_cost = sum(fuel_costs[path[i]] for i in range(len(path)))

    total_profit_over_cost = sum(profit_over_cost[path[i]] for i in range(len(path)))

    return distance_sum + fuel_cost - total_profit_over_cost


def simulated_annealing(initial_path, initial_temp, cooling_rate):

    current_path = initial_path[:]

    current_distance = total_distance(current_path)

    best_path = current_path[:]

    best_distance = current_distance

    temp = initial_temp

    while temp > 1:

        swap_idx1, swap_idx2 = random.sample(range(num_cities), 2)

        neighbor_path = current_path[:]

        neighbor_path[swap_idx1], neighbor_path[swap_idx2] = neighbor_path[swap_idx2], neighbor_path[swap_idx1]

        neighbor_distance = total_distance(neighbor_path)

        if neighbor_distance < current_distance or random.random() < math.exp((current_distance - neighbor_distance) / temp):

            current_path = neighbor_path

            current_distance = neighbor_distance

            if current_distance < best_distance:

                best_path = current_path[:]

                best_distance = current_distance

        temp *= cooling_rate

    return best_path, best_distance


def grover_oracle():

    n = int(math.ceil(math.log2(len(population))))

    qc = QuantumCircuit(n, name='Oracle')

    best_path = min(population, key=total_distance)

    best_path_index = population.index(best_path)

    qc.x(list(range(n)))

    qc.mct(list(range(n-1)), n-1)

    qc.x(list(range(n)))

    return qc


def use_grover():

    n = int(math.ceil(math.log2(len(population))))

    simulator = AerSimulator()

    oracle = grover_oracle()

    problem = AmplificationProblem(oracle=oracle)

    grover = Grover(iterations=1)

    grover_circuit = grover.construct_circuit(problem)

    grover_circuit.measure_all()

    t_qc = transpile(grover_circuit, simulator)

    result = simulator.run(t_qc).result()

    counts = result.get_counts()

    top_measurement = max(counts, key=counts.get)

    index = int(top_measurement, 2)

    return population[index]


def run_algorithm(method):

    if method == 'GA':

        parent1, parent2 = random.choices(population, k=2)

        crossover_point = random.randint(1, num_cities - 1)

        child = parent1[:crossover_point] + [x for x in parent2 if x not in parent1[:crossover_point]]

        if random.random() < mutation_rate:

            swap_idx1, swap_idx2 = random.sample(range(num_cities), 2)

            child[swap_idx1], child[swap_idx2] = child[swap_idx2], child[swap_idx1]

        return child

    elif method == 'SA':

        parent = random.choice(population)

        child, _ = simulated_annealing(parent, 1000, 0.99)

        return child

    else:

        parent = use_grover()

        return parent[:]


num_cities = 4

cities = [(random.randint(0, 100), random.randint(0, 100)) for _ in range(num_cities)]

fuel_costs = [random.randint(1, 10) for _ in range(num_cities)]

profit_over_cost = [random.uniform(1, 3) for _ in range(num_cities)]

weather_conditions = [random.choice(["sunny", "cloudy", "storms"]) for _ in range(num_cities)]

traffic_conditions = [random.choice(["clear", "light", "heavy"]) for _ in range(num_cities)]

population_size = 16

population = [random.sample(range(num_cities), num_cities) for _ in range(population_size)]

mutation_rate = 0.2


with ThreadPoolExecutor() as executor:

    methods = ['GA', 'SA', 'Grover']

    new_population = list(executor.map(run_algorithm, methods))


population = new_population

best_path = min(population, key=total_distance)

print("Best path:", best_path)

print("Total distance:", total_distance(best_path))