from Interprete.OperacionesConExpresiones.Opera_Relacionales import Opera_Relacionales
from Interprete.Condicionantes.Condicion import Condicion
from Interprete.SELECT.select import select
from Interprete.Arbol import Arbol

from Parser.Reportes.Nodo import Nodo

reservadas = {

	# Boolean Type
	'boolean': 'BOOLEAN',
	'true': 'TRUE',
	'false': 'FALSE',
	'order': 'ORDER',

	'into': 'INTO',

	# operator Precedence
	'isnull': 'ISNULL',
	'notnull': 'NOTNULL',

	# Definition
	'replace': 'REPLACE',
	'owner': 'OWNER',
	'show': 'SHOW',
	'databases': 'DATABASES',
	'MAP' : 'MAP',
	'LIST' : 'LIST',

	# Inheritance
	'inherits': 'INHERITS',

	# ESTRUCTURAS DE CONSULTA Y DEFINICIONES
	'select'  : 'SELECT',
	'insert'  : 'INSERT',
	'update'  : 'UPDATE',
	'drop'  : 'DROP',
	'delete'  : 'DELETE',
	'alter'  : 'ALTER',
	'constraint'  : 'CONSTRAINT',
	'from' : 'FROM',
	'group' : 'GROUP',
	'by'  : 'BY',
	'where'  : 'WHERE',
	'having'   : 'HAVING',
	'create' : 'CREATE',
	'type' : 'TYPE',
	'primary' : 'PRIMARY',
	'foreign' : 'FOREIGN',
	'add' : 'ADD',
	'rename' : 'RENAME',
	'set' : 'SET',
	'key' : 'KEY',
	'if' : 'IF',
	'unique' : 'UNIQUE',
	'references' : 'REFERENCES',
	'check' : 'CHECK',
	'column' : 'COLUMN',
	'database' : 'DATABASE',
	'table' : 'TABLE',
	'text' : 'TEXT',
	'float' : 'FLOAT',
	'values' : 'VALUES',
	'int' : 'INT',
	'default' : 'DEFAULT',
	'null' : 'NULL',

	# TIPOS NUMERICOS
	'smallint' : 'SMALLINT',
	'integer' : 'INTEGER',
	'bigint' : 'BIGINT',
	'decimal' : 'DECIMAL',
	'numeric' : 'NUMERIC',
	'real' : 'REAL',
	'double' : 'DOUBLE',
	'precision' : 'PRECISION',
	'money' : 'MONEY',
	'varying' : 'VARYING',
	'varchar' : 'VARCHAR',
	'character' : 'CHARACTER',
	'char' : 'CHAR',
	'clear' : 'CLEAR',

	# TIPOS EN FECHAS
	'timestamp' : 'TIMESTAMP',
	'date' : 'DATE',
	'time' : 'TIME',
	'interval' : 'INTERVAL',
	'year' : 'YEAR',
	'day' : 'DAY',
	'hour' : 'HOUR',
	'minute' : 'MINUTE',
	'second' : 'SECOND',
	'to' : 'TO',

	# ENUM
	'enum'  : 'ENUM',

	# OPERADORES LOGICOS
	'and' : 'AND',
	'or'  : 'OR',
	'not'   : 'NOT',

	# PREDICADOS DE COMPARACION
	'between'   : 'BETWEEN',
	'unknown' : 'UNKNOWN',
	'is'    : 'IS',
	'distinct'  : 'DISTINCT',

	# FUNCIONES MATEMATICAS
	'abs' : 'ABS',
	'cbrt' : 'CBRT',
	'ceil' : 'CEIL',
	'ceiling' : 'CEILING',
	'degrees' : 'DEGREES',
	'div' : 'DIV',
	'exp' : 'EXP',
	'factorial' : 'FACTORIAL',
	'floor' : 'FLOOR',
	'gcd' : 'GCD',
	'lcm' : 'LCM',
	'ln' : 'LN',
	'log' : 'LOG',
	'log10' : 'LOG10',
	'min_scale' : 'MIN_SCALE',
	'mod' : 'MOD',
	'pi' : 'PI',
	'power' : 'POWER',
	'radians' : 'RADIANS',
	'round' : 'ROUND',
	'scale' : 'SCALE',
	'sign' : 'SIGN',
	'sqrt' : 'SQRT',
	'trim_scale' : 'TRIM_SCALE',
	'truc' : 'TRUC',
	'width_bucker' : 'WIDTH_BUCKET',
	'random' : 'RANDOM',
	'setseed' : 'SETSEED',
	'contains' : 'CONTAINS',
	'remove': 'REMOVE',

	# FUNCIONES DE AGREGACION
	'count' : 'COUNT',
	'sum' : 'SUM',
	'avg' : 'AVG',
	'max' : 'MAX',
	'min' : 'MIN',

	# FUNCIONES TRIGONOMETRICAS
	'acos' : 'ACOS',
	'acosd' : 'ACOSD',
	'asin' : 'ASIN',
	'asind' : 'ASIND',
	'atan' : 'ATAN',
	'atand' : 'ATAND',
	'atan2' : 'ATAN2',
	'atan2d' : 'ATAN2D',
	'cos' : 'COS',
	'cosd' : 'COSD',
	'cot' : 'COT',
	'cotd' : 'COTD',
	'sin' : 'SIN',
	'sind' : 'SIND',
	'tan' : 'TAN',
	'tand' : 'TAND',
	'sinh' : 'SINH',
	'cosh' : 'COSH',
	'tanh' : 'TANH',
	'asinh' : 'ASINH',
	'acosh   ' : 'ACOSH',
	'atanh' : 'ATANH',
	'SIZE' : 'SIZE',

	# FUNCIONES DE CADENA BINARIAS
	'length' : 'LENGTH',
	'substring' : 'SUBSTRING',
	'trim' : 'TRIM',
	'get_byte' : 'GET_BYTE',
	'md5' : 'MD5',
	'set_byte' : 'SET_BYTE',
	'sha256' : 'SHA256',
	'substr' : 'SUBSTR',
	'convert' : 'CONVERT',
	'encode' : 'ENCODE',
	'decode' : 'DECODE',

	# COINCidenCIA POR PATRON
	'like' : 'LIKE',
	'ilike' : 'ILIKE',
	'similar' : 'SIMILAR',
	'as' : 'AS',
	'couter' : 'COUTER',

	# SUBQUERYS
	'in' : 'IN',
	'exists' : 'EXISTS',
	'any' : 'ANY',
	'all' : 'ALL',
	'some' : 'SOME',

	# JOINS
	'join' : 'JOIN',
	'inner' : 'INNER',
	'left' : 'LEFT',
	'right' : 'RIGHT',
	'full' : 'FULL',
	'outer' : 'OUTER',
	'on' : 'ON',

	# ORDENAMIENTO DE FILAS
	'asc' : 'ASC',
	'desc' : 'DESC',
	'nulls' : 'NULLS',
	'first' : 'FIRST',
	'last' : 'LAST',

	# EXPRESIONES
	'case' : 'CASE',
	'when' : 'WHEN',
	'then' : 'THEN',
	'end' : 'END',
	'greatest' : 'GREATEST',
	'least' : 'LEAST',

	# LIMITE Y OFFSET
	'limit' : 'LIMIT',
	'offset' : 'OFFSET',

	# CONSULTAS DE COMBINACION
	'union' : 'UNION',
	'intersect' : 'INTERSECT',
	'except' : 'EXCEPT'

}

tokens  = [
	'PT',
	'DOBPTS',
	'MAS',
	'MENOS',
	'MULTI',
	'DIVISION',
	'MODULO',
	'IGUAL',
	'PARIZQ',
	'PARDER',
	'PTCOMA',
	'COMA',
	'TKNOT',
	'NOTBB',
	'ANDBB',
	'ORBB',
	'NUMERAL',
	'TKEXP',
	'SHIFTIZQ',
	'SHIFTDER',
	'IGUALQUE',
	'DISTINTO',
	'MAYORIG',
	'MENORIG',
	'MAYORQUE',
	'MENORQUE',
	'CORIZQ',
	'CORDER',
	'DOSPTS',
	'TKDECIMAL',
	'ENTERO',
	'CADENA',
	'CADENADOBLE',
	'ID'
] + list(reservadas.values())

# Tokens
t_PT        = r'\.'
t_DOBPTS    = r'::'
t_CORIZQ      = r'\['
t_CORDER      = r']'

t_MAS       = r'\+'
t_MENOS     = r'-'
t_TKEXP     = r'\^'
t_MULTI     = r'\*'
t_DIVISION  = r'/'
t_MODULO   = r'%'
t_IGUAL     = r'='
t_PARIZQ    = r'\('
t_PARDER    = r'\)'
t_PTCOMA    = r';'
t_COMA      = r','
t_TKNOT       = r'!'
t_NOTBB     = r'~'
t_ANDBB     = r'&'
t_ORBB      = r'\|'

t_NUMERAL   = r'\#'

t_SHIFTIZQ  = r'<<'
t_SHIFTDER  = r'>>'
t_IGUALQUE  = r'=='
t_DISTINTO  = r'!='
t_MAYORIG   = r'>='
t_MENORIG   = r'<='
t_MAYORQUE  = r'>'
t_MENORQUE  = r'<'
t_DOSPTS    = r':'

def t_ENTERO(t):
	r'\d+'
	try:
		t.value = int(t.value)
	except ValueError:
		print("Integer value too large %d", t.value)
		t.value = 0
	return t

def t_TKDECIMAL(t):
	r'\d+\.\d+'
	try:
		t.value = float(t.value)
	except ValueError:
		print("Float value too large %d", t.value)
		t.value = 0
	return t

def t_CADENA(t):
	r'\'.*?\''
	t.value = t.value[1:-1]
	return t

def t_CADENADOBLE(t):
	r'\".*?\"'
	t.value = t.value[1:-1]
	return t

def t_ID(t):
	 r'[a-zA-Z_][a-zA-Z_0-9]*'
	 t.type = reservadas.get(t.value.lower(),'ID')
	 return t

t_ignore = " \t"

def t_newline(t):
	r'\n+'
	t.lexer.lineno += len(t.value) # t.value.count("\n")

def t_COMENTARIO_SIMPLE(t):
	r'\--.*\n'
	t.lexer.lineno += 1

def t_COMENTARIO_MULTILINEA(t):
	r'/\*(.|\n)*?\*/'
	t.lexer.lineno += t.value.count('\n')

def t_error(t):
	print("Caracter NO Valido: '%s'" % t.value[0])
	t.lexer.skip(1)
	print(t.value[0])

# -----------------------------------------------------------------------------------
# ---------------------- SINTACTICO -------------------------------------------------
# -----------------------------------------------------------------------------------

#-----------------------
import ply.lex as lex
lexer2 = lex.lex()
#-----------------------
precedence = (
	#('left','CONCAT'),
	#('left','MENOR','MAYOR','IGUAL','MENORIGUAL','MAYORIGUAL','DIFERENTE'),
	('left','MENORQUE','MAYORQUE','IGUAL','MENORIG','MAYORIG','DISTINTO'),
	('left','MAS','MENOS'),
	('left','MULTI','DIVISION','MODULO'),
	('left','TKEXP'),
	#('right','UMENOS'),
)

def p_init(t):
	'init : sentences'
	t[0] = Nodo("init", "")
	t[0].add(t[1])

def p_sentences(t):
	'''
		sentences   : sentences setInstruccions
					| setInstruccions
	'''
	if len(t) == 3:  # listawhere atributoselect
		t[1].add(t[2])
		t[0] = t[1]
	else:  # atributoselect
		t[0] = Nodo("sentences", "")
		t[0].add(t[1])

def p_setInstruccions(t):
	'''
		setInstruccions   : sentence PTCOMA
	'''
	t[0] = Nodo("setInstruccions", "")
	t[0].add(t[1])

def p_sentence(t):
	'''
		sentence     : ddl
	'''
	t[0] = Nodo("sentence", "")
	t[0].add(t[1])

def p_ddl(t):
	'''
		ddl  : select
			 | table_create
			 | insert
			 | update
			 | deletetable
	'''
	t[0] = Nodo("ddl", "")
	t[0].add(t[1])

def p_select(t):
	'''
		select  : SELECT listavalores FROM exp listawhere
	'''
	t[0] = Nodo("select", "")
	t[1].add(Nodo(t[1], ''))
	t[0].add(t[2])
	t[1].add(Nodo(t[3], ''))
	t[0].add(t[4])
	t[0].add(t[5])

def p_listawhere(t):
	'''
		listawhere  : listawhere atributoselect
					| atributoselect
	'''
	if len(t) == 3:  # listawhere atributoselect
		t[1].add(t[2])
		t[0] = t[1]
	else:  # atributoselect
		t[0] = Nodo("listawhere", "")
		t[0].add(t[1])

def p_atributoselect(t):
	'''
		atributoselect  : WHERE exp
						| ORDER BY exp ordenamiento
						| GROUP BY exp
						| LIMIT exp
	'''
	t[0] = Nodo("atributoselect", "")
	if t[1].lower() == "where":
		t[1].add(Nodo(t[1], ''))
		t[1].add(t[2])
	elif t[1].lower() == "order":
		t[1].add(Nodo(t[1]+' '+t[2], ''))
		t[1].add(t[3])
		t[1].add(t[4])
	elif t[1].lower() == "group":
		t[1].add(Nodo(t[1] + ' ' + t[2], ''))
		t[1].add(t[3])
	elif t[1].lower() == "limit":
		t[1].add(Nodo(t[1], ''))
		t[1].add(t[2])

def p_ordenamiento(t):
	'''
		ordenamiento   : ASC
					   | DESC
	'''
	t[0] = Nodo("ordenamiento", "")
	t[1].add(Nodo(t[1], ''))

def p_listavalores(t):
	'''
		listavalores   : listavalores COMA exp
					   | exp
	'''
	if len(t) == 4: #listavalores COMA exp
		t[1].add(t[3])
		t[0] = t[1]
	else: # exp
		t[0] = Nodo("listavalores", "")
		t[0].add(t[1])

def p_exp(t):
	'''
		exp   : MAS exp
			  | MENOS exp
			  | exp TKEXP 	exp
			  | exp MULTI 	exp
			  | exp DIVISION exp
			  | exp MODULO exp
			  | exp MAS exp
			  | exp MENOS exp
			  | exp BETWEEN exp
			  | exp IN exp
			  | exp LIKE exp
			  | exp ILIKE exp
			  | exp SIMILAR exp
			  | exp IGUAL exp
			  | exp MAYORQUE exp
			  | exp MENORQUE exp
			  | exp MAYORIG exp
			  | exp MENORIG exp
			  | exp IS exp
			  | exp ISNULL exp
			  | exp NOTNULL exp
			  | NOT exp
			  | exp AND exp
			  | exp OR exp
	'''
	t[0] = Nodo("exp", "")
	if len(t) == 3:#LITERAL exp
		t[0].add(Nodo(t[1], ''))
		t[0].add(t[2])
	elif len(t) == 4:#exp LITERAL exp
		t[0].add(t[1])
		t[0].add(Nodo(t[2], ''))
		t[0].add(t[3])

def p_expSimples(t):
	'''
		exp         :   ID
					| ENTERO
					| TKDECIMAL
					| TRUE
					| FALSE
					| CADENADOBLE
					| CADENA
	'''
	t[0] = Nodo("exp", "")
	t[0].add(Nodo(t[1], ''))

# ---------------CREATE TABLE---------------
def p_table_create(t):
	'''
		table_create : CREATE TABLE ID PARIZQ lista_table COMA listadolprimary PARDER
					 | CREATE TABLE ID PARIZQ lista_table PARDER
					 | CREATE TABLE IF NOT EXISTS ID PARIZQ lista_table COMA listadolprimary PARDER
					 | CREATE TABLE IF NOT EXISTS ID PARDER lista_table PARDER
	'''
	t[0] = Nodo("table_create", "")
	if len(t) == 9:
		#CREATE TABLE ID PARIZQ lista_table COMA listadolprimary PARDER
		t[1].add(Nodo(t[1]+' '+t[2]+' '+t[3],''))
		t[1].add(t[5])
		t[1].add(t[7])
	elif len(t) == 7:
		#CREATE TABLE ID PARIZQ lista_table PARDER
		t[1].add(Nodo(t[1]+' '+t[2]+' '+t[3],''))
		t[1].add(t[5])
	elif len(t) == 12:
		#CREATE TABLE IF NOT EXISTS ID PARIZQ lista_table COMA listadolprimary PARDER
		t[1].add(Nodo(t[1]+' '+t[2]+' '+t[3]+' '+t[4]+' '+t[5]+' '+t[6],''))
		t[1].add(t[8])
		t[1].add(t[10])
	elif len(t) == 10:
		#CREATE TABLE IF NOT EXISTS ID PARDER lista_table PARDER
		t[1].add(Nodo(t[1]+' '+t[2]+' '+t[3]+' '+t[4]+' '+t[5]+' '+t[6],''))
		t[1].add(t[8])

def p_lista_table(t):
	'''
		lista_table  : lista_table COMA atributo_table
					 | atributo_table
	'''
	if len(t) == 3: #lista_table COMA atributo_table
		t[1].add(t[3])
		t[0] = t[1]
	else: # atributo_table
		t[0] = Nodo("lista_table", "")
		t[0].add(t[1])

def p_listadolprimary(t):
	'''
		listadolprimary  : listadolprimary COMA lista_primary
						 | lista_primary
	'''
	if len(t) == 3: #listadolprimary COMA lista_primary
		t[1].add(t[3])
		t[0] = t[1]
	else: # lista_primary
		t[0] = Nodo("listadolprimary", "")
		t[0].add(t[1])

def p_lista_primary(t):
	'''
		lista_primary : PRIMARY KEY PARIZQ listaids PARDER
					  | FOREIGN KEY PARIZQ listaids PARDER REFERENCES ID PARIZQ listaids PARDER
					  | CONSTRAINT ID CHECK PARIZQ exp PARDER
					  | UNIQUE PARIZQ listaids PARDER
	'''
	t[0] = Nodo("lista_primary", "")
	if t[1].tolower() == 'primary':#PRIMARY KEY PARIZQ listaids PARDER
		t[0].add(Nodo(t[1]+''+t[2], ''))
		t[1].add(t[4])
	elif t[1].tolower() == 'foreign':#FOREIGN KEY PARIZQ listaids PARDER REFERENCES ID PARIZQ listaids PARDER
		t[0].add(Nodo(t[1]+''+t[2], ''))
		t[1].add(t[4])
		t[0].add(Nodo(t[6]+''+t[7], ''))
		t[1].add(t[9])
	elif t[1].tolower() == 'contraint': #CONSTRAINT ID CHECK PARIZQ exp PARDER
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(Nodo(t[3], ''))
		t[1].add(t[5])
	elif t[1].tolower() == 'unique':#UNIQUE PARIZQ listaids PARDER
		t[0].add(Nodo(t[1], ''))
		t[1].add(t[3])

def p_atributo_table(t):
	'''
		atributo_table : ID  tipocql listaespecificaciones
					   | ID  tipocql
	'''
	t[0] = Nodo("atributo_table", "")
	if len(t)==3:#ID  tipocql
		t[0].add(Nodo(t[1], ''))
		t[1].add(t[2])
	else:#ID  tipocql listaespecificaciones
		t[0].add(Nodo(t[1], ''))
		t[1].add(t[2])
		t[1].add(t[3])

def p_listaespecificaciones(t):
	'''
		listaespecificaciones  : listaespecificaciones especificaciones
							   | especificaciones
	'''
	if len(t) == 3: #listaespecificaciones especificaciones
		t[1].add(t[2])
		t[0] = t[1]
	else: # especificaciones
		t[0] = Nodo("listaespecificaciones", "")
		t[0].add(t[1])

def p_especificaciones(t):
	'''
		especificaciones : UNIQUE
						 | NULL
						 | PRIMARY KEY
						 | NOT NULL
						 | REFERENCES ID
						 | CONSTRAINT ID
						 | DEFAULT exp
						 | CHECK PARIZQ exp PARDER
	'''
	t[0] = Nodo("especificaciones", "")

	if len(t)==3:
		if t[1].tolower()=='default':# DEFAULT exp
			t[0].add(Nodo(t[1], ''))
			t[0].add(t[2])
		else:  #| PRIMARY KEY | NOT NULL | REFERENCES ID | CONSTRAINT ID
			t[0].add(Nodo(t[1], ''))
			t[0].add(Nodo(t[2], ''))

	elif len(t) == 5:  #CHECK PARIZQ exp PARDER
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(t[3])
		t[0].add(Nodo(t[4], ''))

	else: #UNIQUE | NULL | PRIMARY KEY | NOT NULL
		t[0].add(Nodo(t[1], ''))

def p_tipocql(t):
	'''
		tipocql : ID
				| tipo
	'''
	t[0] = Nodo("tipo", "")
	t[0].add(Nodo(t[1], ''))

def p_tipo(t):
	'''
		 tipo : SMALLINT
			  | INTEGER
			  | BIGINT
			  | DECIMAL
			  | NUMERIC
			  | REAL
			  | TIME
			  | MONEY
			  | TEXT
			  | DATE
			  | TIMESTAMP
			  | INTERVAL
			  | BOOLEAN
			  | DOUBLE 	  PRECISION
			  | VARCHAR   PARIZQ 		 exp PARDER
			  | CHARACTER PARIZQ 		 exp PARDER
			  | CHAR 	  PARIZQ 	     exp PARDER
			  | CHARACTER VARYING PARIZQ exp PARDER
	'''
	t[0] = Nodo("tipo", "")

	if len(t) ==2:
	#SMALLINT | INTEGER | BIGINT | DECIMAL |
	# NUMERIC | REAL | TIME | MONEY | TEXT | DATE | TIMESTAMP |
	# INTERVAL | BOOLEAN
		t[0].add(Nodo(t[1], ''))
	elif len(t) == 3:#DOUBLE 	  PRECISION
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
	elif len(t) ==5:# VARCHAR   PARIZQ exp PARDER | CHARACTER PARIZQ
		# exp PARDER | CHAR PARIZQ exp PARDER
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(t[3])
		t[0].add(Nodo(t[4], ''))
	elif len(t) ==6:
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(Nodo(t[3], ''))
		t[0].add(t[4])
		t[0].add(Nodo(t[5], ''))

# ---------------INSERT---------------
def p_insert(t):
	'''
		insert : INSERT INTO ID VALUES PARIZQ listavalores PARDER
			   | INSERT INTO ID PARIZQ listaids PARDER VALUES PARIZQ listavalores PARDER
	'''
	t[0] = Nodo("insert", "")
	if len(t) ==7: #INSERT INTO ID VALUES PARIZQ listavalores PARDER
		t[0].add(Nodo(t[1]+' '+t[2]+' '+t[3]+' '+t[4], ''))
		t[0].add(t[6])

	elif len(t) == 11: #INSERT INTO ID PARIZQ listaids PARDER VALUES PARIZQ listavalores PARDER
		t[0].add(Nodo(t[1]+' '+t[2]+' '+t[3], ''))
		t[0].add(t[5])
		t[0].add(Nodo(t[7], ''))
		t[0].add(t[9])

def p_listaids(t):
	'''
		listaids : listaids COMA ID
				 | ID
	'''
	if len(t) == 4: #listaids COMA ID
		t[1].add(Nodo(t[3],''))
		t[0] = t[1]
	else: # ID
		t[0] = Nodo("listaids", "")
		t[0].add(Nodo(t[1],''))

# ---------------UPDATE---------------
def p_update(t):
	'''
		update : UPDATE ID SET listaupdate WHERE exp
			   | UPDATE ID SET listaupdate
	'''
	t[0] = Nodo("update", "")

	if len(t)==7:#UPDATE ID SET listaupdate WHERE exp
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(Nodo(t[3], ''))
		t[0].add(t[4])
		t[0].add(Nodo(t[5], ''))
		t[0].add(t[6])
	elif len(t)==5:#UPDATE ID SET listaupdate
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(Nodo(t[3], ''))
		t[0].add(t[4])

def p_listaupdate(t):
	'''
		listaupdate : listaupdate COMA asignacionupdate
					| asignacionupdate
	'''
	if len(t) == 4: # listaupdate COMA asignacionupdate
		t[1].add(t[3])
		t[0] = t[1]
	else:           # asignacionupdate
		t[0] = Nodo("listaupdate", "")
		t[0].add(t[1])

def p_asignacionupdate(t):
	'''
		asignacionupdate : acceso IGUAL exp
	'''
	t[0] = Nodo("asignacionupdate", "")
	t[0].add(t[1])
	t[0].add(Nodo(t[2], ''))
	t[0].add(t[3])

# TODO: Segun la gramatica, hace falta la produccion 'Variable' cuya exp. reg. es: "@[A-Za-z][_A-Za-z0-9]*"
def p_acceso(t):
	'''
		acceso : acceso PT ID
			   | acceso  CORIZQ exp CORDER
			   | ID
	'''
	t[0] = Nodo("acceso", "")

	if len(t) == 4:#acceso PT ID
		t[0].add(t[1])
		t[0].add(Nodo(t[2], ''))
		t[0].add(Nodo(t[3], ''))
		pass
	elif len(t) == 5: #acceso  CORIZQ exp CORDER
		t[0].add(t[1])
		t[0].add(Nodo(t[2], ''))
		t[0].add(t[3])
		t[0].add(Nodo(t[4], ''))
	elif len(t) == 2: # ID
		t[0].add(Nodo(t[1], ''))

def p_acceso1(t):
	'''
		acceso : acceso PT funcioncollection
	'''
	t[0] = Nodo("acceso", "")
	t[0].add(t[1])
	t[0].add(Nodo(t[2], ''))
	t[0].add(t[3])

def p_funcioncollection(t):
	'''
		funcioncollection   : INSERT    PARIZQ exp COMA exp PARDER
							| INSERT    PARIZQ exp PARDER
							| SET       PARIZQ exp COMA exp PARDER
							| REMOVE    PARIZQ exp PARDER
							| SIZE      PARIZQ PARDER
							| CLEAR     PARIZQ PARDER
							| CONTAINS 	PARIZQ exp PARDER
							| LENGTH    PARIZQ PARDER
							| SUBSTRING PARIZQ exp COMA exp PARDER
	'''
	t[0] = Nodo("funcioncollection", "")

	if t[1].lower() == 'insert':

		if len(t) ==7: #INSERT PARIZQ exp COMA exp PARDER
			t[0].add(Nodo(t[1],''))
			t[0].add(Nodo(t[2],''))
			t[0].add(t[3])
			t[0].add(Nodo(t[4],''))
			t[0].add(t[5])
			t[0].add(Nodo(t[6],''))

		elif len(t) == 5: #INSERT PARIZQ exp PARDER
			t[0].add(Nodo(t[1],''))
			t[0].add(Nodo(t[2],''))
			t[0].add(t[3])
			t[0].add(Nodo(t[4],''))

	elif t[1].lower() == 'set': #SET PARIZQ exp COMA exp PARDER
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(t[3])
		t[0].add(Nodo(t[4], ''))
		t[0].add(t[5])
		t[0].add(Nodo(t[6], ''))

	elif t[1].lower() == 'remove': #REMOVE PARIZQ exp PARDER
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(t[3])
		t[0].add(Nodo(t[4], ''))

	elif t[1].lower() == 'size': #SIZE PARIZQ PARDER
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(Nodo(t[3], ''))

	elif t[1].lower() == 'clear': #CLEAR PARIZQ PARDER
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(Nodo(t[3], ''))

	elif t[1].lower() == 'contains': #CONTAINS PARIZQ exp PARDER
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(t[3])
		t[0].add(Nodo(t[4], ''))

	elif t[1].lower() == 'length': #LENGTH PARIZQ PARDER
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(Nodo(t[3], ''))

	elif t[1].lower() == 'substring': #SUBSTRING PARIZQ exp COMA exp PARDER
		t[0].add(Nodo(t[1], ''))
		t[0].add(Nodo(t[2], ''))
		t[0].add(t[3])
		t[0].add(Nodo(t[4], ''))
		t[0].add(t[5])
		t[0].add(Nodo(t[6], ''))

# ---------------DELETE---------------
def p_deletetable(t):
	'''
		deletetable : DELETE FROM ID WHERE exp
					| DELETE FROM ID
					| DELETE listaatributos FROM ID WHERE exp
					| DELETE listaatributos FROM ID
	'''
	t[0] = Nodo("deletetable", "")

	if len(t)==6: # DELETE FROM ID WHERE exp
		t[0].add(Nodo(t[1],''))
		t[0].add(Nodo(t[2],''))
		t[0].add(Nodo(t[3],''))
		t[0].add(Nodo(t[4],''))
		t[0].add(t[5])

	elif len(t) == 4:  # DELETE FROM ID
		t[0].add(Nodo(t[1],''))
		t[0].add(Nodo(t[2],''))
		t[0].add(Nodo(t[3],''))

	elif len(t) == 7:  # DELETE listaatributos FROM ID WHERE exp
		t[0].add(Nodo(t[1],''))
		t[0].add(t[2])
		t[0].add(Nodo(t[3],''))
		t[0].add(Nodo(t[4],''))
		t[0].add(Nodo(t[6],''))
		t[0].add(t[7])

	elif len(t) == 5:  # DELETE listaatributos FROM ID
		t[0].add(Nodo(t[1],''))
		t[0].add(t[2])
		t[0].add(Nodo(t[3],''))
		t[0].add(Nodo(t[4],''))

def p_listaatributos(t):
	'''
		listaatributos : listaatributos COMA acceso
					   | acceso
	'''
	if len(t) == 4:
		t[1].add(t[3])
		t[0] = t[1]
	else:
		t[0] = Nodo("listaatributos","")
		t[0].add(t[1])

# ---------------ERROR SINTACTICO---------------
def p_error(t):
	print(t)
	print("Error sintáctico en '%s'" % t.value)

import ply.yacc as yacc
parser = yacc.yacc()

def parse(input) :
	global cadena,lisErr, dot
	#parser = yacc.yacc()
	lexer2.lineno=1
	#par= parser.parse("ADD")
	#print(par)
	return parser.parse(input)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2018 GoPro Inc.
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

import os
import os.path as op
import sys

from PyQt5 import QtCore, QtGui, QtWidgets

from pynodegl_utils.com import query_subproc
from pynodegl_utils.config import Config
from pynodegl_utils.misc import Media
from pynodegl_utils.scriptsmgr import ScriptsManager

from pynodegl_utils.ui.gl_view import GLView
from pynodegl_utils.ui.graph_view import GraphView
from pynodegl_utils.ui.export_view import ExportView
from pynodegl_utils.ui.serial_view import SerialView
from pynodegl_utils.ui.toolbar import Toolbar
from pynodegl_utils.ui.hooks import Hooks

class MainWindow(QtWidgets.QSplitter):

    error = QtCore.pyqtSignal(str)

    def __init__(self, module_pkgname, assets_dir, hooksdir):
        super(MainWindow, self).__init__(QtCore.Qt.Horizontal)
        self._win_title_base = 'Node.gl viewer'
        self.setWindowTitle(self._win_title_base)

        self._module_pkgname = module_pkgname
        self._scripts_mgr = ScriptsManager(module_pkgname)
        self._hooksdir = hooksdir

        medias = None
        if assets_dir:
            medias = []
            for f in sorted(os.listdir(assets_dir)):
                ext = f.rsplit('.', 1)[-1].lower()
                path = op.join(assets_dir, f)
                if op.isfile(path) and ext in ('mp4', 'mkv', 'avi', 'webm', 'mov', 'lrv'):
                    try:
                        media = Media(path)
                    except:
                        pass
                    else:
                        medias.append(media)

        self._medias = medias

        get_scene_func = self._get_scene

        self._hooks = None
        self._config = Config(module_pkgname)

        # Apply previous geometry (position + dimensions)
        rect = self._config.get('geometry')
        if rect:
            geometry = QtCore.QRect(*rect)
            self.setGeometry(geometry)

        gl_view = GLView(get_scene_func, self._config)
        graph_view = GraphView(get_scene_func, self._config)
        export_view = ExportView(get_scene_func, self._config)
        serial_view = SerialView(get_scene_func)

        self._tabs = [
            ('Player view', gl_view),
            ('Graph view', graph_view),
            ('Export', export_view),
            ('Serialization', serial_view),
        ]
        self._last_tab_index = -1

        self._tab_widget = QtWidgets.QTabWidget()
        for tab_name, tab_view in self._tabs:
            self._tab_widget.addTab(tab_view, tab_name)
        self._tab_widget.currentChanged.connect(self._currentTabChanged)

        self._scene_toolbar = Toolbar(self._config)
        self._scene_toolbar.sceneChanged.connect(self._scene_changed)
        self._scene_toolbar.sceneChanged.connect(self._scene_changed_hook)
        self._scene_toolbar.sceneChanged.connect(self._config.scene_changed)
        self._scene_toolbar.aspectRatioChanged.connect(gl_view.set_aspect_ratio)
        self._scene_toolbar.aspectRatioChanged.connect(export_view.set_aspect_ratio)
        self._scene_toolbar.aspectRatioChanged.connect(self._config.set_aspect_ratio)
        self._scene_toolbar.samplesChanged.connect(gl_view.set_samples)
        self._scene_toolbar.samplesChanged.connect(self._config.set_samples)
        self._scene_toolbar.frameRateChanged.connect(gl_view.set_frame_rate)
        self._scene_toolbar.frameRateChanged.connect(graph_view.set_frame_rate)
        self._scene_toolbar.frameRateChanged.connect(export_view.set_frame_rate)
        self._scene_toolbar.frameRateChanged.connect(self._config.set_frame_rate)
        self._scene_toolbar.logLevelChanged.connect(self._config.set_log_level)
        self._scene_toolbar.clearColorChanged.connect(gl_view.set_clear_color)
        self._scene_toolbar.clearColorChanged.connect(self._config.set_clear_color)
        self._scene_toolbar.backendChanged.connect(gl_view.set_backend)
        self._scene_toolbar.backendChanged.connect(self._config.set_backend)

        self._scene_toolbar.hudChanged.connect(self._config.set_hud)

        self._errbuf = QtWidgets.QPlainTextEdit()
        self._errbuf.setFont(QtGui.QFontDatabase.systemFont(QtGui.QFontDatabase.FixedFont))
        self._errbuf.setReadOnly(True)
        self._errbuf.hide()

        self._hooks_lbl = QtWidgets.QLabel()
        self._hooks_layout = QtWidgets.QHBoxLayout()
        self._hooks_layout.addWidget(self._hooks_lbl)
        self._hooks_widget = QtWidgets.QWidget()
        self._hooks_widget.setLayout(self._hooks_layout)
        self._hooks_widget.hide()

        tabs_and_errbuf = QtWidgets.QVBoxLayout()
        tabs_and_errbuf.addWidget(self._tab_widget)
        tabs_and_errbuf.addWidget(self._errbuf)
        tabs_and_errbuf.addWidget(self._hooks_widget)
        tabs_and_errbuf_widget = QtWidgets.QWidget()
        tabs_and_errbuf_widget.setLayout(tabs_and_errbuf)

        self.addWidget(self._scene_toolbar)
        self.addWidget(tabs_and_errbuf_widget)
        self.setStretchFactor(1, 1)

        self._scene_toolbar.reload_btn.clicked.connect(self._scripts_mgr.reload)  # TODO: drop
        self._scripts_mgr.error.connect(self._all_scripts_err)
        self._scripts_mgr.scriptsChanged.connect(self._scene_toolbar.on_scripts_changed)
        self._scripts_mgr.start()

        self.error.connect(self._scene_err)

        # Load the previous scene if the current and previously loaded
        # module packages match
        prev_pkgname = self._config.get('pkg')
        prev_module = self._config.get('module')
        prev_scene = self._config.get('scene')
        if prev_pkgname == module_pkgname:
            self._scene_toolbar.load_scene_from_name(prev_module, prev_scene)

    @QtCore.pyqtSlot(int, int, str)
    def _hooks_uploading(self, i, n, filename):
        self._hooks_widget.show()
        self._hooks_lbl.setText('Uploading [%d/%d]: %s...' % (i, n, filename))

    @QtCore.pyqtSlot(str, str)
    def _hooks_building_scene(self, backend, system):
        self._hooks_widget.show()
        self._hooks_lbl.setText('Building %s scene in %s...' % (system, backend))

    @QtCore.pyqtSlot()
    def _hooks_sending_scene(self):
        self._hooks_widget.show()
        self._hooks_lbl.setText('Sending scene...')

    @QtCore.pyqtSlot()
    def _hooks_done(self):
        self._hooks_widget.hide()

    @QtCore.pyqtSlot(str)
    def _scene_err(self, err_str):
        if err_str:
            self._errbuf.setPlainText(err_str)
            self._errbuf.show()
            sys.stderr.write(err_str)
        else:
            self._errbuf.hide()

    @QtCore.pyqtSlot(str)
    def _all_scripts_err(self, err_str):
        self._scene_toolbar.clear_scripts()
        self._scene_err(err_str)

    def _get_scene(self, **cfg_overrides):
        cfg = self._scene_toolbar.get_cfg()
        if cfg['scene'] is None:
            return None
        cfg['pkg'] = self._module_pkgname
        cfg['medias'] = self._medias
        cfg.update(cfg_overrides)

        self._scripts_mgr.pause()
        ret = query_subproc(query='scene', **cfg)
        if 'error' in ret:
            self._scripts_mgr.update_filelist(ret['filelist'])
            self._scripts_mgr.resume()
            self.error.emit(ret['error'])
            return None

        self.error.emit(None)
        self._scripts_mgr.set_filelist(ret['filelist'])
        self._scripts_mgr.resume()
        self._scene_toolbar.set_cfg(ret)

        return ret

    @QtCore.pyqtSlot(str, str)
    def _scene_changed(self, module_name, scene_name):
        self.setWindowTitle('%s - %s.%s' % (self._win_title_base, module_name, scene_name))
        self._currentTabChanged(self._tab_widget.currentIndex())

    @QtCore.pyqtSlot(str, str)
    def _scene_changed_hook(self, module_name, scene_name):
        if self._hooks:
            self._hooks.wait()
        self._hooks = Hooks(self._get_scene, self._hooksdir)
        self._hooks.uploadingFileNotif.connect(self._hooks_uploading)
        self._hooks.buildingSceneNotif.connect(self._hooks_building_scene)
        self._hooks.sendingSceneNotif.connect(self._hooks_sending_scene)
        self._hooks.finished.connect(self._hooks_done)
        self._hooks.error.connect(self._hooks_error)
        self._hooks.start()

    @QtCore.pyqtSlot(str)
    def _hooks_error(self, err):
        QtWidgets.QMessageBox.critical(self, 'Hook error', err, QtWidgets.QMessageBox.Ok)

    def _emit_geometry(self):
        geometry = (self.x(), self.y(), self.width(), self.height())
        self._config.geometry_changed(geometry)

    @QtCore.pyqtSlot(QtGui.QResizeEvent)
    def resizeEvent(self, resize_event):
        super(MainWindow, self).resizeEvent(resize_event)
        self._emit_geometry()

    @QtCore.pyqtSlot(QtGui.QMoveEvent)
    def moveEvent(self, move_event):
        super(MainWindow, self).moveEvent(move_event)
        self._emit_geometry()

    @QtCore.pyqtSlot(QtGui.QCloseEvent)
    def closeEvent(self, close_event):
        for name, widget in self._tabs:
            widget.close()
        super(MainWindow, self).closeEvent(close_event)

    @QtCore.pyqtSlot(int)
    def _currentTabChanged(self, index):
        next_view = self._tabs[index][1]
        prev_view = self._tabs[self._last_tab_index][1]
        if index != self._last_tab_index and hasattr(prev_view, 'leave'):
            prev_view.leave()
        if hasattr(next_view, 'enter'):
            next_view.enter()
        self._last_tab_index = index


#
# @lc app=leetcode.cn id=63 lang=python3
#
# [63] 不同路径 II
#

# @lc code=start
class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        if not obstacleGrid: return 0
        if not obstacleGrid[0]: return 0
        m, n = len(obstacleGrid), len(obstacleGrid[0])

        # # 二维数组
        # dp = [[0 for _ in range(n)] for _ in range(m)]

        # for row in range(m):
        #     if obstacleGrid[row][0] != 1:
        #         dp[row][0] = 1
        #     else:
        #         for i in range(row, m):
        #             dp[i][0] = 0
        #         break

        # for col in range(n):
        #     if obstacleGrid[0][col] != 1:
        #         dp[0][col] = 1
        #     else:
        #         for j in range(col, n):
        #             dp[0][j] = 0
        #         break

        # for r in range(1, m):
        #     for c in range(1, n):
        #         if obstacleGrid[r][c] == 1:
        #             dp[r][c] = 0
        #         else:
        #             dp[r][c] = dp[r-1][c] + dp[r][c-1]
        # return dp[m-1][n-1]

        # 一维数组
        dp = [0 for _ in range(n)]

        for col in range(n):
            if obstacleGrid[0][col] == 1:
                for c in range(col, n):
                    dp[c] = 0
                break
            else:
                dp[col] = 1

        for r in range(1, m):
            for c in range(n):
                if obstacleGrid[r][c] == 1:
                    dp[c] = 0
                else:
                    dp[c] += dp[c-1] if c > 0 else 0
        return dp[-1]

# @lc code=end


#Encoding: UTF-8
import turtle
Maki = turtle.Turtle()

def dibujarEstrella(t, n):
    for i in range(n):
        t.forward(100)
        t.left(180 - 180/n)
def paresYnones(numeroPrueba):
    numeroProbacion=numeroPrueba%2
    if numeroProbacion==0:
        conclusion=False
    else:
        conclusion=True
    return(conclusion)

def Main():
    numeroDeLados=int(input("Ingrese un número impar mayor a 3 para dibujar una estrella"))
    if numeroDeLados<=2:
        print("No hay suficientes lados")
    else:
        lados=paresYnones(numeroDeLados)
        if lados==True:
            dibujarEstrella(Maki, numeroDeLados)
        else:
            print("Favor de ingresar un número impar")

Main()


from random import choice
iniciachat = input()
conversa1 = str("Me chamo bbot1, qual é o seu nome? ")
conversa2 = str("qual seu nome?")
conversa3 = str(" Eu sou o bbot, como vc se chama? ")

opcao = [conversa1,conversa2,conversa3]

escolha = choice(opcao)
resposta = input(escolha)

resposta2 = input(format('') + (" muito prazer " + resposta + ", você está bem? "))

if (resposta2.upper() == "SIM"):
    resposta3 = input("que ótimo, fico feliz! posso te fazer uma pergunta? ")

    if (resposta3.upper() == "SIM"):

        resposta4 = input("opa que bom, qual dos dois elementos é mais pesado? metal ou algodão? ")

        if (resposta4 == "nenhum dos dois"):
            print(" correto vc acertou, parabéns " " vc é bem inteligente!")
            input(' ')
            print(" Fiquei muito feliz em te conhecer, espero conversar com vc novamente! um abraço! ")

        else:
            print(" uhm! vc errou. a resposta certa seria nenhuma das duas,"'\n'
                  "pois um kilo de metal tem o mesmo peso que um kilo de algodão.")
            input(' ')
            input(" talvez da proxima vc acerte kk ")
            print(" quando quiser bater um papo me chama aki bye bye!")

    else:
        print(" Poxa, tudo bem, agente conversa um outra hora então.Um abraço!")

else:
     resposta5 = input("poxa, que pena, posso ajudar? ")

     if (resposta5.upper() == "SIM"):
         resposta6 = input("ok, Me diga. Você esta triste? ")

         if (resposta6.upper() == "SIM"):
             print(" Em momentos ruins assim é bom ficar perto de alguém que te alegre ou ouvir musicas bem animadas!,"
                   "tente fazer isso ok?")
             l = input(" ")
             print(" Eu tenho certeza que vai ficar tudo bem, quando quiser conversar de novo me chama aki !")

     else:
         print(" puxa, vc está fazendo jogo duro, espero que as coisas melhorem pra vc "
              "se quiser conversar de novo me chama aki, um abraço !")
         import os
         os.startfile(' ')


from django.conf.urls import url

from home import views

app_name='home'

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^login', views.enter, name='enter'),
    url(r'^register$', views.UserFormView.as_view(), name='register'),
    url(r'^construction', views.construction, name='construction'),
    url(r'^logout_user', views.logout_user, name='logout_user'),
    url(r'^editor', views.online_editor, name='online_editor'),
    url(r'^practice', views.practice, name='practice')

]


from insights.specs import Specs
from insights.tests import InputData, run_test

from src.puptoo.process.profile import system_profile

REDHAT_RELEASE_8_0 = """Red Hat Enterprise Linux release 8.0"""
OS_RELEASE_8_0 = """
NAME="Red Hat Enterprise Linux"
VERSION="8.0 (Ootpa)"
ID="rhel"
PRETTY_NAME="Red Hat Enterprise Linux 8.1 (Ootpa)"
""".strip()

REDHAT_RELEASE_7_2 = """Red Hat Enterprise Linux Server release 7.2 (Maipo)"""
OS_RELEASE_7_2 = """
NAME="Red Hat Enterprise Linux"
VERSION="7.2.0 (Ootpa)"
ID="rhel"
PRETTY_NAME="Red Hat Enterprise Linux 7.2 (Ootpa)"
""".strip()

REDHAT_RELEASE_CENTOS_7_9 = "CentOS Linux release 7.9.2009 (Core)"
OS_RELEASE_CENTOS_7_9 = """
NAME="CentOS Linux"
ID="centos"
PRETTY_NAME="CentOS Linux 7 (Core)"
""".strip()

REDHAT_RELEASE_CENTOS_9 = "CentOS Stream release 9"
OS_RELEASE_CENTOS_9 = """
NAME="CentOS Stream"
ID="centos"
PRETTY_NAME="CentOS Stream 9"
""".strip()

REDHAT_RELEASE_SERVER_7_9 = "Red Hat Enterprise Linux Server release 7.9 (Maipo)"
OS_RELEASE_ORACLE_7_9 = """
NAME="Oracle Linux Server"
VERSION="7.9"
ID="ol"
PRETTY_NAME="Red Hat Enterprise Linux"
""".strip()

def test_os_release():

    input_data = InputData()
    input_data.add(Specs.redhat_release, REDHAT_RELEASE_8_0)
    input_data.add(Specs.os_release, OS_RELEASE_8_0)
    result = run_test(system_profile, input_data)
    expected_result = {
        "major": 8,
        "minor": 0,
        "name": "RHEL"
    }
    assert result["os_release"] == "8.0"
    assert result["system_update_method"] == "dnf"
    assert result["operating_system"] == expected_result

    input_data = InputData()
    input_data.add(Specs.redhat_release, REDHAT_RELEASE_7_2)
    input_data.add(Specs.os_release, OS_RELEASE_7_2)
    result = run_test(system_profile, input_data)
    expected_result = {
        "major": 7,
        "minor": 2,
        "name": "RHEL"
    }
    assert result["os_release"] == "7.2"
    assert result["system_update_method"] == "yum"
    assert result["operating_system"] == expected_result

    input_data = InputData()
    input_data.add(Specs.redhat_release, REDHAT_RELEASE_CENTOS_7_9)
    input_data.add(Specs.os_release, OS_RELEASE_CENTOS_7_9)
    result = run_test(system_profile, input_data)
    expected_result = {
        "major": 7,
        "minor": 9,
        "name": "CentOS Linux"
    }
    assert result["os_release"] == "7.9"
    assert result["system_update_method"] == "yum"
    assert result["operating_system"] == expected_result

    input_data = InputData()
    input_data.add(Specs.redhat_release, REDHAT_RELEASE_CENTOS_9)
    input_data.add(Specs.os_release, OS_RELEASE_CENTOS_9)
    result = run_test(system_profile, input_data)
    assert result.get("operating_system") == None

    input_data = InputData()
    input_data.add(Specs.redhat_release, REDHAT_RELEASE_SERVER_7_9)
    input_data.add(Specs.os_release, OS_RELEASE_ORACLE_7_9)
    result = run_test(system_profile, input_data)
    assert result.get("operating_system") == None


import tweepy
from time import sleep
#Authentication into tweepy
auth = tweepy.OAuthHandler('ENV VARIABLE')
auth.set_access_token('ENV VARIABLE 2')
api = tweepy.API(auth)

#Verify Credentials
try:
    api.verify_credentials()
    print("Authentication OK")
except:
    print("Error During Authentication.")

#Open up list of people to notify, split into content
noti_people = open("peopletonoti.txt", "r", encoding="utf8")
content = noti_people.read().split()
completed = open("peoplenotified.txt", "r", encoding = "utf8")
content2 = completed.read().split()
#Infinite loop code
while True:
    public_tweets = api.home_timeline(count=20)
    #Loop through each public tweet
    for tweet in reversed(public_tweets):
        #Create an ID for the current tweet we are grabbing.
        newID = tweet.id
        print (tweet.user.screen_name)
        if((tweet.user.screen_name in content) and (tweet.id not in content2)):
            #Reply to each tweet with 'Noti, update mostRecentReply'
            handle = tweet.user.screen_name
            api.update_status('@' + str(handle) + ' Noti', tweet.id)
            print("Responded to User")
            #Write Tweet ID to peoplenotified.txt, and add tweet id to content2
            content2.append(tweet.id)
            with open('peoplenotified.txt', 'a') as the_file:
                the_file.write(str(tweet.id) +'\n')

    sleep(120)
#The logic is we will get the most recent tweet on our timeline constantly.
#If any of those tweets are ever by someone in the notifications textfile,
#AND we haven't already replied to it (that's what mostRecentReply is for),
#Then we reply noti.

#We run the reversed timeline grab because the IDs should only go upwards when
# tweeting? must confirm


from django.urls import path
from . import views

app_name = 'blog'

urlpatterns = [
    # post views
    # blog/get_posts
    path('get_posts', views.get_posts, name='get_posts'),
    # blog/add_post&content=..&title=..
    path('add_post', views.add_post, name='add_post'),
    # blog/post/'5'/add_comment?&content=..
    path('post/<int:post_id>/add_comment', views.add_comment, name='add_comment'),
    # blog/register?username=..&email=..&password=..
    path('register', views.register, name='register'),
    # blog/login?username=..&password=..
    path('login', views.login_f, name='login'),
    # blog/users/'username'/profile
    path('users/<str:username>/profile', views.profile, name='profile'),
    # blog/about
    path('about', views.about, name='about'),
    path('doc', views.doc, name='doc'),
    path('openapi.json', views.openapi, name='openapi.json')
]


#librairies and functions
import matplotlib.pyplot as plt
import numpy as np
from math import *
from Physical_constants import *
from Conversion_factors import *
from Functions import integration_log
from optical_depth import *

##=========##
# Functions #
##=========##

def f_eq3(epsc, E, T):

    """
    Return the function that we integration to obtain the transmittance

    Parameters:
	epsc 	 : center-of-momentum system energy of a photon (keV/mc2)
	E	     : energy of the gamma photon (keV)
	T	     : temperature of the source (K)
    """

    def cross_section(epsc):

        def parameter_s(epsc):

            return epsc**2

        def parameter_beta(epsc):

            s = parameter_s(epsc)
            return np.sqrt(1 - 1/s)

        beta = parameter_beta(epsc)
        return (1 - beta**2) * ((3 - beta**4) * np.log((1 + beta)/(1 - beta)) - 2 * beta * (2 - beta**2))

    log = np.log(1 - np.exp(- (epsc * mc2)**2/(E * (kb*erg2kev) * T)))
    sigma = cross_section(epsc)
    return -epsc**3 * sigma * log

if __name__ == '__main__':

    #For the vector eps, E
    number_bin_E = 80
    number_bin_epsc = 20.0

    #Constants
    R = 0                                           # distance to the centre of the object (kpc)
    Rs = 8.5                                        # distance to the centre of the Sun (kpc)
    alpha = 0                                       # right ascension (rad)
    rho = np.sqrt(R**2 + Rs**2 - 2*R*Rs*np.cos(alpha))  # kpc
    L = np.sqrt(R**2 + rho**2)                          # kpc
    L = L * kpc2cm                                      # cm
    T = 2.7                                         # temperature of the CMB (K)

    # Energy of the gamma-photon
    Emin = 1e-1*TeV2keV 			                # we choose Emin = 10^-1 TeV (keV)
    Emax = 1e5*TeV2keV 			                    # we choose Emax = 10^5 TeV (keV)
    E = np.logspace(log10(Emin), log10(Emax), number_bin_E)         # keV
    E_tev = E/TeV2keV 					                            # TeV

    # Computes the optical depth
    integral_x = np.zeros_like(E)

    for i in range(len(E)):
        epsc_min = mc2/mc2                                                          # keV/mc2
        epsc_max = epsc_min + np.sqrt(10*(kb*erg2kev)*E[i]*T/mc2**2)                 # keV/mc2
        epsc = np.logspace(log10(epsc_min), log10(epsc_max), int(log10(epsc_max/epsc_min)*number_bin_epsc))   # keV/mc2
        integrand = f_eq3(epsc, E[i], T)

        integral_x[i] = integration_log(epsc, integrand)

    hpbar = hp/(2*np.pi)
    tau = integral_x * L * 4 * (kb*erg2kev) * T/((hpbar*erg2kev * cl)**3 * np.pi**2 * E**2) * 1/2.0 * np.pi * r0**2 * mc2**3 * mc2

    fig = plt.figure()
    ax = fig.add_subplot(111)
    plt.xscale('log')
    plt.xlabel(r'$E_\gamma$' '(TeV)')
    plt.ylabel(r'$\exp(-\tau_{\gamma \gamma})$')
    plt.text(0.75, 0.95,'equation 3 of Moskalenko', horizontalalignment='left', verticalalignment='center', transform = ax.transAxes)
    plt.title('Transmittance of VHE 'r'$\gamma$' '-rays in interaction with CMB photons')
    plt.plot(E_tev, np.exp(-tau))
    plt.show()


import unittest
import numpy as np

from force_bdss_prototype.initializer.initializer import Initializer
from force_bdss_prototype.databases.material_db_access import Material_db_access

A = { "name": "eductA", "manufacturer": "", "pdi": 0 }
B = { "name": "eductB", "manufacturer": "", "pdi": 0 }
C = { "name": "contamination", "manufacturer": "", "pdi": 0 }
P = { "name": "product", "manufacturer": "", "pdi": 0 }
R = { "reactants": [A, B], "products": [P] }
m_db_access = Material_db_access.getInstance()
p_A = m_db_access.get_pure_component_density(A)
p_B = m_db_access.get_pure_component_density(B)
p_C = m_db_access.get_pure_component_density(C)
p_array = np.array([p_A, p_B, p_C])
nptype = type(np.array([]))

class InitializerTestCase(unittest.TestCase):

    def test_instance(self):
        ini = Initializer.getInstance(R)
        self.assertIsInstance(ini, Initializer)

    def test_init_data_return_type(self):
        ini = Initializer.getInstance(R)
        self.assertEqual(type(ini.get_init_data_kin_model(R, C)), nptype)

    def test_init_data_return_shape(self):
        ini = Initializer.getInstance(R)
        self.assertEqual(ini.get_init_data_kin_model(R, C).shape, (7,))

    def test_init_data_concentration_consistency(self):
        ini = Initializer.getInstance(R)
        concentrations = ini.get_init_data_kin_model(R, C)[np.array([0, 1, 4])]
        conservation = np.sum(concentrations / p_array)
        self.assertTrue(conservation - 1 < 1e-6)

    def test_mat_relation_return_type(self):
        ini = Initializer.getInstance(R)
        M_v, M_delta_H = ini.get_material_relation_data(R)
        self.assertEqual(type(M_v), nptype)
        self.assertEqual(type(M_delta_H), nptype)

    def test_mat_relation_return_shape(self):
        ini = Initializer.getInstance(R)
        M_v, M_delta_H = ini.get_material_relation_data(R)
        self.assertEqual(M_v.shape, (2,))
        self.assertEqual(M_delta_H.shape, (2,))

    def test_mat_relation_delta_H(self):
        ini = Initializer.getInstance(R)
        _, M_delta_H = ini.get_material_relation_data(R)
        self.assertTrue(M_delta_H[0] < M_delta_H[1])


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Created by HazzaCheng on 2019-07-03

import matplotlib.pyplot as plt
import numpy as np
import sklearn

from shallow_nn_model import ShallowNeuralNetWorkModel
from planar_utils import load_planar_dataset, plot_decision_boundary

if __name__ == '__main__':
    """
    datasets
    """
    X, Y = load_planar_dataset()
    # Visualize the datasets:
    plt.scatter(X[0, :], X[1, :], c=Y.flatten(), s=40, cmap=plt.cm.Spectral)
    plt.show()
    print('The shape of X is: ' + str(X.shape))
    print('The shape of Y is: ' + str(Y.shape))
    print('I have m = %d training examples!' % (X.shape[1]))

    """
    simple logistic regression
    """
    # Train the logistic regression classifier
    clf = sklearn.linear_model.LogisticRegressionCV()
    clf.fit(X.T, Y.T.flatten())
    # Plot the decision boundary for logistic regression
    plt.title("Logistic Regression")
    plot_decision_boundary(lambda x: clf.predict(x), X, Y.flatten())
    plt.show()
    # Print accuracy
    LR_predictions = clf.predict(X.T)
    print('Accuracy of logistic regression: %d ' % float(
        (np.dot(Y, LR_predictions) + np.dot(1 - Y, 1 - LR_predictions)) / float(Y.size) * 100) +
        '% ' + "(percentage of correctly labelled datapoints)")

    """
    neural network model
    """
    network = ShallowNeuralNetWorkModel()

    plt.figure(figsize=(16, 32))
    hidden_layer_sizes = [1, 2, 3, 4, 5, 10, 20, 50, 70, 100]
    for i, n_h in enumerate(hidden_layer_sizes):
        plt.subplot(5, 2, i + 1)
        plt.title('Hidden Layer of size %d' % n_h)
        parameters = network.get_model(X, Y, n_h, num_iterations=5000)
        plot_decision_boundary(
            lambda x: network.predict(
                parameters, x.T), X, Y.flatten())
        predictions = network.predict(parameters, X)
        accuracy = float(
            (np.dot(
                Y,
                predictions.T) +
                np.dot(
                1 -
                Y,
                1 -
                predictions.T)) /
            float(
                Y.size) *
            100)
        print("Accuracy for {} hidden units: {} %".format(n_h, accuracy))
    plt.show()


import os
import time
import sys
import math
import numpy as np
import pandas as pd
from scipy.sparse import csr_matrix
from sklearn.neighbors import NearestNeighbors
from fuzzywuzzy import fuzz

# file path setting
path = os.path.abspath(os.path.dirname(sys.argv[0]))
movies_filename = 'movies.csv'
ratings_filename = 'ratings.csv'

# read data
df_movies = pd.read_csv(
    os.path.join(path+'/ml-latest',movies_filename),
    usecols=['movieId', 'title'],
    dtype={'movieId': 'int32', 'title': 'str'})

df_ratings = pd.read_csv(
    os.path.join(path+'/ml-latest', ratings_filename),
    usecols=['userId', 'movieId', 'rating'],
dtype={'userId': 'int32', 'movieId': 'int32', 'rating': 'float32'})

num_users = len(df_ratings.userId.unique())
num_items = len(df_ratings.movieId.unique())

# get count
df_ratings_cnt_tmp = pd.DataFrame(df_ratings.groupby('rating').size(), columns=['count'])

# there are a lot more counts in rating of zero
total_cnt = num_users * num_items
rating_zero_cnt = total_cnt - df_ratings.shape[0]
# append counts of zero rating to df_ratings_cnt
df_ratings_cnt = df_ratings_cnt_tmp.append(
    pd.DataFrame({'count': rating_zero_cnt}, index=[0.0]),
    verify_integrity=True,).sort_index()

# add log count
df_ratings_cnt['log_count'] = np.log(df_ratings_cnt['count'])
df_movies_cnt = pd.DataFrame(df_ratings.groupby('movieId').size(), columns=['count'])
df_movies_cnt['count'].quantile(np.arange(1, 0.6, -0.05))
# filter data
popularity_thres = 50
popular_movies = list(set(df_movies_cnt.query('count >= @popularity_thres').index))
df_ratings_drop_movies = df_ratings[df_ratings.movieId.isin(popular_movies)]

# get number of ratings given by every user
df_users_cnt = pd.DataFrame(df_ratings_drop_movies.groupby('userId').size(), columns=['count'])

# filter data
ratings_thres = 50
active_users = list(set(df_users_cnt.query('count >= @ratings_thres').index))
df_ratings_drop_users = df_ratings_drop_movies[df_ratings_drop_movies.userId.isin(active_users)]

# pivot and create movie-user matrix
movie_user_mat = df_ratings_drop_users.pivot(index='movieId', columns='userId', values='rating').fillna(0)
# create mapper from movie title to index
movie_to_idx = {
    movie: i for i, movie in
    enumerate(list(df_movies.set_index('movieId').loc[movie_user_mat.index].title))
}
# transform matrix to scipy sparse matrix
movie_user_mat_sparse = csr_matrix(movie_user_mat.values)

# define model
model_knn = NearestNeighbors(metric='cosine', algorithm='brute', n_neighbors=20, n_jobs=-1)
# fit
model_knn.fit(movie_user_mat_sparse)

def fuzzy_matching(mapper, fav_movie, verbose=True):
    match_tuple = []
    # get match
    for title, idx in mapper.items():
        ratio = fuzz.ratio(title.lower(), fav_movie.lower())
        if ratio >= 60:
            match_tuple.append((title, idx, ratio))
    # sort
    match_tuple = sorted(match_tuple, key=lambda x: x[2])[::-1]
    if not match_tuple:
        print('Oops! No match is found')
        return
    if verbose:
        print('Found possible matches in our database: {0}\n'.format([x[0] for x in match_tuple]))
    return match_tuple[0][1]

def make_recommendation(model_knn=model_knn, data=movie_user_mat_sparse, mapper=movie_to_idx, fav_movie='iron man', n_recommendations=10):
    # fit
    model_knn.fit(data)
    # get input movie index
    print('Input movie:', fav_movie)
    idx = fuzzy_matching(mapper, fav_movie, verbose=True)
    # inference
    distances, indices = model_knn.kneighbors(data[idx], n_neighbors=n_recommendations+1)
    # get list of raw idx of recommendations
    raw_recommends = \
        sorted(list(zip(indices.squeeze().tolist(), distances.squeeze().tolist())), key=lambda x: x[1])[:0:-1]
    # get reverse mapper
    reverse_mapper = {v: k for k, v in mapper.items()}
    # print recommendations
    result = []
    print('Recommendations for {}:'.format(fav_movie))
    for i, (idx, dist) in enumerate(raw_recommends):
        print('{0}: {1}, with distance of {2}'.format(i+1, reverse_mapper[idx], dist))
        result.append(reverse_mapper[idx])
    return result


#!/usr/bin/env python-mr

from collections import defaultdict
from _.data.formatting.blocks import Block

def graph(lines):
  adjacent = defaultdict(set)
  for line in lines:
    n1, n2 = line.split("-")
    adjacent[n1].add(n2)
    adjacent[n2].add(n1)
  return adjacent

def big_cave(cave):
  # defined as a cave with 2 or more neighbours.
  return cave.isupper()

LOAD = "content"
def REWRITE(lines):
  return graph(lines)

def all_paths(graph):
  def pathsr(acc, novisit):
    cur = acc[-1]
    if cur == "end":
      yield ",".join(acc)
      return

    for n in graph[cur]:
      if n in novisit:
        continue
      acc_n = [*acc, n]
      nv = novisit
      if not big_cave(n):
        nv = set(novisit)
        nv.add(n)
      yield from pathsr(acc_n, nv)

  return list(pathsr(["start"], set(["start"])))

def PART1(inputs):
  print(inputs)
  for p in all_paths(inputs):
    #print(p)
    pass
  return len(all_paths(inputs))

def double_visit_paths(graph):
  def pathsr(acc, novisit, candoublevisit=True):
    cur = acc[-1]
    if cur == "end":
      yield ",".join(acc)
      return

    for n in graph[cur]:
      double = candoublevisit
      if n in novisit:
        if double and n not in ("start", "end"):
          double = False
        else:
          continue

      acc_n = [*acc, n]
      nv = novisit
      if not big_cave(n):
        nv = set(novisit)
        nv.add(n)
      yield from pathsr(acc_n, nv, double)

  return list(pathsr(["start"], set(["start"])))

def PART2(inputs):
  paths = double_visit_paths(inputs)
  #paths.sort()
  for p in paths:
    #print(p)
    pass
  return len(paths)


import os
import sys

import theano
import theano.tensor as T
from theano import printing
from theano.ifelse import ifelse

import numpy as np
from numpy import random as rng

import config
from Conv1d import Conv1DLayer
from NN4LogReg import NN4LogReg
from NN4Normal import NN4Normal
from ResNet4Distance import ResNet
from DilatedResNet4Distance import DilatedResNet
from utils import OuterConcatenate, MidpointFeature
import DistanceUtils

from config import Response2LabelName, Response2LabelType

##this class calculates the convolution of 1D sequence and then convert it to a 2D matrix using OuterConcatenate
class Conv1D2Matrix:

	def __init__(self, rng, input, n_in, n_hiddens=[], halfWinSize=0, mask=None):
	## input has shape (batchSize, seqLen, n_in) where n_in is the number of features at each position
	## all the sequences aligned at the right hand side, mask is used for the left hand side positions
	## mask has shape (batchSize, #positions_to_be_masked )

	## n_hiddens specify the number of hidden neurons at all the hidden layers
	## halfWinSize specify the half window size of the convolution operation

		self.input = input
		self.mask = mask
		self.n_in = n_in
		self.halfWinSize = halfWinSize

		self.layers = []
		self.params = []
		self.paramL1 = 0
		self.paramL2 = 0

		n_out_at_last_layer = n_in
		output_at_last_layer = input

		for i in range(len(n_hiddens)):
			layer = Conv1DLayer(rng, input=output_at_last_layer, numOfInFeatures=n_out_at_last_layer, numOfOutFeatures=n_hiddens[i], halfWinSize=halfWinSize, mask=mask)
			self.layers.append(layer)
			n_out_at_last_layer = n_hiddens[i]
			output_at_last_layer = layer.output

			self.params += layer.params
			self.paramL1 += layer.paramL1
			self.paramL2 += layer.paramL2

		## conv_out has shape (batchSize, seqLen, n_out_at_last_layer ), it is the final convolution result
		conv_out = output_at_last_layer

		## now we take the OuterConcatenate operation, the result has shape (batchSize, seqLen, seqLen, 2 * n_out_at_last_layer)
		self.output = OuterConcatenate (input = conv_out)
		self.n_out = 2 * n_out_at_last_layer

		##add the below two lines for convenience
		self.conv_out = conv_out
		self.n_conv_out = n_out_at_last_layer

def TestConv1D2Matrix():
	x = T.tensor3('x')
	conv1dlayer = Conv1D2Matrix( rng=np.random.RandomState(), input=x, n_in=2, n_hiddens=[3], halfWinSize=1)
	f = theano.function([x], conv1dlayer.output)
	a = np.random.uniform(0, 1, (2, 7, 2)).astype(np.float32)
	print(a)
	print(f(a))

## 2D convolution on a matrix for distance matrix prediction
## no pooling is allowed here
class Conv2D4DistMatrix:
	def __init__(self, rng, input, n_in=1, n_hiddens=None, halfWinSize=0, mask=None, activation=T.nnet.relu):
		## input has shape (batchSize, nRows, nCols, n_in) where n_in is the number of input features at each element
		## here we assume that input[0], input[1], ...., input[batchSize -1 ] are aligned at the right bottom
		## nrows and ncols are unknown
		## mask has shape (batchSize, #rows_to_be_masked, nCols), mask is a binary matrix with 0 indicates padding positions and 1 real data position

		##hwsz is the half window size of the filter shape
		##mask is used to reduce noise introduced by padding. all the matrices in a batch shall be aligned at the right bottom corner

		self.input = input
		self.n_in = n_in
		self.n_hiddens = n_hiddens
		self.halfWinSize = halfWinSize
		self.mask = mask

		##the window size of our filters is always odd
		wSize = 2*halfWinSize + 1

		self.params = []
		self.paramL1 = 0
		self.paramL2 = 0

		## reshape input so that it has shape (batchSize, n_in, nRows, nCols)
		output_in_last_layer = input.dimshuffle(0, 3, 1, 2)

		n_out_in_last_layer = n_in

		for i in range(len(n_hiddens)):
			W_shape = (n_hiddens[i], n_out_in_last_layer, wSize, wSize)

			W_values = np.asarray(
			rng.uniform( low = - np.sqrt(6. / (n_out_in_last_layer * wSize * wSize + n_hiddens[i])),
			 high =  np.sqrt(6. / (n_out_in_last_layer * wSize * wSize + n_hiddens[i])),
			size = W_shape
			),
			dtype = theano.config.floatX
			)
			if activation == T.nnet.relu:
				W_values = np.asarray(
				rng.normal( scale = np.sqrt(2. / (n_out_in_last_layer * wSize * wSize + n_hiddens[i])), size = W_shape),
				dtype = theano.config.floatX
				)

			b_shape = (n_hiddens[i], )
			b_values = np.asarray (rng.uniform(low = -.0, high =.0, size = b_shape), dtype=theano.config.floatX )

			W = theano.shared (value = W_values, name = 'conv2d_W_' + str(i), borrow = True)
			b = theano.shared (value = b_values, name = 'conv2d_b_' + str(i), borrow = True)

			shape_in_last_layer = (None, n_out_in_last_layer, None, None)

			## Please make sure that conv2d_out has shape (batchSize, n_hiddens[i], nRows, nCols)
			conv2d_out = T.nnet.conv2d(output_in_last_layer, W, input_shape = shape_in_last_layer, filter_shape=W_shape, border_mode='half')
			if activation is not None:
				out2 = activation(conv2d_out + b.dimshuffle('x', 0, 'x', 'x'))
			else:
				out2 = (conv2d_out + b.dimshuffle('x', 0, 'x', 'x'))

			if mask is not None:
				## mask has shape (batchSize, #rows_to_be_masked, nCols)

				## a subtensor of out2 along the horiz direction
				out2_sub_horiz = out2[:, :, :mask.shape[1], :]
				mask_horiz = mask.dimshuffle(0, 'x', 1, 2)
				out3 = T.set_subtensor(out2[:, :, :mask.shape[1], :], T.mul(out2_sub_horiz, mask_horiz) )

				## a subtensor of out3 along the vertical direction
				out3_sub_vertical = out3[:, :, :, :mask.shape[1] ]
				mask_vertical = mask.dimshuffle(0, 'x', 2, 1)
				out4 = T.set_subtensor(out3[:, :, :, :mask.shape[1] ], T.mul(out3_sub_vertical, mask_vertical) )

				output_in_last_layer = out4
			else:
				output_in_last_layer = out2

			n_out_in_last_layer = n_hiddens[i]

			self.params += [W, b]
			self.paramL1 += (abs(W).sum() +  abs(b).sum())
			self.paramL2 += ((W**2).sum() + (b**2).sum())

		##change the shape of the final output to (batchSize, nRows, nCols, n_out)
		self.output = output_in_last_layer.dimshuffle(0, 2, 3, 1)
		self.n_out = n_out_in_last_layer

def TestConv2D4DistMatrix():
	x = T.tensor4('x')
	conv2dlayer = Conv2D4DistMatrix( rng=np.random.RandomState(), input=x, n_in=2, n_hiddens=[3], halfWinSize=1)
	f = theano.function([x], conv2dlayer.output)
	a = np.random.uniform(0, 1, (2, 7, 7, 2)).astype(np.float32)
	print(a)
	print(f(a))

"""
def SeparateTrainByRange(rng, conv_out, n_in, numLabels, n_hiddens_logreg=None):

    batchSize, dataLen, dataLen, tmp_n = conv_out.shape

    n_in4logreg = n_in

    ##theano currently does not have triu for tensor3, so we have to do some work here
    M1s = T.ones((dataLen, dataLen), dtype=np.int8)
    M1s_3d = T.ones((batchSize, dataLen, dataLen), dtype=np.int8)
    Sep24Mat = T.triu(M1s, 24) + T.tril(M1s, -24)
    Sep12Mat = T.triu(M1s, 12) + T.tril(M1s, -12)
    Sep6Mat = T.triu(M1s, 6) + T.tril(M1s, -6)

    LRselection = Sep24Mat.dimshuffle('x',0,1)
    MRselection = (Sep12Mat - Sep24Mat).dimshuffle('x', 0, 1)
    SRselection = (Sep6Mat - Sep12Mat ).dimshuffle('x', 0, 1)
    LRselection = T.mul( LRselection, M1s_3d )
    MRselection = T.mul( MRselection, M1s_3d )
    SRselection = T.mul( SRselection, M1s_3d )

    selections = [ LRselection, MRselection, SRselection ]

    regressors = []
    output_2d = T.ones((batchSize, dataLen, dataLen), dtype=np.int8)*(-1)
    output_2d_prob = T.zeros((batchSize, dataLen, dataLen, numLabels), dtype=theano.config.floatX)

    for sel in selections:
        selected = conv_out[sel.nonzero()]
        regressor = MLLogReg(rng=rng, input=selected, n_in=n_in4logreg, n_out=numLabels, n_hiddens=n_hiddens_logreg)
        regressors.append(regressor)
        output_2d = T.set_subtensor(self.output_2d[ sel.nonzero() ], T.cast(regressor.y_pred, 'int8') )
        output_2d_prob = T.set_subtensor(self.output_2d_prob[ sel.nonzero() ], regressor.p_y_given_x )

    return selections, regressors, output_2d, output_2d_prob
"""

## this is the main class for the prediction of inter-residue distance, hydrogen bonding and beta-pairing
class ResNet4DistMatrix:
	def __init__(self, rng, seqInput, matrixInput, mask_seq=None, mask_matrix=None,
				 embedInput=None, modelSpecs = None):
		"""
		seqInput has shape (batchSize, seqLen, n_in_seq)
		matrixInput has shape (batchSize, seqLen, seqLen, n_in_matrix)
		mask_seq has shape (batchSize, #cols_to_be_masked)
		mask_matrix has shape (batchSize, #rows_to_be_masked, seqLen)
		embedInput has shape (batchSize, seqLen, n_in2)
		"""

		assert (modelSpecs is not None)

		self.modelSpecs = modelSpecs
		self.responses = modelSpecs['responses']

		## set the number of hidden neurons and number of layers
		n_in_seq = modelSpecs['n_in_seq']
		n_in_matrix = modelSpecs['n_in_matrix']
		n_hiddens_seq = modelSpecs['conv1d_hiddens']
		n_hiddens_matrix = modelSpecs['conv2d_hiddens']
		n_hiddens_logreg = modelSpecs['logreg_hiddens']
		seq_repeats = modelSpecs['conv1d_repeats']
		matrix_repeats = modelSpecs['conv2d_repeats']

		## half win size for convolutional operation
		if modelSpecs['network'].startswith('DilatedResNet'):
			hwsz_matrix = modelSpecs['conv2d_hwszs']
			hwsz_seq = [modelSpecs['conv1d_hwsz'] ]* len(n_hiddens_seq)
			dilation_seq = [1] * len(n_hiddens_seq)
			dilation_matrix = modelSpecs['conv2d_dilations']
		else:
			hwsz_matrix=modelSpecs['halfWinSize_matrix']
			hwsz_seq=modelSpecs['halfWinSize_seq']

		## masks to reduce impact of padding zeros
		self.mask_1d = mask_seq
		self.mask_2d = mask_matrix

		self.layers = []

		# sequence convolution
		if modelSpecs['network'].startswith('DilatedResNet'):
			seqConv = DilatedResNet(rng, input=seqInput, n_in=n_in_seq, n_hiddens=n_hiddens_seq, n_repeats=seq_repeats, halfWinSize=hwsz_seq, dilation=dilation_seq, mask=mask_seq, activation=modelSpecs['activation'], batchNorm=modelSpecs['batchNorm'], version=modelSpecs['network'])
		else:
			seqConv = ResNet(rng, input=seqInput, n_in=n_in_seq, n_hiddens=n_hiddens_seq, n_repeats=seq_repeats, halfWinSize=hwsz_seq, mask=mask_seq, activation=modelSpecs['activation'], batchNorm=modelSpecs['batchNorm'], version=modelSpecs['network'])
		self.layers.append(seqConv)

		## transform 1d sequence to 2d matrix
		seq2matrixMode = modelSpecs['seq2matrixMode']
		seq2matrixLayers = []
		embedLayers = []

		## determine if we shall use the sequential features or not. The sequential features include sequence profile (PSSM), predicted secondary structure and predicted solvent accessibility
		## useSequentialFeatures is True by default
		useSequentialFeatures = ('UseSequentialFeatures' in modelSpecs \
								 and (modelSpecs['UseSequentialFeatures'] is True))

		## use OuterConcatenation operation to convert sequence features into pairwise features
		if 'OuterCat' in seq2matrixMode and useSequentialFeatures:
			##midpointfeature has shape (batchSize, seqLen, seqLen, n_midpoint_out)
			midpointfeature, n_midpoint_out = MidpointFeature(seqConv.output, seqConv.n_out)

			##remove noise in midpointfeature
			## mask_matrix is used to reduce noise introduced by padding positions
			mid_subtensor = midpointfeature[:, :mask_matrix.shape[1], :, :]
			midpointfeature = T.set_subtensor(mid_subtensor, T.mul(mask_matrix.dimshuffle(0,1,2,'x'), mid_subtensor) )
			mid_subtensor2 = midpointfeature[:, :, :mask_matrix.shape[1], : ]
			midpointfeature = T.set_subtensor(mid_subtensor2, T.mul(mask_matrix.dimshuffle(0,2,1,'x'), mid_subtensor2) )

			## here we use convolution with halfWinSize=0 to reduce model complexity
			compressLayer = Conv2D4DistMatrix(rng, input=midpointfeature, n_in=n_midpoint_out, n_hiddens=seq2matrixMode['OuterCat'], halfWinSize=0, mask=mask_matrix )
			seq2matrixLayers.append(compressLayer)

		## embedding primary sequence and/or predicted secondary structure
		if embedInput is not None:
			from EmbeddingLayer import MetaEmbeddingLayer

			if 'Seq+SS' in seq2matrixMode:
				n_out_embed = seq2matrixMode['Seq+SS']
			elif 'SeqOnly' in seq2matrixMode:
				n_out_embed = seq2matrixMode['SeqOnly']
			else:
				print('At least one of two embedding modes Seq+SS or SeqOnly shall be specified.')
				sys.exit(-1)

			embedLayer = MetaEmbeddingLayer(embedInput, modelSpecs['n_in_embed'], n_out_embed)
			seq2matrixLayers.append(embedLayer)
			embedLayers.append(embedLayer)

		self.layers += seq2matrixLayers

		input_2d = T.concatenate( [ matrixInput ] + [ layer.output for layer in seq2matrixLayers], axis=3)
		n_input2d = n_in_matrix + sum([ layer.n_out for layer in seq2matrixLayers ])

		if modelSpecs['network'].startswith('ResNet'):
			matrixConv=ResNet(rng, input=input_2d, n_in=n_input2d, n_hiddens=n_hiddens_matrix, n_repeats=matrix_repeats, halfWinSize=hwsz_matrix, mask=mask_matrix, activation=modelSpecs['activation'], batchNorm=modelSpecs['batchNorm'], version=modelSpecs['network'])
		elif modelSpecs['network'].startswith('DilatedResNet'):
			matrixConv=DilatedResNet(rng, input=input_2d, n_in=n_input2d, n_hiddens=n_hiddens_matrix, n_repeats=matrix_repeats, halfWinSize=hwsz_matrix, dilation=dilation_matrix, mask=mask_matrix, activation=modelSpecs['activation'], batchNorm=modelSpecs['batchNorm'], version=modelSpecs['network'])
		else:
			print('Unimplemented deep network type: ', modelSpecs['network'])
			exit(-1)

		self.layers.append(matrixConv)

		conv_out = matrixConv.output

		selected = conv_out.dimshuffle(3, 0, 1, 2).flatten(2).dimshuffle(1, 0)
		n_in4logreg = matrixConv.n_out

		self.outputList = []
		self.output_probList = []
		self.predictors = []

		self.params4var = []
		self.paramL14var = 0
		self.paramL24var = 0

		for res in modelSpecs['responses']:
			labelType = Response2LabelType(res)
			predictor = None

			if labelType.startswith('Discrete'):
				assert (config.responseValueDims[labelType] == 1)
				predictor = NN4LogReg(rng=rng, input=selected, n_in=n_in4logreg, n_out=config.responseProbDims[labelType], n_hiddens=n_hiddens_logreg)
			elif labelType.startswith('LogNormal') or labelType.startswith('Normal'):
				predictor = NN4Normal(rng=rng, input=selected, n_in=n_in4logreg, n_variables=config.responseValueDims[labelType], n_out=config.responseProbDims[labelType], n_hiddens=n_hiddens_logreg)
				## recording parameters specific for variance prediction
				self.params4var += predictor.params4var
				self.paramL14var += predictor.paramL14var
				self.paramL24var += predictor.paramL24var
			else:
				print('incorrect response name or label type: ', res)
				exit(-1)

			self.layers.append(predictor)
			self.predictors.append(predictor)

			## output in 2d matrix
			output_2d = predictor.y_pred.reshape( (conv_out.shape[0], conv_out.shape[1], conv_out.shape[2], config.responseValueDims[labelType]) )
			output_2d_prob = predictor.output.reshape( (conv_out.shape[0], conv_out.shape[1], conv_out.shape[2], config.responseProbDims[labelType] ) )

			self.outputList.append( output_2d )
			self.output_probList.append( output_2d_prob )

		self.output = T.concatenate( self.outputList, axis=3 )
		self.output_prob = T.concatenate( self.output_probList, axis=3 )

		## collect all the model parameters and their norms
		self.params = []
		self.paramL2 = 0
		self.paramL1 = 0

		for layer in self.layers:
			self.params  += layer.params
			self.paramL2 += layer.paramL2
			self.paramL1 += layer.paramL1

	def loss(self, zList, weightList=None, useMeanOnly=False):
		losses = []
		if weightList is not None and len(weightList)>0:
			for predictor, z, w in zip(self.predictors, zList, weightList):
				if (z.ndim == 3 ):
					zflat = z.flatten().dimshuffle(0, 'x')
				elif (z.ndim == 4):
					zflat = z.dimshuffle(3, 0, 1, 2).flatten(2).dimshuffle(1, 0)
				else:
					print('unsupported ndim for z in errors():', z.ndim)
					exit(-1)
				assert (w.ndim == 3)
				wflat = w.flatten().dimshuffle(0, 'x')

				## zflag shall have shape (batchSize, valueDims) and wflag shall have shape (batchSize, 1)
				losses.append(  predictor.loss(zflat, useMeanOnly=useMeanOnly, sampleWeight=wflat)   )
		else:
			for predictor, z in zip(self.predictors, zList):
				if (z.ndim == 3):
					zflat = z.flatten().dimshuffle(0, 'x')
				elif (z.ndim == 4):
					zflat = z.dimshuffle(3, 0, 1, 2).flatten(2).dimshuffle(1, 0)
				else:
					print('unsupported ndim for z in errors():', z.ndim)
					exit(-1)

			## zflag shall have shape (batchSize, valueDims)
			losses.append(  predictor.loss(zflat, useMeanOnly=useMeanOnly )  )

		## losses is a list of scalar
		return T.stack(losses)

	## calculate errors for one response with label Type Discrete12C, Discrete25C, Discrete52C, return a tensor with ndim=1
	def errors4one(self, z, out, weight=None, distLabelType='12C'):
		distBins = config.distCutoffs[distLabelType]
		label8 = DistanceUtils.LabelsOfOneDistance(config.ContactDefinition, distBins)
		label15 = DistanceUtils.LabelsOfOneDistance(config.InteractionLimit, distBins)

		z3C = T.cast( T.ge(z, label8), 'int32') + T.cast( T.ge(z, label15), 'int32')
		o3C = T.cast( T.ge(out, label8), 'int32') + T.cast( T.ge(out, label15), 'int32')

		if weight is not None:
			err = T.sum( T.mul(weight, T.neq(o3C, z3C) ) )*1./T.sum(weight)
		else:
			err = T.mean( T.neq(o3C , z3C) )

		## err is s scalar, convert it to a tensor with ndim=1
		return T.stack([err] )

	## this function returns a vector of errors, the size of this vector is equal to the sum of ValueDims for all the responses
	def errors(self, zList, weightList=None):
		errs = []
		if weightList is not None and len(weightList)>0:
			for res, predictor, z, w, o in zip(self.responses, self.predictors, zList, weightList, self.outputList):
				labelType = Response2LabelType(res)
				numLabels = config.responseProbDims[labelType]

				## if the label type is Discrete25C, Discrete52C, Discrete12C
				if labelType.startswith('Discrete') and numLabels > 3:
					assert (z.ndim == 3 and config.responseValueDims[labelType] == 1 )
					o2 = o.flatten(3)
					## here we convert 12C, 25C, and 52C to 3C for error calculation, which makes the result easier to interpret
					errs.append( self.errors4one(z, o2, weight=w, distLabelType=labelType[len('Discrete'): ] ) )
				else:
					## call the error function of each predictor
					if (z.ndim == 3 ):
						zflat = z.flatten().dimshuffle(0, 'x')
					elif (z.ndim == 4 ):
						zflat = z.dimshuffle(3, 0, 1, 2).flatten(2).dimshuffle(1, 0)
					else:
						print('unsupported ndim for z in errors():', z.ndim)
						exit(-1)

					assert (w.ndim == 3)
					wflat = w.flatten().dimshuffle(0, 'x')
					e = predictor.errors(zflat, sampleWeight=wflat)
					## e is a tensor with ndim=1
					errs.append(e)

		else:
			for res, predictor, z, o in zip(self.responses, self.predictors, zList, self.outputList):
				labelType = Response2LabelType(res)
				numLabels = config.responseProbDims[labelType]
				if labelType.startswith('Discrete') and numLabels > 3 :
					assert (z.ndim == 3 and config.responseValueDims[labelType] == 1 )
					o2 = o.flatten(3)
					errs.append( self.errors4one(z, o, distLabelType=labelType[len('Discrete'): ] ) )
				else:
					## call the error function of each predictor
					if (z.ndim == 3):
						zflat = z.flatten().dimshuffle(0, 'x')
					elif (z.ndim == 4):
						zflat = z.dimshuffle(3, 0, 1, 2).flatten(2).dimshuffle(1, 0)
					else:
						print('unsupported ndim for z in errors():', z.ndim)
						exit(-1)
					e = predictor.errors(zflat)
					## e is a tensor with ndim=1
					errs.append(e)

		return T.concatenate(errs)

	## this function returns the long-, medium- and short-range prediction accuracy when proteinLen*topRatio predicted contacts are evaluated
	## note that the average accuracy is only for one batch. To calculate the avg accuracy of multiple batches, u may have to take into consideration
	## the fact that two batches may have different numbers of proteins
	## this function returns a 3*2 matrix where rows 0, 1, and 2 correspond to long-, medium- and short-range accuracy.
	## column 0 is the accuracy and column 1 is the average number of predicted contacts among all the top proteinLen*topRatio predicted contacts
	## the average number of predicted contacts may not be equal to avg(proteinLen)* topRatio when topRatio is big and proteinLen is small
	##def TopAccuracyByRange(self, zList, topRatio=0.5):
	def TopAccuracyByRange(self, zList):
		currentResponse = None
		topRatio = 0.5

	## in this function, we assume that pred is a tensor3 of floatX and truth is a matrix
	## pred has shape (dataLen, dataLen, 2) and truth has shape (dataLen, dataLen)
	## we also assume that label 0 is positive and label 1 is negative

	## the result is not 100% accurate for non-symmetric response, e.g., hydrogen-bonding matrix
	def TopAccuracy2C(pred=None, truth=None, symmetric=False):
		M1s = T.ones_like(truth, dtype=np.int8)
		LRsel = T.triu(M1s, 24)
		MLRsel = T.triu(M1s, 12)
		SMLRsel = T.triu(M1s, 6)
		MRsel = MLRsel - LRsel
		SRsel = SMLRsel - MLRsel

		dataLen = truth.shape[0]

		pred0 = pred[:,:,0]

		if symmetric:
			avg_pred = (pred0 + pred0.dimshuffle(1, 0) )/2.0
		else:
			avg_pred = pred0

		#pred_truth = T.concatenate( (avg_pred, truth.dimshuffle(0, 1, 'x') ), axis=2)
		pred_truth = T.stack( [avg_pred, T.cast(truth, 'int32')], axis=2 )

		accuracyList = []
		for Rsel in [ LRsel, MRsel, MLRsel, SRsel]:
			selected_pred_truth = pred_truth[Rsel.nonzero()]

			## sort by the predicted value for label 0 from the largest to the smallest
			selected_pred_truth_sorted = selected_pred_truth[ (selected_pred_truth[:,0]).argsort()[::-1] ]

			#print 'topRatio =', topRatio
			numTops = T.minimum( T.iround(dataLen * topRatio), selected_pred_truth_sorted.shape[0])

			selected_sorted_truth = T.cast(selected_pred_truth_sorted[:, -1], 'int32')
			numTruths = T.bincount(selected_sorted_truth, minlength=2 )
			numCorrects = T.bincount( selected_sorted_truth[0:numTops], minlength=2 )
			#numTops = T.minimum(numTops, numTruths[0])
			accuracyList.append( T.stack( [numCorrects[0] *1./(numTops + 0.001), numTops, numTruths[0] ], axis=0)  )

		return T.stacklists( accuracyList )

	def TopAccuracyNormal(pred=None, truth=None, symmetric=True):
		truth_new = T.ge(truth, config.ContactDefinition )

		if pred.ndim == 2:
			pred_new = -pred.dimshuffle(0, 1, 'x')
		else:
			pred_new = -pred

		return TopAccuracy2C(pred = pred_new, truth = truth_new, symmetric=symmetric)

	def TopAccuracyLogNormal(pred=None, truth=None, symmetric=True):
		truth_new = T.ge(truth, T.log(config.ContactDefinition) )

		if pred.ndim == 2:
			pred_new = -pred.dimshuffle(0, 1, 'x')
		else:
			pred_new = -pred

		return TopAccuracy2C(pred = pred_new, truth = truth_new, symmetric=symmetric)

	## in this function, we assume that pred is tensor3 of float and truth is a matrix of int8 or int
	## pred has shape (dataLen, dataLen, numLabels), having the predicted probability of each label
	## truth has shape (dataLen, dataLen)
	def TopAccuracyMultiC(pred=None, truth=None, subType=None, symmetric=True):
		## convert pred and truth to 2C
		distBins = config.distCutoffs[subType]
		label8 = DistanceUtils.LabelsOfOneDistance(config.ContactDefinition, distBins)
		label15 = DistanceUtils.LabelsOfOneDistance(config.InteractionLimit, distBins)
		truth1 = T.cast( T.ge(truth, label8), 'int32')
		truth_new = truth1
		pred1 = T.sum(pred[:,:,:label8], axis=2, keepdims=True)
		pred2 = T.sum(pred[:,:,label8:], axis=2, keepdims=True)
		pred_new = T.concatenate( (pred1, pred2), axis=2)
		return TopAccuracy2C(pred=pred_new, truth=truth_new, symmetric=symmetric)

	##def EvaluateAccuracy(pred_prob, truth, pad_len, response):
	def EvaluateAccuracy(pred_prob, truth, pad_len):
		pred_in_correct_shape = T.cast( pred_prob[pad_len:, pad_len: ], dtype=theano.config.floatX)
		truth_in_correct_shape = truth[pad_len:, pad_len: ]

		labelType = Response2LabelType(currentResponse)
		atomType = Response2LabelName(currentResponse)
		symmetric = ( atomType in ['CaCa', 'CbCb', 'CgCg', 'Beta'] )

		if labelType.startswith('LogNormal'):
			return TopAccuracyLogNormal(pred=pred_in_correct_shape, truth=truth_in_correct_shape, symmetric=symmetric)
		elif labelType.startswith('Normal'):
			return TopAccuracyNormal(pred=pred_in_correct_shape, truth=truth_in_correct_shape, symmetric=symmetric)
		elif labelType.startswith('Discrete'):
			subType = labelType[len('Discrete'): ]
			if subType.startswith('2C'):
				return TopAccuracy2C(pred=pred_in_correct_shape, truth=truth_in_correct_shape, symmetric=symmetric)
			else:
				return TopAccuracyMultiC(pred=pred_in_correct_shape, truth=truth_in_correct_shape, subType=subType, symmetric=symmetric)
		else:
			print('unsupported label type in EvaluateAccuracy: ', labelType)
			exit(-1)

		accuracyList = []
		for res, out_prob, z, ratio in zip(self.responses, self.output_probList, zList, self.modelSpecs['topRatios'] ):
			## currently TopAccuracy only works when the dimension of each z is 3
			assert z.ndim == 3
			if self.mask_1d is not None:
				paddingLens = self.mask_1d.shape[1] - T.sum(self.mask_1d, axis=1)
			else:
				paddingLens = T.zeros_like(z[:,0,0], dtype=np.int32)
			currentResponse = res
			topRatio = ratio
			##here we use scan to calculate accuracy for each protein
			result, updates = theano.scan(fn=EvaluateAccuracy, outputs_info=None, sequences=[out_prob, z, paddingLens] )
			accuracy = T.mean(result, axis=0)
			accuracyList.append(accuracy)

		return T.stacklists(accuracyList)

def BuildModel(modelSpecs, forTrain=True):
	rng = np.random.RandomState()

	## x is for sequential features and y for matrix (or pairwise) features
	x = T.tensor3('x')
	y = T.tensor4('y')

	## mask for x and y, respectively
	xmask = T.bmatrix('xmask')
	ymask = T.btensor3('ymask')

	xem = None
	##if any( k in modelSpecs['seq2matrixMode'] for k in ('SeqOnly', 'Seq+SS') ):
	if config.EmbeddingUsed(modelSpecs):
		xem = T.tensor3('xem')
		distancePredictor = ResNet4DistMatrix( rng, seqInput=x,
											   matrixInput=y, mask_seq=xmask, mask_matrix=ymask,
											   embedInput=xem, modelSpecs=modelSpecs )
	else:
		distancePredictor = ResNet4DistMatrix( rng, seqInput=x,
											   matrixInput=y, mask_seq=xmask, mask_matrix=ymask,
											   modelSpecs=modelSpecs )

	## labelList is a list of label tensors, each having shape (batchSize, seqLen, seqLen) or (batchSize, seqLen, seqLen, valueDims[response] )
	labelList = []
	if forTrain:
		## when this model is used for training. We need to define the label variable
		for response in modelSpecs['responses']:
			labelType = Response2LabelType(response)
			rValDims = config.responseValueDims[labelType]

			if labelType.startswith('Discrete'):
				if rValDims > 1:
				## if one response is a vector, then we use a 4-d tensor
				## wtensor is for 16bit integer
					labelList.append( T.wtensor4('Tlabel4' + response ) )
				else:
					labelList.append( T.wtensor3('Tlabel4' + response ) )
			else:
				if rValDims > 1:
					labelList.append( T.tensor4('Tlabel4' + response ) )
				else:
					labelList.append( T.tensor3('Tlabel4' + response ) )

	## weightList is a list of label weight tensors, each having shape (batchSize, seqLen, seqLen)
	weightList = []
	if len(labelList)>0 and modelSpecs['UseSampleWeight']:
		weightList = [ T.tensor3('Tweight4'+response) for response in modelSpecs['responses'] ]

	## for prediction, both labelList and weightList are empty
	return distancePredictor, x, y, xmask, ymask, xem, labelList, weightList

def TestResNet4DistMatrix():
	x = T.tensor3('x')
	y = T.tensor4('y')
	xmask = T.bmatrix('xmask')
	ymask = T.btensor3('ymask')
	selection = T.wtensor3('selection')

	import cPickle
	fh = open('seqDataset4HF.pkl')
	data = cPickle.load(fh)
	fh.close()

	distancePredictor = ResNet4DistMatrix( rng=np.random.RandomState(), seqInput=x, matrixInput=y, n_in_seq=data[0][0].shape[2], n_in_matrix=data[1][0].shape[3], n_hiddens_seq=[3, 5], n_hiddens_matrix=[2], hwsz_seq=4, hwsz_matrix=4, mask_seq=xmask, mask_matrix=ymask)

	"""
	f = theano.function([x, y, xmask, ymask], distancePredictor.output_1d)
	g = theano.function([x, y, xmask, ymask], distancePredictor.output_2d)
	"""

	dataLen = 300
	batchSize = 60
	a = np.random.uniform(0, 1, (batchSize, dataLen, 20)).astype(np.float32)
	b = np.random.uniform(0, 1, (batchSize, dataLen, dataLen, 3)).astype(np.float32)
	amask = np.zeros((batchSize, 0)).astype(np.int8)
	bmask = np.zeros((batchSize, 0, dataLen)).astype(np.int8)
	sel = np.ones((batchSize, dataLen, dataLen)).astype(np.int8)
	#print a
	#print b
	c = np.random.uniform(0, 3, (batchSize, dataLen, dataLen)).round().astype(np.int8)
	np.putmask(c, c>=2, 2)
	"""
	c[0, 1, 13]=1
	c[0, 2, 15]=1
	c[0, 4, 16]=1

	c[0, 1, 27]=1
	c[0, 2, 28]=1
	c[0, 4, 29]=1

	c[1, 0, 13]=2
	c[1, 1, 15]=2
	c[1, 3, 16]=2

	c[2, 0, 23]=2
	c[2, 1, 25]=2
	c[2, 3, 26]=2
	"""
	#sel = c

	#out1d = f(a, b, amask, bmask)
	#out2d = g(a, b, amask, bmask)

	#print out1d
	#print out2d

	z = T.btensor3('z')
	loss = distancePredictor.loss(z, selection)
	errs = distancePredictor.ErrorsByRange(z)
	accs = distancePredictor.TopAccuracyByRange(z)
	confM = distancePredictor.confusionMatrix(z)

	h = theano.function([x, y, xmask, ymask, selection, z], confM, on_unused_input='ignore')
	#l, e, accu = h(a, b, amask, bmask, sel, c)

	cms = []
	for i in np.arange(5):
		cm = h(data[0][i], data[1][i], data[2][i], data[3][i], data[4][i], data[5][i])
		print(cm)
		cms.append(cm)

	sumofcms = np.sum(cms, axis=0)*1.

	for i in range(sumofcms.shape[0]):
		sumofcms[i] /= np.sum(sumofcms[i])

	confusions = sumofcms
	print(confusions)
	print(np.sum(confusions[0]))
	print(np.sum(confusions[1]))
	print(np.sum(confusions[2]))

	"""
	params = contactPredictor.params
	cost = loss + 0.1 * contactPredictor.paramL2
	grads = [ T.grad(cost, p) for p in params ]
	fg = theano.function([x, y, xmask, ymask, selection, z], grads)
	g0 = fg(a, b, amask, bmask, sel, c)

	param_shapes = [ p.get_value().shape for p in params ]
	print(g0)
	"""

if __name__ == "__main__":
	#TestOuterConcatenate()

	#TestConv1D2Matrix()

	#TestConv2D4DistMatrix()

	TestResNet4DistMatrix()

	#TestMidpointFeature()


import collections
import auxiliary

def breadth_first_search(initial_state, goal_state):
    open_set = collections.deque()
    closed_set = set()
    come_from = dict()

    open_set.append(initial_state)
    come_from[initial_state] = None

    while len(open_set) > 0:
        state = open_set.popleft()

        if state == goal_state:
            return auxiliary.construct_path(come_from, state)

        for child_state in auxiliary.get_children(state):
            if child_state in closed_set:
                continue
            if child_state not in open_set:
                come_from[child_state] = state
                open_set.append(child_state)

        closed_set.add(state)

if __name__ == "__main__":
    initial = ((2, 8, 1), (4, 6, 3), (0, 7, 5))
    goal = ((1, 2, 3), (8, 0, 4), (7, 6, 5))
    # initial = ((8, 6, 7), (2, 5, 4), (3, 0, 1))
    # goal = ((1, 2, 3), (4, 5, 6), (7, 8, 0))
    path = breadth_first_search(initial, goal)
    auxiliary.print_path(path)


# Mega Case Study - Make a Hybrid Deep Learning Model

# Part 1 - Identify the Frauds with the Self-Organizing Map

# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# Importing the dataset
dataset = pd.read_csv('Credit_Card_Applications.csv')
X = dataset.iloc[:, :-1].values
y = dataset.iloc[:, -1].values

# Feature Scaling
from sklearn.preprocessing import MinMaxScaler
sc = MinMaxScaler(feature_range = (0, 1))
X = sc.fit_transform(X)

# Training the SOM
from minisom import MiniSom
som = MiniSom(x = 10, y = 10, input_len = 15, sigma = 1.0, learning_rate = 0.5)
som.random_weights_init(X)
som.train_random(data = X, num_iteration = 100)

# Visualizing the results
from pylab import bone, pcolor, colorbar, plot, show
bone()
pcolor(som.distance_map().T)
colorbar()
markers = ['o', 's']
colors = ['r', 'g']
for i, x in enumerate(X):
    w = som.winner(x)
    plot(w[0] + 0.5,
         w[1] + 0.5,
         markers[y[i]],
         markeredgecolor = colors[y[i]],
         markerfacecolor = 'None',
         markersize = 10,
         markeredgewidth = 2)
show()

# Finding the frauds
rows = 10   # dimensions of SOM
cols = 10

# Add indices to SOM values & sort by value
helper = np.concatenate(
    (som.distance_map().reshape(rows*cols, 1),         # the SOM map values
     np.arange(rows*cols).reshape(rows*cols, 1)),      # concatenated with an index
    axis=1)                                            # as a 2D matrix with 2 columns of data
helper = helper[helper[:, 0].argsort()][::-1]          # sort by first column (map values) and reverse (so top values are first)

# First choose how many cells to take as outliers
use_threshold = True   # toggle usage for calculating indices (pick cells that exceed threshold or use hardcoded number of cells)
top_cells = 4          # 4 out of 100 seems a valid idea, but ideally it might be chosen after inspecting the current SOM plot
threshold = 0.8        # Use threshold to select top cells

# Take indices that correspond to cells we're interested in
idx = helper[helper[:, 0] > threshold, 1] if use_threshold else helper[:top_cells, 1]

# Find the data entries assigned to cells corresponding to the selected indices
result_map = []
mappings = som.win_map(X)
for i in range(rows):
    for j in range(cols):
        if (i*rows+j) in idx:
            if len(result_map) == 0:
                result_map = mappings[(i,j)]
            else:
                # Sometimes a cell contains no observations (customers)... weird
                # This will cause numpy to raise an exception so guard against that!
                if len(mappings[(i,j)]) > 0:
                    result_map = np.concatenate((result_map, mappings[(i,j)]), axis=0)

# finally we get our fraudster candidates
frauds = sc.inverse_transform(result_map)

# This is the list of potential cheaters (customer ids)
#print(frauds[:, 0])

# Part 2 - Going from Unsupervised to Supervised Deep Learning

# Creating the matrix of features
customers = dataset.iloc[:, 1:].values

# Creating the dependent variable
is_fraud = np.zeros(len(dataset))
for i in range(len(dataset)):
    if dataset.iloc[i,0] in frauds:
        is_fraud[i] = 1

# Feature Scaling
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
customers = sc.fit_transform(customers)

# Part 2 - Create the ANN!

# Importing the Keras libraries and packages
from keras.models import Sequential
from keras.layers import Dense

# Initialising the ANN
classifier = Sequential()

# Adding the input layer and the first hidden layer
classifier.add(Dense(units = 2, kernel_initializer = 'uniform', activation = 'relu', input_dim = 15))

# Adding the output layer
classifier.add(Dense(units = 1, kernel_initializer = 'uniform', activation = 'sigmoid'))

# Compiling the ANN
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])

# Fitting the ANN to the Training set
classifier.fit(customers, is_fraud, batch_size = 1, epochs = 2)

# Predicting the probabilities of frauds
y_pred = classifier.predict(customers)
y_pred = np.concatenate((dataset.iloc[:, 0:1].values, y_pred), axis = 1)

# sort np array by index 1 (probability of being a cheater)
y_pred = y_pred[y_pred[:, 1].argsort()]

Deep Learning/Unsupervised Learning/Self Organizing Maps (SOM)/Hybrid Supervised-Unsupervised Fraud Detection Model/mega_case_study_improved.py