import pandas as pd
import torch
from src.common.tools import model_device
from src.callback.progressbar import ProgressBar
from configs.basic_config import config

class Generator(object):
    def __init__(self, model, tok, logger, n_gpu, input_len=None):
        self.model = model
        self.tok = tok
        self.logger = logger
        self.input_len = input_len
        self.model, self.device = model_device(n_gpu=n_gpu, model=self.model)

    def generate_example(self,
                         data,
                         sampler,
                         max_length,
                         relation_index=None,
                         repetition_penalty=None,
                         no_repeat_ngram_size=None,
                         length_penalty=None,
                         num_return_sequences=1,
                         save_prefix=None,
                         add_cls=False):

        pbar = ProgressBar(n_total=len(data), desc='Testing')
        print_interval = len(data) // 10

        all_generated_sents = []
        all_label_sents = []
        all_input_sents = []
        all_encoder_states = []
        all_cls_ids = []
        all_self_attention = []
        all_cross_attentions = []
        all_encoder_attentions = []
        all_input_ids = []
        all_output_ids = []
        all_input_mask = []

        relations = config['relations']

        with torch.no_grad():
            for step, batch in enumerate(data):
                batch = tuple(t.to(self.device) for t in batch)
                input_ids, input_mask, segment_ids, label_ids, labels_masks, cls_label = batch

                # [bsz, ln]
                batch_size, ln = input_ids.shape

                char_relation = self.tok(relations, padding=True, return_length=True, return_tensors='pt')
                relation_ids = char_relation["input_ids"].to(input_ids.device)
                relation_mask = char_relation["attention_mask"].to(input_ids.device)

                dim = relation_ids.size(0)

                kg_input_ids = []
                for i in range(batch_size):
                    cur_kg_input_ids = []
                    cur_input_ids = input_ids[i]
                    cur_ln = input_mask[i].sum()
                    for j in range(dim):
                        char_ln = relation_mask[j].sum()
                        cur_relation_ids = relation_ids[j]
                        if cur_ln + char_ln > ln:
                            it = torch.cat([cur_input_ids[:ln - char_ln - 1], cur_input_ids[cur_ln - 1:cur_ln],
                                            cur_relation_ids[:char_ln]],
                                           dim=-1).unsqueeze(0)
                            cur_kg_input_ids.append(it)
                        else:
                            it = torch.cat(
                                [cur_input_ids[:cur_ln], cur_relation_ids[:char_ln], cur_input_ids[cur_ln + char_ln:]],
                                dim=-1).unsqueeze(0)
                            cur_kg_input_ids.append(it)
                    kg_input_ids.append(torch.cat(cur_kg_input_ids, dim=0).unsqueeze(0))
                kg_input_ids = torch.cat(kg_input_ids, dim=0)
                kg_input_masks = kg_input_ids.ne(self.tok.pad_token_id).int()

                # Encoder the story
                encoder_outputs = self.model.encoder(input_ids=input_ids,
                                                     input_masks=input_mask,
                                                     segment_ids=segment_ids,
                                                     kg_input_ids=kg_input_ids,
                                                     kg_input_masks=kg_input_masks,
                                                     )

                encoder_hidden_states = encoder_outputs["encoder_hidden_states"]
                encoder_attentions = encoder_outputs["encoder_attention_mask"]

                if relation_index is not None:
                    encoder_attentions[:, :dim] = 0
                    encoder_attentions[:, relation_index] = 1

                decoder_input_ids = torch.ones([batch_size, 1], dtype=torch.long) * self.tok.bos_token_id
                decoder_input_ids = decoder_input_ids.to(self.device)
                batch_data = {}
                batch_data["input_ids"] = decoder_input_ids
                batch_data["input_attention_mask"] = torch.ones_like(decoder_input_ids, dtype=torch.long)
                batch_data["encoder_hidden_states"] = encoder_hidden_states
                batch_data["encoder_padding_mask"] = encoder_attentions

                decoder = self.model.decoder

                sampling_result = sampler.generate_sequence(batch_data,
                                                            decoder,
                                                            start_idx=1,
                                                            end_len=max_length,
                                                            repetition_penalty=repetition_penalty,
                                                            no_repeat_ngram_size=no_repeat_ngram_size,
                                                            length_penalty=length_penalty,
                                                            num_return_sequences=num_return_sequences)
                seqs = sampling_result["beams"]
                # decoder_hidden_states = sampling_result["hidden_states"]
                all_generated_sents += seqs

                label_sent = self.tok.batch_decode(label_ids, skip_special_tokens=True)
                all_label_sents += label_sent

                input_sent = self.tok.batch_decode(input_ids, skip_special_tokens=True)
                all_input_sents += input_sent

                all_encoder_states.append(encoder_hidden_states)

                output_ids = sampling_result["output_ids"]
                assert output_ids.size(0) == batch_size
                output_mask = (1 - output_ids.eq(self.tok.pad_token_id).int()).to(self.device)

                decoder_outputs = decoder(input_ids=output_ids,
                                          attention_mask=output_mask,
                                          encoder_hidden_states=encoder_hidden_states,
                                          encoder_attention_mask=encoder_attentions,
                                          past_key_values=None,
                                          inputs_embeds=None,
                                          use_cache=None,
                                          output_attentions=True,
                                          output_hidden_states=None,
                                          return_dict=True, )

                attentions = decoder_outputs["attentions"]  # list of [bsz, self.num_heads, tgt_len, src_len]
                cross_attentions = decoder_outputs[
                    "cross_attentions"]  # list of [bsz, self.num_heads, tgt_len, src_len]

                # print(f"attention from last decoder layer: {attentions[-1].size()}")
                # print(f"cross attention from last encoder layer: {cross_attentions[-1].size()}")
                # print(f"attention from last encoder layer: {encoder_attentions[-1].size()}")
                all_encoder_attentions.append(encoder_attentions[0].cpu().detach())
                all_self_attention.append(attentions[0].cpu().detach())
                all_cross_attentions.append(cross_attentions[0].cpu().detach())
                all_input_ids.append(input_ids.cpu().detach())
                all_output_ids.append(output_ids.cpu().detach())
                all_input_mask.append(input_mask.cpu().detach())

                if add_cls:
                    decoder_hidden_states = decoder_outputs["hidden_states"]  # [bsz, ln, E]
                    eos_hidden_states = []
                    eos_index = torch.sum(output_mask, dim=1) - 2  # [bsz]
                    batch_size = eos_index.size(0)
                    for i in range(batch_size):
                        eos_hidden_states.append(decoder_hidden_states[i, eos_index[i], :])
                    eos_hidden_states = torch.cat([x.unsqueeze(0) for x in eos_hidden_states])
                    cls_logits = self.model.classification_head(eos_hidden_states)  # [bsz, num_labels]
                    cls_ids = torch.argmax(cls_logits.softmax(dim=-1), dim=-1)
                    all_cls_ids.append(cls_ids)

                if (step + 1) % max(1, print_interval) == 0:
                    show_info = pbar(step=step)
                    self.logger.info(show_info)

            data = {"input_ids": all_input_ids,
                    "input_mask": all_input_mask,
                    "output_ids": all_output_ids,
                    "encoder_attentions": all_encoder_attentions,
                    "self_attention": all_self_attention,
                    "cross_attentions": all_cross_attentions
                    }

            # file_path = f"test_attentions_layer_0_{self.args.data_name}.pkl"
            # import pickle
            # with open(file_path, 'wb') as f:
            #     pickle.dump(data, f)

            if save_prefix is not None:
                columns = ["input", "generated", "reference"]
                # print(f"all_generated_sents: {len(all_generated_sents)} -- all_label_sents: {len(all_label_sents)}")
                df = pd.DataFrame(columns=columns)
                df["input"] = all_input_sents
                df["generated"] = all_generated_sents
                df["reference"] = all_label_sents
                if len(all_cls_ids) != 0:
                    df["cls_id"] = torch.cat(all_cls_ids, dim=0).cpu().detach().tolist()
                df.to_csv(f"{save_prefix}")

                self.logger.info(f"save sentences in csv files: {save_prefix}. Done!")

            if 'cuda' in str(self.device):
                torch.cuda.empty_cache()

        return all_label_sents, all_generated_sents, all_encoder_states, all_cls_ids

    def generate_explanation(self,
                             data,
                             KG_model,
                             sampler,
                             max_length,
                             relations=None,
                             repetition_penalty=None,
                             no_repeat_ngram_size=None,
                             length_penalty=None,
                             save_prefix=None,
                             KG_only=False,
                             num_return_sequences=1):

        pbar = ProgressBar(n_total=len(data), desc='Testing')
        print_interval = len(data) // 10

        all_generated_sents = []
        all_label_sents = []
        all_input_sents = []
        all_encoder_states = []
        all_cls_ids = []

        relations = relations if relations is not None else config['relations']

        with torch.no_grad():
            for step, batch in enumerate(data):
                batch = tuple(t.to(self.device) for t in batch)
                input_ids, input_mask, segment_ids, label_ids, labels_masks, labels_segment_ids, cls_label = batch

                # [bsz, ln]
                batch_size, ln = input_ids.shape

                char_relation = self.tok(relations, padding=True, return_length=True, return_tensors='pt')
                relation_ids = char_relation["input_ids"].to(input_ids.device)
                relation_mask = char_relation["attention_mask"].to(input_ids.device)

                dim = relation_ids.size(0)

                kg_input_ids = []
                for i in range(batch_size):
                    cur_kg_input_ids = []
                    cur_input_ids = input_ids[i]
                    cur_ln = input_mask[i].sum()
                    for j in range(dim):
                        char_ln = relation_mask[j].sum()
                        cur_relation_ids = relation_ids[j]
                        if cur_ln + char_ln > ln:
                            it = torch.cat([cur_input_ids[:ln - char_ln - 1], cur_input_ids[cur_ln - 1:cur_ln],
                                            cur_relation_ids[:char_ln]],
                                           dim=-1).unsqueeze(0)
                            cur_kg_input_ids.append(it)
                        else:
                            it = torch.cat(
                                [cur_input_ids[:cur_ln], cur_relation_ids[:char_ln], cur_input_ids[cur_ln + char_ln:]],
                                dim=-1).unsqueeze(0)
                            cur_kg_input_ids.append(it)
                    kg_input_ids.append(torch.cat(cur_kg_input_ids, dim=0).unsqueeze(0))
                kg_input_ids = torch.cat(kg_input_ids, dim=0).to(self.device)
                kg_input_masks = kg_input_ids.ne(self.tok.pad_token_id).int().to(self.device)

                # Encoder the story
                if KG_only:
                    encoder = KG_model.get_encoder().to(self.device)
                    encoder_outputs = encoder(input_ids=kg_input_ids.reshape([batch_size * dim, ln]),
                                              attention_mask=kg_input_masks.reshape([batch_size * dim, ln]),
                                              inputs_embeds=None,
                                              output_attentions=None,
                                              output_hidden_states=None,
                                              return_dict=None, )
                    KG_hidden_states = encoder_outputs[0]
                else:
                    encoder_outputs = self.model.encoder(input_ids=input_ids,
                                                         input_masks=input_mask,
                                                         segment_ids=segment_ids,
                                                         kg_input_ids=kg_input_ids,
                                                         kg_input_masks=kg_input_masks,
                                                         )

                    KG_hidden_states = encoder_outputs["kg_hidden_states"]  # [bsz, dim, ln, E]

                bsz, dim, ln = kg_input_masks.size()

                decoder_input_ids = torch.ones([batch_size * dim, 1], dtype=torch.long) * self.tok.bos_token_id
                decoder_input_ids = decoder_input_ids.to(self.device)
                batch_data = {}
                batch_data["input_ids"] = decoder_input_ids
                batch_data["input_attention_mask"] = torch.ones_like(decoder_input_ids, dtype=torch.long).to(
                    self.device)
                batch_data["encoder_hidden_states"] = KG_hidden_states.reshape([batch_size * dim, ln, -1]).to(
                    self.device)
                batch_data["encoder_padding_mask"] = kg_input_masks.reshape([batch_size * dim, ln]).to(self.device)

                decoder = KG_model.to(self.device)

                sampling_result = sampler.generate_sequence(batch_data,
                                                            decoder,
                                                            start_idx=1,
                                                            end_len=max_length,
                                                            repetition_penalty=repetition_penalty,
                                                            no_repeat_ngram_size=no_repeat_ngram_size,
                                                            length_penalty=length_penalty,
                                                            bart_model=True,
                                                            num_return_sequences=num_return_sequences)
                seqs = sampling_result["beams"]

                # decoder_hidden_states = sampling_result["hidden_states"]
                dim = dim * num_return_sequences
                seqs_results = []
                for i in range(batch_size):
                    batch_seqs = seqs[i * dim:(i + 1) * dim]
                    batch_seqs_list = []
                    for j in range(int(dim / num_return_sequences)):
                        batch_seqs_list.append(
                            '|'.join(batch_seqs[j * num_return_sequences: (j + 1) * num_return_sequences]))
                    # print(f"batch_seqs_list: {len(batch_seqs_list)},\n {batch_seqs_list}")
                    seqs_results.append(batch_seqs_list)
                all_generated_sents += seqs_results

                input_sent = self.tok.batch_decode(input_ids, skip_special_tokens=True)
                all_input_sents += input_sent

                output_ids = sampling_result["output_ids"]
                assert output_ids.size(0) == batch_size * dim

                if (step + 1) % max(1, print_interval) == 0:
                    show_info = pbar(step=step)
                    self.logger.info(show_info)

            if save_prefix is not None:
                if "csv" in save_prefix:
                    df = pd.DataFrame(all_generated_sents, columns=relations)
                    df.to_csv(f"{save_prefix}")
                else:
                    assert "pkl" in save_prefix
                    import pickle
                    with open(save_prefix, 'wb') as f:
                        pickle.dump({"input": all_input_sents,
                                     "generated": all_generated_sents}, f)

                self.logger.info(f"save sentences in csv files: {save_prefix}. Done!")

            if 'cuda' in str(self.device):
                torch.cuda.empty_cache()

        return all_label_sents, all_generated_sents, all_encoder_states, all_cls_ids


"""
Leia 5 valores Inteiros. A seguir mostre quantos valores digitados foram pares, quantos valores digitados foram ímpares, quantos valores digitados foram positivos e quantos valores digitados foram negativos.
Entrada

O arquivo de entrada contém 5 valores inteiros quaisquer.
Saída

Imprima a mensagem conforme o exemplo fornecido, uma mensagem por linha, não esquecendo o final de linha após cada uma.
"""
#Criação da lista onde ficarão as entradas.
valores = []
#Sistema para a entrada de 5 elementos na lista "valores".
for i in range(5):
    valores.append(int(input()))
#Dicionário onde ficam os contadores de números pares, ímpares, positivos e negativos
contadores = {"pares": 0, "impares": 0, "positivos": 0, "negativos": 0}
#For para avaliar cada número da lista "valores" e adicionarem pontos nos
#contadores dependendo do resultado
for i in valores:
    if i % 2 == 0:
        contadores["pares"] += 1
    else:
        contadores["impares"] += 1
    if i > 0:
        contadores["positivos"] += 1
    elif i < 0:
        contadores["negativos"] += 1
#Saída dos dados
print(f'{contadores["pares"]} valor(es) par(es)')
print(f'{contadores["impares"]} valor(es) impar(es)')
print(f'{contadores["positivos"]} valor(es) positivo(s)')
print(f'{contadores["negativos"]} valor(es) negativo(s)')

Iniciante/1066 - Pares, Ímpares, Positivos e Negativos.py


from odoo import api, fields, models

class ProductTemplate(models.Model):
    _inherit = "product.template"

    @api.multi
    def action_fix_uom_consistency(self):
        for rec in self:
            self.env['stock.move'].search(
                ['product_tmpl_id', '=', rec.id],
                ['product_uom.category_id.id', '!=', rec.id],
            )


import setuptools

import versioneer

DESCRIPTION_FILES = ["pypi-intro.rst"]

long_description = []
import codecs
for filename in DESCRIPTION_FILES:
    with codecs.open(filename, 'r', 'utf-8') as f:
        long_description.append(f.read())
long_description = "\n".join(long_description)

setuptools.setup(
    name = "root-solver",
    version = versioneer.get_version(),
    packages = setuptools.find_packages('src'),
    package_dir = {'': 'src'},
    install_requires = [
        "numpy",
    ],
    python_requires = '>=3.4',
    author = "James Tocknell",
    author_email = "aragilar@gmail.com",
    description = "Root solver for polynomial equations",
    long_description = long_description,
    license = "3-clause BSD",
    keywords = "root solver",
    url = "https://root-solver.readthedocs.io",
    project_urls={
        'Documentation': 'https://root-solver.readthedocs.io',
        'Source': 'https://github.com/aragilar/root-solver/',
        'Tracker': 'https://github.com/aragilar/root-solver/issues',
    },
    classifiers=[
        'Development Status :: 3 - Alpha',
        'Intended Audience :: Developers',
        'Intended Audience :: Science/Research',
        'License :: OSI Approved :: BSD License',
        'Topic :: Scientific/Engineering',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: 3 :: Only',
    ],
    cmdclass=versioneer.get_cmdclass(),
)


import asyncio
import logging
import threading
from typing import List

from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
from starlette.websockets import WebSocket, WebSocketDisconnect

from .saver import Saver
from .transport import Transfer, InputData

logging.basicConfig(level=logging.INFO)

app = FastAPI()

transfer = Transfer()
saver = Saver()

class WebSocketSender:
    clients: [WebSocket] = []
    messages: [InputData] = []
    is_on_thread = False

    async def send(self, data):
        for client in self.clients.copy():
            try:
                await client.send_json({"data": data})
            except (WebSocketDisconnect, RuntimeError):
                try:
                    self.clients.remove(client)
                except ValueError:
                    pass

    async def thread_async(self):
        if self.is_on_thread:
            return
        else:
            self.is_on_thread = True

        while True:
            if self.messages:
                messages = [self.messages.pop() for _ in range(len(self.messages))]
                await self.send(messages)
                await asyncio.sleep(0.5)

class Messages:
    messages: List[InputData] = []

web_socket_sender = WebSocketSender()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.on_event("startup")
async def startup():
    transfer.callbacks.append(saver.save)
    transfer.callbacks.append(web_socket_sender.messages.append)
    transfer.callbacks.append(Messages.messages.append)
    threading.Thread(target=transfer.thread, daemon=True).start()

@app.on_event("shutdown")
def shutdown():
    transfer.is_on = False
    logging.basicConfig(level=logging.DEBUG)
    transfer.callbacks.remove(saver.save)
    transfer.callbacks.remove(web_socket_sender.messages.append)
    transfer.callbacks.remove(Messages.messages.append)
    saver.close()

@app.websocket("/ws")
async def ws(websocket: WebSocket):
    await websocket.accept()
    web_socket_sender.clients.append(websocket)
    await web_socket_sender.thread_async()

@app.get("/messages")
async def list_messages():
    return Messages.messages


from art import logo

def resources_sufficient(order_ingredients):
    """Returns True if the drink can be made, returns False if resources are insufficient"""
    for item in order_ingredients:
        if order_ingredients[item] > resources[item]:
            print(f"Sorry there is not enough {item}. Please make another choice.")
            return False
    return True

def process_coins():
    """Returns the total of coins received from the customer"""
    print("Please insert coins.")
    total = int(input("how many quarters? ")) * 0.25
    total += int(input("how many dimes? ")) * 0.10
    total += int(input("how many nickels? ")) * 0.05
    total += int(input("how many pennies? ")) * 0.01
    return total

def transaction_successful(money_received, drink_cost):
    """Returns True if payment is accepted, returns False if funds are insufficient"""
    if money_received >= drink_cost:
        change = round(money_received - drink_cost, 2)
        print(f"Here is ${change:.2f} in change.")
        global profit
        profit += drink_cost
        return True
    else:
        print("Sorry that's not enough money. Money refunded.")
        return False

def make_coffee(drink_name, order_ingredients):
    """Deduct the required ingredients from the coffee machine resources"""
    for item in order_ingredients:
        resources[item] -= order_ingredients[item]
    print(f"Here is your {drink_name} ☕. Enjoy!")

MENU = {
    "espresso": {
        "ingredients": {
            "water": 50,
            "coffee": 18,
        },
        "cost": 1.5,
    },
    "latte": {
        "ingredients": {
            "water": 200,
            "milk": 150,
            "coffee": 24,
        },
        "cost": 2.5,
    },
    "cappuccino": {
        "ingredients": {
            "water": 250,
            "milk": 100,
            "coffee": 24,
        },
        "cost": 3.0,
    }
}

resources = {
    "water": 300,
    "milk": 200,
    "coffee": 100,
}

profit = 0
machine_on = True

while machine_on:
    print(logo)
    choice = input("What would you like? (espresso/latte/cappuccino): ")
    if choice == "off":
        machine_on = False
        print("Coffee machine powering down. Please remove any perishable resources.")
    elif choice == "report":
        print(f"Water: {resources['water']}ml")
        print(f"Milk: {resources['milk']}ml")
        print(f"Coffee: {resources['coffee']}g")
        print(f"Money: ${profit:.2f}")
    else:
        try:
            drink = MENU[choice]
            if resources_sufficient(drink['ingredients']):
                print(f"Price: ${drink['cost']:.2f}")
                payment = process_coins()
                if transaction_successful(payment, drink['cost']):
                    make_coffee(choice, drink['ingredients'])
        except KeyError:
            print("Not a valid choice. Please try again.")


#############################################################################
# Simplex Algorithm
# by David You
#############################################################################

#################################################
# Note:
# Although the code does not have 2dList function to output values,
# I used the print2dList function to help me see the matrices
# Thus, I decided to include it in my citation
#################################################

# Helper function for print2dList.
# Taken from https://www.cs.cmu.edu/~112/notes/notes-2d-lists.html
# This finds the maximum length of the string
# representation of any item in the 2d list
def maxItemLength(a):
    maxLen = 0
    rows = len(a)
    cols = len(a[0])
    for row in range(rows):
        for col in range(cols):
            maxLen = max(maxLen, len(str(a[row][col])))
    return maxLen

# Because Python prints 2d lists on one row,
# we might want to write our own function
# that prints 2d lists a bit nicer.
def print2dList(a):
    if (a == []):
        # So we don't crash accessing a[0]
        print([])
        return
    rows = len(a)
    cols = len(a[0])
    fieldWidth = maxItemLength(a)
    print("[ ", end="")
    for row in range(rows):
        if (row > 0): print("\n  ", end="")
        print("[ ", end="")
        for col in range(cols):
            if (col > 0): print(", ", end="")
            # The next 2 lines print a[row][col] with the given fieldWidth
            formatSpec = "%" + str(fieldWidth) + "s"
            print(formatSpec % str(a[row][col]), end="")
        print(" ]", end="")
    print("]")

#################################################

# Algorithmic thinking and sample problems taken from
# https://courses.cs.washington.edu/courses/cse521/13wi/slides/09lp.pdf
# https://www.youtube.com/watch?v=8_D3gkrgeK8
# https://www.youtube.com/watch?v=iwDiG2mR6FM
# https://www.geeksforgeeks.org/simplex-algorithm-tabular-method/
# http://fourier.eng.hmc.edu/e176/lectures/NM/node32.html
# http://www.ms.uky.edu/~rwalker/Class%20Work%20Solutions/class%20work%208%20solutions

import string
import copy

def removeExtraWords(L):
    # Takes in a list and removes the extra words 'Max' or 'Min'
    i = 0
    while i < len(L):
        elem = L[i]
        if ("Max" in elem) or ("Min" in elem):
            L.remove(elem)
        i += 1
    return L

def removeOperators(L):
    # Takes in a list and removes all the non-alphanumeric values
    # For negative signs, I add the negative sign in front of the following element
    i = 0
    while i < len(L):
        elem = L[i]
        if (("+" in elem) or ("=" in elem) or (">=" in elem) or ("<=" in elem)):
            L.remove(elem)
        elif ("-" in elem) and (len(elem) == 1):
            L[i+1] = "-" + L[i+1]
            L.remove(elem)
        i += 1
    return L

def cleanUpConstraints(L):
    # Takes a list and returns a 2d list with each initial element as a list
    # And each entry in the string as an item in the list
    outerList = []
    for elem in L:
        innerList = elem.split(" ")
        outerList.append(innerList)
    return outerList

def addSlackVariables(constraint,slackVariable):
    #Takes a 1d list and adds in the slackVariable number (int) to the
    #Second to last value of each list
    slackVariableStr = 's' + str(slackVariable)
    constraint.insert(-1,slackVariableStr)
    return constraint

def flipOptimizationFunctionSigns(L):
    # Takes in the optimization function list and flips the signs
    for i in range(len(L)):
        entry = L[i]
        if (entry != 'z') and ('x' in entry):
            if entry[0] == "-":
                L[i] = entry[1:]
                entry = entry[1:]
            else:
                L[i] = "-" + entry
    return L

def checkEasyChangeMinToMax(problem):
    # Checks to ensure that the all the constraints have linear expressions
    # With the variables less than or equal to a constant
    textList = problem.splitlines()
    initialConstraints = textList[3:-1]
    modifiedConstraints = initialConstraints[:-1]
    for constraint in modifiedConstraints:
        if ("<=" not in constraint):
            return False
    return True

def easyChangeMinToMax(optimizationFunction):
    # If the constraints involve linear expressions with the variables
    # less than or equal to a constant. I use the trick that minimizing
    # this function C is the same as maximizing the function p = −z
    optimizationFunctionList = optimizationFunction.split(" ")
    flipOptimizationFunctionSigns(optimizationFunctionList)
    optimizationFunctionList[0] = "Maximize:"
    newOptimiztionFunction = " ".join(optimizationFunctionList)
    return newOptimiztionFunction

def getInitialInformation(problem):
    # Given a problem, returns the initial constraints and the optimization function
    textList = problem.splitlines()
    optimizationFunction = textList[1]
    # The last line of every problem is the lower bound, which is always going to be zero
    # This bound is not used in the simplex tableau
    initialConstraints = textList[3:-1]
    lowerBound = textList[-1]
    return (optimizationFunction,initialConstraints,lowerBound)

def getKeyInformation(problem):
    # Given a text, the function returns the a 2d List of the key information
    # Key information: constraint equations with slack variables and optimization function
    optimizationFunction, initialConstraints, lowerBound = getInitialInformation(problem)

    # If I start out with a minimization function, that is easily changable
    # I simply switch it so that the optimization function is reversed
    if "Min" in optimizationFunction:
        optimizationFunction = easyChangeMinToMax(optimizationFunction)

    # I remove the extra words from the optimization line
    optimizationFunction = removeExtraWords(optimizationFunction.split(" "))

    # I want to remove all the operators and add a "-" sign to the next value if it's negative
    cleanedOptimizationFunction = removeOperators(optimizationFunction)
    cleanedConstraints = cleanUpConstraints(initialConstraints)
    for equation in cleanedConstraints:
        removeOperators(equation)

    # I move all variables in the optimization function to one side
    # Keeping z positive and flipping the signs of everything else
    optimizationFunctionWithFlippedSigns = flipOptimizationFunctionSigns(cleanedOptimizationFunction)

    # I add in the slack variables to the constraint equations
    for i in range(len(cleanedConstraints)):
        curConstraint = cleanedConstraints[i]
        slackVariable = i + 1
        constraintWithSlackVariables = addSlackVariables(curConstraint,slackVariable)

    # Finally I want to add the function I want to optimize at the end of the 2d list
    cleaned2dList = copy.deepcopy(cleanedConstraints)
    cleaned2dList.append(optimizationFunctionWithFlippedSigns)
    return cleaned2dList

def getCoefficient(entry):
    # Returns the numerical coefficients of algebraic values with the sign
    # Only 'x' will have coefficients besides 1
    if isinstance(entry,int):
        # Accounts for all the zeros I inserted
        return entry
    elif entry.isdigit():
        # Accounts for the non-zero integers
        return int(entry)
    else:
        # Accounts for all the variables
        if (entry[0].isalpha()):
            return 1
        else:
            if ("x" in entry) :
                # Accounts for coefficients of -1 before the 'x'
                if ("-x" in entry):
                    return -1
                else:
                    replacement = entry.find('x')
                    coefficient = int(entry[:replacement])
                    return coefficient

def removeCoefficientsFromX(L):
    # Takes in the 2d list and removes the coefficient for every 'x'
    for innerList in L:
        for i in range(len(innerList)):
            entry = innerList[i]
            if ("x" in entry) and (entry.find('x') != 0):
                replacement = entry.find('x')
                newEntry = entry[replacement:]
                innerList[i] = newEntry
    return L

def makeListOfAllVariables(text):
    # Takes in a 2dList and creates a 1dList with all the different variables
    # Without the coefficients
    newList = (getKeyInformation(text))
    cleanedList = removeCoefficientsFromX(newList)
    variableList = []
    for innerList in newList:
        for entry in innerList:
            if (entry not in variableList) and (not entry.isdigit()):
                variableList.append(entry)
    return variableList

def addZerosToMatrix(problem):
    # For spaces where there is no variable, input 0
    # Add zero in the optimization function as well since
    # I am moving all variables on one side
    newList = getKeyInformation(problem)
    variableList = makeListOfAllVariables(problem)
    for i in range(len(variableList)):
        currentCol = variableList[i]
        for innerList in newList:
            for j in range(len(innerList)):
                innerListEntry = innerList[i]
                if i == j:
                    if currentCol not in innerListEntry:
                        innerList.insert(i,0)
    newList[-1].append(0)
    return newList

def addHeaderToMatrix(problem):
    # Adds a row with the variable name
    L = addZerosToMatrix(problem)
    variableList = makeListOfAllVariables(problem)
    variableList.append('num')
    L.insert(0,variableList)
    return L

def createSimplexTalbeau(problem):
    # Creates the matrix with the coefficients of the constraints
    # Moves all variables in the optimization function to one side
    # Includes a header to indicate the column identity
    origMatrix = addHeaderToMatrix(problem)
    rows,cols = len(origMatrix), len(origMatrix[0])
    for i in range(1,rows):
        for j in range(cols):
            entry = origMatrix[i][j]
            origMatrix[i][j] = getCoefficient(entry)
    return origMatrix

def getCol(header,startRow,stopRow,matrix):
    # Takes in a specific header, the starting row and ending row
    # And returns a list of that column
    rows = len(matrix[startRow:stopRow])
    headers = matrix[0]
    col = headers.index(header)
    colList = []
    for row in range(startRow,stopRow):
        entry = matrix[row][col]
        colList.append(entry)
    return colList

def getColWithMostNegVal(matrix):
    # Finds the column with the most negative value and
    # Returns the column and the value
    # If two values are equal, then it retursn the leftmost one
    headers = matrix[0]
    lastRow = len(matrix) - 1
    mostNegVal = 0
    colWithMostNegVal = 0
    storeHeader = headers[0]
    for i in range(len(headers)):
        header = headers[i]
        elem = getCol(header,lastRow,lastRow+1,matrix)[0]
        if elem < mostNegVal:
            mostNegVal = elem
            colWithMostNegVal = i
            storeHeader = header
    return (colWithMostNegVal,storeHeader)

def largestConstraint(pivotColList,numColList):
    # Takes in two different columns and returns the
    # value in the pivot column and row where the biggest constraint occurs
    # If two constraints are the same, then it returns the upmost one
    mostStringent = 10**10 # Smallest value, the given values should never be <0
    constraintRow = 0
    for i in range(len(pivotColList)):
        pivotVal = pivotColList[i]
        numVal = numColList[i]
        if (pivotVal != 0):
            constraint = numVal/pivotVal
            if (constraint < mostStringent) and (constraint >= 0):
                mostStringent = constraint
                constraintRow = i
    val = pivotColList[constraintRow]
    return (val,constraintRow,mostStringent)

def getPivot(matrix):
    # Finds the pivot value, row, and column that will be used
    # for the basis of all calculations
    rows = len(matrix)
    (colWithMostNegVal,storeHeader) = getColWithMostNegVal(matrix)
    startRow, endRow = 1, rows-1
    pivotColList = getCol(storeHeader,startRow,endRow,matrix)
    numColList = getCol('num',startRow,endRow,matrix)
    (val, constraintRow, mostStringent) = largestConstraint(pivotColList,numColList)
    pivotRow = startRow + constraintRow
    return (val, pivotRow, colWithMostNegVal)

def makePivotOne(pivotVal,pivotRow,matrix):
    # Takes in the pivotRow and makes the pivot 1, changing all other
    # Values in the row accordingly
    pivotRowList = matrix[pivotRow]
    newPivotRowList = []
    multiplier = 1/pivotVal
    for value in pivotRowList:
        newValue = value*multiplier
        newValue = round(newValue,3)
        newPivotRowList.append(newValue)
    return newPivotRowList

def calculateNewRow(negativeMultiplier,otherRowList,pivotRowList):
    # Calculates the new row based on the pivot row and the original other row
    newOtherRow = []
    for i in range(len(pivotRowList)):
        pivotRowEntry = pivotRowList[i]
        otherRowEntry = otherRowList[i]
        newOtherRowEntry = (negativeMultiplier*pivotRowEntry) + otherRowEntry
        newOtherRow.append(round(newOtherRowEntry,3))
    return newOtherRow

def getPivotAdjustedRow(matrix,row,pivotRow,pivotCol):
    # Changes the other row so that it has a 0 in the pivot column
    negativeMultiplier = -(matrix[row][pivotCol])
    newRow = calculateNewRow(negativeMultiplier,matrix[row],matrix[pivotRow])
    return newRow

def simplexAlgorithm(matrix):
    # Recursively applies the simplex algorithm until all values in
    # The last row are greater than 0
    rows, cols = len(matrix), len(matrix[0])
    lastRow = matrix[-1]
    if min(lastRow) >= 0:
        return matrix
    else:
        (pivotVal,pivotRow,pivotCol) = getPivot(matrix)
        newPivotRowList = makePivotOne(pivotVal,pivotRow,matrix)
        matrix[pivotRow] = newPivotRowList
        for row in range(1,pivotRow):
            newRow = getPivotAdjustedRow(matrix,row,pivotRow,pivotCol)
            matrix[row] = newRow
        for row in range(pivotRow + 1,rows):
            newRow = getPivotAdjustedRow(matrix,row,pivotRow,pivotCol)
            matrix[row] = newRow
        return simplexAlgorithm(matrix)

def simplexAlgorithmWrapper(problem):
    # Wrapper Function for the simplex algorithm
    matrix = createSimplexTalbeau(problem)
    optimizedMatrix = simplexAlgorithm(matrix)
    return optimizedMatrix

def getOptimizedValue(problem):
    try:
        # Takes in an optimized matrix and returns the optimized value
        if ("Min" in problem) and (not checkEasyChangeMinToMax(problem)):
            problem = hardChangeMinToMax(problem)
        optimizedMatrix = simplexAlgorithmWrapper(problem)
        rows,cols = len(optimizedMatrix), len(optimizedMatrix[0])
        lastRow,lastCol = rows-1,cols-1
        optimizedValue = round(optimizedMatrix[lastRow][lastCol])
        # If you want to see the 2d matrix, uncomment the next line
        #print(print2dList(optimizedMatrix))
        if "Min" in problem:
            return -1*optimizedValue
        return optimizedValue
    except:
        return "Solution not possible"

#########################################################
# Changes Minimization Function to Maximization Function
#########################################################

def makeMinCoefficientMatrix(initialConstraints,optimizationFunction):
    # Takes in a minimization function and turns the coefficents into a matrix
    # With all the coefficients
    optimizationFunction = removeExtraWords(optimizationFunction.split(" "))
    cleanedConstraints = cleanUpConstraints(initialConstraints)
    matrix = cleanedConstraints
    matrix.append(optimizationFunction)
    for row in matrix:
        removeOperators(row)
    rows, cols = len(matrix), len(matrix[0])
    for row in range(rows):
        for col in range(cols):
            entry = matrix[row][col]
            matrix[row][col] = getCoefficient(entry)
    return matrix

def transposeMatrix(matrix):
    # Tranposes a matrix
    newMatrix = []
    rows, cols = len(matrix), len(matrix[0])
    for col in range(cols):
        newRow = []
        for row in range(rows):
            newRow.append(matrix[row][col])
        newMatrix.append(newRow)
    return newMatrix

def addInVariables(matrix):
    # Adds in variables x1, x2, ... to the matrix corresponding to that column
    rows, cols = len(matrix), len(matrix[0])
    for row in range(rows):
        for col in range(cols-1):
            variable = 'x' + str(col+1)
            entry = matrix[row][col]
            if (entry != 1):
                matrix[row][col] = str(entry) + variable
            else:
                matrix[row][col] = variable
    # The last value of the equation is always 'z', the value I will optimize
    matrix[rows-1][cols-1] = 'z'
    return matrix

def makeEquationList(equation):
    # Takes in a list with the variables and outputs the equation as a list
    newEquation = equation
    newEquation[-1] = str(newEquation[-1])
    for i in range(1,len(equation)-1):
        entry = equation[i]
        if entry[0] == "-":
            newEquation.insert(i,"-")
        else:
            newEquation.insert(i,"+")
    if 'z' in equation:
        newEquation.insert(-1,'=')
    else:
        newEquation.insert(-1,'<=')
    return newEquation

def changeEquationIntoString(matrix,row):
    # Changes the equation into a string
    equation = matrix[row]
    newEquation = makeEquationList(equation)
    newEquationString = " ".join(newEquation)
    return newEquationString

def addOperators(matrix,row,L):
    # Takes in a row in the matrix and modifies L with that row
    # Setting up the list so that it can be turned into a string
    newEquationString = changeEquationIntoString(matrix,row)
    if ('z' in newEquationString):
        L.insert(0,newEquationString)
    else:
        L.append(newEquationString)
    return L

def stringModifiers(maxProblemList,bound):
    # Modifies the final part of the min problem to match the constraints in the
    # Max problems
    maxProblemList.append(bound)
    maxProblemList.insert(1, 'Constraints:')
    maxProblemList[0] = "Maximize: " + maxProblemList[0]
    maxProblem = "\n" + "\n".join(maxProblemList)
    return maxProblem

def hardChangeMinToMax(problem):
    # Changes a minimization function into a maximization function
    # By rewriting the entire problem as a maximization function
    optimizationFunction, initialConstraints, lowerBound = getInitialInformation(problem)
    matrix = makeMinCoefficientMatrix(initialConstraints,optimizationFunction)
    transposedMatrix = transposeMatrix(matrix)
    addInVariables(transposedMatrix)
    rows, cols = len(transposedMatrix), len(transposedMatrix[0])
    maxProblemList = []
    for row in range(rows):
        maxProblemList = addOperators(transposedMatrix,row, maxProblemList)
    maxProblem = stringModifiers(maxProblemList,lowerBound)
    return maxProblem

#########################################################

#################################################
# Test Functions
#################################################

def testRemoveOperators():
    print('Testing removeOperaters()...', end='')
    L = ['2x1', '+', '5x2', '=', 'z']
    assert(removeOperators(L) == ['2x1','5x2','z'])
    L = ['2x1', '-', '5x2', '=', 'z']
    assert(removeOperators(L) == ['2x1','-5x2','z'])
    L = ['x1', '+', 'x2', '=', '6']
    assert(removeOperators(L) == ['x1','x2','6'])
    L = ['-x1', '-', '4x2', '=', '-3']
    assert(removeOperators(L) == ['-x1','-4x2','-3'])
    L = ['x2', '<=', '3']
    assert(removeOperators(L) == ['x2','3'])
    print('Passed!')

def testGetKeyInformation():
    print('Testing getKeyInformation()...', end='')
    # Taken from https://www.geeksforgeeks.org/simplex-algorithm-tabular-method/
    problem = '''
Maximize: 2x1 + 5x2 = z
Constraints:
x1 + x2 <= 6
x2 <= 3
x1 + 2x2 <= 9
x1, x2 >= 0
'''
    assert(getKeyInformation(problem) == [['x1','x2','s1','6'],
                                          ['x2','s2','3'],
                                          ['x1','2x2','s3','9'],
                                          ['-2x1','-5x2','z']])
    # Taken from https://www.youtube.com/watch?v=iwDiG2mR6FM
    problem1 = '''
Maximize: 8x1 + 10x2 + 7x3 = z
Constraints:
x1 + 3x2 + 2x3 <= 10
x1 + 5x2 + x3 <= 8
x1, x2, x3 >= 0
'''
    assert(getKeyInformation(problem1) == [['x1', '3x2', '2x3','s1','10'],
                                           ['x1', '5x2', 'x3' ,'s2', '8'],
                                           ['-8x1','-10x2','-7x3','z']])
    # Taken from https://courses.cs.washington.edu/courses/cse521/13wi/slides/09lp.pdf
    problem2 = '''
Maximize: 15x1 + 10x2 = z
Constraints:
x1 <= 2
x2 <= 3
x1 + x2 <= 4
x1, x2 >= 0
'''
    assert(getKeyInformation(problem2) == [['x1',  's1',  '2'],
                                           ['x2',  's2',  '3'],
                                           ['x1',  'x2',  's3','4'],
                                           ['-15x1','-10x2','z']])
    # Taken from http://fourier.eng.hmc.edu/e176/lectures/NM/node32.html
    problem3 = '''
Maximize: 2x1 + 3x2 = z
Constraints:
2x1 + x2 <= 18
6x1 + 5x2 <= 60
2x1 + 5x2 <= 40
x1, x2 >= 0
'''
    assert(getKeyInformation(problem3) == [['2x1', 'x2',  's1', '18'],
                                           ['6x1', '5x2', 's2', '60'],
                                           ['2x1', '5x2', 's3', '40'],
                                           ['-2x1', '-3x2', 'z']])
    print('Passed!')

def testAddHeaderToMatrix():
    print('Testing addHeaderToMatrix()...', end='')
    problem = '''
Maximize: 2x1 + 5x2 = z
Constraints:
x1 + x2 <= 6
x2 <= 3
x1 + 2x2 <= 9
x1, x2 >= 0
'''
    assert(addHeaderToMatrix(problem) == [[ 'x1',    'x2', 's1', 's2', 's3', 'z', 'num'],
                                          [ 'x1',    'x2', 's1',    0,    0,   0,  '6' ],
                                          [    0,    'x2',    0, 's2',    0,   0,  '3' ],
                                          [ 'x1',   '2x2',    0,    0, 's3',   0,  '9' ],
                                          ['-2x1', '-5x2',    0,    0,    0, 'z',   0  ]])
    problem1 = '''
Maximize: 8x1 + 10x2 + 7x3 = z
Constraints:
x1 + 3x2 + 2x3 <= 10
x1 + 5x2 + x3 <= 8
x1, x2, x3 >= 0
'''
    assert(addHeaderToMatrix(problem1) == [[  'x1',    'x2',   'x3', 's1', 's2', 'z', 'num'],
                                           [  'x1',   '3x2',  '2x3', 's1',    0,   0, '10' ],
                                           [  'x1',   '5x2',   'x3',    0, 's2',   0,  '8' ],
                                           ['-8x1', '-10x2', '-7x3',    0,    0,  'z',  0  ]])
    problem2 = '''
Maximize: 15x1 + 10x2 = z
Constraints:
x1 <= 2
x2 <= 3
x1 + x2 <= 4
x1, x2 >= 0
'''
    assert(addHeaderToMatrix(problem2) == [[   'x1', 's1',    'x2', 's2', 's3', 'z', 'num'],
                                           [   'x1', 's1',       0,    0,    0,   0,  '2' ],
                                           [      0,    0,    'x2', 's2',    0,   0,  '3' ],
                                           [   'x1',    0,    'x2',    0, 's3',   0,  '4' ],
                                           ['-15x1',    0, '-10x2',    0,    0, 'z',   0  ]])
    problem3 = '''
Maximize: 2x1 + 3x2 = z
Constraints:
2x1 + x2 <= 18
6x1 + 5x2 <= 60
2x1 + 5x2 <= 40
x1, x2 >= 0
'''
    assert(addHeaderToMatrix(problem3) == [[  'x1',   'x2', 's1', 's2', 's3', 'z', 'num'],
                                           [ '2x1',   'x2', 's1',    0,    0,   0,  '18' ],
                                           [ '6x1',  '5x2',    0, 's2',    0,   0,  '60' ],
                                           [ '2x1',  '5x2',    0,    0, 's3',   0,  '40' ],
                                           ['-2x1', '-3x2',    0,    0,    0, 'z',   0  ]])
    print('Passed!')

def testGetCoefficient():
    print('Testing getCoefficient()...', end='')
    assert(getCoefficient('x1') == 1)
    assert(getCoefficient('x2') == 1)
    assert(getCoefficient('s1') == 1)
    assert(getCoefficient('s2') == 1)
    assert(getCoefficient('z') == 1)
    assert(getCoefficient('3x1') == 3)
    assert(getCoefficient('12x2') == 12)
    assert(getCoefficient('15112x3') == 15112)
    assert(getCoefficient('-3x1') == -3)
    assert(getCoefficient('-12x2') == -12)
    assert(getCoefficient('-15112x3') == -15112)
    print('Passed!')

def testCreateSimplexTalbeau():
    print('Testing createSimplexTalbeau()...', end='')
    problem = '''
Maximize: 2x1 + 5x2 = z
Constraints:
x1 + x2 <= 6
x2 <= 3
x1 + 2x2 <= 9
x1, x2 >= 0
'''
    assert(createSimplexTalbeau(problem) == [['x1', 'x2', 's1', 's2', 's3', 'z', 'num'],
                                            [   1,    1,    1,    0,    0,   0,    6  ],
                                            [   0,    1,    0,    1,    0,   0,    3  ],
                                            [   1,    2,    0,    0,    1,   0,    9  ],
                                            [  -2,   -5,    0,    0,    0,   1,    0  ]])
    problem1 = '''
Maximize: 8x1 + 10x2 + 7x3 = z
Constraints:
x1 + 3x2 + 2x3 <= 10
x1 + 5x2 + x3 <= 8
x1, x2, x3 >= 0
'''
    assert(createSimplexTalbeau(problem1) == [['x1', 'x2', 'x3', 's1', 's2', 'z', 'num'],
                                             [    1,   3,    2,    1,    0,   0,    10 ],
                                             [    1,   5,    1,    0,    1,   0,     8 ],
                                             [   -8, -10,   -7,    0,    0,   1,     0 ]])
    problem2 = '''
Maximize: 15x1 + 10x2 = z
Constraints:
x1 <= 2
x2 <= 3
x1 + x2 <= 4
x1, x2 >= 0
'''
    assert(createSimplexTalbeau(problem2) == [['x1', 's1', 'x2', 's2', 's3', 'z', 'num'],
                                             [   1,    1,    0,    0,    0,   0,    2  ],
                                             [   0,    0,    1,    1,    0,   0,    3  ],
                                             [   1,    0,    1,    0,    1,   0,    4  ],
                                             [ -15,    0,  -10,    0,    0,   1,    0  ]])
    problem3 = '''
Maximize: 2x1 + 3x2 = z
Constraints:
2x1 + x2 <= 18
6x1 + 5x2 <= 60
2x1 + 5x2 <= 40
x1, x2 >= 0
'''
    assert(createSimplexTalbeau(problem3) == [['x1', 'x2', 's1', 's2', 's3', 'z', 'num'],
                                              [  2,    1,    1,    0,    0,   0,    18 ],
                                              [  6,    5,    0,    1,    0,   0,    60 ],
                                              [  2,    5,    0,    0,    1,   0,    40 ],
                                              [ -2,   -3,    0,    0,    0,   1,    0  ]])
    print('Passed!')

def testGetCol():
    print('Testing getCol()...', end='')
    problem = '''
Maximize: 2x1 + 5x2 = z
Constraints:
x1 + x2 <= 6
x2 <= 3
x1 + 2x2 <= 9
x1, x2 >= 0
'''
    matrix = createSimplexTalbeau(problem)
    """
    matrix:
    [[  x1,  x2,  s1,  s2,  s3,   z, num ]
    [    1,   1,   1,   0,   0,   0,   6 ]
    [    0,   1,   0,   1,   0,   0,   3 ]
    [    1,   2,   0,   0,   1,   0,   9 ]
    [   -2,  -5,   0,   0,   0,   1,   0 ]]
    """
    assert(getCol('num',1,4,matrix) == [6, 3, 9])
    assert(getCol('x1',1,5,matrix) == [1, 0, 1, -2])
    assert(getCol('x2',0,3,matrix) == ['x2', 1, 1])
    assert(getCol('s1',0,0,matrix) == [])
    assert(getCol('s1',0,1,matrix) == ['s1'])
    assert(getCol('s3',0,5,matrix) == ['s3', 0, 0, 1, 0])
    assert(getCol('s3',5,5,matrix) == [])
    print('Passed!')

def testGetColWithMostNegVal():
    print('Testing getColWithMostNegVal()...', end='')
    problem = '''
Maximize: 2x1 + 5x2 = z
Constraints:
x1 + x2 <= 6
x2 <= 3
x1 + 2x2 <= 9
x1, x2 >= 0
'''
    matrix = createSimplexTalbeau(problem)
    assert(getColWithMostNegVal(matrix) == (1,'x2'))
    problem1 = '''
Maximize: 8x1 + 10x2 + 7x3 = z
Constraints:
x1 + 3x2 + 2x3 <= 10
x1 + 5x2 + x3 <= 8
x1, x2, x3 >= 0
'''
    matrix = createSimplexTalbeau(problem1)
    assert(getColWithMostNegVal(matrix) == (1,'x2'))
    problem2 = '''
Maximize: 15x1 + 10x2 = z
Constraints:
x1 <= 2
x2 <= 3
x1 + x2 <= 4
x1, x2 >= 0
'''
    matrix = createSimplexTalbeau(problem2)
    assert(getColWithMostNegVal(matrix) == (0,'x1'))
    problem3 = '''
Maximize: 2x1 + 3x2 = z
Constraints:
2x1 + x2 <= 18
6x1 + 5x2 <= 60
2x1 + 5x2 <= 40
x1, x2 >= 0
'''
    matrix = createSimplexTalbeau(problem3)
    assert(getColWithMostNegVal(matrix) == (1,'x2'))
    print('Passed!')

def testGetOptimizedValue():
    print('Testing getOptimizedValue()...', end='')
    problem = '''
Maximize: 2x1 + 5x2 = z
Constraints:
x1 + x2 <= 6
x2 <= 3
x1 + 2x2 <= 9
x1, x2 >= 0
'''
    assert(getOptimizedValue(problem) == 21)
    problem1 = '''
Maximize: 8x1 + 10x2 + 7x3 = z
Constraints:
x1 + 3x2 + 2x3 <= 10
x1 + 5x2 + x3 <= 8
x1, x2, x3 >= 0
'''
    assert(getOptimizedValue(problem1) == 64)
    problem2 = '''
Maximize: 15x1 + 10x2 = z
Constraints:
x1 <= 2
x2 <= 3
x1 + x2 <= 4
x1, x2 >= 0
'''
    assert(getOptimizedValue(problem2) == 50)
    problem3 = '''
Maximize: 2x1 + 3x2 = z
Constraints:
2x1 + x2 <= 18
6x1 + 5x2 <= 60
2x1 + 5x2 <= 40
x1, x2 >= 0
'''
    assert(getOptimizedValue(problem3) == 28)

    # Additional Examples taken from
    # https://college.cengage.com/mathematics/larson/elementary_linear/4e/shared/downloads/c09s3.pdf
    problem4 = '''
Maximze: 4x1 + 6x2 = z
Constraints:
-x1 + x2 <= 11
x1 + x2 <= 27
2x1 + 5x2 <= 90
x1, x2, >= 0
'''
    assert(getOptimizedValue(problem4) == 132)
    problem5 = '''
Maximize: 2x1 - x2 + 2x3 = z
Constraints:
2x1 + x2 <= 10
x1 + 2x2 - 2x3 <= 20
x2 + 2x3 <= 5
x1, x2, x3 >= 0
'''
    assert(getOptimizedValue(problem5) == 15)
    problem6 = '''
Maximize: 3x1 + 2x2 + x3 = z
Constraints:
4x1 + x2 + x3 = 30
2x1 + 3x2 + x3 <= 60
x2 + 2x3 <= 40
x1, x2, x3 >= 0
'''
    assert(getOptimizedValue(problem6) == 45)
    problem7 = '''
Minimize: -2x1 + x2 = z
Constraints:
x1 + 2x2 <= 6
3x1 + 2x2 <= 12
x1, x2, >= 0
'''
    assert(getOptimizedValue(problem7) == -8)
    # Taken from https://www.youtube.com/watch?v=8_D3gkrgeK8
    problem8 = '''
Minimize: 3x1 + 9x2 = z
Constraints:
2x1 + x2 >= 8
x1 + 2x2 >= 8
x1, x2 >= 0
'''
    assert(getOptimizedValue(problem8) == 24)
    # Taken from http://www.ms.uky.edu/~rwalker/Class%20Work%20Solutions/class%20work%208%20solutions
    problem9 = '''
Minimize: 2x1 + 5x2 = z
Constraints:
x1 + 2x2 >= 4
3x1 + 2x2 >= 3
x1, x2 >= 0
'''
    assert(getOptimizedValue(problem9) == 8)
    print('Passed!')

def testHardChangeMinToMax():
    print('Testing hardChangeMinToMax()...', end='')
    problem8 = '''
Minimize: 3x1 + 9x2 = z
Constraints:
2x1 + x2 >= 8
x1 + 2x2 >= 8
x1, x2 >= 0
'''
    maxProblem8 = '''
Maximize: 8x1 + 8x2 = z
Constraints:
2x1 + x2 <= 3
x1 + 2x2 <= 9
x1, x2 >= 0'''
    assert(hardChangeMinToMax(problem8) == maxProblem8)
    assert(len(hardChangeMinToMax(problem8)) == len(maxProblem8))
    problem9 = '''
Minimize: 2x1 + 5x2 = z
Constraints:
x1 + 2x2 >= 4
3x1 + 2x2 >= 3
x1, x2 >= 0
'''
    maxProblem9 = '''
Maximize: 4x1 + 3x2 = z
Constraints:
x1 + 3x2 <= 2
2x1 + 2x2 <= 5
x1, x2 >= 0'''
    assert(hardChangeMinToMax(problem9) == maxProblem9)
    assert(len(hardChangeMinToMax(problem9)) == len(maxProblem9))
    print('Passed!')

def testAll():
    testRemoveOperators()
    testGetKeyInformation()
    testAddHeaderToMatrix()
    testGetCoefficient()
    testCreateSimplexTalbeau()
    testGetCol()
    testGetColWithMostNegVal()
    testGetOptimizedValue()
    testHardChangeMinToMax()

#testAll()


# Create by Abhiram
# This file has binary tree implemented using Linked List Method.
# I am also implementing different methtods related to the Binary tree.
# Pre-Order, In-Order and Post Order traversal. I am also implementing the level order traversal which is similar to Breadth first search for the graphs.
# Searching an element. Adding an element and deleting an element and its different conditions.

from logging import root
from queue import Queue as q

class TreeNode:
    def __init__(self, data):
        self.data = data
        self.leftChild= None
        self.rightChild= None

rootNode= TreeNode("Drinks")
rootNode.leftChild= TreeNode("Cold")
rootNode.rightChild= TreeNode("Hot")

# Pre order traversal is Center-> Left -> Right
# Time complexity is O(N) as we have to traverse through each and every node.
# Space Complexity is O(n) since we are using the recursive way, we have to use the stack in ram.
def preOrderTraversal(rootNode):
    if not rootNode:
        return
    print(rootNode.data)
    preOrderTraversal(rootNode.leftChild)
    preOrderTraversal(rootNode.rightChild)

print("Pre Order Traversal")
preOrderTraversal(rootNode)

# Inorder Traversal is Left -> Center -> Right
# Time complexity is again O(n) as we have to traverse through n items
# Space complexity is also O(n) as we are using the stacks in the recursive calls.
def inOrderTraversal(rootNode):
    if not rootNode:
        return
    inOrderTraversal(rootNode.leftChild)
    print(rootNode.data)
    inOrderTraversal(rootNode.rightChild)

print("In Order Traversal")
inOrderTraversal(rootNode)

# Post order traversal is Left -> Right-> center
# This to is O(n) from both time and space complexity.
def postOrderTraversal(rootNode):
    if not rootNode:
        return
    postOrderTraversal(rootNode.leftChild)
    postOrderTraversal(rootNode.rightChild)
    print(rootNode.data)

print("Post Order Traversal")
postOrderTraversal(rootNode)

# This is the code for Level order traversal.
# This is also the BFS way of accessing the binary tree.
# Here we add the elements to the queue as we traverse them and then dequeue them one by one in order to access their child elements.
# Time complexity is O(n) as we have to go through all the elements. Space is also O(n) as I think we have to add all the elements in the queue.

def levelOrderTraversal(rootNode):
    if rootNode is None:
        return
    else:
        tempQueue= q()
        tempQueue.enqueue(rootNode)
        while not tempQueue.isEmpty():
            currentNode= tempQueue.dequeue()
            print(currentNode.data)
            if currentNode.leftChild is not None:
                tempQueue.enqueue(currentNode.leftChild)
            if currentNode.rightChild is not None:
                tempQueue.enqueue(currentNode.rightChild)

print("Level Order Traversal")
levelOrderTraversal(rootNode)

# This is the code for Sraching a node in the tree.
# There are 2 ways we can use One of the DFS based traversals or BFS based traversals which is queue based.
# Recommended is BFS since it is a queue based approach. But we are going to try both.

# Here we will use pre order traversal for finding the node.
def preOrderTraversalSearchVal(rootNode, nodeValue):
    if not rootNode:
        return
    elif rootNode.data == nodeValue:
        return "Value Present"
    else:
        flagValue= preOrderTraversalSearchVal(rootNode.leftChild, nodeValue)
        if flagValue== "Value Present":
            return "Value Present"
        flagValue= preOrderTraversalSearchVal(rootNode.rightChild, nodeValue)
        if flagValue== "Value Present":
            return "Value Present"
    return "Value Not Present"

print("Searching for the Value DFS Way")
print(preOrderTraversalSearchVal(rootNode, "Drinks"))
print(preOrderTraversalSearchVal(rootNode, "Coffee"))

# Here we will try to implement he BFS way of searching the value. For this we will use the Queue DS used in the Level Order traversal.

def levelOrderTraversalSearchVal(rootNode, nodeValue):
    if not rootNode:
        return
    else:
        currentQueue= q()
        currentQueue.enqueue(rootNode)
        while not currentQueue.isEmpty():
            currentNode = currentQueue.dequeue()
            if currentNode.data == nodeValue:
                return "Value Present"
            # Add the nodes to the queue
            if currentNode.leftChild is not None:
                currentQueue.enqueue(currentNode.leftChild)
            if currentNode.rightChild is not None:
                currentQueue.enqueue(currentNode.rightChild)

        return "Value Not Present"

print("Searching for the value BFS Way")
print(levelOrderTraversalSearchVal(rootNode, "Hot"))
print(levelOrderTraversalSearchVal(rootNode, "Tea"))

# Here we will implement the code for inserting an element into binary tree.
# Here I will implement the BFS way of implementing the BT where we do the level order search.

def insertNode(rootNode, nodeValue):
    if rootNode is None:
        rootNode= TreeNode(nodeValue)
        print("Value Inserted at RootNode")
        return
    # If the root node is not none
    # Create a queue DS and insert root node into it.
    tempQueue= q()
    tempQueue.enqueue(rootNode)
    # Loop till the queue has some elements.
    while not tempQueue.isEmpty():
        currentNode = tempQueue.dequeue()
        if currentNode.leftChild is None:
            currentNode.leftChild= TreeNode(nodeValue)
            print("Value inserted as left child")
            return
        else:
            tempQueue.enqueue(currentNode.leftChild)

        if currentNode.rightChild is None:
            currentNode.rightChild= TreeNode(nodeValue)
            print("Value inserted as right child")
            return
        else:
            tempQueue.enqueue(currentNode.rightChild)

print("Inserting Value")
insertNode(rootNode, "Pepsi")
insertNode(rootNode, "Cola")
levelOrderTraversal(rootNode)

'''
Next is code to delete the Binary Tree
Here the approach that I need to follow is
    - First get the deepest node in the tree.
    - Then replace the value of the deepest node in the tree with the value we want to delete.
    - Then delete the deepest node.

    We will write separate methods to get the deepest node and then delete it.
'''

# Here the logic is, we do the level order traversal and the node at the end is the deepest node.
def getDeepestNode(rootNode):
    if rootNode is None:
        return
    tempQueue= q()
    tempQueue.enqueue(rootNode)
    while not tempQueue.isEmpty():
        temp= tempQueue.dequeue()
        if temp.leftChild:
            tempQueue.enqueue(temp.leftChild)

        if temp.rightChild:
            tempQueue.enqueue(temp.rightChild)

    return temp

# Here I am planning to delete the deepest node:
# This method will take rootnode and the deepest Node. i.e reference to both
# We will again do the level order traversal and once we reach the deepest node, we will set the reference to None.

def delDeepestNode(rootNode, dNode):
    if rootNode is None:
        return
    tempQueue= q()
    tempQueue.enqueue(rootNode)
    while not tempQueue.isEmpty():
        currentNode= tempQueue.dequeue()
        if currentNode== dNode:
            currentNode= None
            return
        if currentNode.leftChild:
            if currentNode.leftChild== dNode:
                currentNode.leftChild= None
                return
            else:
                tempQueue.enqueue(currentNode.leftChild)
        if currentNode.rightChild:
            if currentNode.rightChild== dNode:
                currentNode.rightChild= None
                return
            else:
                tempQueue.enqueue(currentNode.rightChild)

# Here in this method I will actually delete the node.
# What I want to do is,
#   - Get the reference to the deepest Node
#   - Then perform the level order traversal to find the node.
#   - Then once the node to be deleted is found, replace the current node with the deepest node.
#   - Once that is done, Delete the deepest node.

def delNode(rootNode, nodeValue):
    pass

# Code to delete the entire binary tree.

def delBinaryTree(rootNode):
    pass


from bs4 import BeautifulSoup
import requests
from datetime import datetime

# https://amzn.to/3E7V45Y -> Cetus Pro FPV

def cetus_price():
  url = 'https://amzn.to/3E7V45Y'
  headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}

  response = requests.get(url, headers=headers)
  soup = BeautifulSoup(response.content, 'html.parser')

  price = soup.find('span', attrs={'class': 'a-offscreen'}).text

  price_text = "The current price of Cetus Pro FPV is: " + str(price)

  return price_text


"""
Created on Fri Dec  3 09:10:44 2021

@author: adaskin
"""
import random
import math
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from sim_tree import generate_tree_elements,sum_of_nonzeropaths
import sklearn.datasets as datasets
import scipy.sparse

def polar2xy(r, theta):
    x = r*math.cos(theta)
    y = r*math.sin(theta)
    return x,y

def randPolarDot(r1, r2):
    r = random.random() # [0, 1]
    r = r*(r2-r1) + r1
    theta = random.random()*math.pi*2 #hatali
    return r, theta
figure, ax1 = plt.subplots()
#ax2 = figure2.add_subplot(2,2,1,projection='3d')

CL = ['tab:blue','tab:orange','tab:green','tab:red','tab:purple','tab:brown']
nrings = 4
ndots = 256

ringSize = 5;

X = np.zeros([nrings*ndots,2])
count_dot = 0
for iring in range(nrings):
    for jdot in range(ndots):

        [r, theta] = randPolarDot(iring*ringSize, (iring+1)*ringSize)
        [x, y] = polar2xy(r, theta)
        X[count_dot,:] = [x, y]
        count_dot += 1

        ax1.scatter(x, y, color=CL[iring],marker='.')
        #ax2.scatter3D(x, y, x**2+y**2, c=CL[iring]);

#ax1.set_xlabel("x")
#ax1.set_ylabel("y")
figure.savefig('rings.eps', bbox_inches='tight')
figure.savefig('rings.png',bbox_inches='tight')

threshold = 0.020

G = X@X.transpose()
if scipy.sparse.issparse(G):
    G = G.toarray()

psi = G.flatten()
psi_norm = np.linalg.norm(psi)
psi = psi/psi_norm
(usv_tree, nonzeropath) = generate_tree_elements(psi)
L = []
for i in range(int(psi.size/2)-1, psi.size-1):
    if isinstance(usv_tree[i], tuple):
        u, s, v, sprev = usv_tree[i]
        print("shape:", v.shape)
        L.append(usv_tree[i][3])
    else:
        L.append(0)
fig, ax = plt.subplots()
ax.axvline(threshold, linestyle='--')
values, bins, bars = ax.hist(L)

ax.set_xlabel("probability (coefficient) of the path")
ax.set_ylabel("Number of paths")
ax.set_title('n: {}-qubits, data: {} '.format(int(np.log2(psi.size)), 'rings'))
ax.bar_label(bars, fontsize=9, color='red')

p, npaths = sum_of_nonzeropaths(usv_tree,threshold)
print(np.linalg.norm(p-psi))
print(np.linalg.norm(p-psi,1))
print(np.dot(psi,p))
#X_tensor = psi_norm*p.reshape(N,N)
norm_of_diff = np.linalg.norm(psi-p)
print("norm of diff:",norm_of_diff)
ax.text(0.75, 0.75, 'norm of diff={:5.2E}'.format(norm_of_diff), horizontalalignment='center',
     verticalalignment='center', transform=ax.transAxes)
#print("mean error matrix unnormalized:",np.mean((X_tensor-G)**2))
plt.savefig('rings20qubits.eps', bbox_inches='tight')
plt.savefig('rings20qubits.png',bbox_inches='tight')


'''
反转单链表和双链表
'''

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class DoubleListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None
        self.last = None

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head:
            return None

        pre = None
        cur = head

        while cur:
            temp = cur.next
            cur.next = pre
            pre = cur
            cur = temp

        return pre

    def reverseDoubleList(self, head):
        pre = None
        while head:
            next = head.next
            head.next = pre
            head.last = next
            pre = head
            head = next
        return pre


import json
import os

import click
from twarc.decorators2 import FileSizeProgressBar
from twarc.expansions import ensure_flattened

@click.command()
@click.option(
    '--granularity',
    '-g',
    type=click.Choice(
        ['year', 'month', 'day', 'hour', 'minute', 'second'],
        case_sensitive=False
    ),
    default='day',
    show_default=True,
    help='Granularity of temporal windows'
)
@click.argument('infile', type=click.File('r'), default='-')
@click.argument('outdir', type=click.Path(exists=False))
def divide(granularity, infile, outdir):
    '''
    Divides the input file in an output file for each temporal window.
    Each output file contains the tweets published in its temporal window.
    Output files are saved in the output directory,
    and their names are the dates of the temporal windows.
    If an output file already exists, new output is appended to the old one.
    '''
    indices = {
        'year': 4,
        'month': 7,
        'day': 10,
        'hour': 13,
        'minute': 16,
        'second': 19
    }
    index = indices[granularity]

    with FileSizeProgressBar(infile, None) as progress:
        for line in infile:
            for t in ensure_flattened(json.loads(line)):
                date = t['created_at'][:index]
                with open(os.path.join(outdir, date + '.jsonl'), 'a') as out:
                    out.write(json.dumps(t) + '\n')
            progress.update(len(line))


import neurals.data_generation_config as dgc
import neurals.distancefield_utils as df
import model.param as model_param

import copy
import numpy as np
import open3d as o3d
import os
from scipy.spatial.transform import Rotation as scipy_rot
import torch.utils.data

# Each file correspond to a pointcloud
class SmallDataset(torch.utils.data.dataset.Dataset):
    def __init__(self, seed_folder="seeds",
                       point_clouds=["pose_0_pcd", "pose_1_pcd", "pose_2_pcd", "pose_3_pcd", "pose_4_pcd"],
                       has_negative_grasp=False,
                       use_scale = False):
        self.point_clouds = []
        self.point_normals = []
        pose_index = []
        for point_cloud in point_clouds:
            pose_index.append(int(point_cloud[5:7]))
            pcd = o3d.io.read_point_cloud(f"data/{seed_folder}/pointclouds/{point_cloud}.ply")
            pcd_np = np.asarray(pcd.points)
            normal_np = np.asarray(pcd.normals)
            if pcd_np.shape[0] < 1024:
                print(pcd_np.shape[0],point_cloud)
                assert(False)
            idx = np.random.choice(pcd_np.shape[0], 1024, replace=False)
            self.point_clouds.append(pcd_np[idx])
            self.point_normals.append(normal_np[idx])

        self.scales = []
        if os.path.isdir(f"data/{seed_folder}/scales") and use_scale:
            for idx in pose_index:
                scale = np.load(f"data/{seed_folder}/scales/pose_{idx:02}.npy")
                self.scales.append(scale)

        self.positive_grasps = []
        self.positive_pcd_mapping = []
        positive_grasp_files = os.listdir(f"data/{seed_folder}/grasps/")
        positive_grasp_files.sort(key=lambda x: int(x[5:7]))
        positive_files = []
        for positive_grasp_file in positive_grasp_files:
            if int(positive_grasp_file[5]) in pose_index:
                positive_files.append(positive_grasp_file)
        for i,positive_grasp_file in enumerate(positive_files):
            self.positive_grasps.append(np.load(f"data/{seed_folder}/grasps/{positive_grasp_file}")[:,:,:3])
            self.positive_pcd_mapping += [i] * len(self.positive_grasps[-1])

        if has_negative_grasp:
            self.negative_grasps = []
            self.negative_pcd_mapping = []
            negative_grasp_files = os.listdir(f"data/{seed_folder}/bad_grasps/")
            negative_grasp_files.sort(key=lambda x: int(x[5:7]))
            negative_files = []
            for negative_grasp_file in negative_grasp_files:
                if int(negative_grasp_file[5]) in pose_index:
                    negative_files.append(negative_grasp_file)
            for i, negative_grasp_file in enumerate(negative_files):
                self.negative_grasps.append(np.load(f"data/{seed_folder}/bad_grasps/{negative_grasp_file}")[:,:,:3])
                self.negative_pcd_mapping += [i] * len(self.negative_grasps[-1])

        if has_negative_grasp:
            self.grasps = np.concatenate(self.positive_grasps+self.negative_grasps, axis=0)
            self.pcd_mapping = np.array(self.positive_pcd_mapping+self.negative_pcd_mapping)
            self.labels = np.array([1]*len(self.positive_pcd_mapping)+[0]*len(self.negative_pcd_mapping))
        else:
            self.grasps = np.concatenate(self.positive_grasps, axis=0)
            self.pcd_mapping = np.array(self.positive_pcd_mapping)
            self.labels = np.array([1]*len(self.grasps))
        self.grasps = self.grasps.reshape(len(self.grasps),-1)
        print(self.grasps.shape)
        self.point_clouds = np.asarray(self.point_clouds)

    def __len__(self):
        return len(self.pcd_mapping)

    def __getitem__(self, idx):
        ans = {}
        ans["point_cloud"] = self.point_clouds[self.pcd_mapping[idx]]
        ans["point_normals"] = self.point_normals[self.pcd_mapping[idx]]
        ans["fingertip_pos"] = self.grasps[idx]
        ans["intrinsic_score"] = self.labels[idx] # Good or bad pointclouds
        ans["label"] = self.pcd_mapping[idx]
        if self.scales != []:
            ans["scale"] = self.scales[self.pcd_mapping[idx]]
        return ans

# Dataset for score function, add noise tensor in order to prevent overfitting
class ScoreDataset(torch.utils.data.dataset.Dataset):
    """
    Remark: To avoid overfitting between each round, we need to recreate dataset after each
    optimization iteration.
    """
    def __init__(self, score_file="score_data", noise_scale = 0.0, has_distance_field=False):
        self.noise_scale = noise_scale
        self.has_distance_field = has_distance_field
        data = np.load(f"data/score_function_data/{score_file}.npz")
        self.scores = data["scores"]
        self.point_clouds = data["point_clouds"] + np.random.normal(size=data["point_clouds"].shape,
                                                                       scale=self.noise_scale)
        self.point_clouds = data["point_clouds"]
        self.conditions = data["conditions"]
        if has_distance_field:
            # Need to create different environments for computing distance field
            self.point_cloud_labels = data["point_cloud_labels"]
            self.envs = [env() for env in df.env_lists]
            self.load_env_configs()
            self.point_cloud_dfs = []
            for i, pcd in enumerate(self.point_clouds):
                self.point_cloud_dfs.append(self.compute_distance_field(pcd, int(self.point_cloud_labels[i])))
            self.point_cloud_dfs = np.asarray(self.point_cloud_dfs)

    def load_env_configs(self):
        self.pcd_to_env = []
        self.pcd_pos = []
        self.pcd_rotation = []
        filelist = os.listdir("data/seeds_scale/obj_pose")
        filelist.sort(key = lambda x: int(x[5]))
        for file in filelist:
            z = np.load(f"data/seeds_scale/obj_pose/{file}")
            self.pcd_to_env.append(int(z['env_id']))
            self.pcd_pos.append(z['trans'])
            self.pcd_rotation.append(z['rot'])

    def __len__(self):
        return len(self.scores)

    def compute_distance_field(self, pcd, pcd_id):
        """
        Assume pcd is a numpy array
        """
        pcd_o3d = o3d.geometry.PointCloud(o3d.utility.Vector3dVector(pcd))
        env_id = self.pcd_to_env[pcd_id]
        dist_env = self.envs[env_id]
        pcd_o3d.rotate(self.pcd_rotation[pcd_id])
        pcd_o3d.translate(self.pcd_pos[pcd_id])
        points = np.asarray(pcd_o3d.points)
        dist_field = dist_env.get_points_distance(points)
        return dist_field.numpy()

    def __getitem__(self, idx):
        ans = {}
        ans["point_cloud"] = self.point_clouds[idx] # np.random.normal(size=self.point_clouds[idx].shape, scale=self.noise_scale)
        ans["condition"] = self.conditions[idx]
        ans["score"] = self.scores[idx]
        if self.has_distance_field:
            ans["point_cloud_df"] = self.point_cloud_dfs[idx]
        return ans


# https://github.com/SwarnadeepGhosh
# Six Days Weather Forecast using Python and MetaWeather API

import requests
import time

API_ROOT = 'https://www.metaweather.com'
API_LOCATION = '/api/location/search/?query='  # + city
API_WEATHER = '/api/location/'  # + woeid

def print_pause(printable_data):
    time.sleep(1)
    print(printable_data+'\n')

def display_weather(weather_data):
    for i in range(len(weather_data)):
        date = weather_data[i]['applicable_date']
        state = weather_data[i]['weather_state_name']
        max_temp = weather_data[i]['max_temp']
        max_temp = round(max_temp, 2)
        min_temp = weather_data[i]['min_temp']
        min_temp = round(min_temp, 2)
        print(f" {date} \t {state} \t High: {max_temp}°C \t Low: {min_temp}°C")

def check_again():
    again = input('\nDo You want to check again ? (y/n) ').lower()
    if again == 'n':
        print_pause('Have a Good Day ..')
        time.sleep(1.5)
    elif again == 'y':
        weather_report()
    else:
        print('I cant understand, Please try again..')
        check_again()

def weather_report():
    try:
        print('Swarnadeep Welcomes you to the Weather Report Forecast.\n')
        time.sleep(1)
        city = input('Where in the World are you ? ')
        print_pause('\nGetting Location Data...')
        r1 = requests.get(API_ROOT + API_LOCATION + city)
        # if r1.status_code == 200:
        location_data = r1.json()
        woeid = location_data[0]['woeid']
        # print("Where on Earth ID is : "+str(woeid))
        print_pause('Location Data Fetched successfully...')
        time.sleep(1)

        r2 = requests.get(API_ROOT + API_WEATHER + str(woeid))
        print_pause('Getting Weather Data, Please wait...')
        print_pause('Weather Data of ' + city.capitalize() + ':')
        # We will get a dictionary having keys: consolidated_weather, time, sun_rise, sun_set, timezone_name, parent, sources, title, location_type, woeid, latt_long, timezone.
        weather_data = r2.json()['consolidated_weather']
        # We will get 6 day Weather Forecast data in weather data as a list of dictionaries.
        # Each day having keys: id,weather_state_name, weather_state_abbr, wind_direction_compass, created, applicable_date, min_temp, max_temp, the_temp, wind_speed, wind_direction, air_pressure, humidity, visibility, predictability
        display_weather(weather_data)
        check_again()

    except requests.exceptions.ConnectionError:
        print('Sorry there is a network error')
        time.sleep(1)

    except:
        print("I don't know where that is. Please enter only famous cities.\n")
        time.sleep(1)
        weather_report()

if __name__ == '__main__':
    weather_report()


# -*- coding: utf-8 -*-
# @Author: kivensu
# @Date:   2018-11-19 16:13:28
# @Last Modified by:   kivensu
# @Last Modified time: 2018-11-19 16:18:21
# @Email: 749243884@qq.com
prompt = "\nPlease enter the name of city you hava visted: "
prompt += "\n(Enter 'quit' when you are finished.)"

while True:
    city = str(input(prompt))
    if city == 'quit':
        break
    else:
        print("I'd love to go to " + city.title() + "!")


import copy
import time

class Problem(object):

    def __init__(self, initial):
        self.initial = initial
        self.type = len(initial)
        self.height = int(self.type/3)

    def goal_test(self, state):
        total = sum(range(1, self.type+1))

        for row in range(self.type):
            if (len(state[row]) != self.type) or (sum(state[row]) != total):
                return False

            column_total = 0
            for column in range(self.type):
                column_total += state[column][row]

            if (column_total != total):
                return False

        for column in range(0,self.type,3):
            for row in range(0,self.type,self.height):

                block_total = 0
                for block_row in range(0,self.height):
                    for block_column in range(0,3):
                        block_total += state[row + block_row][column + block_column]

                if (block_total != total):
                    return False

        return True

    def filter_values(self, values, used):
        return [number for number in values if number not in used]

    def get_spot(self, board, state):
        for row in range(board):
            for column in range(board):
                if state[row][column] == 0:
                    return row, column

    def filter_row(self, state, row):
        number_set = range(1, self.type+1)
        in_row = [number for number in state[row] if (number != 0)]
        options = self.filter_values(number_set, in_row)
        return options

    def filter_col(self, options, state, column):
        in_column = []
        for column_index in range(self.type):
            if state[column_index][column] != 0:
                in_column.append(state[column_index][column])
        options = self.filter_values(options, in_column)
        return options

    def filter_quad(self, options, state, row, column):
        in_block = []
        row_start = int(row/self.height)*self.height
        column_start = int(column/3)*3

        for block_row in range(0, self.height):
            for block_column in range(0,3):
                in_block.append(state[row_start + block_row][column_start + block_column])
        options = self.filter_values(options, in_block)
        return options

    def actions(self, state):
        row,column = self.get_spot(self.type, state)

        options = self.filter_row(state, row)
        options = self.filter_col(options, state, column)
        options = self.filter_quad(options, state, row, column)

        for number in options:
            new_state = copy.deepcopy(state)
            new_state[row][column] = number
            yield new_state

class Node:

    def __init__(self, state, g):
        self.state = state
        self.g = g
        self.h = 0
        self.marked = 0
        for i in range(len(state)):
            for j in range(len(state[i])):
                if state[i][j] == 0:
                    self.h = self.h + 1

    def expand(self, problem):
        self.marked = 1
        return [Node(state, self.g + 1) for state in problem.actions(self.state)]

    def getAn(self):
        return self.g + self.h

def RBFS(problem):
    nodes = []
    start = Node(problem.initial, 0)

    nodes.append(start)

    while nodes:
        min_node = nodes[0]
        for node in nodes:
            if node.getAn() < min_node.getAn():
                min_node = node

        if problem.goal_test(min_node.state):
            return min_node.state

        nodes.remove(min_node)
        for node in min_node.expand(problem):
            nodes.append(node)

    return None

def solve_RBFS(board):
    print ("\nSolving with RBFS ...")
    start_time = time.time()
    problem = Problem(board)
    solution = RBFS(problem)
    elapsed_time = time.time() - start_time

    if solution:
        print ("Found solution")
        for row in solution:
            print (row)
    else:
        print ("No possible solutions")

    print ("Time: " + str(elapsed_time))


from lesson09HW.classes.connection_to_db import ConnectionToDB
from lesson09HW.classes.planet import Planet

class PlanetController:

    def add_planet(self, planet):
        connection_to_db = ConnectionToDB()
        current_connection = connection_to_db.get_connection()
        cursor = current_connection.cursor()

        cursor.execute(f'INSERT INTO Planets (name, radius, core_temperature, has_atmosphere, has_life, galaxy_id) '
                       f'VALUES ("{planet.name}", "{planet.radius}", "{planet.core_temperature}", '
                       f'"{planet.has_atmosphere}", "{planet.has_life}", "{planet.galaxy_id}")')
        current_connection.commit()
        connection_to_db.disconnect_from_db()

    def get_planets(self):
        connection_to_db = ConnectionToDB()
        current_connection = connection_to_db.get_connection()
        cursor = current_connection.cursor()
        cursor.execute(f'SELECT * FROM Planets')
        planets = [Planet(item[1], item[2], item[3], item[4], item[5], item[6], id=item[0]) for item in cursor.fetchall()]
        connection_to_db.disconnect_from_db()
        return planets

    def get_planets_with_life_by_galaxy(self, galaxy_name):
        connection_to_db = ConnectionToDB()
        current_connection = connection_to_db.get_connection()
        cursor = current_connection.cursor()
        cursor.execute(f'SELECT * FROM Planets INNER JOIN Galaxies ON Planets.galaxy_id = Galaxies.id '
                       f'WHERE Galaxies.name = "{galaxy_name}" AND Planets.has_life = 1')
        planets = [Planet(item[1], item[2], item[3], item[4], item[5], item[6], id=item[0]) for item in cursor.fetchall()]
        connection_to_db.disconnect_from_db()
        return planets

    def get_planets_with_min_radius(self):
        connection_to_db = ConnectionToDB()
        current_connection = connection_to_db.get_connection()
        cursor = current_connection.cursor()
        cursor.execute(f'SELECT * FROM Planets WHERE radius = (select min(radius)from Planets)')
        planets = [Planet(item[1], item[2], item[3], item[4], item[5], item[6], id=item[0]) for item in cursor.fetchall()]
        connection_to_db.disconnect_from_db()
        return planets

    def get_planet_with_max_satellites(self):
        connection_to_db = ConnectionToDB()
        current_connection = connection_to_db.get_connection()
        cursor = current_connection.cursor()
        cursor.execute(f'SELECT * FROM Satellites GROUP BY planet_id ORDER BY count(planet_id) DESC LIMIT 1')
        satellite = cursor.fetchall()
        cursor.execute(f'SELECT * FROM Planets WHERE id = {satellite[0][3]}')
        planet = cursor.fetchall()
        connection_to_db.disconnect_from_db()
        return Planet(planet[0][1], planet[0][2], planet[0][3], planet[0][4], planet[0][5], planet[0][6], id=planet[0][0])


import cv2 as cv
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.cm as cm
from time import sleep
import numpy as np

face_detector = cv.CascadeClassifier('haarcascade_frontalface_default.xml')

def show_points(room_size,tracked_points,cam_position,pad=2):

    room_width = room_size[2]-room_size[0];
    room_height = room_size[3]-room_size[1];
    rectangle = plt.Rectangle((0,0), room_width, room_height);#, fc='r')
    plt.plot((cam_position[0],cam_position[0]), (0,room_height),color='yellow',linewidth=5);
    plt.gca().add_patch(rectangle)
    plt.xlim((room_size[0]-pad,room_size[2]+pad));
    plt.ylim((room_size[1]-pad,room_size[3]+pad));
    plt.plot(cam_position[0],cam_position[1],marker='D',color='red',markersize=25,label=' Web Camera');

    temp_id = 0;
    colormap = plt.cm.gist_ncar;
    colorst = [colormap(i) for i in np.linspace(0, 0.9,len(tracked_points))];  #to get each person a different color
    for i in tracked_points:
        temp_id += 1;
        plt.plot(i[0],i[1],marker='o',color=colorst[temp_id-1]);
        plt.pause(0.5);

    plt.legend(loc='best');
    plt.pause(0.5);
    plt.clf();#to reuse the same plot and alleviates the use of explicit closing of plots.