import logging
import typing as ty

import requests
from flask import Blueprint, Response

_LOG = logging.getLogger(__name__)
BP = Blueprint("proxy", __name__, url_prefix="/proxy")

_EXCLUDED_HEADERS = [
    "content-encoding",
    "content-length",
    "transfer-encoding",
    "connection",
]

@BP.route("/<path:path>", methods=["GET"])
def proxy(path: str) -> ty.Any:
    _LOG.debug("proxy request to: %s", path)

    resp = requests.get(path, timeout=30)
    headers = [
        (name, value)
        for (name, value) in resp.raw.headers.items()
        if name.lower() not in _EXCLUDED_HEADERS
    ]

    _LOG.debug("proxy request result: status: %r", resp.status_code)
    return Response(resp.content, resp.status_code, headers)


# Databricks notebook source
# MAGIC %md
# MAGIC
# MAGIC

# COMMAND ----------

# MAGIC %md
# MAGIC
# MAGIC ##Read Clicks Kinesis streams and produce the Bronze and Silver medallion tables

# COMMAND ----------

# DBTITLE 1,Clean up - in case I needed to rerun
dbutils.fs.rm("s3://aws-cdl-devdays/clicks-bronze", True)
dbutils.fs.rm("s3://aws-cdl-devdays/clicks-silver", True)
dbutils.fs.rm("s3://aws-cdl-devdays/checkpoint-clicks-bronze", True)
dbutils.fs.rm("s3://aws-cdl-devdays/checkpoint-clicks-silver", True)

# COMMAND ----------

# MAGIC %sql USE aws_cdl_devdays;

# COMMAND ----------

# DBTITLE 1,Read Kinesis Stream
from pyspark.sql.types import *
from pyspark.sql.functions import *

clicks_schema= StructType() \
          .add("uid", StringType()) \
          .add("clickTimestamp", TimestampType()) \
          .add("exchangeID", IntegerType()) \
          .add ("publisher", StringType()) \
          .add ("creativeID", IntegerType()) \
          .add("click", StringType()) \
          .add ("advertiserID", IntegerType()) \
          .add("browser", StringType()) \
          .add("geo", StringType()) \
          .add("bidAmount", DoubleType())

clicks = spark \
  .readStream \
  .format("kinesis") \
  .option("streamName", "aws-cdl-devdays-clicks") \
  .option("initialPosition", "latest") \
  .option("region", "us-west-2") \
  .load()

# COMMAND ----------

# DBTITLE 1,Convert JSON to String, and add Partitioning Columns
clicks_raw = clicks.selectExpr("cast (data as STRING) jsonData", "approximateArrivalTimestamp") \
                 .withColumn("approximateArrivalDate",to_date(col("approximateArrivalTimestamp")))
display(clicks_raw)

# COMMAND ----------

# MAGIC %md
# MAGIC
# MAGIC ##Write Click data from Kinesis to Bronze delta table

# COMMAND ----------

# DBTITLE 1,Write to Bronze Table
clicks_raw.writeStream \
    .format("delta") \
    .outputMode("append") \
    .option("checkpointLocation","s3://aws-cdl-devdays/checkpoint-clicks-bronze") \
    .partitionBy("approximateArrivalDate") \
    .trigger(processingTime='30 seconds') \
    .start("s3://aws-cdl-devdays/clicks-bronze")

# COMMAND ----------

# DBTITLE 1,Create Metastore Reference - Bronze Data
# MAGIC %sql
# MAGIC DROP TABLE IF EXISTS aws_cdl_devdays.clicks_bronze;
# MAGIC CREATE TABLE aws_cdl_devdays.clicks_bronze USING DELTA LOCATION "s3://aws-cdl-devdays/clicks-bronze"

# COMMAND ----------

# DBTITLE 1,Safely query the Clicks Bronze Data
# MAGIC %sql
# MAGIC SELECT * FROM aws_cdl_devdays.clicks_bronze
# MAGIC LIMIT 10;

# COMMAND ----------

# MAGIC %sql
# MAGIC SELECT COUNT(*) FROM aws_cdl_devdays.clicks_bronze

# COMMAND ----------

# MAGIC %md
# MAGIC ### Databricks Utilities - dbutils
# MAGIC * For in-notebook documentation on DBUtils you can execute the command `dbutils.help()`.
# MAGIC * See also Databricks Utilities for Notebooks

# COMMAND ----------

dbutils.notebook.exit("stop")

# COMMAND ----------

# DBTITLE 1,Read Bronze Delta table as a stream, and parse schema
bronze_data = spark \
  .readStream \
  .format("delta") \
  .load("s3://aws-cdl-devdays/clicks-bronze") \
  .select(from_json("jsonData", clicks_schema).alias("fields"), "approximateArrivalDate", "approximateArrivalTimestamp") \
  .select("fields.*","approximateArrivalDate","approximateArrivalTimestamp")

# COMMAND ----------

# DBTITLE 1,Perform some cleaning
#Example cleaning, lowercase browser and create date column
bronze_data_cleaned = bronze_data.withColumn("browserCleaned",lower(col("browser"))) \
                                 .withColumn("clickDate",to_date(col("clickTimestamp")))

# COMMAND ----------

display(bronze_data_cleaned)

# COMMAND ----------

# MAGIC %md
# MAGIC
# MAGIC ##Write Click data from Bronze to Silver delta table

# COMMAND ----------

# DBTITLE 1,Write parsed + cleaned Clicks data to silver
bronze_data_cleaned.writeStream \
    .format("delta") \
    .outputMode("append") \
    .option("checkpointLocation","s3://aws-cdl-devdays/checkpoint-clicks-silver") \
    .partitionBy("clickDate") \
    .trigger(processingTime='30 seconds') \
    .start("s3://aws-cdl-devdays/clicks-silver")

# COMMAND ----------

# DBTITLE 1,Create metastore reference - Silver Data
# MAGIC %sql
# MAGIC DROP TABLE IF EXISTS aws_cdl_devdays.clicks_silver;
# MAGIC CREATE TABLE aws_cdl_devdays.clicks_silver USING DELTA LOCATION "s3://aws-cdl-devdays/clicks-silver"

# COMMAND ----------

# MAGIC %sql
# MAGIC SELECT * FROM aws_cdl_devdays.clicks_silver
# MAGIC LIMIT 10;

# COMMAND ----------

# MAGIC %sql
# MAGIC SELECT COUNT(*) FROM aws_cdl_devdays.clicks_silver;

# COMMAND ----------

# MAGIC %sql
# MAGIC SELECT COUNT(*) FROM aws_cdl_devdays.clicks_bronze;

# COMMAND ----------

# DBTITLE 1,Read the Profiles
people_profile = spark.read.format("delta").load("s3://aws-cdl-devdays/data/people-profile")

# COMMAND ----------

display(people_profile)

# COMMAND ----------

people_profile.count()

# COMMAND ----------

# DBTITLE 1,Read point-in-time Clicks_Silver into a DataFrame
clicks_silver = spark.read.format("delta").load("s3://aws-cdl-devdays/clicks-silver/")

# COMMAND ----------

clicks_silver.count()

# COMMAND ----------

# DBTITLE 1,Perform a Left Outer join between Clicks_Silver and the People_profile dataset
clicks_with_profile = clicks_silver.join(people_profile, on="uid", how="left")
clicks_with_profile.createOrReplaceTempView("clicks_view")

# COMMAND ----------

dbutils.fs.rm('s3://aws-cdl-devdays/clicks-with-profile', True)

# COMMAND ----------

# MAGIC %sql
# MAGIC DROP TABLE IF EXISTS clicks_with_profile;
# MAGIC
# MAGIC CREATE TABLE clicks_with_profile
# MAGIC USING delta
# MAGIC LOCATION "s3://aws-cdl-devdays/clicks-with-profile"
# MAGIC AS SELECT * FROM clicks_view;
# MAGIC
# MAGIC -- View Delta Lake table
# MAGIC SELECT *
# MAGIC FROM clicks_with_profile
# MAGIC LIMIT 10;

# COMMAND ----------

# MAGIC %sql
# MAGIC SELECT COUNT(*) FROM clicks_with_profile;

# COMMAND ----------

# MAGIC %sql
# MAGIC select geo, sum(bidAmount) as sum_bidAmount FROM clicks_with_profile group by geo order by sum_bidAmount desc

# COMMAND ----------

# MAGIC %sql
# MAGIC DESCRIBE history clicks_with_profile

# COMMAND ----------

# MAGIC %md
# MAGIC ### [Back to the main demo - Step4](https://field-eng.cloud.databricks.com/#notebook/1566801/command/1566811)


import logging
import datetime

class CustomFormatter(logging.Formatter):
    """Logging colored formatter, adapted from https://stackoverflow.com/a/56944256/3638629"""

    grey        = '\x1b[38;21m'
    blue        = '\x1b[38;5;39m'
    yellow      = '\x1b[38;5;226m'
    red         = '\x1b[38;5;196m'
    bold_red    = '\x1b[31;1m'
    green       = '\u001b[32m'
    magenta     = '\u001b[35m'
    cyan        = '\u001b[36m'
    reset       = '\x1b[0m'

    def __init__(self, fmt):
        super().__init__()
        self.fmt = fmt
        self.FORMATS = {
            logging.DEBUG: self.grey + self.fmt + self.reset,
            logging.INFO: self.cyan + self.fmt + self.reset,
            logging.WARNING: self.yellow + self.fmt + self.reset,
            logging.ERROR: self.red + self.fmt + self.reset,
            logging.CRITICAL: self.bold_red + self.fmt + self.reset
        }

    def format(self, record):
        log_fmt = self.FORMATS.get(record.levelno)
        formatter = logging.Formatter(log_fmt)
        return formatter.format(record)

# Define format for logs
fmt = "%(asctime)s | %(filename)s | %(levelname)s | %(message)s" #[line:%(lineno)d]"

# Create stdout handler for logging to the console (logs all five levels)
today = datetime.date.today()
logging.basicConfig(
    level=logging.DEBUG,
    filename='Image_restorer_{}.log'.format(today.strftime('%Y_%m_%d')),
    filemode='a',
    format=fmt,
    force=True
)

stdout_handler = logging.StreamHandler()
stdout_handler.setFormatter(CustomFormatter(fmt))
logging.getLogger().addHandler(stdout_handler)


# -*- coding: UTF-8 -*-
import numpy as np
import cv2
import matplotlib.pyplot as plt
import math

#To not abbreviate big matrices
np.set_printoptions(threshold='nan')

#0º step: Get the images and change the type
originalImage = cv2.imread('Cameraman.tif', 0)
originalImage = np.float32(originalImage)
M, N = np.shape(originalImage) #Number of lines and columns

#1º step: Get the filling parameters--------------------------------------------
M, N = np.shape(originalImage)
P = 2 * M
Q = 2 * N
distance = np.zeros((P,Q), dtype=np.float32)
H1 = np.zeros((P,Q), dtype=np.float32)
H2 = np.zeros((P,Q), dtype=np.float32)
filteredDft1 = np.zeros((P,Q), dtype=np.float32)
filteredDft2 = np.zeros((P,Q), dtype=np.float32)
D01 = 50
D02 = 50

#2º step: Building an image with the length of P and Q--------------------------
transformedImage = np.zeros((P,Q), dtype=np.float32)

for i in range(M):
    for j in range(N):
        transformedImage[i][j] = originalImage[i][j]

#3º step: Centering the Image---------------------------------------------------
#To move the information in the corners to the center in the frequency domain
def centeringImage(image):
    P, Q = np.shape(image)
    for i in range(P):
        for j in range(Q):
            image[i][j] = image[i][j] * (-1)**(i+j)
    return image

transformedImage = centeringImage(transformedImage)

#4º step: FFT calculation-------------------------------------------------------
dft1 = np.fft.fft2(transformedImage)
dft2 = np.fft.fft2(transformedImage)
#dft_shift = np.fft.fftshift(dft) #(another way) To move the information in the corners to the center in the frequency domain
#5º step: Apply the filter H: H(i,j)F(i,j)--------------------------------------

#Distance calculation to create the filters
for i in range(P):
    for j in range(Q):
        distance[i][j] = math.sqrt( (i - P/2)**2 + (j - Q/2)**2 )

#Creating the filters and applying then
for i in range(P):
    for j in range(Q):
        if distance[i][j] < D01:
            H1[i][j] = 1

        if distance[i][j] > D02:
            H2[i][j] = 1

        filteredDft1[i][j] =  H1[i][j]*dft1[i][j]
        filteredDft2[i][j] =  H2[i][j]*dft2[i][j]
#6º step: Applying the inverse transform----------------------------------------

img_back1 = np.fft.ifft2(filteredDft1)
img_back1 = centeringImage(img_back1)
transformedImage1 = np.zeros((M,N), dtype=np.float32)

img_back2 = np.fft.ifft2(filteredDft2)
img_back2 = centeringImage(img_back2)
transformedImage2 = np.zeros((M,N), dtype=np.float32)
#7º step: Resize the image------------------------------------------------------
for i in range(M):
    for j in range(N):
        value1 = img_back1[i][j]
        if value1 > 255:
            value1 = 255

        if value1 < 0:
            value1 = 0

        value2 = img_back2[i][j]
        if value2 > 255:
            value2 = 255

        if value2 < 0:
            value2 = 0
        transformedImage1[i][j] = value1
        transformedImage2[i][j] = value2

#8º step: Showing the results---------------------------------------------------
transformedImage1 = np.uint8(transformedImage1)
transformedImage2 = np.uint8(transformedImage2)

plt.figure(1)
plt.subplot(121),plt.imshow(originalImage, cmap = 'gray')
plt.title('Imagem de entrada '), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(transformedImage1, cmap = 'gray')
plt.title('Aplicando passa baixa'), plt.xticks([]), plt.yticks([])

plt.figure(2)
plt.subplot(121),plt.imshow(originalImage, cmap = 'gray')
plt.title('Imagem de entrada '), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(transformedImage2, cmap = 'gray')
plt.title('Aplicando passa alta'), plt.xticks([]), plt.yticks([])

plt.show()


# NOTES: Game responds to Player - also Start, Loop and Exit
# Will import from ALL Class: Board, Position, Validator, Player

from Board import Board
from Position import Position
from Validator import Validator
from Player import Player

class Game:

    col = 0     # Beginning Value for Col
    row = 0     # Beginning Value for Row

    # Get Name from Player
    def get_player_name(self, user_name):
        player = Player()
        player.player_name(user_name)

        # Begin Loop
        while True:
            user_input = input("enter a command:").split(" ")
            print("\n")

            # Respond to Player
            if user_input[0] == 'place':
                command = user_input[0]
                user_ship = user_input[1].split(",")
                orientation = user_ship[0]
                r = user_ship[1]
                row = int(r)
                c = user_ship[2]
                col = int(c)

                place = Validator()
                place.is_valid_position(row, col)

                b1 = Board()
                b1.place_ship(orientation, row, col)

                if orientation == 'h':
                    p1 = Position()
                    p1.horizontal_position(row, col)

                elif orientation == 'v':
                    p2 = Position()
                    p2.vertical_position(row, col)
            # Show Ship
            elif user_input[0] == 'show':
                b2 = Board()
                b2.show_ships(row, col)
            # Exit Loop
            elif user_input[0] == 'exit':
                print("\nSee you later.\n")
                break
            else:
                # Provide this message when entered value is not in the choices.
                print("\nI don't understand that choice, please try again.\n")


from win32api import *
from time import sleep
import keyboard
import win32api, win32con

def recorder():
    with open("recording.txt", "w") as f:
        while True:
            sleep(0.01)
            x, y = GetCursorPos()
            print("{},{}".format(x, y))
            f.write("{},{}\n".format(x, y))
            try:
                if keyboard.is_pressed('q'):
                    print('Stopped Recording!')
                    break
            except:
                break

def playback():
    mouse_list = []
    with open("recording.txt", "r") as f:
        for i in f:
            i = i.strip('\n')
            i = i.split(",")
            for j in range(0, len(i)):
                i[j] = int(i[j])
            mouse_list.append(i)

    for i in mouse_list:
        if keyboard.is_pressed('q'):
                print('Stopped Playing')
                break
        sleep(0.02)
        x, y = i
        win32api.mouse_event(win32con.MOUSEEVENTF_MOVE | win32con.MOUSEEVENTF_ABSOLUTE, int(x/1920*65535.0), int(y/1080*65535.0))

def main():

    while True:
        try:
            if keyboard.is_pressed('f1'):
                print('Recording...')
                recorder()
            if keyboard.is_pressed('f2'):
                print('Playback...')
                playback()
                print('Playback Finished!...')

            if keyboard.is_pressed('f3'):
                break

        except:
             break

if __name__ == "__main__":
    main()


import json
import os
import const

class ProfileSet:
    def __init__(self):
        self.R4Data = list()
        self.QOPData = list()
        self.RANKData = list()
        self.GraphsColors = ["#000000", "#000000", "#000000", "#000000", "#000000", "#000000", "#000000", "#000000"]
        self.GraphsValues = ["1", "100", "10", "0", "1000", "10"]
        self.AproxColors = ["#000000", "#000000"]
        self.AproxValues = ["1", "100", "10", "0", "1000", "10"]

        if not os.path.isfile("profile.json"):
            return

        with open("profile.json", 'r') as f:
            jsText = json.load(f)
            self.__dict__ = json.loads(jsText)

    def SaveToFile(self):
        with open("profile.json", 'w') as f:
            jsText = json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4, ensure_ascii=False)
            json.dump(jsText, f)

    def DataPrint(self, setList):
        retval = ""
        for item in setList:
            retval += str(item['Number']) + ' ' + str(item['Time']) + ' ' + str(item['Value']) + '\n'
        return retval

    def GenRankData(self):
        self.RANKData = list()
        for r4 in self.R4Data:
            for qop in self.QOPData:
                if qop['Number'] == r4['Number']:
                    self.RANKData.append({'Number' : r4['Number'], 'Time' : qop['Time'], 'Value' : r4['Value'] - qop['Value']})
                    break

    def GenR4Data(self):
        self.R4Data = list()
        for qop in self.QOPData:
            for rank in self.RANKData:
                if rank['Number'] == qop['Number']:
                    self.R4Data.append({'Number' : qop['Number'], 'Time' : qop['Time'], 'Value' : rank['Value'] + qop['Value']})
                    break

    def GenQOPData(self):
        self.QOPData = list()
        for r4 in self.R4Data:
            for rank in self.RANKData:
                if rank['Number'] == r4['Number']:
                    self.R4Data.append({'Number' : r4['Number'], 'Time' : rank['Time'], 'Value' : r4['Value'] - rank['Value']})
                    break

    def ReadData(self, file, typeLoad):
        newList = list()
        while True:
            line = file.readline().rstrip()
            if not line:
                break

            items = line.split(' ')
            if len(items) != 3:
                continue

            newList.append({'Number' : int(items[0]), 'Time' : float(items[1]), 'Value' : int(items[2])})

        if typeLoad == const.FOR_R4:
            self.R4Data = newList
        elif typeLoad == const.FOR_QOP:
            self.QOPData = newList
        elif typeLoad == const.FOR_RANK:
            self.RANKData = newList

    def AppendData(self, filename, typeLoad):
        with open(filename, 'r') as f:
            if typeLoad == const.FOR_ALL:
                self.R4Data = list()
                self.QOPData = list()
                self.RANKData = list()

                while True:
                    line = f.readline().rstrip()
                    if not line:
                        break

                    items = line.split(' ')
                    if len(items) != 5:
                        return 0

                    self.R4Data.append({'Number' : int(items[0]), 'Time' : float(items[1]), 'Value' : int(items[2])})
                    self.QOPData.append({'Number' : int(items[0]), 'Time' : float(items[1]), 'Value' : int(items[3])})
                    self.RANKData.append({'Number' : int(items[0]), 'Time' : float(items[1]), 'Value' : int(items[4])})
            else:
                self.ReadData(f, typeLoad)
                if len(self.R4Data) and len(self.QOPData) != "":
                    self.GenRankData()
                elif len(self.RANKData) != "" and len(self.QOPData):
                    self.GenR4Data()
                elif len(self.RANKData) != "" and len(self.R4Data) != "":
                    self.GenQOPData()
            return 1


import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

# parameter settings for RQ GPIS
alpha = 100
sigma = 1
l = 0.01

# parameter settings for log-GPIS
Lambda = 100
v = 3 / 2
scale = np.sqrt(2 * v)

# parameter setting for GP
noise = 0.05

def pair_dist(x1, x2):
    return np.linalg.norm(x2 - x1, axis=-1)

def cdist(x, y):
    return np.sqrt(np.sum((x[:, None] - y[None]) ** 2, axis=-1))

def pair_diff(x1, x2):
    return x1 - x2

def cdiff(x, y):
    return x[:, None] - y[None]

def cov(x1, x2, gpis=1):
    d = cdist(x1, x2)
    # RQ GPIS
    if gpis == 1:
        return sigma ** 2 * (1 + (d / l) ** 2 / (2 * alpha)) ** (-alpha)
    # log-GPIS
    elif gpis == 2:
        return (1 + d * (np.sqrt(2 * v)) * (Lambda / scale)) * np.exp(-1 * (d * (np.sqrt(2 * v)) * (Lambda / scale)))

def cov_grad(x1, x2, gpis=1):
    pair_diff = cdiff(x1, x2)
    d = np.linalg.norm(pair_diff, axis=-1)
    # RQ GPIS
    if gpis == 1:
        return (sigma ** 2 * (-alpha) * (1 + (d / l) ** 2 / (2 * alpha)) ** (-alpha - 1) * (
                d / (alpha * l ** 2))).reshape((x1.shape[0], x2.shape[0], 1)) * pair_diff
    # log-GPIS
    elif gpis == 2:
        return (- ((np.sqrt(2 * v)) * (Lambda / scale)) ** 2 * np.exp(
            -1 * (d * (np.sqrt(2 * v)) * (Lambda / scale)))).reshape((x1.shape[0], x2.shape[0], 1)) * pair_diff

def fibonacci_sphere(num_samples):
    points = []
    phi = np.pi * (3. - np.sqrt(5.))  # golden angle in radians
    y = np.linspace(1, -1, num_samples)
    radius = np.sqrt(1 - y * y)
    theta = phi * np.arange(num_samples)
    x = np.cos(theta) * radius
    z = np.sin(theta) * radius
    return x, y, z

def reverting_function(x, gpis=1):
    # RQ GPIS
    if gpis == 1:
        return np.sqrt(np.abs(2 * alpha * l ** 2 * ((x / sigma ** 2) ** (1 / (-alpha)) - 1)))
    # log-GPIS
    elif gpis == 2:
        return -(1 / Lambda) * np.log(np.abs(x))

def reverting_function_derivative(x, gpis=1):
    # RQ GPIS
    if gpis == 1:
        return (l ** 2 * (-(x / sigma ** 2) ** (-1 / alpha - 1)) / sigma ** 2) / reverting_function(x, gpis)
    # log-GPIS
    elif gpis == 2:
        return -1 / (Lambda * x)

model = None

def queryOne(points, query):
    global model
    # 1: RQ GPIS, 2: log-GPIS
    gpis = 1

    N_obs = points.shape[0]
    k = cov(query, points, gpis)

    if model is None:
        K = cov(points, points, gpis)
        y = np.ones((N_obs, 1))
        model = np.linalg.solve(K + noise * np.identity(N_obs), y)

    # distance inference
    mu = k @ model
    mean = reverting_function(mu, gpis)

    # gradient inference
    covariance_grad = cov_grad(query, points, gpis)
    mu_derivative = np.sum(covariance_grad * model[None, :, :], axis=1)
    grad = reverting_function_derivative(mu, gpis) * mu_derivative
    grad = grad.T

    # gradient normalization
    # norms = np.linalg.norm(grad, axis=0, keepdims=True)
    # grad = np.where(norms != 0, grad, grad / np.min(np.abs(grad), axis=0))
    grad /= np.linalg.norm(grad, axis=0, keepdims=True)
    # grad = np.where(norms != 0, grad / norms, grad)

    return mean, grad

def GPIS(points):
    global model
    # 1: RQ GPIS, 2: log-GPIS
    gpis = 1

    # using a 2D plane to query the distances
    start = -np.pi
    end = np.pi
    samples = int((end - start) / 0.05) + 1
    xg, yg = np.meshgrid(np.linspace(start, end, samples), np.linspace(start, end, samples))
    querySlice = np.column_stack((xg.reshape(-1), yg.reshape(-1), np.zeros(xg.shape).reshape(-1)))

    N_obs = points.shape[0]

    K = cov(points, points, gpis)
    k = cov(querySlice, points, gpis)
    y = np.ones((N_obs, 1))
    model = np.linalg.solve(K + noise * np.identity(N_obs), y)

    # distance inference
    mu = k @ model
    mean = reverting_function(mu, gpis)

    # gradient inference
    covariance_grad = cov_grad(querySlice, points, gpis)
    mu_derivative = np.sum(covariance_grad * model[None, :, :], axis=1)
    grad = reverting_function_derivative(mu, gpis) * mu_derivative
    grad = grad.T

    # gradient normalization
    # norms = np.linalg.norm(grad, axis=0, keepdims=True)
    # grad = np.where(norms != 0, grad, grad / np.min(np.abs(grad), axis=0))
    grad /= np.linalg.norm(grad, axis=0, keepdims=True)

    # GPIS visualization
    xg = querySlice[:, 0].reshape(xg.shape)
    yg = querySlice[:, 1].reshape(yg.shape)
    zg = np.zeros(xg.shape)

    xd = grad[0].reshape(xg.shape)
    yd = grad[1].reshape(yg.shape)
    zd = grad[2].reshape(xg.shape)
    colors = np.arctan2(xd, yd)

    mean = mean.reshape(xg.shape)

    return xg, yg, zg, xd, yd, zd, mean, colors

if __name__ == "__main__":
    # creating a sphere point cloud
    N_obs = 100  # number of observations
    sphereRadius = 1
    xa, yb, zc = fibonacci_sphere(N_obs)
    sphere = sphereRadius * np.column_stack((xa, yb, zc))

    xg, yg, zg, xd, yd, zd, mean, colors = GPIS(sphere)

    fig = plt.figure(figsize=(15, 5))
    fig.suptitle('GPIS result')

    # First subplot
    ax = fig.add_subplot(1, 2, 1, projection='3d')
    surf = ax.plot_surface(xg, yg, mean, cmap=cm.coolwarm,
                           linewidth=0, antialiased=False)
    plt.colorbar(surf, shrink=0.5, aspect=5, ax=ax)
    ax.set_title('Distance field')

    # Second subplot
    ax = fig.add_subplot(1, 2, 2)
    colormap = cm.inferno
    ax.scatter(sphere[:, 0], sphere[:, 1], alpha=0.05)
    ax.quiver(xg, yg, xd, yd, colors, angles='xy', scale=100)
    ax.set_aspect('equal')
    ax.set_title('Gradient field')

    plt.show()


import subprocess
import threading
import fcntl
import os
import time

class DezzerPlayer():

    def __init__(self):
        self._process = None
        self._callback = None
        self._thread = None

    def exit(self):
        self._callback = None
        self.stop()

    def stop(self):
        print("stopping thread now ...")
        if self._process:
            self.communicate('exit')
            #line, err = self._process.communicate('exit\n'.encode())
            #print("result from process: " + str(line))

    def pause(self):
        print("pause deezer player")
        self.communicate('pause')

    def resume(self):
        print("resume deezer player")
        self.communicate('resume')

    def communicate(self, input):
        if self._process:
            command = input + '\n'
            #line, err = self._process.communicate(command.encode())

            self._process.stdin.write(command.encode())
            if self._process:
                self._process.stdin.flush()

            stdout = ''
            stderr = ''
            is_stdout_failed = True
            is_stderr_failed = True
            sleep = 0.2
            error_count = 0
            while True:
                # Read from stdout
                print("read stdout")
                try:
                    stdout = self._process.stdout.read()
                    break
                except Exception:
                    pass
                time.sleep(sleep)
                if(error_count > 1):
                    break
                error_count = error_count + 1

            error_count = 0
            while True:
                # Read from stderr
                print("read stderr")
                try:
                    stderr = self._process.stderr.read()
                    break
                except Exception:
                    pass
                time.sleep(sleep)
                if(error_count > 1):
                    break
                error_count = error_count + 1

            #print("stdout from process: " + str(stdout))
            #print("stderr from process: " + str(stderr))

    def play(self, dz_track_uri, callback):
        self.exit()
        self._callback = callback
        dz_track_uri = str(dz_track_uri)
        #command = "./NanoPlayer dz_track dzmedia:///track/85509044"
        command = "./Player/NanoPlayer dz_track dzmedia:///track/" + dz_track_uri
        print(command)

        self.popenAndCall(command)

    def popenAndCall(self, command):
        """
        Runs the given args in a subprocess.Popen, and then calls the function
        onExit when the subprocess completes.
        onExit is a callable object, and popenArgs is a list/tuple of args that
        would give to subprocess.Popen.
        """

        def runInThread(command, nothing):

            self._process = subprocess.Popen(command.split()
                ,stdin=subprocess.PIPE
                ,stdout=subprocess.PIPE
                ,stderr=subprocess.PIPE
                ,shell=False)

            # Fix the pipes to be nonblocking
            fcntl.fcntl(self._process.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
            fcntl.fcntl(self._process.stderr.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)

            self._process.wait()

            if self._callback:
                self._callback()
                #print("callback was called. terminate process and set to null.")
            #self._process = None
            return

        thread = threading.Thread(target=runInThread, args=(command, None))
        thread.start()
        # returns immediately after the thread starts
        return thread

Player = DezzerPlayer()


import os
import requests

from dateutil.parser import parse
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

class GmailApiUtils:
    LABELS_LIST = ['INBOX', 'UNREAD', 'IMPORTANT', 'SENT', 'DRAFT', 'SPAM', 'TRASH']
    EMAIL_VALUE_MAP = {
        'from': lambda email_headers_dict: email_headers_dict['From'],
        'to': lambda email_headers_dict: email_headers_dict['To'],
        'subject': lambda email_headers_dict: email_headers_dict['Subject'],
        'date_received': lambda email_headers_dict: (parse(email_headers_dict['Date'], ignoretz=True).date()
                                                     if 'Date' in email_headers_dict
                                                     else parse(email_headers_dict['date'], ignoretz=True).date())
    }

    def __init__(self):
        self.service = self.authenticate(['https://www.googleapis.com/auth/gmail.modify'])
        self.messages = self.service.users().messages()

    def authenticate(self, scopes):
        creds = None
        # The file token.json stores the user's access and refresh tokens, and is
        # created automatically when the authorization flow completes for the first time.
        if os.path.exists('token.json'):
            creds = Credentials.from_authorized_user_file('token.json', scopes)

        # If there are no (valid) credentials available, let the user log in.
        if not creds or not creds.valid:
            if creds and creds.expired and creds.refresh_token:
                creds.refresh(Request())
            else:
                flow = InstalledAppFlow.from_client_secrets_file(
                    'credentials.json', scopes)
                creds = flow.run_local_server(port=0)

            # Save the credentials for the next run
            with open('token.json', 'w') as token:
                token.write(creds.to_json())

        try:
            service = build('gmail', 'v1', credentials=creds)
            return service
        except HttpError as error:
            print(f'Error occurred in authenticate: {error}')
            return None

    def fetch_emails(self, labelIds=['INBOX']):
        emails = self.messages.list(userId='me', labelIds=labelIds).execute()
        return emails['messages']

    def fetch_emails_with_data(self, labelIds=['INBOX', 'IMPORTANT']):
        emails = self.messages.list(userId='me', labelIds=labelIds).execute()
        return [self.get_email(email['id']) for email in emails['messages']]

    def get_email(self, email_id):
        email = self.messages.get(userId='me', id=email_id).execute()
        return email

    def mark_label(self, email_id, label):
        # HACK: Mark email as read as READ is not a label
        if label == 'READ':
            self.messages.modify(userId='me', id=email_id, body={'removeLabelIds': ['UNREAD']}).execute()
            return

        if label not in self.LABELS_LIST:
            raise Exception(f'Invalid label: {label}')
        self.messages.modify(userId='me', id=email_id, body={'addLabelIds': [label]}).execute()

    def move_email(self, email_id, destination):
        available_destinations = ['INBOX', 'SPAM', 'TRASH']
        if destination not in available_destinations:
            raise Exception(f'Invalid destination: {destination}')

        remove_labels = available_destinations.remove(destination)
        body = {'removeLabelIds': remove_labels, 'addLabelIds': [destination]}
        self.messages.modify(userId='me', id=email_id, body=body).execute()

    def mark_label_via_api(self, email_id, label):
        modify_url = f'https://gmail.googleapis.com/gmail/v1/users/me/messages/{email_id}/modify'
        if label == 'READ':
            body = {'removeLabelIds': ['UNREAD']}
        else:
            body = {'addLabelIds': [label]}
        response = requests.post(
            modify_url,
            json=body,
            headers={'Authorization': f'Bearer {self.service._http.credentials.token}'})
        response.raise_for_status()
        return response.json()

    def move_email_via_api(self, email_id, destination):
        modify_url = f'https://gmail.googleapis.com/gmail/v1/users/me/messages/{email_id}/modify'
        available_destinations = ['INBOX', 'SPAM', 'TRASH']
        if destination not in available_destinations:
            raise Exception(f'Invalid destination: {destination}')

        remove_labels = available_destinations.remove(destination)
        body = {'removeLabelIds': remove_labels, 'addLabelIds': [destination]}
        response = requests.post(
            modify_url,
            json=body,
            headers={'Authorization': f'Bearer {self.service._http.credentials.token}'})
        response.raise_for_status()
        return response.json()


import pirog as p
from pirog import *

p.make_pirog(3,5)
""" overcook """
# """Возвращает словарь с информацией о человеке"""

def make_pirog(flour, sugar):
    if flour > 7:
        print('Big')
    if sugar > 2:
        print('Think about your health')

make_pirog(8,3)


import sys
from time import time
import numpy as np
import matplotlib.pyplot as plt
from dask import delayed
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
from skimage.data import lfw_subset
from skimage.transform import integral_image
from skimage.feature import haar_like_feature
from skimage.feature import haar_like_feature_coord
from skimage.feature import draw_haar_like_feature
import os
import glob
from PIL import Image
from sklearn import metrics

os.getcwd()
os.chdir('D:\CVproject02')
def in_array():
    Fimg = glob.glob("D:\\CVproject02\\Face16\\*.bmp")
    NFimg = glob.glob("D:\\CVproject02\\Nonface16\\*.bmp")
    p=len(Fimg[1600:2700])
    q=len(NFimg[2700:4800])
    data_x=Fimg[1600:2700]+ NFimg[2700:4800]
    x = np.array([np.array(Image.open(fname)) for fname in data_x])
    return x,p,q

def test_array():
    Fimg = glob.glob("D:\\CVproject02\\Face16\\*.bmp")
    NFimg = glob.glob("D:\\CVproject02\\Nonface16\\*.bmp")
    p=len(Fimg[1600:1700])
    q=len(NFimg[2700:2800])
    data_x=Fimg[1600:1700]+ NFimg[2700:2800]
    x = np.array([np.array(Image.open(fname)) for fname in data_x])
    return x,p,q

def extract_feature_image(img, feature_type, feature_coord):
    """Extract the haar feature for the current image"""
    ii = integral_image(img)
    return haar_like_feature(ii, 0, 0, ii.shape[0], ii.shape[1],
                             feature_type=feature_type,
                             feature_coord=feature_coord)
images = in_array()[0]
face_count=in_array()[1]
non_face_count=in_array()[2]

feature_types = ['type-2-x','type-3-x','type-3-y','type-4','type-2-y']

# Build a computation graph using Dask. This allows the use of multiple
# CPU cores later during the actual computation
X = delayed(extract_feature_image(img, feature_types, None) for img in images)
t_start = time()
X = np.array(X.compute(scheduler='threads'))
N=X.shape[0]
time_full_feature_comp = time() - t_start
y = np.array([1] * face_count + [-1] * non_face_count)
feature_coord, feature_type = \
    haar_like_feature_coord(width=images.shape[2], height=images.shape[1],
                            feature_type=feature_types)
#Threshold Computation
haar_face=X[:100,:]
haar_non_face=X[100:200,:]
mean_face=np.mean(haar_face,axis=0)
mean_non_face=np.mean(haar_non_face,axis=0)
temp=np.stack((mean_face,mean_non_face))
thresh=np.mean(temp,axis=0)

t=10
a=[]
h_x_=[]
h_t_x_=[]
weights=np.ones(N)/N
weak_classifiers=[]
for t in range(t):
#Adaboost
    e_h = np.empty((thresh.shape))
    k=X>=thresh
    h_x_not_y = np.vstack((np.where(k[:face_count,:]==False,1,0*k[:face_count,:]),\
                               np.where(~k[face_count:,:]==False,1,0*~k[face_count:,:])))
    e_h=np.dot(weights,h_x_not_y)
    min=np.argsort(e_h)[0]
    weak_classifiers=np.append(weak_classifiers,min)
    min_e=e_h[min]
    alpha=0.5*np.log((1-min_e)/min_e)
    h_x = np.vstack((np.where(k[:face_count,:]==False,-1,1*k[:face_count,:]),\
                               np.where(~k[face_count:,:]==False,1,-1*~k[face_count:,:])))
    h_t_x=h_x[:,min]

    #h_t_x_=np.append(h_t_x_,h_t_x)
    term= -1*alpha*np.multiply(h_t_x,y)
    z_t=np.multiply(weights,np.exp(term)).sum()
    weights=np.multiply(weights,np.exp(term))/z_t
    a.append(alpha)

#Testing
weak_classifiers=weak_classifiers.astype('int')
images_test = test_array()[0]
face_count_test = test_array()[1]
non_face_count_test = test_array()[2]
time_full_feature_comp = time() - t_start
y_test = np.array([1] * face_count_test + [-1] * non_face_count_test)

x_test = delayed(extract_feature_image(img, feature_type[weak_classifiers],feature_coord[weak_classifiers]) for img in images_test)
t_start = time()
x_test = np.array(x_test.compute(scheduler='threads'))

i=np.multiply(x_test,a)
output=np.sign(np.sum(i,axis=1))
s =  output == y_test
err=0
for i in range(s.shape[0]):
    if s[i]==True:
        err=err+1
accuracy =err/images_test.shape[0]
print("accuracy: "+"{:.2%}".format(accuracy))

fig, axes = plt.subplots(5, 2)
for idx, ax in enumerate(axes.ravel()):
    image = images_test[0]
    image = draw_haar_like_feature(image, 0, 0,16,16,
                                   [feature_coord[weak_classifiers[idx]]])
    ax.imshow(image)
    ax.set_xticks([])
    ax.set_yticks([])

_ = fig.suptitle('The most important features after boosting')

plt.show()
fpr,tpr,h=metrics.roc_curve(y_test,s)
plt.plot(fpr, tpr)

plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic')
plt.show()


import sys

input = sys.stdin.readline

def binary_search(num, book1):
    lt = 0
    rt = len(book1) - 1

    while lt <= rt:
        mid = (lt + rt) // 2
        if book1[mid] == num:
            return 1
        elif book1[mid] < num:
            lt = mid + 1
        else:
            rt = mid - 1
    return 0

if __name__ == "__main__":
    t = int(input())
    for _ in range(t):
        n = int(input())
        book1 = sorted(list(map(int, input().split())))
        m = int(input())
        book2 = list(map(int, input().split()))
        for num in book2:
            print(binary_search(num, book1))


#! /usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function

import sys

def python_version_supported():
    major, minor = sys.version_info[:2]
    return (major == 2 and minor >= 7) or (major, minor) >= (3, 2)

if not python_version_supported():
    sys.exit("Error: Translator only supports Python >= 2.7 and Python >= 3.2.")

from collections import defaultdict
from copy import deepcopy
from itertools import product

import axiom_rules
import numeric_axiom_rules
import fact_groups
import instantiate
import normalize
import options
import pddl
import pddl_parser
import sas_tasks
import simplify
import timers
import tools

# TODO: The translator may generate trivial derived variables which are always
# true, for example if there is a derived predicate in the input that only
# depends on (non-derived) variables which are detected as always true.
# Such a situation was encountered in the PSR-STRIPS-DerivedPredicates domain.
# Such "always-true" variables should best be compiled away, but it is
# not clear what the best place to do this should be. Similar
# simplifications might be possible elsewhere, for example if a
# derived variable is synonymous with another variable (derived or
# non-derived).

DEBUG = True

simplified_effect_condition_counter = 0
added_implied_precondition_counter = 0

def strips_to_sas_dictionary(groups, num_axioms, num_axiom_map, num_fluents, assert_partial, include_numeric=True):
    dictionary = {}
    numeric_dictionary = {}
#     print("Creating_strips_to_sas_dictionary. Numeric Axioms:")
#     for nax in num_axioms:
#         nax.dump()
#     print("Numeric Action Map for S2S is")
#     for entry in num_axiom_map:
#         print("%s -> %s" % (entry, num_axiom_map[entry]))
#    print("S2S from groups:")
#    for element in groups:
#        print(element)
    for var_no, group in enumerate(groups):
        for val_no, atom in enumerate(group):
            dictionary.setdefault(atom, []).append((var_no, val_no))
    if assert_partial:
        assert all(len(sas_pairs) == 1
                   for sas_pairs in dictionary.values())
    ranges = [len(group) + 1 for group in groups]

    num_count = 0
    if include_numeric:
        redundant_axioms = []
        for axiom in num_axioms:
            if axiom.effect in num_axiom_map:
                redundant_axioms.append(axiom.effect)
            else:
#                print("AE adding %s -> %d" % (axiom.effect, num_count))
                numeric_dictionary[axiom.effect]= num_count
                num_count += 1
        for axiom_effect in redundant_axioms:
                numeric_dictionary[axiom_effect] = numeric_dictionary[num_axiom_map[axiom_effect].effect]
        fluent_list = list(num_fluents)
#         print("List of all numeric fluents:")
#         for element in fluent_list:
#             print("   %s" % element)
        fluent_list.sort(lambda x,y: cmp(str(x), str(y)))
        for fluent in fluent_list: # are partially contained in num_axiom
            if fluent not in numeric_dictionary:
#                print("Num-Variable #%d \t-> %s" % (num_count, fluent))
                numeric_dictionary[fluent]=num_count
                num_count += 1
    # ranges: the range of each FDR variable in groups (including "none of those")
    # dictionary: mapping from grounded facts to the index of the corresponding FDR variable-value pair
    #             e.g. Atom on(A, B) mapsto (5, 2) --> fact #2 of the (selected mutex) group # 5
    # numeric dictionary: maps the name of numeric ground facts to the corresponding real valued variable
    #             no ranges are given for such variables as the range is "infinite" (no finite domain representation)
    #             (in reality the range is obviously a finite number of 2^64 bits (double representation))
    return ranges, dictionary, num_count, numeric_dictionary

def translate_strips_conditions_aux(conditions, dictionary, ranges, numeric_dictionary, comparison_axioms, mutex_check = False):
    condition = {}
    comp_axiom_dict = comparison_axioms[0]
    sas_comp_axioms = comparison_axioms[1]
    for fact in conditions:
        if (isinstance(fact,pddl.FunctionComparison) or
            isinstance(fact,pddl.NegatedFunctionComparison)):
#            print("comparison condition in translate strips condition aux:")
            if fact not in dictionary:
#                print("Fact is not in dictionary")
                for part in fact.parts: # TODO: remove this assertion check when not debugging
                    assert part in numeric_dictionary
                parts = [numeric_dictionary[part] for part in fact.parts]
                key = (fact.comparator, tuple(parts))
                negated = fact.negated
                if key in comp_axiom_dict:
#                    print("key %s ist im comp_axiom_dict" % [key])
#                    print(comp_axiom_dict)
                    fact = comp_axiom_dict[key]
                    if negated:
#                       print("(nach dem negieren)")
                        fact = fact.negate()
                else:
                    axiom = sas_tasks.SASCompareAxiom(fact.comparator,
                                                      parts, len(ranges))
                    if negated:
                        negfact = fact
                        posfact = fact.negate()
                    else:
                        posfact = fact
                        negfact = fact.negate()

                    if not mutex_check: # if mutexes are checked the axioms will not be added because the
                            # strips to sas dictionary would not be updated properly otherwise
                        sas_comp_axioms.append(axiom)
                        comp_axiom_dict[key] = posfact
                    dictionary.setdefault(posfact,[]).append((len(ranges), 0))
                    dictionary.setdefault(negfact,[]).append((len(ranges), 1))
                    ranges.append(3)
#            print (dictionary[fact])
            var, val = dictionary[fact][0]
            if (var in condition and val not in condition[var]):
                # Conflicting conditions on this variable: Operator invalid.
                return None
            condition[var] = set([val])
        else:
            if fact.negated:
                # we handle negative conditions later, because then we
                # can recognize when the negative condition is already
                # ensured by a positive condition
                continue
            for var, val in dictionary.get(fact, ()):
                # The default () here is a bit of a hack. For goals (but
                # only for goals!), we can get static facts here. They
                # cannot be statically false (that would have been
                # detected earlier), and hence they are statically true
                # and don't need to be translated.
                # TODO: This would not be necessary if we dealt with goals
                # in the same way we deal with operator preconditions etc.,
                # where static facts disappear during grounding. So change
                # this when the goal code is refactored (also below). (**)
                if (condition.get(var) is not None and
                    val not in condition.get(var)):
                    # Conflicting conditions on this variable: Operator invalid.
                    return None
                condition[var] = set([val])

    def number_of_values(var_vals_pair):
        var, vals = var_vals_pair
        return len(vals)

    for fact in conditions:
        if (isinstance(fact,pddl.FunctionComparison) or
            isinstance(fact,pddl.NegatedFunctionComparison)):
            continue
        if fact.negated:
           ## Note  Here we use a different solution than in Sec. 10.6.4
           ##       of the thesis. Compare the last sentences of the third
           ##       paragraph of the section.
           ##       We could do what is written there. As a test case,
           ##       consider Airport ADL tasks with only one airport, where
           ##       (occupied ?x) variables are encoded in a single variable,
           ##       and conditions like (not (occupied ?x)) do occur in
           ##       preconditions.
           ##       However, here we avoid introducing new derived predicates
           ##       by treat the negative precondition as a disjunctive
           ##       precondition and expanding it by "multiplying out" the
           ##       possibilities.  This can lead to an exponential blow-up so
           ##       it would be nice to choose the behaviour as an option.
            done = False
            new_condition = {}
            atom = pddl.Atom(fact.predicate, fact.args)  # force positive
            for var, val in dictionary.get(atom, ()):
                # see comment (**) above
                poss_vals = set(range(ranges[var]))
                poss_vals.remove(val)

                if condition.get(var) is None:
                    assert new_condition.get(var) is None
                    new_condition[var] = poss_vals
                else:
                    # constrain existing condition on var
                    prev_possible_vals = condition.get(var)
                    done = True
                    prev_possible_vals.intersection_update(poss_vals)
                    if len(prev_possible_vals) == 0:
                        # Conflicting conditions on this variable:
                        # Operator invalid.
                        return None

            if not done and len(new_condition) != 0:
                # we did not enforce the negative condition by constraining
                # an existing condition on one of the variables representing
                # this atom. So we need to introduce a new condition:
                # We can select any from new_condition and currently prefer the
                # smallest one.
                candidates = sorted(new_condition.items(), key=number_of_values)
                var, vals = candidates[0]
                condition[var] = vals

    def multiply_out(condition):  # destroys the input
        sorted_conds = sorted(condition.items(), key=number_of_values)
        flat_conds = [{}]
        for var, vals in sorted_conds:
            if len(vals) == 1:
                for cond in flat_conds:
                    cond[var] = vals.pop()  # destroys the input here
            else:
                new_conds = []
                for cond in flat_conds:
                    for val in vals:
                        new_cond = deepcopy(cond)
                        new_cond[var] = val
                        new_conds.append(new_cond)
                flat_conds = new_conds
        return flat_conds

    return multiply_out(condition)

def translate_strips_conditions(conditions, dictionary, ranges, numeric_dictionary,
                                mutex_dict, mutex_ranges, comp_axioms):
    if not conditions:
        return [{}]  # Quick exit for common case.

    # Check if the condition violates any mutexes.
    if translate_strips_conditions_aux(conditions, mutex_dict, mutex_ranges,
									numeric_dictionary, comp_axioms, True) is None:
        return None

    return translate_strips_conditions_aux(conditions, dictionary, ranges, numeric_dictionary, comp_axioms)

def translate_strips_operator(operator, dictionary, ranges, numeric_dictionary, mutex_dict,
                              mutex_ranges, implied_facts, comp_axioms, num_vals, relevant_numeric_vars):
    conditions = translate_strips_conditions(operator.precondition, dictionary,
                                             ranges, numeric_dictionary, mutex_dict, mutex_ranges, comp_axioms)

    if conditions is None:
        return []
    sas_operators = []
    for condition in conditions:
        op = translate_strips_operator_aux(operator, dictionary, ranges, numeric_dictionary,
                                           mutex_dict, mutex_ranges,
                                           implied_facts, condition, comp_axioms, num_vals, relevant_numeric_vars)
        if op is not None:
            sas_operators.append(op)
    return sas_operators

def negate_and_translate_condition(condition, dictionary, ranges, numeric_dict, mutex_dict,
                                   mutex_ranges, comp_axioms):
    # condition is a list of lists of literals (DNF)
    # the result is the negation of the condition in DNF in
    # finite-domain representation (a list of dictionaries that map
    # variables to values)
    negation = []
    if [] in condition:  # condition always satisfied
        return None  # negation unsatisfiable
    for combination in product(*condition):
        cond = [l.negate() for l in combination]
        cond = translate_strips_conditions(cond, dictionary, ranges, numeric_dict,
                                           mutex_dict, mutex_ranges, comp_axioms)
        if cond is not None:
            negation.extend(cond)
    return negation if negation else None

def translate_strips_operator_aux(operator, dictionary, ranges, numeric_dictionary, mutex_dict,
                                  mutex_ranges, implied_facts, condition, comp_axioms, num_vals, relevant_numeric):
#    if DEBUG: print("Translating strips operator >%s< to SAS" % operator.name)
#     for entry in dictionary:
#         print("%s \t-> %s" % (entry, dictionary[entry]))
#     print("implied facts = %s" % implied_facts)
#     print("Numeric Dictionary = ")
#     for entry in numeric_dictionary:
#         print("%s \t-> %s" % (entry, numeric_dictionary[entry]))

    # collect all add effects
    effects_by_variable = defaultdict(lambda: defaultdict(list))
    # effects_by_variables: var -> val -> list(FDR conditions)
    add_conds_by_variable = defaultdict(list)
    for conditions, fact in operator.add_effects:
        eff_condition_list = translate_strips_conditions(conditions, dictionary,
                                                         ranges, numeric_dictionary, mutex_dict,
                                                         mutex_ranges, comp_axioms)
        if eff_condition_list is None:  # Impossible condition for this effect.
            continue
        for var, val in dictionary[fact]:
            effects_by_variable[var][val].extend(eff_condition_list)
            add_conds_by_variable[var].append(conditions)
#    print("the following defaultdict was created and contains the add effects")
#    print(effects_by_variable)
#    for key in effects_by_variable:
#        print("%s \t-> %s" % (key,effects_by_variable[key]))

    # collect all del effects
    del_effects_by_variable = defaultdict(lambda: defaultdict(list))
    for conditions, fact in operator.del_effects:
        eff_condition_list = translate_strips_conditions(conditions, dictionary,
                                                         ranges, numeric_dictionary, mutex_dict,
                                                         mutex_ranges, comp_axioms)
        if eff_condition_list is None:  # Impossible condition for this effect.
            continue
        for var, val in dictionary[fact]:
            del_effects_by_variable[var][val].extend(eff_condition_list)
#    print("the following dictionary contains (conditional) delete effects")
#    for key in del_effects_by_variable:
#        print("%s \t-> %s" % (key,del_effects_by_variable[key]))

    # collect all (numeric) assignment effects
    ass_effects_by_variable = defaultdict(lambda: defaultdict(list))
    # effects_by_variables: num_var -> dict( (assexpr, assvar) -> [conditions])
    # num_var: affected variable
    # assexpr: "= + - * /

    for conditions, assignment in operator.assign_effects:
        eff_condition_list = translate_strips_conditions(conditions, dictionary,
                                                         ranges, numeric_dictionary, mutex_dict,
                                                         mutex_ranges, comp_axioms)
        if eff_condition_list is None:  # Impossible condition for this effect.
            continue
        #assert(assignment.expression in numeric_dictionary), "%s not in numeric dictionary" % assignment.expression
        if assignment.expression in numeric_dictionary:
            ass_effects_by_variable[numeric_dictionary[assignment.fluent]][(assignment.symbol, numeric_dictionary[assignment.expression])].extend(eff_condition_list)
    # add effect var=none_of_those for all del effects with the additional
    # condition that the deleted value has been true and no add effect triggers
    for var in del_effects_by_variable:
        no_add_effect_condition = negate_and_translate_condition(
            add_conds_by_variable[var], dictionary, ranges, numeric_dictionary, mutex_dict,
            mutex_ranges, comp_axioms)
        if no_add_effect_condition is None:  # there is always an add effect
            continue
        none_of_those = ranges[var] - 1
        for val, conds in del_effects_by_variable[var].items():
            for cond in conds:
                # add guard
                if var in cond and cond[var] != val:
                    continue  # condition inconsistent with deleted atom
                cond[var] = val
                # add condition that no add effect triggers
                for no_add_cond in no_add_effect_condition:
                    new_cond = dict(cond)
                    # This is a rather expensive step. We try every no_add_cond
                    # with every condition of the delete effect and discard the
                    # overal combination if it is unsatisfiable. Since
                    # no_add_effect_condition is precomputed it can contain many
                    # no_add_conds in which a certain literal occurs. So if cond
                    # plus the literal is already unsatisfiable, we still try
                    # all these combinations. A possible optimization would be
                    # to re-compute no_add_effect_condition for every delete
                    # effect and to unfold the product(*condition) in
                    # negate_and_translate_condition to allow an early break.
                    for cvar, cval in no_add_cond.items():
                        if cvar in new_cond and new_cond[cvar] != cval:
                            # the del effect condition plus the deleted atom
                            # imply that some add effect on the variable
                            # triggers
                            break
                        new_cond[cvar] = cval
                    else:
                        effects_by_variable[var][none_of_those].append(new_cond)

    return build_sas_operator(operator.name, condition, effects_by_variable, ass_effects_by_variable,
                              operator.cost, ranges, implied_facts, relevant_numeric)

def build_sas_operator(name, condition, effects_by_variable, ass_effects_by_variable, deprecated_cost, ranges,
                       implied_facts, relevant_numeric_variables):
#    print("build_sas_operator with relevant vars:", relevant_numeric_variables)
#    if DEBUG: print("Building SAS Operator %s with %d logic and %d numeric effects" % (name, len(effects_by_variable),len(ass_effects_by_variable)))
    if options.add_implied_preconditions:
        implied_precondition = set()
        for fact in condition.items():
            implied_precondition.update(implied_facts[fact])
    prevail_and_pre = dict(condition)
    pre_post = []
    num_pre_post = []
    for var in effects_by_variable:
        orig_pre = condition.get(var, -1)
        added_effect = False
        for post, eff_conditions in effects_by_variable[var].items():
            pre = orig_pre
            # if the effect does not change the variable value, we ignore it
            if pre == post:
                continue
            eff_condition_lists = [sorted(eff_cond.items())
                                   for eff_cond in eff_conditions]
            if ranges[var] == 2:
                # Apply simplifications for binary variables.
                if prune_stupid_effect_conditions(var, post,
                                                  eff_condition_lists):
                    global simplified_effect_condition_counter
                    simplified_effect_condition_counter += 1
                if (options.add_implied_preconditions and pre == -1 and
                        (var, 1 - post) in implied_precondition):
                    global added_implied_precondition_counter
                    added_implied_precondition_counter += 1
                    pre = 1 - post
            for eff_condition in eff_condition_lists:
                # we do not need to represent a precondition as effect condition
                # and we do not want to keep an effect whose condition contradicts
                # a pre- or prevail condition
                filtered_eff_condition = []
                eff_condition_contradicts_precondition = False
                for variable, value in eff_condition:
                    if variable in prevail_and_pre:
                        if prevail_and_pre[variable] != value:
                            eff_condition_contradicts_precondition = True
                            break
                    else:
                        filtered_eff_condition.append((variable, value))
                if eff_condition_contradicts_precondition:
                    continue
                pre_post.append((var, pre, post, filtered_eff_condition))
                added_effect = True
        if added_effect:
            # the condition on var is not a prevail condition but a
            # precondition, so we remove it from the prevail condition
            condition.pop(var, -1)

    for numvar in ass_effects_by_variable:
#        if DEBUG: print("Numeric effect on numvar = %s" % numvar)
#        orig_pre = condition.get(numvar, -1)
#        assert orig_pre == -1 # numeric variables cannot occur in preconditions (instead propositional variables are derived by axioms)
#    numeric variables and logic variables are not stored in the same data structures, but they *do* can have the same index within their
#    respective arrays
        for (ass_op, post_var), eff_conditions in ass_effects_by_variable[numvar].items():
#            if DEBUG: print("assignment operator : >%s<" % ass_op)
#            if DEBUG: print("post condition variable : %d" % post_var)
            # otherwise the condition on numvar is not a prevail condition but a
            # precondition, so we remove it from the prevail condition
            eff_condition_lists = [sorted(eff_cond.items())
                                   for eff_cond in eff_conditions]
            for eff_condition in eff_condition_lists:
                # we do not need to represent a precondition as effect condition
                num_pre_post.append((numvar, ass_op, post_var, eff_condition))
#    if DEBUG: print("pre_post = %s " % pre_post)
#    if DEBUG: print("num_pre_post = %s " % num_pre_post)
    if not pre_post: # build only operators with at least one regular effect (not instrumentation)
        irrelevant = True
        for effect in  num_pre_post:
#            print ("numeric effect ", effect)
            if effect[0] in relevant_numeric_variables:
#                print("RELEVANT! because ", effect[0], " is in ", relevant_numeric_variables)
                irrelevant = False
                break
        if irrelevant:
#            if DEBUG: print("operator is noop - return None")
            return None
    prevail = list(condition.items())
    return sas_tasks.SASOperator(name, prevail, pre_post, num_pre_post, deprecated_cost)

def prune_stupid_effect_conditions(var, val, conditions):
    ## (IF <conditions> THEN <var> := <val>) is a conditional effect.
    ## <var> is guaranteed to be a binary variable.
    ## <conditions> is in DNF representation (list of lists).
    ##
    ## We simplify <conditions> by applying two rules:
    ## 1. Conditions of the form "var = dualval" where var is the
    ##    effect variable and dualval != val can be omitted.
    ##    (If var != dualval, then var == val because it is binary,
    ##    which means that in such situations the effect is a no-op.)
    ## 2. If conditions contains any empty list, it is equivalent
    ##    to True and we can remove all other disjuncts.
    ##
    ## returns True when anything was changed
    if conditions == [[]]:
        return False  # Quick exit for common case.
    assert val in [0, 1]
    dual_fact = (var, 1 - val)
    simplified = False
    for condition in conditions:
        # Apply rule 1.
        while dual_fact in condition:
            # print "*** Removing dual condition"
            simplified = True
            condition.remove(dual_fact)
        # Apply rule 2.
        if not condition:
            conditions[:] = [[]]
            simplified = True
            break
    return simplified

def translate_strips_axiom(axiom, dictionary, ranges, num_dict, mutex_dict, mutex_ranges, comp_ax):
    conditions = translate_strips_conditions(axiom.condition, dictionary,
                                             ranges, num_dict, mutex_dict, mutex_ranges, comp_ax)
    if conditions is None:
        return []
    if axiom.effect.negated:
        [(var, _)] = dictionary[axiom.effect.positive()]
        effect = (var, ranges[var] - 1)
    else:
        [effect] = dictionary[axiom.effect]
    axioms = []
    for condition in conditions:
        axioms.append(sas_tasks.SASAxiom(condition.items(), effect))
    return axioms

def translate_numeric_axiom(axiom, prop_dictionary, num_dictionary):
    effect = num_dictionary.get(axiom.effect)
    op = axiom.op
    parts = []
    for part in axiom.parts:
        if isinstance(part, pddl.PrimitiveNumericExpression):
            parts.append(num_dictionary.get(part))
        else: # part is PropositionalNumericAxiom
            parts.append(prop_dictionary.get(part.effect)[0])
    return sas_tasks.SASNumericAxiom(op, parts, effect)

def translate_strips_operators(actions, strips_to_sas, ranges, numeric_strips_to_sas, mutex_dict,
                               mutex_ranges, implied_facts, comp_axioms, num_vals, relevant_numeric_vars):
    result = []
    for action in actions:
        sas_ops = translate_strips_operator(action, strips_to_sas, ranges, numeric_strips_to_sas, mutex_dict, mutex_ranges, implied_facts, comp_axioms, num_vals, relevant_numeric_vars)
        result.extend(sas_ops)
    return result

def translate_strips_axioms(axioms, strips_to_sas, ranges, num_dict, mutex_dict,
                            mutex_ranges, comp_ax):
    result = []
    for axiom in axioms:
        sas_axioms = translate_strips_axiom(axiom, strips_to_sas, ranges, num_dict,
                                            mutex_dict, mutex_ranges, comp_ax)
        result.extend(sas_axioms)
    return result

def add_key_to_comp_axioms(comparison_axioms, translation_key): # Adds a "human" readable name to each propositional variable
    for axiom in comparison_axioms[1]:
        value_list = []
        assert axiom.effect == len(translation_key), "current effect %s != next variable %s" % (axiom.effect, len(translation_key))
        value_list.append(str(axiom))
        value_list.append(str(axiom.invert_comparator()))
        value_list.append('<none of those>')
        translation_key.append(value_list)

def dump_task(init, goals, actions, axioms, axiom_layer_dict):
    old_stdout = sys.stdout
    with open("output.dump", "w") as dump_file:
        sys.stdout = dump_file
        print("Initial state")
        for atom in init:
            print(atom)
        print()
        print("Goals")
        for goal in goals:
            print(goal)
        for action in actions:
            print()
            print("Action")
            action.dump()
        for axiom in axioms:
            print()
            print("Axiom")
            axiom.dump()
        print()
        print("Axiom layers")
        for atom, layer in axiom_layer_dict.items():
            print("%s: layer %d" % (atom, layer))
    sys.stdout = old_stdout

def translate_task(strips_to_sas, ranges, translation_key, numeric_strips_to_sas, num_count,
                   mutex_dict, mutex_ranges, mutex_key,
                   init, num_init, goal_list, global_constraint,
                   actions, axioms, num_axioms,
                   num_axioms_by_layer,
                   num_axiom_map, const_num_axioms,
                   metric, implied_facts, init_constant_predicates, init_constant_numerics):
    with timers.timing("Processing axioms", block=True):
        axioms, axiom_init, axiom_layer_dict = axiom_rules.handle_axioms(
            actions, axioms, goal_list, global_constraint)
    init = init + axiom_init
    if options.dump_task:
        # Remove init facts that don't occur in strips_to_sas: they're constant.
        nonconstant_init = filter(strips_to_sas.get, init)
        dump_task(nonconstant_init, goal_list, actions, axioms, axiom_layer_dict)

    init_values = [rang - 1 for rang in ranges]
    # Closed World Assumption: Initialize to "range - 1" == Nothing.
    for fact in init:
        pairs = strips_to_sas.get(fact, [])  # empty for static init facts
        for var, val in pairs:
            curr_val = init_values[var]
            if curr_val != ranges[var] - 1 and curr_val != val:
                assert False, "Inconsistent init facts! [fact = %s]" % fact
            init_values[var] = val

    comparison_axioms = [{},[]]
    goal_dict_list = translate_strips_conditions(goal_list, strips_to_sas, ranges, numeric_strips_to_sas,
                                                 mutex_dict, mutex_ranges, comparison_axioms)
    global_constraint_dict_list = translate_strips_conditions([global_constraint], strips_to_sas, ranges, numeric_strips_to_sas,
                                                 mutex_dict, mutex_ranges, comparison_axioms)
#    print("goal_dict_list = %s" % goal_dict_list)
#    print("comparison_axioms = %s" %comparison_axioms)
    if goal_dict_list is None:
        # "None" is a signal that the goal_list is unreachable because it
        # violates a mutex.
        return unsolvable_sas_task("Goal violates a mutex")

    assert len(goal_dict_list) == 1, "Negative goal not supported"
    ## we could substitute the negative goal literal in
    ## normalize.substitute_complicated_goal, using an axiom. We currently
    ## don't do this, because we don't run into this assertion, if the
    ## negative goal is part of finite domain variable with only two
    ## values, which is most of the time the case, and hence refrain from
    ## introducing axioms (that are not supported by all heuristics)
    goal_pairs = list(goal_dict_list[0].items())
    if not goal_pairs:
        return solvable_sas_task("Empty goal")
    sas_goal = sas_tasks.SASGoal(goal_pairs)

    assert len(global_constraint_dict_list) == 1 # the key is the axiom fluent, the value (0) the evaluation to true

    num_init_values = [0.0]*num_count # initialize numeric varialbes with 0.0
#     if DEBUG:
#         print("Strips-to-sas dict is")
#         for entry in strips_to_sas:
#             print("%s -> %s"%(entry, strips_to_sas[entry]))
#         print("Numeric Strips-to-sas dict is")
#         for entry in numeric_strips_to_sas:
#             print("%s -> %s"%(entry,numeric_strips_to_sas[entry]))

    relevant_numeric = []
    for fact in num_init:
        var = numeric_strips_to_sas.get(fact.fluent,-1)
        if var > -1:
            val = fact.expression.value
            num_init_values[var]=val
            if fact.fluent.ntype == 'R':
                # the corresponding numeric variable is "regular" and therefore relevant
                relevant_numeric.append(var)

    operators = translate_strips_operators(actions, strips_to_sas, ranges, numeric_strips_to_sas,
                                           mutex_dict, mutex_ranges,
                                           implied_facts, comparison_axioms, num_init_values, relevant_numeric)

    axioms = translate_strips_axioms(axioms, strips_to_sas, ranges, numeric_strips_to_sas, mutex_dict,
                                     mutex_ranges, comparison_axioms)

    sas_num_axioms = [translate_numeric_axiom(axiom,strips_to_sas, numeric_strips_to_sas) for axiom in num_axioms
                      if axiom not in const_num_axioms and
                      axiom.effect not in num_axiom_map]

    axiom_layers = [-1] * len(ranges) # default axiom layer is -1
    ## each numeric axiom gets its own layer (a wish of a colleague for
    ## knowledge compilation or search. If you use only the translator,
    ## you can change this)
    num_axiom_layers = [-1] * num_count
    num_axiom_layer = 0
    for layer in num_axioms_by_layer:
        num_axioms_by_layer[layer].sort(lambda x,y: cmp(x.name,y.name))
        for axiom in num_axioms_by_layer[layer]:
            if axiom.effect not in num_axiom_map:
                var = numeric_strips_to_sas[axiom.effect]
                if layer == -1:
                    num_axiom_layers[var] = -1
                else:
                    num_axiom_layers[var] = num_axiom_layer
                    num_axiom_layer += 1
#    print("comparison_axioms = %s" %comparison_axioms)
    comp_axiom_init = [2] * len(comparison_axioms[1]) # initializing comparison axioms with value 3 (none of those)
    init_values.extend(comp_axiom_init) #

    for axiom in comparison_axioms[1]:
        axiom_layers[axiom.effect] = num_axiom_layer
    for atom, layer in axiom_layer_dict.iteritems():
        assert layer >= 0
        [(var, val)] = strips_to_sas[atom]
        axiom_layers[var] = layer + num_axiom_layer + 1
    add_key_to_comp_axioms(comparison_axioms, translation_key)
    variables = sas_tasks.SASVariables(ranges, axiom_layers, translation_key, num_axiom_layer)

    num_variables = [-1] * num_count
    num_var_types = ['U'] * num_count # variable type is unknown
    for entry in numeric_strips_to_sas:
        num_variables[numeric_strips_to_sas[entry]] = entry
        num_var_types[numeric_strips_to_sas[entry]] = entry.ntype
    assert num_count == len(num_variables), "%d nc <-> variables %d"%(num_count,len(num_variables))

    numeric_variables = sas_tasks.SASNumericVariables(num_variables, num_axiom_layers, num_var_types)
    mutexes = [sas_tasks.SASMutexGroup(group) for group in mutex_key]

    for axiom in const_num_axioms:
#         print("Axiom = %s" % axiom)
#         print("Axiom.effect = %s" % axiom.effect)
#         print("corresponding variable = %s" % numeric_strips_to_sas.get(axiom.effect))
        var = numeric_strips_to_sas.get(axiom.effect)
        val = axiom.parts[0].value
        num_init_values[var]=val

    sas_init = sas_tasks.SASInit(init_values, num_init_values)
#    print("SASInit is")
#    sas_init.dump()

    # look up metric fluent
    if metric[1] == -1:
        # minimize unit cost, no metric fluent specified
        assert metric[0] == '<'
        sas_metric = metric
    else:
        assert metric[1] in numeric_strips_to_sas, "Metric fluent %s missing in strips_to_sas_dict" % metric[1]
        # look up (possibly derived) metric fluent to be optimized
        sas_metric = (metric[0], numeric_strips_to_sas[metric[1]])

#    print ("debug check metric: metric=")
#    print (metric)
#    print ("sas_metric fluent %d" % sas_metric[1])
#    print ("Returning task with global constraint = ",global_constraint_dict_list[0].items()[0])

    return sas_tasks.SASTask(variables, numeric_variables, mutexes, sas_init, sas_goal,
                             operators, axioms, comparison_axioms[1], sas_num_axioms,
							 global_constraint_dict_list[0].items()[0], sas_metric,
                             init_constant_predicates, init_constant_numerics)

def trivial_task(solvable):
    variables = sas_tasks.SASVariables(
        [2], [-1], [["Atom dummy(val1)", "Atom dummy(val2)"]], 0)
    # We create no mutexes: the only possible mutex is between
    # dummy(val1) and dummy(val2), but the preprocessor would filter
    # it out anyway since it is trivial (only involves one
    # finite-domain variable).
    num_variables = sas_tasks.SASNumericVariables(['total-cost'], [-1], ['I']) # no numeric variables
    mutexes = []
    init = sas_tasks.SASInit([0],[0])
    if solvable:
        goal_fact = (0, 0)
    else:
        goal_fact = (0, 1)
    goal = sas_tasks.SASGoal([goal_fact])
    operators = []
    axioms = []
    comp_axioms = []
    numeric_axioms = []
    global_constraint = (0, 0)
    metric = ('<', 0)
    init_constant_predicates = []
    init_constant_numerics = []
    return sas_tasks.SASTask(variables, num_variables, mutexes, init, goal,
                 operators, axioms, comp_axioms, numeric_axioms, global_constraint,
                 metric, init_constant_predicates, init_constant_numerics)

def solvable_sas_task(msg):
    print("%s! Generating solvable task..." % msg)
    return trivial_task(solvable=True)

def unsolvable_sas_task(msg):
    print("%s! Generating unsolvable task..." % msg)
    return trivial_task(solvable=False)

def pddl_to_sas(task):
    with timers.timing("Instantiating", block=True):
        (relaxed_reachable, atoms, num_fluents, actions, axioms, num_axioms,
            init_constant_predicates, init_constant_numerics,
            reachable_action_params) = instantiate.explore(task)

    if DEBUG: print("Task converted to SAS.")
#    task.function_administrator.dump()
    if DEBUG: print("Relaxed_reachable: %s" % relaxed_reachable)
    if DEBUG: print("List of %d Atoms:" % len(atoms))
#     for atom in atoms:
#         atom.dump()
    if DEBUG: print("List of %d numeric Fluents:" % len(num_fluents))
#     for fluent in num_fluents:
#         fluent.dump()
    if len(num_fluents) == 0:
        assert False
    if DEBUG: print("List of %d Actions:" % len(actions))
#     for action in actions:
#         print(action.name)
    if DEBUG: print("List of %d propositional Axioms:" % len(axioms))
#    if len(axioms) > 0:
#        axioms[0].dump()
#        print("layer=%s"%axioms[0].__class__ )
#    for axiom in axioms:
#        axiom.dump()
    if DEBUG: print("List of %d numeric Axioms:" % len(num_axioms))
#     for numax in num_axioms:
#         numax.dump()
    if DEBUG: print("List of %d constant predicates from initial state" % len(init_constant_predicates))
#     for icp in init_constant_predicates:
#         icp.dump()
    if DEBUG: print("List of %d constant numeric predicates from initial state"% len(init_constant_numerics))
#     for icn in init_constant_numerics:
#         icn.dump()
    if DEBUG: print("List of %d reachable Action Parameters:"% len(reachable_action_params))
#     for rap in reachable_action_params:
#         rap.dump()

    if not relaxed_reachable:
        return unsolvable_sas_task("No relaxed solution")

    # HACK! Goals should be treated differently.
    if isinstance(task.goal, pddl.Conjunction):
        goal_list = task.goal.parts
    else:
        goal_list = [task.goal]
    for item in goal_list:
        assert isinstance(item, pddl.Literal)

    assert isinstance(task.global_constraint, pddl.Literal)
 #   if DEBUG: print("Global constraint Literal is ", task.global_constraint)

    with timers.timing("Computing fact groups", block=True):
        # groups: the ground facts are grouped in order to create multi valued variables
        # mutex_groups: includes all mutex groups, so a fact can appear in multiple groups
        # translation key: the names of the grounded facts of the MVV determined in groups, including "NegatedAtom" for binary and "none of those" for multi valued variables
        groups, mutex_groups, translation_key = fact_groups.compute_groups(
            task, atoms, reachable_action_params)
#        print ("Fact groups (%d) computed %s" % (len(groups),[len(group) for group in groups]))
#        print ("Full mutex groups (%d) containing %s:" % (len(mutex_groups),[len(group) for group in mutex_groups]))

    with timers.timing("Handling numeric axioms"):
        num_axioms_by_layer, max_num_layer, num_axiom_map, const_num_axioms = \
            numeric_axiom_rules.handle_axioms(num_axioms)

    with timers.timing("Building STRIPS to SAS dictionary"):
        ranges, strips_to_sas, num_count, numeric_strips_to_sas = strips_to_sas_dictionary(
            groups, num_axioms, num_axiom_map, num_fluents, assert_partial=options.use_partial_encoding)
#     if DEBUG:
#         print("Strips to sas dictionary (%s entries)" % len(strips_to_sas))
#         for entry in sorted(strips_to_sas.items(), key=lambda x:x[1]): # sort by value
#             print("%s -> %s" % entry)
#         print(ranges)
#         print("Numeric Strips to sas dictionary (%s entries)" % len(numeric_strips_to_sas))
#         for entry in numeric_strips_to_sas:
#             print("%s -> %s" % (entry, numeric_strips_to_sas[entry]))

#     print ("pddl2sas Zwischendebug: metric = ", task.metric)
#     assert task.metric[1] in numeric_strips_to_sas

    with timers.timing("Building dictionary for full mutex groups"):
        mutex_ranges, mutex_dict, _, _ = strips_to_sas_dictionary(
            mutex_groups, num_axioms, num_axiom_map, num_fluents, assert_partial=False, include_numeric=False)

    if options.add_implied_preconditions:
        with timers.timing("Building implied facts dictionary..."):
            implied_facts = build_implied_facts(strips_to_sas, groups,
                                                mutex_groups)
    else:
        implied_facts = {}

    with timers.timing("Building mutex information", block=True):
        mutex_key = build_mutex_key(strips_to_sas, mutex_groups)

    with timers.timing("Translating task", block=True):
        sas_task = translate_task(
            strips_to_sas, ranges, translation_key, numeric_strips_to_sas, num_count,
            mutex_dict, mutex_ranges, mutex_key, task.init, task.num_init, goal_list,
			task.global_constraint, actions, axioms, num_axioms, num_axioms_by_layer,
			num_axiom_map, const_num_axioms, task.metric, implied_facts,
			init_constant_predicates, init_constant_numerics)
#    print("len(variables.valuenames) = %s" % len(sas_task.variables.value_names))

    print("%d effect conditions simplified" %
          simplified_effect_condition_counter)
    print("%d implied preconditions added" %
          added_implied_precondition_counter)

#    print("created sas_task")
#    sas_task.dump()

    if options.filter_unreachable_facts:
        with timers.timing("Detecting unreachable propositions", block=True):
            try:
                simplify.filter_unreachable_propositions(sas_task)
            except simplify.Impossible:
                return unsolvable_sas_task("Simplified to trivially false goal")
            except simplify.TriviallySolvable:
                return solvable_sas_task("Simplified to empty goal")

#    print("translate pddl to sas returns task")
    return sas_task

def build_mutex_key(strips_to_sas, groups):
    group_keys = []
    for group in groups:
        group_key = []
        for fact in group:
            if strips_to_sas.get(fact):
                for var, val in strips_to_sas[fact]:
                    group_key.append((var, val))
            else:
                print("not in strips_to_sas, left out:", fact)
        group_keys.append(group_key)
    return group_keys

def build_implied_facts(strips_to_sas, groups, mutex_groups):
    ## Compute a dictionary mapping facts (FDR pairs) to lists of FDR
    ## pairs implied by that fact. In other words, in all states
    ## containing p, all pairs in implied_facts[p] must also be true.
    ##
    ## There are two simple cases where a pair p implies a pair q != p
    ## in our FDR encodings:
    ## 1. p and q encode the same fact
    ## 2. p encodes a STRIPS proposition X, q encodes a STRIPS literal
    ##    "not Y", and X and Y are mutex.
    ##
    ## The first case cannot arise when we use partial encodings, and
    ## when we use full encodings, I don't think it would give us any
    ## additional information to exploit in the operator translation,
    ## so we only use the second case.
    ##
    ## Note that for a pair q to encode a fact "not Y", Y must form a
    ## fact group of size 1. We call such propositions Y "lonely".

    ## In the first step, we compute a dictionary mapping each lonely
    ## proposition to its variable number.
    lonely_propositions = {}
    for var_no, group in enumerate(groups):
        if len(group) == 1:
            lonely_prop = group[0]
            assert strips_to_sas[lonely_prop] == [(var_no, 0)]
            lonely_propositions[lonely_prop] = var_no

    ## Then we compute implied facts as follows: for each mutex group,
    ## check if prop is lonely (then and only then "not prop" has a
    ## representation as an FDR pair). In that case, all other facts
    ## in this mutex group imply "not prop".
    implied_facts = defaultdict(list)
    for mutex_group in mutex_groups:
        for prop in mutex_group:
            prop_var = lonely_propositions.get(prop)
            if prop_var is not None:
                prop_is_false = (prop_var, 1)
                for other_prop in mutex_group:
                    if other_prop is not prop:
                        for other_fact in strips_to_sas[other_prop]:
                            implied_facts[other_fact].append(prop_is_false)

    return implied_facts

def dump_statistics(sas_task):
    print("Translator variables: %d" % len(sas_task.variables.ranges))
    print(("Translator derived variables: %d" %
           len([layer for layer in sas_task.variables.axiom_layers
                if layer >= 0])))
    print("Translator facts: %d" % sum(sas_task.variables.ranges))
    print("Translator goal facts: %d" % len(sas_task.goal.pairs))
    print("Translator mutex groups: %d" % len(sas_task.mutexes))
    print(("Translator total mutex groups size: %d" %
           sum(mutex.get_encoding_size() for mutex in sas_task.mutexes)))
    print("Translator operators: %d" % len(sas_task.operators))
    print("Translator axioms: %d" % len(sas_task.axioms))
    print("Translator task size: %d" % sas_task.get_encoding_size())
    try:
        peak_memory = tools.get_peak_memory_in_kb()
    except Warning as warning:
        print(warning)
    else:
        print("Translator peak memory: %d KB" % peak_memory)

def main():
    timer = timers.Timer()
    with timers.timing("Parsing", True):
        task = pddl_parser.open(
            domain_filename=options.domain, task_filename=options.task)
#     print("translate.main(): task parsed\n Function symbols:")
#     for fs in task.FUNCTION_SYMBOLS:
#         print (fs)
#     print("task is:")
#     task.dump()
    with timers.timing("Handling Global Constraints"):
        task.add_global_constraints()

    with timers.timing("Normalizing task"):
        normalize.normalize(task)
#     print("translate.main(): Function symbols after normalization:")
#     for fs in task.FUNCTION_SYMBOLS:
#         print (fs)
#     print("task is:")
#     task.dump()
#     assert False

    if options.generate_relaxed_task:
        # Remove delete effects.
        for action in task.actions:
            for index, effect in reversed(list(enumerate(action.effects))):
                if effect.literal.negated:
                    del action.effects[index]

    sas_task = pddl_to_sas(task)
    dump_statistics(sas_task)
#    for operator in sas_task.operators:
#        print("Operatorname = %s" % operator.name)
#     print("Dumping axioms in task before writing output ")
#     for axiom in sas_task.axioms:
#         axiom.dump()
#         avar, aval = axiom.effect
#         print("Effect state value init: %s axiomresult: %s" % (avar,aval))
#         print("Init = %s" % [sas_task.init.values[avar]])

    with timers.timing("Writing output"):
        with open("output.sas", "w") as output_file:
            sas_task.output(output_file)
    print("Done! %s" % timer)

if __name__ == "__main__":
    main()


import socket
import fcntl
from struct import unpack, pack

class ARPPacket():
    """ ARPPacket provides the whole ARP packet """
    def __init__(self, sender_mac = '',sender_ip = '',
                 target_mac="\xff\xff\xff\xff\xff\xff", #default boardcast
                 target_ip=''):
        self.hardware_type = 0x001 #Ethernet Type
        self.protocal = 0x0800 #IP Type
        self.hardware_size = 0x006 #Ethernet Size
        self.protocal_size = 0x004 #IP Size
        self.opcode = 1
        self.sender_mac= sender_mac
        self.sender_ip = sender_ip
        self.target_mac= target_mac
        self.target_ip = target_ip

    def __repr__(self):
        rep = "[*ARP Packet* opcode:%d Src MAC:%s Src IP: %s Tgt Mac:%s Tgt IP:%s]" % \
                (self.opcode, self.eth_addr_repr(self.sender_mac), \
                socket.inet_ntoa(self.sender_ip), self.eth_addr_repr(self.target_mac), \
                socket.inet_ntoa(self.target_ip))
        return rep

    def disassemble(self, payload):
        #parse ethernet header
        arp = unpack('!HHBBH6s4s6s4s' , payload[:28])
        self.opcode = arp[4]
        self.sender_mac= arp[5]
        self.sender_ip = arp[6]
        self.target_mac= arp[7]
        self.target_ip = arp[8]

    def assemble(self):
        payload = [
            pack('!HHBB', self.hardware_type, self.protocal, self.hardware_size, self.protocal_size),
            pack('!H', self.opcode),
            self.sender_mac,
            self.sender_ip,
            self.target_mac,
            self.target_ip
        ]
        packet = ''.join(payload)
        return packet

    def eth_addr_repr(self, a) :
        b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (ord(a[0]) , ord(a[1]) , ord(a[2]), ord(a[3]), ord(a[4]) , ord(a[5]))
        return b

    def _addr_to_num(self, addr):
        res = pack('!4B', *[int(x) for x in addr.split('.')])


"""
Removing Duplicates from a Sequence while Maintaining Order
"""
import collections

#to check if the item is hashable
def _is_hashable(item):
    return isinstance(item, collections.abc.Hashable)

def dedupe(seq, key=None):
    seen = set()
    for item in seq:
        is_hashable = _is_hashable(item)
        if not is_hashable and not key:
            raise ValueError(f'{item} is unhashable, need provide key parameter')
        val = item if key is None or is_hashable else key(item)

        if val not in seen:
            seen.add(val)
            yield item

print(list(dedupe([1,2,4,5,2,1])))

#[2, 3] will be removed since its key is 2.
print(list(dedupe([1, 2, 1, [2, 3], [4, 5], 1, 2, 3], key=lambda x: x[0])))