# Load in a search graph
# Compute Q-tilde for each edge and node
# Compute Delta(Q-tilde) and IG(Q-tilde) for each edge in relation to its parent
# ?? Error bars ??
# Plot IG(Q-tilde) vs Delta(Q-tilde) for each edge

from datetime import datetime
import json
import networkx as nx
import numpy as np
import pandas as pd
from pathlib import Path
import seaborn as sns
import matplotlib.pyplot as plt
from typing import Any, Optional
import warnings

from circuitree.viz import plot_network
from circuitree.models import SimpleNetworkGrammar
from circuitree.modularity import information_gain
from graph_utils import compute_Q_tilde, merge_search_graphs

_network_kwargs = dict(
    padding=0.5,
    lw=1,
    node_shrink=0.7,
    offset=0.8,
    auto_shrink=0.9,
    width=0.005,
    plot_labels=False,
)

def main(
    graph_gml: Path,
    root_node: Optional[Any] = None,
    attrs_json: Optional[Path] = None,
    save: bool = False,
    save_dir: Optional[Path] = None,
    fmt: str = "png",
    dpi: int = 300,
    figsize: tuple = (5, 3),
    network_figsize: tuple = (3, 3),
    network_kwargs: Optional[dict] = None,
    n_motifs: int = 8,
    palette: str = "muted",
    multiple: str = "fill",
    legend_title: str = "Motif combination",
    bins=100,
):
    # Load the search graph, a DAG with a single root, from one or more GML files
    if isinstance(graph_gml, Path):
        G: nx.DiGraph = nx.read_gml(graph_gml)
    else:
        print(f"Merging {len(graph_gml)} search graphs...")
        search_graphs = [nx.read_gml(gml) for gml in graph_gml]
        G: nx.DiGraph = merge_search_graphs(search_graphs)
        print(f"Done. Merged graph has {len(G.nodes)} nodes.")

    # Get the root node
    if root_node is None:
        with Path(attrs_json).open("r") as f:
            root_node = json.load(f)["root"]

    # Compute Q-tilde for each edge and node
    compute_Q_tilde(G, root_node=root_node)

    # Compute Delta P and Delta H for each edge and store
    edges = []
    dPs = []
    dHbars = []
    Qroot = G.nodes[root_node]["Q_tilde"]
    for *edge, Qj in G.edges(data="Q_tilde"):
        Qi = G.nodes[edge[0]]["Q_tilde"]
        dP = Qj - Qi
        if dP == 0:
            continue
        dHbar = information_gain(Qj, Qroot)
        edges.append(tuple(edge))
        dPs.append(dP)
        dHbars.append(dHbar)

    dP_dict = dict(zip(edges, dPs))

    # tell seaborn to shut up
    warnings.filterwarnings(action="ignore", category=FutureWarning)

    # Plot Delta P vs Delta H
    # sns.set_theme(style="whitegrid")
    fig = plt.figure(figsize=figsize)
    p = sns.scatterplot(x=dPs, y=dHbars, s=5)
    plt.tight_layout()

    # # Plot Delta P on the x axis with jitter
    # sns.set_theme(style="whitegrid")
    # fig = plt.figure(figsize=figsize)
    # p = sns.stripplot(x=dPs, jitter=0.3)
    # plt.tight_layout()

    if save:
        today = datetime.today().strftime("%y%m%d")
        fpath = Path(save_dir).joinpath(f"{today}_IG_vs_dP_3tf_1mil.{fmt}")
        print(f"Writing to: {fpath.resolve().absolute()}")
        plt.savefig(fpath, dpi=dpi)

    ...

    # Given a number of actions M to choose from, compute the probability of success for each action combination
    # This is just the Q-tilde of each node layer M
    # Should exclude edges that do termination
    layer_num = []
    nodes = []
    p_success = []
    visits = []
    for i, layer in enumerate(nx.bfs_layers(G, root_node)):
        nonterminals = [n for n in layer if G.out_degree(n) > 0]
        nodes.extend(nonterminals)
        # rewards = [G.nodes[n]["Q_tilde"] for n in nonterminals]
        p_success.extend([G.nodes[n]["Q_tilde"] for n in nonterminals])
        visits.extend([G.nodes[n]["visits"] for n in nonterminals])
        layer_num.extend([i] * len(nonterminals))
    df = pd.DataFrame(dict(node=nodes, p_success=p_success, visits=visits))
    df["layer"] = pd.Categorical(
        layer_num, categories=sorted(set(layer_num)), ordered=True
    )
    # Standard error of the mean of Bernoulli is sqrt(p(1-p) / N)
    df["std_dev"] = np.sqrt(df["p_success"] * (1 - df["p_success"]) / df["visits"])

    # Plot the distribution of Q-tilde on the x axis and the # layers on the y axis
    # sns.set_theme(style="whitegrid")
    # df = df.sort_values("p_success", ascending=False).head(100)
    df["log_Qratio"] = np.log10(best_motifs_in_layer_df["p_success"] / Qroot)
    fig = plt.figure(figsize=figsize)
    plt.scatter(df["log_Qratio"], df["layer"], s=1)
    plt.errorbar(
        df["log_Qratio"],
        df["layer"],
        xerr=df["std_dev"],
        fmt="none",
        ecolor="gray",
        # zorder=0,
        lw=0.5,
    )
    plt.tight_layout()

    if save:
        today = datetime.today().strftime("%y%m%d")
        fpath = Path(save_dir).joinpath(f"{today}__Qtilde_vs_layer_3tf_1mil.{fmt}")
        print(f"Writing to: {fpath.resolve().absolute()}")
        plt.savefig(fpath, dpi=dpi)

    # Get the top N nodes with the highest Q-tilde as motif candidates
    top_Qs = df.sort_values("p_success", ascending=False).head(n_motifs)
    motifs = top_Qs["node"].tolist()
    motif_Qs = top_Qs["p_success"].tolist()

    grammar = SimpleNetworkGrammar(
        components=["A", "B", "C"], interactions=["activates", "inhibits"]
    )
    network_kwargs = _network_kwargs | (network_kwargs or dict())
    for i, (motif, q) in enumerate(zip(motifs, motif_Qs)):
        fig = plt.figure(figsize=network_figsize)
        plt.title(f"Q={q:.3f}", size=10)
        plot_network(
            *grammar.parse_genotype(motif, nonterminal_ok=True), **network_kwargs
        )
        plt.xlim(-1.7, 1.7)
        plt.ylim(-1.2, 2.0)

        if save:
            today = datetime.today().strftime("%y%m%d")
            fpath = Path(save_dir).joinpath(f"{today}_3tf_1mil_motif_{i+1}.{fmt}")
            print(f"Writing to: {fpath.resolve().absolute()}")
            plt.savefig(fpath, dpi=dpi)

    # Plot the best motif at each layer
    best_motifs_in_layer_df = df.loc[df.groupby("layer")["p_success"].idxmax()]
    best_motifs_in_layer = best_motifs_in_layer_df["node"].tolist()
    best_motif_Qs = best_motifs_in_layer_df["p_success"].tolist()
    for i, (motif, q) in enumerate(zip(best_motifs_in_layer, best_motif_Qs)):
        fig = plt.figure(figsize=network_figsize)
        plt.title(f"Q={q:.3f}", size=10)
        plot_network(
            *grammar.parse_genotype(motif, nonterminal_ok=True), **network_kwargs
        )
        plt.xlim(-1.7, 1.7)
        plt.ylim(-1.2, 2.0)

        if save:
            today = datetime.today().strftime("%y%m%d")
            fpath = Path(save_dir).joinpath(f"{today}_3tf_1mil_{i}_edges.{fmt}")
            print(f"Writing to: {fpath.resolve().absolute()}")
            plt.savefig(fpath, dpi=dpi)

if __name__ == "__main__":
    # 5 million MCTS iterations - all 12 replicates
    graph_gml = Path(
        "data/oscillation/mcts/bootstrap_long_230928_000832/231006_merged_tree_iter5000000.gml"
    )
    graph_attrs_json = graph_gml.parent.joinpath(
        "0/oscillation_mcts_bootstrap_5000000_tree.json"
    )

    # graph_gml = list(
    #     Path(
    #         "data/oscillation/mcts/bootstrap_long_230928_000832",
    #     ).glob(
    #         "*/oscillation_mcts_bootstrap_5000000_tree.gml",
    #     )
    # )
    # graph_attrs_json = graph_gml[0].parent.joinpath(
    #     "oscillation_mcts_bootstrap_5000000_tree.json"
    # )

    save_dir = Path("figures/oscillation")

    main(
        graph_gml,
        attrs_json=graph_attrs_json,
        save=True,
        save_dir=save_dir,
        fmt="pdf",
    )


from collections import defaultdict

def load_data(filename):
	"""
	Load data as 2d array
	"""
	with open(filename) as file:
		raw_data = file.read().strip()
	data = [row.split("-") for row in raw_data.split("\n")]
	return data

def create_dict(data):
	"""
	in: 2D array in format
		[['start', 'A'], ['start', 'b']]
	out: Dict to act as an adjacency list in format
		{'start':	['A', 'b'],
		'A'	 		['start', 'c', 'b', 'end'],
		'b':		['start', 'A', 'd', 'end'],
		'c':		['A'], 'd': ['b'],
		'end':		['A', 'b']}
	 """
	connections = defaultdict(list)
	for a, b in data:
		# punt a is de naam van het punt,
		# b is waar je naartoe kan vanaf punt a
		# maak met connections[a] nieuw element in dict met key a
		# voeg met .append(b) connected punt toe aan lijst van values die bij key a horen
		# als connection[a] al bestaat wordt er geen nieuw element met key a aangemaakt,
		# maar wordt nog een bestemming toegevoegd aan de connections met dat punt
		# andersom ook toevoegen want de connecties werken twee richtingen op
		connections[a].append(b)
		connections[b].append(a)
	return connections

def dfs(visited, neighbours, cave):
	"""
	Depth-first search: algorithm for tree traversal on graph or tree data structures.
	"""
	global paths

	if cave == "end":
		paths += 1
		return
	if cave in visited and cave.islower():
		return
	if cave.islower():
		visited.add(cave)
	for next_cave in neighbours[cave]:
		# dont go back to start
		if next_cave == "start":
			continue
		# keep going to next cave with recursion, until "end" is reached
		dfs(visited, neighbours, next_cave)
	# remove last visited cave in current path from visited set when stepping back in recursion depth
	if cave.islower():
		visited.remove(cave)
	return

def most_common(lst):
	"""
	Find most common item in list
	"""
	if len(lst) > 0:
		return max(set(lst), key=lst.count)
	else:
		return 0

def check_counts(lst, cave):
	"""
	Return True:
	- when cave is present 1 time and other small cave is present 2 times
	- when cave is present 2 times
	"""
	if lst.count(cave) == 2:
		return True
	item = most_common(lst)
	common_count = lst.count(item)
	if lst.count(cave) == 1 and common_count == 2:
		return True
	else:
		return False

def dfs2(visited, neighbours, cave):
	"""
	Depth-first search: algorithm for tree traversal on graph or tree data structures.
	"""
	global paths

	if cave == "end":
		paths += 1
		return
	if check_counts(visited, cave):
		return
	if cave.islower():
		visited.append(cave)
	for next_cave in neighbours[cave]:
		# dont go back to start
		if next_cave == "start":
			continue
		# keep going to next cave with recursion, until "end" is reached
		dfs2(visited, neighbours, next_cave)
	# remove last visited cave in current path from visited set when stepping back in recursion depth
	if cave.islower():
		visited.remove(cave)
	return

if __name__ == "__main__":
	global paths
	paths = 0
	data = load_data("input.txt")
	connections = create_dict(data)

	# part 1
	visited = set()
	dfs(visited, connections, "start")
	print("part 1: ", paths)

	# part 2
	paths = 0
	visited = []
	dfs2(visited, connections, "start")
	print("part 2: ", paths)


import cv2

def getXY(evt, x, y, flags, userdata ):
	if evt == cv2.EVENT_LBUTTONDOWN:
		print("X: " + str(x) + " Y: " + str(y))
		value = im[y,x]
		print("B: " + str(value[0]) + " G: " + str(value[1]) +
			" R: " + str(value[2]))
		circles.append([x,y])
	if evt == cv2.EVENT_RBUTTONDOWN:
		circles.clear()

im = cv2.imread('color_bars.png')
im1 = im.copy()
window_title = "Color Bars"
circles = []

while True:
	print(circles)
	for circle in circles:
		cv2.circle(im1, (circle[0], circle[1]), 10, (255,0,0),2)

	if len(circles) == 0:
		im1 = im.copy()

	#cv2.circle(im, (x,y), 10, (255,0,0), 2)
	cv2.imshow(window_title, im1)
	cv2.setMouseCallback(window_title, getXY, "Hello")
	k = cv2.waitKey(10)

	if k == ord('q') & 0xFF:
		break


#!/usr/bin/env python
# -*- coding: utf-8 -*-
try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup

with open('README.md', 'r') as f:
    readme = f.read()

setup(
    name='satellite6-upgrade',
    version='0.1.0',
    description='Tools to perform and test satellite6 upgrade.'
    'And test framework that validates entities postupgrade.',
    long_description=readme,
    author=u'Jitendra Yejare',
    author_email='jyejare@redhat.com',
    url='https://github.com/SatelliteQE/satellite6-upgrade',
    packages=['satellite6-upgrade'],
    package_data={'': ['LICENSE']},
    package_dir={'satellite6-upgrade': 'satellite6-upgrade'},
    include_package_data=True,
    install_requires=[
        'Fabric',
        'ovirt-engine-sdk-python==3.6.8.0',
        'pycurl',
        'pytest',
        'python-bugzilla==1.2.2',
        'python-novaclient',
        'requests',
        'robozilla'
        'shade'
    ],
    license='GNU GPL v3.0',
    classifiers=(
        'Development Status :: 5 - Production/Stable',
        'Intended Audience :: Developers',
        'Intended Audience :: Testers',
        'Natural Language :: English',
        'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
    ),
)


#!/usr/bin/envp ython3

# --------------------------------------------------
# FLightsGUI.py
# Alex Harris and Dez Turkson
# March/April 2021
# --------------------------------------------------

from ManagerView import *
from CustomerView import *
from OpeningView import *
from Plane import *

def main():
    # create initial window
    win = GraphWin("FlightsGUI", 1000, 600)

    # create the different objects for the GUI
    plane = Plane(win)
    openingVIew = OpeningView(win)
    customerView = CustomerView(win, plane)
    managerView = ManagerView(win, plane)

    clicked = True
    # not an infinite loop because of sys.exit calls within classes
    while clicked:
        selection = openingVIew.drawOpeningView()
        if selection == "customer":
            customerView.drawStartCustomerView()
        elif selection == "manager":
            managerView.drawManagerView()

    return

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
"""
A simple python script which creates a map service from a map file (MXD).

UNFINISHED

Written for Python 2.7; will not work with Python 3.x.
TO use with Python 3.x (Pro) convert arcpy.mapping to arcpy.mp
Requires the Esri ArcGIS arcpy module.
"""

from __future__ import absolute_import, division, print_function, unicode_literals

import os

import arcpy

# define local variables
WORKSPACE = r"D:\MapData\Observer"
PROTOCOL = "Test_Protocol_v1"

def main():
    """Create and upload service definition"""

    mxd = os.path.join(WORKSPACE, PROTOCOL + ".mxd")
    map_doc = arcpy.mapping.MapDocument(mxd)
    # connectionfile = 'GIS Servers/ArcGIS on MyServer_6080 (publisher).ags'

    sddraft = os.path.join(WORKSPACE, PROTOCOL + ".sddraft")
    sd_file = os.path.join(WORKSPACE, PROTOCOL + ".sd")

    summary = "Survey Protocol " + PROTOCOL
    tags = "Survey, Protocol, Park Observer, " + PROTOCOL

    # create service definition draft
    analysis = arcpy.mapping.CreateMapSDDraft(
        map_doc,
        sddraft,
        PROTOCOL,
        "ARCGIS_SERVER",
        None,
        False,
        "ParkObserver",
        summary,
        tags,
    )

    # stage and upload the service if the sddraft analysis did not contain errors
    if analysis["errors"] == {}:
        # Execute StageService
        arcpy.StageService_server(sddraft, sd_file)
        # Execute UploadServiceDefinition
        # arcpy.UploadServiceDefinition_server(sd_file, connectionfile)
    else:
        # if the sddraft analysis contained errors, display them
        print(analysis["errors"])

if __name__ == "__main__":
    main()


import streamlit as st
import streamlit_survey as ss
import json
import pandas as pd

survey = ss.StreamlitSurvey("Survey Example - Advanced Usage")

pages_test = survey.pages(11, on_submit=lambda: st.success("Your responses have been recorded. Thank you Tanvir!"))

with pages_test:
    if pages_test.current == 0:
        st.write("Survey Section-1")
        first = survey.radio(
            "Select One: ", options = ["ALFA", "ROMEO", "ASTON", "MARTIN", "AUDI", "BMW"], horizontal=True, id="1"
        )
    if pages_test.current == 1:
        st.write("Survey Section-2")
        first = survey.radio(
            "Select One: ", options = ["CHEVROLET","DODGE","FERRARI","HONDA"], horizontal=True, id="2"
        )

    if pages_test.current == 2:
        st.write("Survey Section-3")
        first = survey.radio(
            "Select One: ", options = ["JAGUAR","LAMBORGHINI","MAZDA","MCLAREN"], horizontal=True, id="3"
        )

    if pages_test.current == 3:
        st.write("Survey Section-4")
        first = survey.radio(
            "Select One: ", options = ["MERCEDES-BENZ","NISSAN","PAGANI AUTOMOBILI S.P.A","PORSCHE"], horizontal=True, id="4"
        )

    if pages_test.current == 4:
        st.write("Survey Section-5")
        first = survey.radio(
            "Select One: ", options = ["FIAT","MINI","SCION","SUBARU"], horizontal=True, id="5"
        )

    if pages_test.current == 5:
        st.write("Survey Section-6")
        first = survey.radio(
            "Select One: ", options = ["BENTLEY","BUICK","FORD","HYUNDAI"], horizontal=True, id="6"
        )

    if pages_test.current == 6:
        st.write("Survey Section-7")
        first = survey.radio(
            "Select One: ", options = ["LEXUS","MASERATI","ROUSH","VOLKSWAGEN"], horizontal=True, id="7"
        )

    if pages_test.current == 7:
        st.write("Survey Section-8")
        first = survey.radio(
            "Select One: ", options = ["ACURA","CADILLAC","INFINITI","KIA"], horizontal=True, id="8"
        )

    if pages_test.current == 8:
        st.write("Survey Section-9")
        first = survey.radio(
            "Select One: ", options = ["MITSUBISHI","ROLLS-ROYCE","TOYOTA","VOLVO"], horizontal=True, id="9"
        )

    if pages_test.current == 9:
        st.write("Survey Section-10")
        first = survey.radio(
            "Select One: ", options = ["CHRYSLER","LINCOLN","GMC","RAM"], horizontal=True, id="10"
        )

    if pages_test.current == 10:
        st.write("Survey Summary")
        json_data = survey.to_json()
        #st.json(json_data)
        df = pd.read_json(json_data)
        st.dataframe(df)

        # Convert to csv for download button
        @st.cache_data
        def convert_df(df):
            # IMPORTANT: Cache the conversion to prevent computation on every rerun
            return df.to_csv().encode('utf-8')

        csv = convert_df(df)

        st.download_button(
            label="Download as CSV",
            data=csv,
            file_name='raw.csv',
            mime='text/csv',
        )


import pandas as pd
import numpy as np

from scipy.stats import norm, chi2, gamma

chat_id = 0 # Ваш chat ID, не меняйте название переменной

def solution(p: float, x: np.array) -> tuple:
    p = 1 - p
    n = len(x)
    x_s = np.square(x)
    R = np.sum(x_s)
    l_g = gamma.ppf(p/2, a = n, scale = 2/n)
    r_g = gamma.ppf(1 - p/2, a = n, scale = 2/n)
    sigma_left = np.sqrt( R / 14 / n / r_g)
    sigma_right = np.sqrt( R / 14 / n / l_g)
    return sigma_left, sigma_right


import cairosvg, io, requests, json, datetime, os
from PIL import Image, ImageDraw, ImageFont

# 1. Get API key from secret
# Moved to request.get

# 2. Get TT info from API
with open("shapes.json", 'r') as f:
    tt_shape = json.load(f)

tts = list(tt_shape.keys())

# 2.1 Try to load history info from file if exist
today = datetime.datetime.today()
ttinfo_path = './tt_history/ttinfo_{}_{}_{}.json'.format(today.year, today.month, today.day)
for _, _, files in os.walk('./tt_history'):
    if ttinfo_path.split('/')[-1] in files:
        with open(ttinfo_path, 'r') as f:
            ttinfo = json.load(f)
    else:
        ttinfo = {}

# 2.2 Get tt info for those not in file
start_idx = 0
call = "https://api.torn.com/torn/{}?selections=territory&key={}"
call_timeout = False
while start_idx < 4150:
    if any(tt in ttinfo for tt in tts[start_idx:start_idx+50]):
        print("skip", start_idx)
        start_idx += 50
        continue

    try_count = 0
    while try_count <= 5:
        try:
            api_key = os.environ["APIKEY"]
            tt_call_res = requests.get(call.format(','.join(tts[start_idx:start_idx+50]), api_key), timeout=5).json()
            break
        except:
            print("call for", start_idx, "timeout, retry", try_count)
            try_count += 1
            if try_count > 5:
                # Reach call limit, dump current tt info and exit
                call_timeout = True
                break
            else:
                continue

    if not tt_call_res["territory"]:
        print("tt all done")
        break
    for k, v in tt_call_res["territory"].items():
        ttinfo[k] = v
    print("done", start_idx)
    start_idx += 50

with open(ttinfo_path, 'w') as f:
    json.dump(ttinfo, f)
if call_timeout:
    exit(-1)

# 3. Fac information
with open("faction_branch.json", "r") as f:
    fb = json.load(f)

ns_faction = fb['ns']
jfk_faction = fb['jfk']
sa_faction = fb['sa']
ptcr_faction = fb['ptcr']
m_faction = fb['m']
facs = [ns_faction, jfk_faction, sa_faction, ptcr_faction, m_faction]

# 4. Draw
# 4.1 Funcs
def make_svg(citymap, tt_color, war_tts, unocc_tts):
    svg_prefix = '<svg width="6384" height="3648" style="background-color: transparent">'
    svg_suffix = '</svg>'
    svg_item = '<path d="{}" stroke-width="0" fill="{}" fill-opacity="0.27"/>'
    svg_unocc = '<path d="{}" stroke-width="0" fill="{}" fill-opacity="0.07"/>'
    svg_war_stroke = '<path d="{}" stroke="{}" stroke-width="3" stroke-opacity="1" fill-opacity="0"/>'
    svg_str = [svg_prefix]
    for tt in tt_color.keys():
        if tt not in tt_shape:
            print(tt, " not in shapes")
            continue
        color = tt_color[tt]
        svg_path = tt_shape[tt]
        if tt in unocc_tts:
            svg_str.append(svg_unocc.format(svg_path, color))
        else:
            svg_str.append(svg_item.format(svg_path, color))
        if tt in war_tts:
            svg_str.append(svg_war_stroke.format(svg_path, war_tts[tt]))
    svg_str.append(svg_suffix)
    out = cairosvg.svg2png(bytestring=''.join(svg_str).encode('utf-8'))
    svgimg = Image.open(io.BytesIO(out)).convert('RGBA')
    citymap.paste(svgimg, (0, 0), svgimg)

def draw_legend(citymap):
    dr = ImageDraw.Draw(citymap, 'RGBA')
    font = ImageFont.truetype('./arial.ttf', 60)
    fac2color = {
        'WestWorld(Monarch&etc.)': 'cyan',
        'CRyPTo(PT&CR&etc.)': 'yellow',
        'SA/RoD': 'DodgerBlue',
        'JFK': '#00b23a',
        'OBN(NS&etc.)': '#f11414',
        'Not Affliated': 'fuchsia',
        'NPC Buildings': 'orange'
    }
    line = 0
    x = 50
    ls = 30
    basey = citymap.size[1] - 50
    for facname, color in fac2color.items():
        y = basey - line * 100
        dr.rectangle((x - ls, y - ls, x + ls, y + ls), 'black', width=1)
        dr.rectangle((x - ls + 5, y - ls + 5, x + ls - 5, y + ls - 5), color, width=1)
        dr.text((x + 50, y - 35), facname, color, font, stroke_fill='black', stroke_width=5)
        line += 1
    basex = 800
    dr.line((basex, basey, basex + 200, basey), 'lime', width=5)
    dr.text((basex + 250, basey - 35),"Fake Wall", 'lime', font, stroke_fill='black', stroke_width=5)
    dr.line((basex, basey - 100, basex + 200, basey - 100), 'red', width=5)
    dr.text((basex + 250, basey - 135),"Real Wall", 'red', font, stroke_fill='black', stroke_width=5)
    dr.text((4200, basey - 200), f'Production by @SPGoding // Created at {today.day}/{today.month}/{today.year}', 'white', font, stroke_fill='black', stroke_width=5)

# 4.2 Main logic
ttcolor = {}
is_war = {}
is_unocc = set()
vis = set()
bfs_queue = []
for tt, detail in ttinfo.items():
    color = None
    facid = detail["faction"]
    if facid in ns_faction:
        color = '#f11414' # red
    elif facid in jfk_faction:
        color = '#00b23a' #green
    elif facid in sa_faction:
        color = 'blue'
    elif facid in ptcr_faction:
        color = 'yellow'
    elif facid in m_faction:
        color = 'cyan'
    elif facid != 0:
        color = '#cc00cc'  # fuchsia
    if color:
        ttcolor[tt] = color
        vis.add(tt)
        bfs_queue.append(tt)
    if 'war' in detail:
        war_detail = detail['war']
        assfac = war_detail['assaulting_faction']
        deffac = war_detail['defending_faction']
        is_war[tt] = 'red'
        for fac in facs:
            if assfac in fac and deffac in fac:
                is_war[tt] = 'lime'
                break

for tt, shape in tt_shape.items():
    if tt not in ttinfo:
        ttcolor[tt] = 'orange'

while bfs_queue:
    tmp = []
    for tt in bfs_queue:
        if tt not in ttinfo:
            print("we need info of", tt)
            continue
        if ttcolor[tt] == '#cc00cc':
            continue
        nbs = ttinfo[tt]['neighbors']
        for nb in nbs:
            if nb not in vis:
                ttcolor[nb] = ttcolor[tt]
                is_unocc.add(nb)
                vis.add(nb)
                tmp.append(nb)
    bfs_queue = tmp

city = Image.open("map.png")
make_svg(city, ttcolor, is_war, is_unocc)
draw_legend(city)
city.save(f"city.jpg")


"""
Given an array nums of size n, return the majority element.

The majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array.

Example 1:
Input: nums = [3,2,3]
Output: 3

Example 2:
Input: nums = [2,2,1,1,1,2,2]
Output: 2
"""

class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        char_count = {}
        majority_count = 0
        majority_elem = -1
        for num in nums:
            if char_count.get(num) == None:
                char_count[num] = 0
            char_count[num] += 1

            if char_count[num] > majority_count:
                majority_count = char_count[num]
                majority_elem = num

        return majority_elem


# conda install pillow

import tkinter as tk
from tkinter import *
import numpy as np
import PIL
from PIL import Image, ImageTk

# array = np.ones((40,40))*150
# img =  ImageTk.PhotoImage(image=Image.fromarray(array))

class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.pack()
        self.create_widgets()

    def say_hi(self):
        print("Hello Terminal")

    def create_widgets(self):
        root.configure(background='white')
        self.configure(background='white')
        root.geometry("1000x900")
        root.title('Romi-2.0 Controller Camera')

        # CREATE SUB FUNCS FOR EACH WIDGET AND THEN RUN ALL FROM HERE

        # Cam label
        self.camLabel = tk.Label(self, width = 100, height=1,
                                bg='white', bd = '0',
                                text='Romi-2.0 Camera')
        self.camLabel.pack(side=TOP)

        # camera image input as np array
        self.canvas = tk.Canvas(self,width=600,height=400, bg='white')
        array = np.random.randint(0, 255, (400, 600))*1.
        self.img =  ImageTk.PhotoImage(image=Image.fromarray(array))
        self.canvas.create_image(300,0, anchor="n", image=self.img)
        self.canvas.pack(side=TOP)

        # keypads
        # insert image from file & resize
        self.keypadCan = tk.Canvas(self, width=260, height=160, bg='white', bd=0)
        self.keypad_img = Image.open("images/kita/keypad symbols.png")
        self.keypad_img = self.keypad_img.resize((260, 160), Image.ANTIALIAS)
        self.keypad_img = ImageTk.PhotoImage(self.keypad_img)
        self.keypadCan.create_image(130, 0, anchor=N, image=self.keypad_img)
        self.keypadCan.pack(side=TOP)

        # print to terminal button
        self.hi_there = tk.Button(self)
        self.hi_there["text"] = "Send Hello to Terminal"
        self.hi_there["command"] = self.say_hi
        self.hi_there.pack(side=TOP)

        # quit menu
        self.quit = tk.Button(self, text="QUIT", fg="red",
                              command=self.master.destroy)
        self.quit.pack(side=TOP)

root = tk.Tk()
app = Application(master=root)
app.mainloop()


#Name: Loc Nguyen
#Date: 05/16/2021
#Objective: Find kth smallest element using merge sort

import time
import random

arraySize = 2**19
k = 2
#define merge sort function
def mergeSort(array):
    #check length of array
    if len(array) > 1:
        divider = len(array)//2
        leftArr = array[:divider]
        rightArr = array[divider:]
        #recursively call merge sort
        mergeSort(leftArr)
        mergeSort(rightArr)

        i,j,k = 0,0,0

        #check length is greater than 0
        while i < len(leftArr) and j < len(rightArr):
            #compare left and right, find smaller element and replace it
            if leftArr[i] < rightArr[j]:
                array[k] = leftArr[i]
                i += 1
            else:
                array[k] = rightArr[j]
                j += 1
            k += 1
        #taking care of leftover elements
        while i < len(leftArr):
            array[k] = leftArr[i]
            i+= 1
            k+= 1

        while j < len(rightArr):
            array[k] = rightArr[j]
            j += 1
            k += 1
    return array

#generate array size for test cases
def inputGenerator(size):
    array = [random.randint(0,size*10) for i in range(arraySize)]
    return array
trialTime = []
for i in range(10):
    print("Trial",i+1)
    start = time.time()

    inputArray = inputGenerator(arraySize)
    #print("Input Array:",inputArray)
    sortedArray = mergeSort(inputArray)

    #print("Sorted Array:",sortedArray)
    print("The kth ( k =",k,") smallest element:",sortedArray[k-1])
    #end of algorithm
    end = time.time()
    executionTime = end - start
    trialTime.append(executionTime)

#sort to find worst and best time to compute average time
trialTime.sort()
averageTime = (sum(trialTime)-trialTime[0] - trialTime[len(trialTime)-1])/(8)
print("Average time is %.5f" % averageTime)


#Temperature graphs from PCC.

import csv

from datetime import datetime

import matplotlib.pyplot as plt

filename = "data/2193109.csv"
# filename = 'data/death_valley_2018_simple.csv'

with open(filename) as f:
    reader = csv.reader(f)
    header_row = next(reader)
    print(header_row)
    date_index = header_row.index('DATE')
    high_index = header_row.index('TMAX')
    low_index = header_row.index('TMIN')
    name_index = header_row.index('NAME')

    place_name = ''
    # Get dates and high and low temperatures from this file.
    dates, highs, lows = [], [], []
    for row in reader:
        if not place_name:
            place_name = row[name_index]
            print(place_name)

        current_date = datetime.strptime(row[date_index], '%Y-%m-%d')
        try:
            high = float(row[high_index])
            low = float(row[low_index])
        except ValueError:
            print(f'Missing data for {current_date}.')
        else:
            dates.append(current_date)
            highs.append(high)
            lows.append(low)

# print(highs)
for index, column_header in enumerate(header_row):
    print(index, column_header)

# Plot the high and low temperatures.
plt.style.use('seaborn')
fig, ax = plt.subplots()
ax.plot(dates, highs, c = 'red', alpha = .5, linewidth = .5)
ax.plot(dates, lows, c = 'blue', alpha = .5, linewidth = .5)
plt.fill_between(dates, highs, lows, facecolor = 'blue', alpha = .1)

# Format plot.
plt.title(f"{place_name} \nhigh and low temperatures - 2018", fontsize = 20)
plt.xlabel('Dates', fontsize = 16)
fig.autofmt_xdate(bottom = .2, rotation = 45, ha = 'center')
plt.ylabel("Temperature (C)", fontsize = 16)
plt.tick_params(axis = 'both', which = 'major', labelsize = 10, pad = 10, length = 10)
plt.ylim(0, 33)

plt.show()


# def words_sorting(*args):
#     res = {}
#
#     for word in args:
#         value = sum([ord(c) for c in word])
#         res[word] = value
#     if sum(res.values()) % 2 !=0:
#         return sorted(res.items(),key=lambda x:-x[1])
#     return sorted(res.items(),key=lambda x:(-x[1],x[0]),reverse=True)

def words_sorting(*args):
    def calculate_word_value(word):
        return sum(ord(x) for x in word)

    word_dict = {word: calculate_word_value(word) for word in args}
    total_words_value = sum(word_dict.values())
    if total_words_value % 2 == 0:
        result = sorted(word_dict.items())

    else:
        result = sorted(word_dict.items(),key=lambda x:-x[1])

    return '\n'.join(f'{word} - {count}' for (word,count) in result)

print("-" *  50)
print(
    words_sorting(
        'escape',
        'charm',
        'mythology'
    ))
print("-" *  50)
print(
    words_sorting(
        'escape',
        'charm',
        'eye'
    ))
print("-" *  50)
print(
    words_sorting(
        'cacophony',
        'accolade'
    ))

Advanced/0.Advanced May 2023/Exam Prep/exam_prep_may_2022/exam_1/word_sorting_3.py


"""
Classes to solve and simulate consumption-savings model with a discrete, exogenous,
stochastic Markov state.  The only solver here extends ConsIndShockModel to
include a Markov state; the interest factor, permanent growth factor, and income
distribution can vary with the discrete state.
"""

import numpy as np

from HARK import AgentType
from HARK.ConsumptionSaving.ConsIndShockModel import (
    ConsIndShockSolver,
    ConsumerSolution,
    IndShockConsumerType,
    PerfForesightConsumerType,
)
from HARK.distribution import MarkovProcess, Uniform, calc_expectation
from HARK.interpolation import (
    CubicInterp,
    LinearInterp,
    LowerEnvelope,
    MargValueFuncCRRA,
    ValueFuncCRRA,
)
from HARK.rewards import (
    CRRAutility,
    CRRAutility_inv,
    CRRAutility_invP,
    CRRAutilityP,
    CRRAutilityP_inv,
    CRRAutilityP_invP,
    CRRAutilityPP,
)

__all__ = ["ConsMarkovSolver", "MarkovConsumerType"]

utility = CRRAutility
utilityP = CRRAutilityP
utilityPP = CRRAutilityPP
utilityP_inv = CRRAutilityP_inv
utility_invP = CRRAutility_invP
utility_inv = CRRAutility_inv
utilityP_invP = CRRAutilityP_invP

class ConsMarkovSolver(ConsIndShockSolver):
    """
    A class to solve a single period consumption-saving problem with risky income
    and stochastic transitions between discrete states, in a Markov fashion.
    Extends ConsIndShockSolver, with identical inputs but for a discrete
    Markov state, whose transition rule is summarized in MrkvArray.  Markov
    states can differ in their interest factor, permanent growth factor, live probability, and
    income distribution, so the inputs Rfree, PermGroFac, IncShkDstn, and LivPrb are
    now arrays or lists specifying those values in each (succeeding) Markov state.
    """

    def __init__(
        self,
        solution_next,
        IncShkDstn_list,
        LivPrb,
        DiscFac,
        CRRA,
        Rfree_list,
        PermGroFac_list,
        MrkvArray,
        BoroCnstArt,
        aXtraGrid,
        vFuncBool,
        CubicBool,
    ):
        """
        Constructor for a new solver for a one period problem with risky income
        and transitions between discrete Markov states.  In the descriptions below,
        N is the number of discrete states.

        Parameters
        ----------
        solution_next : ConsumerSolution
            The solution to next period's one period problem.
        IncShkDstn_list : [distribution.Distribution]
            A length N list of income distributions in each succeeding Markov
            state.  Each income distribution is a
            discrete approximation to the income process at the
            beginning of the succeeding period.
        LivPrb : np.array
            Survival probability; likelihood of being alive at the beginning of
            the succeeding period for each Markov state.
        DiscFac : float
            Intertemporal discount factor for future utility.
        CRRA : float
            Coefficient of relative risk aversion.
        Rfree_list : np.array
            Risk free interest factor on end-of-period assets for each Markov
            state in the succeeding period.
        PermGroFac_list : np.array
            Expected permanent income growth factor at the end of this period
            for each Markov state in the succeeding period.
        MrkvArray : np.array
            An NxN array representing a Markov transition matrix between discrete
            states.  The i,j-th element of MrkvArray is the probability of
            moving from state i in period t to state j in period t+1.
        BoroCnstArt: float or None
            Borrowing constraint for the minimum allowable assets to end the
            period with.  If it is less than the natural borrowing constraint,
            then it is irrelevant; BoroCnstArt=None indicates no artificial bor-
            rowing constraint.
        aXtraGrid: np.array
            Array of "extra" end-of-period asset values-- assets above the
            absolute minimum acceptable level.
        vFuncBool: boolean
            An indicator for whether the value function should be computed and
            included in the reported solution.
        CubicBool: boolean
            An indicator for whether the solver should use cubic or linear inter-
            polation.

        Returns
        -------
        None
        """
        # Set basic attributes of the problem

        self.solution_next = solution_next
        self.IncShkDstn_list = IncShkDstn_list
        self.LivPrb = LivPrb
        self.DiscFac = DiscFac
        self.CRRA = CRRA
        self.BoroCnstArt = BoroCnstArt
        self.aXtraGrid = aXtraGrid
        self.vFuncBool = vFuncBool
        self.CubicBool = CubicBool
        self.Rfree_list = Rfree_list
        self.PermGroFac_list = PermGroFac_list
        self.MrkvArray = MrkvArray
        self.StateCount = MrkvArray.shape[0]

        self.def_utility_funcs()

    def solve(self):
        """
        Solve the one period problem of the consumption-saving model with a Markov state.

        Parameters
        ----------
        none

        Returns
        -------
        solution : ConsumerSolution
            The solution to the single period consumption-saving problem. Includes
            a consumption function cFunc (using cubic or linear splines), a marg-
            inal value function vPfunc, a minimum acceptable level of normalized
            market resources mNrmMin, normalized human wealth hNrm, and bounding
            MPCs MPCmin and MPCmax.  It might also have a value function vFunc
            and marginal marginal value function vPPfunc.  All of these attributes
            are lists or arrays, with elements corresponding to the current
            Markov state.  E.g. solution.cFunc[0] is the consumption function
            when in the i=0 Markov state this period.
        """
        # Find the natural borrowing constraint in each current state
        self.def_boundary()

        # Initialize end-of-period (marginal) value functions
        self.EndOfPrdvFunc_list = []
        self.EndOfPrdvPfunc_list = []
        self.Ex_IncNextAll = (
            np.zeros(self.StateCount) + np.nan
        )  # expected income conditional on the next state
        self.WorstIncPrbAll = (
            np.zeros(self.StateCount) + np.nan
        )  # probability of getting the worst income shock in each next period state

        # Loop through each next-period-state and calculate the end-of-period
        # (marginal) value function
        for j in range(self.StateCount):
            # Condition values on next period's state (and record a couple for later use)
            self.condition_on_state(j)
            self.Ex_IncNextAll[j] = np.dot(
                self.ShkPrbsNext, self.PermShkValsNext * self.TranShkValsNext
            )
            self.WorstIncPrbAll[j] = self.WorstIncPrb

            # Construct the end-of-period marginal value function conditional
            # on next period's state and add it to the list of value functions
            EndOfPrdvPfunc_cond = self.make_EndOfPrdvPfuncCond()
            self.EndOfPrdvPfunc_list.append(EndOfPrdvPfunc_cond)

            # Construct the end-of-period value functional conditional on next
            # period's state and add it to the list of value functions
            if self.vFuncBool:
                EndOfPrdvFunc_cond = self.make_EndOfPrdvFuncCond()
                self.EndOfPrdvFunc_list.append(EndOfPrdvFunc_cond)

        # EndOfPrdvP_cond is EndOfPrdvP conditional on *next* period's state.
        # Take expectations to get EndOfPrdvP conditional on *this* period's state.
        self.calc_EndOfPrdvP()

        # Calculate the bounding MPCs and PDV of human wealth for each state
        self.calc_HumWealth_and_BoundingMPCs()

        # Find consumption and market resources corresponding to each end-of-period
        # assets point for each state (and add an additional point at the lower bound)
        aNrm = (
            np.asarray(self.aXtraGrid)[np.newaxis, :]
            + np.array(self.BoroCnstNat_list)[:, np.newaxis]
        )
        self.get_points_for_interpolation(self.EndOfPrdvP, aNrm)
        cNrm = np.hstack((np.zeros((self.StateCount, 1)), self.cNrmNow))
        mNrm = np.hstack(
            (np.reshape(self.mNrmMin_list, (self.StateCount, 1)), self.mNrmNow)
        )

        # Package and return the solution for this period
        self.BoroCnstNat = self.BoroCnstNat_list
        solution = self.make_solution(cNrm, mNrm)
        return solution

    def def_boundary(self):
        """
        Find the borrowing constraint for each current state and save it as an
        attribute of self for use by other methods.

        Parameters
        ----------
        none

        Returns
        -------
        none
        """
        self.BoroCnstNatAll = np.zeros(self.StateCount) + np.nan
        # Find the natural borrowing constraint conditional on next period's state
        for j in range(self.StateCount):
            PermShkMinNext = np.min(self.IncShkDstn_list[j].atoms[0])
            TranShkMinNext = np.min(self.IncShkDstn_list[j].atoms[1])
            self.BoroCnstNatAll[j] = (
                (self.solution_next.mNrmMin[j] - TranShkMinNext)
                * (self.PermGroFac_list[j] * PermShkMinNext)
                / self.Rfree_list[j]
            )

        self.BoroCnstNat_list = np.zeros(self.StateCount) + np.nan
        self.mNrmMin_list = np.zeros(self.StateCount) + np.nan
        self.BoroCnstDependency = np.zeros((self.StateCount, self.StateCount)) + np.nan
        # The natural borrowing constraint in each current state is the *highest*
        # among next-state-conditional natural borrowing constraints that could
        # occur from this current state.
        for i in range(self.StateCount):
            possible_next_states = self.MrkvArray[i, :] > 0
            self.BoroCnstNat_list[i] = np.max(self.BoroCnstNatAll[possible_next_states])

            # Explicitly handle the "None" case:
            if self.BoroCnstArt is None:
                self.mNrmMin_list[i] = self.BoroCnstNat_list[i]
            else:
                self.mNrmMin_list[i] = np.max(
                    [self.BoroCnstNat_list[i], self.BoroCnstArt]
                )
            self.BoroCnstDependency[i, :] = (
                self.BoroCnstNat_list[i] == self.BoroCnstNatAll
            )
        # Also creates a Boolean array indicating whether the natural borrowing
        # constraint *could* be hit when transitioning from i to j.

    def condition_on_state(self, state_index):
        """
        Temporarily assume that a particular Markov state will occur in the
        succeeding period, and condition solver attributes on this assumption.
        Allows the solver to construct the future-state-conditional marginal
        value function (etc) for that future state.

        Parameters
        ----------
        state_index : int
            Index of the future Markov state to condition on.

        Returns
        -------
        none
        """
        # Set future-state-conditional values as attributes of self
        self.IncShkDstn = self.IncShkDstn_list[state_index]
        self.Rfree = self.Rfree_list[state_index]
        self.PermGroFac = self.PermGroFac_list[state_index]
        self.vPfuncNext = self.solution_next.vPfunc[state_index]
        self.mNrmMinNow = self.mNrmMin_list[state_index]
        self.BoroCnstNat = self.BoroCnstNatAll[state_index]
        self.set_and_update_values(
            self.solution_next, self.IncShkDstn, self.LivPrb, self.DiscFac
        )
        self.DiscFacEff = (
            self.DiscFac
        )  # survival probability LivPrb represents probability from
        # *current* state, so DiscFacEff is just DiscFac for now

        # These lines have to come after set_and_update_values to override the definitions there
        self.vPfuncNext = self.solution_next.vPfunc[state_index]
        if self.CubicBool:
            self.vPPfuncNext = self.solution_next.vPPfunc[state_index]
        if self.vFuncBool:
            self.vFuncNext = self.solution_next.vFunc[state_index]

    def calc_EndOfPrdvPP(self):
        """
        Calculates end-of-period marginal marginal value using a pre-defined
        array of next period market resources in self.mNrmNext.

        Parameters
        ----------
        none

        Returns
        -------
        EndOfPrdvPP : np.array
            End-of-period marginal marginal value of assets at each value in
            the grid of assets.
        """

        def vpp_next(shocks, a_nrm, Rfree):
            return shocks["PermShk"] ** (-self.CRRA - 1.0) * self.vPPfuncNext(
                self.m_nrm_next(shocks, a_nrm, Rfree)
            )

        EndOfPrdvPP = (
            self.DiscFacEff
            * self.Rfree
            * self.Rfree
            * self.PermGroFac ** (-self.CRRA - 1.0)
            * self.IncShkDstn.expected(vpp_next, self.aNrmNow, self.Rfree)
        )
        return EndOfPrdvPP

    def make_EndOfPrdvFuncCond(self):
        """
        Construct the end-of-period value function conditional on next period's
        state.

        Parameters
        ----------
        EndOfPrdvP : np.array
            Array of end-of-period marginal value of assets corresponding to the
            asset values in self.aNrmNow.
        Returns
        -------
        none
        """

        def v_lvl_next(shocks, a_nrm, Rfree):
            return (
                shocks[0] ** (1.0 - self.CRRA) * self.PermGroFac ** (1.0 - self.CRRA)
            ) * self.vFuncNext(self.m_nrm_next(shocks, a_nrm, Rfree))

        EndOfPrdv_cond = self.DiscFacEff * calc_expectation(
            self.IncShkDstn, v_lvl_next, self.aNrmNow, self.Rfree
        )
        EndOfPrdvNvrs = self.u.inv(
            EndOfPrdv_cond
        )  # value transformed through inverse utility
        EndOfPrdvNvrsP = self.EndOfPrdvP_cond * self.u.derinv(
            EndOfPrdv_cond, order=(0, 1)
        )
        EndOfPrdvNvrs = np.insert(EndOfPrdvNvrs, 0, 0.0)
        EndOfPrdvNvrsP = np.insert(
            EndOfPrdvNvrsP, 0, EndOfPrdvNvrsP[0]
        )  # This is a very good approximation, vNvrsPP = 0 at the asset minimum
        aNrm_temp = np.insert(self.aNrmNow, 0, self.BoroCnstNat)
        EndOfPrdvNvrsFunc = CubicInterp(aNrm_temp, EndOfPrdvNvrs, EndOfPrdvNvrsP)
        EndOfPrdvFunc_dond = ValueFuncCRRA(EndOfPrdvNvrsFunc, self.CRRA)

        return EndOfPrdvFunc_dond

    def calc_EndOfPrdvPcond(self):
        """
        Calculate end-of-period marginal value of assets at each point in aNrmNow
        conditional on a particular state occuring in the next period.

        Parameters
        ----------
        None

        Returns
        -------
        EndOfPrdvP : np.array
            A 1D array of end-of-period marginal value of assets.
        """
        EndOfPrdvPcond = ConsIndShockSolver.calc_EndOfPrdvP(self)
        return EndOfPrdvPcond

    def make_EndOfPrdvPfuncCond(self):
        """
        Construct the end-of-period marginal value function conditional on next
        period's state.

        Parameters
        ----------
        None

        Returns
        -------
        EndofPrdvPfunc_cond : MargValueFuncCRRA
            The end-of-period marginal value function conditional on a particular
            state occuring in the succeeding period.
        """
        # Get data to construct the end-of-period marginal value function (conditional on next state)
        self.aNrm_cond = self.prepare_to_calc_EndOfPrdvP()
        self.EndOfPrdvP_cond = self.calc_EndOfPrdvPcond()
        EndOfPrdvPnvrs_cond = self.u.derinv(
            self.EndOfPrdvP_cond, order=(1, 0)
        )  # "decurved" marginal value
        if self.CubicBool:
            EndOfPrdvPP_cond = self.calc_EndOfPrdvPP()
            EndOfPrdvPnvrsP_cond = EndOfPrdvPP_cond * self.u.derinv(
                self.EndOfPrdvP_cond, order=(1, 1)
            )  # "decurved" marginal marginal value

        # Construct the end-of-period marginal value function conditional on the next state.
        if self.CubicBool:
            EndOfPrdvPnvrsFunc_cond = CubicInterp(
                self.aNrm_cond,
                EndOfPrdvPnvrs_cond,
                EndOfPrdvPnvrsP_cond,
                lower_extrap=True,
            )
        else:
            EndOfPrdvPnvrsFunc_cond = LinearInterp(
                self.aNrm_cond, EndOfPrdvPnvrs_cond, lower_extrap=True
            )
        EndofPrdvPfunc_cond = MargValueFuncCRRA(
            EndOfPrdvPnvrsFunc_cond, self.CRRA
        )  # "recurve" the interpolated marginal value function
        return EndofPrdvPfunc_cond

    def calc_EndOfPrdvP(self):
        """
        Calculates end of period marginal value (and marginal marginal) value
        at each aXtra gridpoint for each current state, unconditional on the
        future Markov state (i.e. weighting conditional end-of-period marginal
        value by transition probabilities).

        Parameters
        ----------
        none

        Returns
        -------
        none
        """
        # Find unique values of minimum acceptable end-of-period assets (and the
        # current period states for which they apply).
        aNrmMin_unique, state_inverse = np.unique(
            self.BoroCnstNat_list, return_inverse=True
        )
        self.possible_transitions = self.MrkvArray > 0

        # Calculate end-of-period marginal value (and marg marg value) at each
        # asset gridpoint for each current period state
        EndOfPrdvP = np.zeros((self.StateCount, self.aXtraGrid.size))
        EndOfPrdvPP = np.zeros((self.StateCount, self.aXtraGrid.size))
        for k in range(aNrmMin_unique.size):
            aNrmMin = aNrmMin_unique[k]  # minimum assets for this pass
            which_states = (
                state_inverse == k
            )  # the states for which this minimum applies
            aGrid = aNrmMin + self.aXtraGrid  # assets grid for this pass
            EndOfPrdvP_all = np.zeros((self.StateCount, self.aXtraGrid.size))
            EndOfPrdvPP_all = np.zeros((self.StateCount, self.aXtraGrid.size))
            for j in range(self.StateCount):
                if np.any(
                    np.logical_and(self.possible_transitions[:, j], which_states)
                ):  # only consider a future state if one of the relevant states could transition to it
                    EndOfPrdvP_all[j, :] = self.EndOfPrdvPfunc_list[j](aGrid)
                    if (
                        self.CubicBool
                    ):  # Add conditional end-of-period (marginal) marginal value to the arrays
                        EndOfPrdvPP_all[j, :] = self.EndOfPrdvPfunc_list[j].derivativeX(
                            aGrid
                        )
            # Weight conditional marginal (marginal) values by transition probs
            # to get unconditional marginal (marginal) value at each gridpoint.
            EndOfPrdvP_temp = np.dot(self.MrkvArray, EndOfPrdvP_all)
            EndOfPrdvP[which_states, :] = EndOfPrdvP_temp[
                which_states, :
            ]  # only take the states for which this asset minimum applies
            if self.CubicBool:
                EndOfPrdvPP_temp = np.dot(self.MrkvArray, EndOfPrdvPP_all)
                EndOfPrdvPP[which_states, :] = EndOfPrdvPP_temp[which_states, :]

        # Store the results as attributes of self, scaling end of period marginal value by survival probability from each current state
        LivPrb_tiled = np.tile(
            np.reshape(self.LivPrb, (self.StateCount, 1)), (1, self.aXtraGrid.size)
        )
        self.EndOfPrdvP = LivPrb_tiled * EndOfPrdvP
        if self.CubicBool:
            self.EndOfPrdvPP = LivPrb_tiled * EndOfPrdvPP

    def calc_HumWealth_and_BoundingMPCs(self):
        """
        Calculates human wealth and the maximum and minimum MPC for each current
        period state, then stores them as attributes of self for use by other methods.

        Parameters
        ----------
        none

        Returns
        -------
        none
        """
        # Upper bound on MPC at lower m-bound
        WorstIncPrb_array = self.BoroCnstDependency * np.tile(
            np.reshape(self.WorstIncPrbAll, (1, self.StateCount)), (self.StateCount, 1)
        )
        temp_array = self.MrkvArray * WorstIncPrb_array
        WorstIncPrbNow = np.sum(
            temp_array, axis=1
        )  # Probability of getting the "worst" income shock and transition from each current state
        ExMPCmaxNext = (
            np.dot(
                temp_array,
                self.Rfree_list ** (1.0 - self.CRRA)
                * self.solution_next.MPCmax ** (-self.CRRA),
            )
            / WorstIncPrbNow
        ) ** (-1.0 / self.CRRA)
        DiscFacEff_temp = self.DiscFac * self.LivPrb
        self.MPCmaxNow = 1.0 / (
            1.0
            + ((DiscFacEff_temp * WorstIncPrbNow) ** (1.0 / self.CRRA)) / ExMPCmaxNext
        )
        self.MPCmaxEff = self.MPCmaxNow
        self.MPCmaxEff[self.BoroCnstNat_list < self.mNrmMin_list] = 1.0
        # State-conditional PDV of human wealth
        hNrmPlusIncNext = self.Ex_IncNextAll + self.solution_next.hNrm
        self.hNrmNow = np.dot(
            self.MrkvArray, (self.PermGroFac_list / self.Rfree_list) * hNrmPlusIncNext
        )
        # Lower bound on MPC as m gets arbitrarily large
        temp = (
            DiscFacEff_temp
            * np.dot(
                self.MrkvArray,
                self.solution_next.MPCmin ** (-self.CRRA)
                * self.Rfree_list ** (1.0 - self.CRRA),
            )
        ) ** (1.0 / self.CRRA)
        self.MPCminNow = 1.0 / (1.0 + temp)

    def make_solution(self, cNrm, mNrm):
        """
        Construct an object representing the solution to this period's problem.

        Parameters
        ----------
        cNrm : np.array
            Array of normalized consumption values for interpolation.  Each row
            corresponds to a Markov state for this period.
        mNrm : np.array
            Array of normalized market resource values for interpolation.  Each
            row corresponds to a Markov state for this period.

        Returns
        -------
        solution : ConsumerSolution
            The solution to the single period consumption-saving problem. Includes
            a consumption function cFunc (using cubic or linear splines), a marg-
            inal value function vPfunc, a minimum acceptable level of normalized
            market resources mNrmMin, normalized human wealth hNrm, and bounding
            MPCs MPCmin and MPCmax.  It might also have a value function vFunc
            and marginal marginal value function vPPfunc.  All of these attributes
            are lists or arrays, with elements corresponding to the current
            Markov state.  E.g. solution.cFunc[0] is the consumption function
            when in the i=0 Markov state this period.
        """
        solution = (
            ConsumerSolution()
        )  # An empty solution to which we'll add state-conditional solutions
        # Calculate the MPC at each market resource gridpoint in each state (if desired)
        if self.CubicBool:
            dcda = self.EndOfPrdvPP / self.u.der(np.array(self.cNrmNow), order=2)
            MPC = dcda / (dcda + 1.0)
            self.MPC_temp = np.hstack(
                (np.reshape(self.MPCmaxNow, (self.StateCount, 1)), MPC)
            )
            interpfunc = self.make_cubic_cFunc
        else:
            interpfunc = self.make_linear_cFunc

        # Loop through each current period state and add its solution to the overall solution
        for i in range(self.StateCount):
            # Set current-period-conditional human wealth and MPC bounds
            self.hNrmNow_j = self.hNrmNow[i]
            self.MPCminNow_j = self.MPCminNow[i]
            if self.CubicBool:
                self.MPC_temp_j = self.MPC_temp[i, :]

            # Construct the consumption function by combining the constrained and unconstrained portions
            self.cFuncNowCnst = LinearInterp(
                [self.mNrmMin_list[i], self.mNrmMin_list[i] + 1.0], [0.0, 1.0]
            )
            cFuncNowUnc = interpfunc(mNrm[i, :], cNrm[i, :])
            cFuncNow = LowerEnvelope(cFuncNowUnc, self.cFuncNowCnst)

            # Make the marginal value function and pack up the current-state-conditional solution
            vPfuncNow = MargValueFuncCRRA(cFuncNow, self.CRRA)
            solution_cond = ConsumerSolution(
                cFunc=cFuncNow, vPfunc=vPfuncNow, mNrmMin=self.mNrmMinNow
            )
            if (
                self.CubicBool
            ):  # Add the state-conditional marginal marginal value function (if desired)
                solution_cond = self.add_vPPfunc(solution_cond)

            # Add the current-state-conditional solution to the overall period solution
            solution.append_solution(solution_cond)

        # Add the lower bounds of market resources, MPC limits, human resources,
        # and the value functions to the overall solution
        solution.mNrmMin = self.mNrmMin_list
        solution = self.add_MPC_and_human_wealth(solution)
        if self.vFuncBool:
            vFuncNow = self.make_vFunc(solution)
            solution.vFunc = vFuncNow

        # Return the overall solution to this period
        return solution

    def make_linear_cFunc(self, mNrm, cNrm):
        """
        Make a linear interpolation to represent the (unconstrained) consumption
        function conditional on the current period state.

        Parameters
        ----------
        mNrm : np.array
            Array of normalized market resource values for interpolation.
        cNrm : np.array
            Array of normalized consumption values for interpolation.

        Returns
        -------
        cFuncUnc: an instance of HARK.interpolation.LinearInterp
        """
        cFuncUnc = LinearInterp(
            mNrm, cNrm, self.MPCminNow_j * self.hNrmNow_j, self.MPCminNow_j
        )
        return cFuncUnc

    def make_cubic_cFunc(self, mNrm, cNrm):
        """
        Make a cubic interpolation to represent the (unconstrained) consumption
        function conditional on the current period state.

        Parameters
        ----------
        mNrm : np.array
            Array of normalized market resource values for interpolation.
        cNrm : np.array
            Array of normalized consumption values for interpolation.

        Returns
        -------
        cFuncUnc: an instance of HARK.interpolation.CubicInterp
        """
        cFuncUnc = CubicInterp(
            mNrm,
            cNrm,
            self.MPC_temp_j,
            self.MPCminNow_j * self.hNrmNow_j,
            self.MPCminNow_j,
        )
        return cFuncUnc

    def make_vFunc(self, solution):
        """
        Construct the value function for each current state.

        Parameters
        ----------
        solution : ConsumerSolution
            The solution to the single period consumption-saving problem. Must
            have a consumption function cFunc (using cubic or linear splines) as
            a list with elements corresponding to the current Markov state.  E.g.
            solution.cFunc[0] is the consumption function when in the i=0 Markov
            state this period.

        Returns
        -------
        vFuncNow : [ValueFuncCRRA]
            A list of value functions (defined over normalized market resources
            m) for each current period Markov state.
        """
        vFuncNow = []  # Initialize an empty list of value functions
        # Loop over each current period state and construct the value function
        for i in range(self.StateCount):
            # Make state-conditional grids of market resources and consumption
            mNrmMin = self.mNrmMin_list[i]
            mGrid = mNrmMin + self.aXtraGrid
            cGrid = solution.cFunc[i](mGrid)
            aGrid = mGrid - cGrid

            # Calculate end-of-period value at each gridpoint
            EndOfPrdv_all = np.zeros((self.StateCount, self.aXtraGrid.size))
            for j in range(self.StateCount):
                if self.possible_transitions[i, j]:
                    EndOfPrdv_all[j, :] = self.EndOfPrdvFunc_list[j](aGrid)
            EndOfPrdv = np.dot(self.MrkvArray[i, :], EndOfPrdv_all)

            # Calculate (normalized) value and marginal value at each gridpoint
            vNrmNow = self.u(cGrid) + EndOfPrdv
            vPnow = self.u.der(cGrid)

            # Make a "decurved" value function with the inverse utility function
            # value transformed through inverse utility
            vNvrs = self.u.inv(vNrmNow)
            vNvrsP = vPnow * self.u.derinv(vNrmNow, order=(0, 1))
            mNrm_temp = np.insert(mGrid, 0, mNrmMin)  # add the lower bound
            vNvrs = np.insert(vNvrs, 0, 0.0)
            vNvrsP = np.insert(
                vNvrsP, 0, self.MPCmaxEff[i] ** (-self.CRRA / (1.0 - self.CRRA))
            )
            MPCminNvrs = self.MPCminNow[i] ** (-self.CRRA / (1.0 - self.CRRA))
            vNvrsFunc_i = CubicInterp(
                mNrm_temp, vNvrs, vNvrsP, MPCminNvrs * self.hNrmNow[i], MPCminNvrs
            )

            # "Recurve" the decurved value function and add it to the list
            vFunc_i = ValueFuncCRRA(vNvrsFunc_i, self.CRRA)
            vFuncNow.append(vFunc_i)
        return vFuncNow

def _solve_ConsMarkov(
    solution_next,
    IncShkDstn,
    LivPrb,
    DiscFac,
    CRRA,
    Rfree,
    PermGroFac,
    MrkvArray,
    BoroCnstArt,
    aXtraGrid,
    vFuncBool,
    CubicBool,
):
    """
    Solves a single period consumption-saving problem with risky income and
    stochastic transitions between discrete states, in a Markov fashion.  Has
    identical inputs as solveConsIndShock, except for a discrete
    Markov transitionrule MrkvArray.  Markov states can differ in their interest
    factor, permanent growth factor, and income distribution, so the inputs Rfree,
    PermGroFac, and IncShkDstn are arrays or lists specifying those values in each
    (succeeding) Markov state.

    Parameters
    ----------
    solution_next : ConsumerSolution
        The solution to next period's one period problem.
    IncShkDstn_list : [distribution.Distribution]
        A length N list of income distributions in each succeeding Markov
        state.  Each income distribution is
        a discrete approximation to the income process at the
        beginning of the succeeding period.
    LivPrb : float
        Survival probability; likelihood of being alive at the beginning of
        the succeeding period.
    DiscFac : float
        Intertemporal discount factor for future utility.
    CRRA : float
        Coefficient of relative risk aversion.
    Rfree_list : np.array
        Risk free interest factor on end-of-period assets for each Markov
        state in the succeeding period.
    PermGroGac_list : float
        Expected permanent income growth factor at the end of this period
        for each Markov state in the succeeding period.
    MrkvArray : numpy.array
        An NxN array representing a Markov transition matrix between discrete
        states.  The i,j-th element of MrkvArray is the probability of
        moving from state i in period t to state j in period t+1.
    BoroCnstArt: float or None
        Borrowing constraint for the minimum allowable assets to end the
        period with.  If it is less than the natural borrowing constraint,
        then it is irrelevant; BoroCnstArt=None indicates no artificial bor-
        rowing constraint.
    aXtraGrid: np.array
        Array of "extra" end-of-period asset values-- assets above the
        absolute minimum acceptable level.
    vFuncBool: boolean
        An indicator for whether the value function should be computed and
        included in the reported solution.
    CubicBool: boolean
        An indicator for whether the solver should use cubic or linear inter-
        polation.

    Returns
    -------
    solution : ConsumerSolution
        The solution to the single period consumption-saving problem. Includes
        a consumption function cFunc (using cubic or linear splines), a marg-
        inal value function vPfunc, a minimum acceptable level of normalized
        market resources mNrmMin, normalized human wealth hNrm, and bounding
        MPCs MPCmin and MPCmax.  It might also have a value function vFunc
        and marginal marginal value function vPPfunc.  All of these attributes
        are lists or arrays, with elements corresponding to the current
        Markov state.  E.g. solution.cFunc[0] is the consumption function
        when in the i=0 Markov state this period.
    """
    solver = ConsMarkovSolver(
        solution_next,
        IncShkDstn,
        LivPrb,
        DiscFac,
        CRRA,
        Rfree,
        PermGroFac,
        MrkvArray,
        BoroCnstArt,
        aXtraGrid,
        vFuncBool,
        CubicBool,
    )
    solution_now = solver.solve()
    return solution_now

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

class MarkovConsumerType(IndShockConsumerType):
    """
    An agent in the Markov consumption-saving model.  His problem is defined by a sequence
    of income distributions, survival probabilities, discount factors, and permanent
    income growth rates, as well as time invariant values for risk aversion, the
    interest rate, the grid of end-of-period assets, and how he is borrowing constrained.
    """

    time_vary_ = IndShockConsumerType.time_vary_ + ["MrkvArray"]

    # Is "Mrkv" a shock or a state?
    shock_vars_ = IndShockConsumerType.shock_vars_ + ["Mrkv"]
    state_vars = IndShockConsumerType.state_vars + ["Mrkv"]

    def __init__(self, **kwds):
        IndShockConsumerType.__init__(self, **kwds)
        self.solve_one_period = _solve_ConsMarkov

        if not hasattr(self, "global_markov"):
            self.global_markov = False

    def check_markov_inputs(self):
        """
        Many parameters used by MarkovConsumerType are arrays.  Make sure those arrays are the
        right shape.

        Parameters
        ----------
        None

        Returns
        -------
        None
        """
        StateCount = self.MrkvArray[0].shape[0]

        # Check that arrays are the right shape
        if not isinstance(self.Rfree, np.ndarray) or self.Rfree.shape != (StateCount,):
            raise ValueError(
                "Rfree not the right shape, it should an array of Rfree of all the states."
            )

        # Check that arrays in lists are the right shape
        for MrkvArray_t in self.MrkvArray:
            if not isinstance(MrkvArray_t, np.ndarray) or MrkvArray_t.shape != (
                StateCount,
                StateCount,
            ):
                raise ValueError(
                    "MrkvArray not the right shape, it should be of the size states*statres."
                )
        for LivPrb_t in self.LivPrb:
            if not isinstance(LivPrb_t, np.ndarray) or LivPrb_t.shape != (StateCount,):
                raise ValueError(
                    "Array in LivPrb is not the right shape, it should be an array of length equal to number of states"
                )
        for PermGroFac_t in self.PermGroFac:
            if not isinstance(PermGroFac_t, np.ndarray) or PermGroFac_t.shape != (
                StateCount,
            ):
                raise ValueError(
                    "Array in PermGroFac is not the right shape, it should be an array of length equal to number of states"
                )

        # Now check the income distribution.
        # Note IncShkDstn is (potentially) time-varying, so it is in time_vary.
        # Therefore it is a list, and each element of that list responds to the income distribution
        # at a particular point in time.  Each income distribution at a point in time should itself
        # be a list, with each element corresponding to the income distribution
        # conditional on a particular Markov state.
        # TODO: should this be a numpy array too?
        for IncShkDstn_t in self.IncShkDstn:
            if not isinstance(IncShkDstn_t, list):
                raise ValueError(
                    "self.IncShkDstn is time varying and so must be a list"
                    + "of lists of Distributions, one per Markov State. Found "
                    + f"{self.IncShkDstn} instead"
                )
            elif len(IncShkDstn_t) != StateCount:
                raise ValueError(
                    "List in IncShkDstn is not the right length, it should be length equal to number of states"
                )

    def pre_solve(self):
        """
        Check to make sure that the inputs that are specific to MarkovConsumerType
        are of the right shape (if arrays) or length (if lists).

        Parameters
        ----------
        None

        Returns
        -------
        None
        """
        AgentType.pre_solve(self)
        self.check_markov_inputs()

    def update_solution_terminal(self):
        """
        Update the terminal period solution.  This method should be run when a
        new AgentType is created or when CRRA changes.

        Parameters
        ----------
        none

        Returns
        -------
        none
        """
        IndShockConsumerType.update_solution_terminal(self)

        # Make replicated terminal period solution: consume all resources, no human wealth, minimum m is 0
        StateCount = self.MrkvArray[0].shape[0]
        self.solution_terminal.cFunc = StateCount * [self.cFunc_terminal_]
        self.solution_terminal.vFunc = StateCount * [self.solution_terminal.vFunc]
        self.solution_terminal.vPfunc = StateCount * [self.solution_terminal.vPfunc]
        self.solution_terminal.vPPfunc = StateCount * [self.solution_terminal.vPPfunc]
        self.solution_terminal.mNrmMin = np.zeros(StateCount)
        self.solution_terminal.hRto = np.zeros(StateCount)
        self.solution_terminal.MPCmax = np.ones(StateCount)
        self.solution_terminal.MPCmin = np.ones(StateCount)

    def initialize_sim(self):
        self.shocks["Mrkv"] = np.zeros(self.AgentCount, dtype=int)
        IndShockConsumerType.initialize_sim(self)
        if (
            self.global_markov
        ):  # Need to initialize markov state to be the same for all agents
            base_draw = Uniform(seed=self.RNG.integers(0, 2**31 - 1)).draw(1)
            Cutoffs = np.cumsum(np.array(self.MrkvPrbsInit))
            self.shocks["Mrkv"] = np.ones(self.AgentCount) * np.searchsorted(
                Cutoffs, base_draw
            ).astype(int)
        self.shocks["Mrkv"] = self.shocks["Mrkv"].astype(int)

    def reset_rng(self):
        """
        Extended method that ensures random shocks are drawn from the same sequence
        on each simulation, which is important for structural estimation.  This
        method is called automatically by initialize_sim().

        Parameters
        ----------
        None

        Returns
        -------
        None
        """
        PerfForesightConsumerType.reset_rng(self)

        # Reset IncShkDstn if it exists (it might not because reset_rng is called at init)
        if hasattr(self, "IncShkDstn"):
            T = len(self.IncShkDstn)
            for t in range(T):
                for dstn in self.IncShkDstn[t]:
                    dstn.reset()

    def sim_death(self):
        """
        Determines which agents die this period and must be replaced.  Uses the sequence in LivPrb
        to determine survival probabilities for each agent.

        Parameters
        ----------
        None

        Returns
        -------
        which_agents : np.array(bool)
            Boolean array of size AgentCount indicating which agents die.
        """
        # Determine who dies
        LivPrb = np.array(self.LivPrb)[
            self.t_cycle - 1, self.shocks["Mrkv"]
        ]  # Time has already advanced, so look back one
        DiePrb = 1.0 - LivPrb
        DeathShks = Uniform(seed=self.RNG.integers(0, 2**31 - 1)).draw(
            N=self.AgentCount
        )
        which_agents = DeathShks < DiePrb
        if self.T_age is not None:  # Kill agents that have lived for too many periods
            too_old = self.t_age >= self.T_age
            which_agents = np.logical_or(which_agents, too_old)
        return which_agents

    def sim_birth(self, which_agents):
        """
        Makes new Markov consumer by drawing initial normalized assets, permanent income levels, and
        discrete states. Calls IndShockConsumerType.sim_birth, then draws from initial Markov distribution.

        Parameters
        ----------
        which_agents : np.array(Bool)
            Boolean array of size self.AgentCount indicating which agents should be "born".

        Returns
        -------
        None
        """
        IndShockConsumerType.sim_birth(
            self, which_agents
        )  # Get initial assets and permanent income
        if (
            not self.global_markov
        ):  # Markov state is not changed if it is set at the global level
            N = np.sum(which_agents)
            base_draws = Uniform(seed=self.RNG.integers(0, 2**31 - 1)).draw(N)
            Cutoffs = np.cumsum(np.array(self.MrkvPrbsInit))
            self.shocks["Mrkv"][which_agents] = np.searchsorted(
                Cutoffs, base_draws
            ).astype(int)

    def get_markov_states(self):
        """
        Draw new Markov states for each agent in the simulated population, using
        the attribute MrkvArray to determine transition probabilities.

        Parameters
        ----------
        None

        Returns
        -------
        None
        """
        dont_change = (
            self.t_age == 0
        )  # Don't change Markov state for those who were just born (unless global_markov)
        if self.t_sim == 0:  # Respect initial distribution of Markov states
            dont_change[:] = True

        # Determine which agents are in which states right now
        J = self.MrkvArray[0].shape[0]
        MrkvPrev = self.shocks["Mrkv"]
        MrkvNow = np.zeros(self.AgentCount, dtype=int)

        # Draw new Markov states for each agent
        for t in range(self.T_cycle):
            markov_process = MarkovProcess(
                self.MrkvArray[t], seed=self.RNG.integers(0, 2**31 - 1)
            )
            right_age = self.t_cycle == t
            MrkvNow[right_age] = markov_process.draw(MrkvPrev[right_age])
        if not self.global_markov:
            MrkvNow[dont_change] = MrkvPrev[dont_change]

        self.shocks["Mrkv"] = MrkvNow.astype(int)

    def get_shocks(self):
        """
        Gets new Markov states and permanent and transitory income shocks for this period.  Samples
        from IncShkDstn for each period-state in the cycle.

        Parameters
        ----------
        None

        Returns
        -------
        None
        """
        self.get_markov_states()
        MrkvNow = self.shocks["Mrkv"]

        # Now get income shocks for each consumer, by cycle-time and discrete state
        PermShkNow = np.zeros(self.AgentCount)  # Initialize shock arrays
        TranShkNow = np.zeros(self.AgentCount)
        for t in range(self.T_cycle):
            for j in range(self.MrkvArray[t].shape[0]):
                these = np.logical_and(t == self.t_cycle, j == MrkvNow)
                N = np.sum(these)
                if N > 0:
                    IncShkDstnNow = self.IncShkDstn[t - 1][
                        j
                    ]  # set current income distribution
                    PermGroFacNow = self.PermGroFac[t - 1][
                        j
                    ]  # and permanent growth factor

                    # Get random draws of income shocks from the discrete distribution
                    EventDraws = IncShkDstnNow.draw_events(N)
                    PermShkNow[these] = (
                        IncShkDstnNow.atoms[0][EventDraws] * PermGroFacNow
                    )  # permanent "shock" includes expected growth
                    TranShkNow[these] = IncShkDstnNow.atoms[1][EventDraws]
        newborn = self.t_age == 0
        PermShkNow[newborn] = 1.0
        TranShkNow[newborn] = 1.0
        self.shocks["PermShk"] = PermShkNow
        self.shocks["TranShk"] = TranShkNow

    def read_shocks_from_history(self):
        """
        A slight modification of AgentType.read_shocks that makes sure that MrkvNow is int, not float.

        Parameters
        ----------
        None

        Returns
        -------
        None
        """
        IndShockConsumerType.read_shocks_from_history(self)
        self.shocks["Mrkv"] = self.shocks["Mrkv"].astype(int)

    def get_Rfree(self):
        """
        Returns an array of size self.AgentCount with interest factor that varies with discrete state.

        Parameters
        ----------
        None

        Returns
        -------
        RfreeNow : np.array
             Array of size self.AgentCount with risk free interest rate for each agent.
        """
        RfreeNow = self.Rfree[self.shocks["Mrkv"]]
        return RfreeNow

    def get_controls(self):
        """
        Calculates consumption for each consumer of this type using the consumption functions.

        Parameters
        ----------
        None

        Returns
        -------
        None
        """
        cNrmNow = np.zeros(self.AgentCount) + np.nan
        MPCnow = np.zeros(self.AgentCount) + np.nan
        J = self.MrkvArray[0].shape[0]

        MrkvBoolArray = np.zeros((J, self.AgentCount), dtype=bool)
        for j in range(J):
            MrkvBoolArray[j, :] = j == self.shocks["Mrkv"]

        for t in range(self.T_cycle):
            right_t = t == self.t_cycle
            for j in range(J):
                these = np.logical_and(right_t, MrkvBoolArray[j, :])
                cNrmNow[these], MPCnow[these] = (
                    self.solution[t]
                    .cFunc[j]
                    .eval_with_derivative(self.state_now["mNrm"][these])
                )
        self.controls["cNrm"] = cNrmNow
        self.MPCnow = MPCnow

    def calc_bounding_values(self):
        """
        Calculate human wealth plus minimum and maximum MPC in an infinite
        horizon model with only one period repeated indefinitely.  Store results
        as attributes of self.  Human wealth is the present discounted value of
        expected future income after receiving income this period, ignoring mort-
        ality.  The maximum MPC is the limit of the MPC as m --> mNrmMin.  The
        minimum MPC is the limit of the MPC as m --> infty.  Results are all
        np.array with elements corresponding to each Markov state.

        NOT YET IMPLEMENTED FOR THIS CLASS

        Parameters
        ----------
        None

        Returns
        -------
        None
        """
        raise NotImplementedError()

    def make_euler_error_func(self, mMax=100, approx_inc_dstn=True):
        """
        Creates a "normalized Euler error" function for this instance, mapping
        from market resources to "consumption error per dollar of consumption."
        Stores result in attribute eulerErrorFunc as an interpolated function.
        Has option to use approximate income distribution stored in self.IncShkDstn
        or to use a (temporary) very dense approximation.

        NOT YET IMPLEMENTED FOR THIS CLASS

        Parameters
        ----------
        mMax : float
            Maximum normalized market resources for the Euler error function.
        approx_inc_dstn : Boolean
            Indicator for whether to use the approximate discrete income distri-
            bution stored in self.IncShkDstn[0], or to use a very accurate
            discrete approximation instead.  When True, uses approximation in
            IncShkDstn; when False, makes and uses a very dense approximation.

        Returns
        -------
        None

        Notes
        -----
        This method is not used by any other code in the library. Rather, it is here
        for expository and benchmarking purposes.
        """
        raise NotImplementedError()


from decimal import Decimal

def main():
    max_n = 18

    # is_almost_integer = lambda num: True if f"{num:0.5f}"[-5] in ("9", "0") else False
    def is_almost_integer(anum):
        return True if f"{anum:0.5f}"[-5] in ("9", "0") else False

    rst = get_hickerson_series(max_n)
    for n in range(1, max_n + 1):
        expr = f"h({n}) = {rst[n]:0.3f} : is almost integer? {is_almost_integer(rst[n])}"
        print(expr)

def get_hickerson_series(max_n: int):
    factorials = [1]
    series = [None]
    for n in range(1, max_n + 1):
        factorials.append(factorials[-1] * n)
        eq = factorials[n] / (2 * Decimal(2).ln() ** (n + 1))
        series.append(eq)
    return series

if __name__ == "__main__":
    main()


from tkinter import*
from tkinter import messagebox
import tkinter as tk

import phonebook_gui
import phonebook_func

#Frame is the Tkinter frame class that our own class with inherit from
class ParentWindow(Frame):
    def __inti__(self, master, *args, **kwargs):
        Frame.__init__(self, master, *args, **kwargs)

        self.master = master
        self.master.minsize(500,300) #(height, width)
        self.master.maxsize(500,300)
        #This center windwo method will center our app on the users screen
        phonebook_func.center_window(self,500,300)
        self.master.title("The Tkinter Phonebook Demo")
        self.master.configure(bg="#F0f0f0")
        #This protocol methos is a tkinter built-in method to catch if
        #the user clicks the upper corner, "X" on windows OS
        self.master.protocol("WM_DELETE_WINDOW", lambda: phonebook_func.ask_quit(self))
        arg = self.master

        #load in the GUI widgets form a seperate module
        #keeping your code compartmetalized and cluster free
        phonebook_gui.load_gui(self)

if __name__=="__main__" :
    root = tk.Tk()
    App = ParentWindow(root)
    root.mainloop()


import tensorflow as tf

import config

class Architecture:

    def __init__(self):
        variables = config.Config().variables()
        self.image_dimension = variables['images']['image_dimension']

    def baseline(self):
        """
        Sets-up the baseline architecture

        :return:
        """

        # Base Model
        base = tf.keras.applications.VGG19(include_top=False, input_shape=self.image_dimension, weights='imagenet')
        base.trainable = False

        return base

    def layers(self, hyperparameters, labels, metrics=None):

        # Base
        base = self.baseline()

        # Flattening Object
        flatten = tf.keras.layers.Flatten()

        # The fully connected layers
        alpha_units = tf.keras.layers.Dense(hyperparameters['alpha_units'], activation='relu', name='Alpha')
        alpha_dropout = tf.keras.layers.Dropout(rate=hyperparameters['alpha_dropout'], name='AlphaDropout')
        beta_units = tf.keras.layers.Dense(hyperparameters['beta_units'], activation='relu', name='Beta')
        beta_dropout = tf.keras.layers.Dropout(hyperparameters['beta_dropout'], name='BetaDropout')

        # The classification layer
        classifier = tf.keras.layers.Dense(len(labels), activation=tf.nn.softmax)

        # Build
        model = tf.keras.models.Sequential([base, flatten, alpha_units, alpha_dropout,
                                            beta_units, beta_dropout, classifier])

        # Labels. Case
        # one-hot-code: categorical_crossentropy
        # integers: sparse_categorical_crossentropy
        if metrics is None:
            model.compile(optimizer=hyperparameters['optimization'],
                          loss=tf.keras.losses.categorical_crossentropy)
        else:
            model.compile(optimizer=hyperparameters['optimization'],
                          metrics=metrics,
                          loss=tf.keras.losses.categorical_crossentropy)

        print(base.summary())
        print(model.summary())

        return model


#!/usr/bin/env python
from setuptools import setup
import setuptools

try:
    with open('README.md') as file:
        long_description = file.read()
except Exception as e:
    print('Readme read failed')

setup(
    name='dynamic_unet',
    version='0.1.2',
    description='dynamic_unet',
    long_description='dynamic_unet: https://github.com/Flyfoxs/dynamic_unet',
    url='https://github.com/Flyfoxs/dynamic_unet',
    author='Felix Li',
    author_email='lilao@163.com',
    license='MIT',
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],

    install_requires=[
        "termcolor>=1.1",
        "Pillow==6.2.2",  # torchvision currently does not work with Pillow 7
        "yacs>=0.1.6",
        "tabulate",
        "easydict",
        "nibabel",
        "pydicom",
        "cloudpickle",
        "matplotlib",
        "tqdm>4.29.0",
        "tensorboard",
        "fvcore",
        "future",  # used by caffe2
        "pydot",  # used to save caffe2 SVGs
        "SimpleITK",
        "plotly",
    ],
    keywords='unet fastai',
    packages=setuptools.find_packages(),
)


def maxProfit(self, prices):
    if len(prices) == 1:
        return 0
    index = 1
    min_left = [0] * len(prices)
    min_left[0] = sys.maxsize
    min_value = prices[0]
    while index < len(prices):
        min_left[index] = min_value
        min_value = min(min_value, prices[index])
        index += 1
    ans = 0
    index = 0
    while index < len(prices):
        profit = prices[index] - min_left[index]
        ans = max(ans, profit)
        index += 1
    return ans


import pprint
from pymongo import MongoClient

# Only for testing
from dict_to_json import state

client = MongoClient()

client = MongoClient("localhost", 27017)

db = client["sih-demo"]

try:
    client.admin.command("ping")
    print("Connected to database")
except Exception as e:
    print(e)

def generate_state_from_scratch():
    state = {}
    for dept in db["departments"].find():
        state[dept] = {}
        for doctor in dept["doctors"]:
            state[dept][doctor] = {
                "waitlist": [],
                "length_of_waitlist": 0,
                "current": None,
                "presence": True,
            }

    return state

def generate_state_from_tokens():
    state = {}
    for token in db["tokens"].find():
        if token["departmentId"] not in state:
            state[token["departmentId"]] = {}
        if token["doctorId"] not in state[token["departmentId"]]:
            state[token["departmentId"]][token["doctorId"]] = {
                "waitlist": [],
                "length_of_waitlist": 0,
                "current": None,
                "presence": True,
            }
        state[token["departmentId"]][token["doctorId"]
                                     ]["waitlist"].append(token["_id"])
        state[token["departmentId"]][token["doctorId"]
                                     ]["length_of_waitlist"] += 1
        state[token["departmentId"]][token["doctorId"]]["current"] = state[token["departmentId"]][token["doctorId"]]["waitlist"][0] if len(
            state[token["departmentId"]][token["doctorId"]]["waitlist"]
        ) > 0 else None

    return state

def add_token_to_db(token):
    db["tokens"].insert_one(token)

def remove_token_from_db(tokenId):
    db["tokens"].delete_one({"_id": tokenId})

def get_from_state():
    return db["state"].find_one({})

def save_state(state):
    db["state"].delete_many({})
    db["state"].insert_one(state)

if __name__ == "__main__":
    pprint.pprint(generate_state_from_tokens())
    save_state(state)
    pprint.pprint(get_from_state())

    client.close()


# -*- coding: utf-8 -*-
# vim: noai:ts=4:sw=4:expandtab

import importlib.machinery
import importlib.util
import sys

from .exception import Error
from .trace_decorator import traceLog

current_api_version = '1.1'

class Plugins(object):
    @traceLog()
    def __init__(self, config, state):
        self.config = config
        self._hooks = {}
        self.state = state

        self.already_initialized = False

        self.plugins = config['plugins']
        self.plugin_conf = config['plugin_conf']
        self.plugin_dir = config['plugin_dir']

    def __repr__(self):
        return "<mockbuild.plugin.Plugins: state={0}, _hooks={1}, already_initialized={2}".format(
            self.state, self._hooks, self.already_initialized)

    @traceLog()
    def init_plugins(self, buildroot):
        if self.already_initialized:
            return
        self.already_initialized = True
        for key in list(self.plugin_conf.keys()):
            if key.endswith('_opts'):
                self.plugin_conf[key]['basedir'] = buildroot.basedir
                self.plugin_conf[key]['cache_topdir'] = buildroot.cache_topdir
                self.plugin_conf[key]['cachedir'] = buildroot.cachedir
                self.plugin_conf[key]['root'] = buildroot.shared_root_name
                self.plugin_conf[key]['resultdir'] = buildroot.resultdir

        self.state.start("init plugins")
        # Import plugins  (simplified copy of what yum does). Can add yum
        # features later when we prove we need them.
        for plugin in self.plugins:
            if self.plugin_conf.get("{0}_enable".format(plugin)):
                spec = importlib.machinery.PathFinder.find_spec(plugin, [self.plugin_dir])
                if not spec:
                    buildroot.root_log.warning(
                        "{0} plugin is enabled in configuration but is not installed".format(plugin))
                    continue
                module = importlib.util.module_from_spec(spec)
                spec.loader.exec_module(module)
                sys.modules[spec.name] = module

                if not hasattr(module, 'requires_api_version'):
                    raise Error('Plugin "%s" doesn\'t specify required API version' % plugin)
                requested_api_version = module.requires_api_version
                if requested_api_version != current_api_version:
                    raise Error('Plugin version mismatch - requested = %s, current = %s'
                                % (requested_api_version, current_api_version))

                run_in_bootstrap = getattr(module, "run_in_bootstrap", True)
                # simplified (buildroot.is_bootstrap and run_in_bootstrap) or not buildroot.is_bootstrap
                if not buildroot.is_bootstrap or run_in_bootstrap:
                    module.init(self, self.plugin_conf["{0}_opts".format(plugin)], buildroot)
        self.state.finish("init plugins")

    @traceLog()
    def call_hooks(self, stage, *args, **kwargs):
        required = kwargs.get('required', False)
        if 'required' in kwargs:
            del kwargs['required']
        hooks = self._hooks.get(stage, [])
        if required and not hooks:
            raise Error(
                "Feature {0} is not provided by any of enabled plugins".format(stage))
        for hook in hooks:
            hook(*args, **kwargs)

    @traceLog()
    def add_hook(self, stage, function):
        hooks = self._hooks.get(stage, [])
        if function not in hooks:
            hooks.append(function)
            self._hooks[stage] = hooks


from sys import set_coroutine_origin_tracking_depth
from tkinter import *
from turtle import width
from data import words

# main:
window = Tk()
window.title("Българо-Ромски речник")
# window.geometry("600x300")
#label:
text = Label (window,text="Напишете думата която искате да преведете :")
text.grid(row=0 ,column=0,sticky=W,pady=5 )

#entry text
en_text = Entry(window,width=42*2)
en_text.grid(row=1,column=0,sticky=W)

#prevod function
def click():
    entered_text=en_text.get() # colect the enter text
    prevod.delete(0.0, END) # delete the text
    try:
        definition = words[entered_text.title()]
    except:
        definition = "Съжеляваме не можем да преведем тази дума"
    prevod.insert(END, definition)

#button:
btn = Button(window, text="ПРЕВОД",width=36*2,border=0,command=click,)
btn.grid(row=2,column=0,sticky=W)

#text box
prevod = Text(window,wrap=WORD ,width=63,height=1)
prevod.grid(row=3,column=0,sticky=W)

window.mainloop()


"""
Build a new dataset with random jittered images
"""

import argparse, os
import numpy as np
from tqdm import tqdm
from PIL import Image
import re

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Word Image Similarity script for constructing transformed ground truth')

    parser.add_argument("--data", type=str, default="../gw_20p_wannot", metavar="I",
                        help="directory for the data")
    parser.add_argument("--out", type=str, default="../dataset", metavar="O")

    args = parser.parse_args()

def create_transformed_dataset(args):

    data_dir = args.data
    data_out = args.out

    # Get the names of the image files
    imageFnames = []

    with open(os.path.join(data_dir, "file_order.txt"), "r") as f:
        imageFnames = f.readlines()

    imageFnames = [f.strip() for f in imageFnames]

    # Get the names of the files containing the boxes coordinates
    boxFnames = [f[:-4] + "_boxes.txt" for f in imageFnames]

    words = []

    with open(os.path.join(data_dir, "annotations.txt"), "r", encoding = "iso-8859-1") as f:
        words = [w.strip() for w in f.readlines()]

    nb_transforms = [2 * words.count(w) for w in words]

    if not os.path.exists(data_out):
        os.makedirs(data_out)

    boxes = []
    i = 0
    j = -1
    k = 0

    image = None
    new_words = []

    pbar = tqdm(total=np.sum(nb_transforms), position = 0)

    while i < len(words):

        if k == len(boxes):
            boxes = []
            j += 1
            k = 0

        if boxes == []:
            if j >= len(boxFnames):
                print("ERROR: the end of box files was reached before the end of word list. j={}; i={}".format(j, i))
                break
            image = np.array(Image.open(os.path.join(data_dir, imageFnames[j])))
            with open(os.path.join(data_dir, boxFnames[j])) as f:
                boxes_str = f.readlines()
            coords = [[float(i) for i in re.findall(r"[+-]? *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?", s)] for s in boxes_str]
            boxes = [c[:4] for c in coords if len(c) >= 4]

        new_words.append(words[i])

        a, b = image.shape[0], image.shape[1]
        x1, x2, y1, y2 = int(b * boxes[k][0]), int(b * boxes[k][1]), int(a * boxes[k][2]), int(a * boxes[k][3])
        Sx, Sy = 5, 5

        x1prim = x1 - Sx
        y1prim = y1 - Sy
        x2prim = x2 + Sx
        y2prim = y2 + Sy

        res = image[y1prim:y2prim, x1prim:x2prim]

        im = Image.fromarray(res)
        im.save(os.path.join(data_out, "word-{:06d}.png".format(len(new_words))))
        pbar.update(1)

        k += 1
        i += 1

    with open(os.path.join(data_out, "words.txt"), "w") as f:
        for w in new_words:
            f.write(w + '\n')

if __name__ == "__main__":
    create_transformed_dataset(args)


# -*- coding: utf-8 -*-
"""
Created on Sun Jul 21 00:25:35 2019

@author: Doğan AY
"""
a=int(input("İlK sayıyı giriniz="))
b=int(input("İkinci sayıyı giriniz="))
(a//b)
(a**b)
(a%b)
a+=3
print(a)
a-=5
print(a)
#%%
a=1
b=2
c=5
a==b
a>b
a<b<c
a=b
b is a
x=None
y="senin"
z="seni"
z>y
z in y