text:
module TableManipulation
using  ...PatternStructure.Special
using  ...Destructuring.Applications
using  ...Matching.Function
using  ...Matching.Comparison
using  ...Analyzer.Function
using  ...Dispatch.Structure
import ...Destructuring.Applications: anonds
import ...Helper: clean_code
import Base.Meta: quot
export getmethod, newmethod!, removemethod!,
       prefermethod!, whichmethod, methodconflicts,
       set_conflict_warnings

const Iterable = Union{Tuple, Vector, Set}

WARN_CONFLICTS = :interactive

#----------------------------------------------------------------------------
# get methods from table
#----------------------------------------------------------------------------

function getmethod(table, pattern)
  for method in table.methods
      method.matcher(pattern) && return method
  end
  throw(MetaMethodError(table.name, clean_code(pattern)))
end

#----------------------------------------------------------------------------
# Insert methods in the table
#----------------------------------------------------------------------------

function newmethod!(table, pattern, body, mod, label=unlabeled)
  match  = matcher(pattern)
  method = eval(mod, anonds(Expr(:tuple, pattern), body))
  tree   = analyze(pattern)

  metamethod = MetaMethod(label, match, method, tree)
  addmethod!(table, metamethod)
  addlabel!(table, metamethod)
  nothing
end

function addmethod!(table, method)
  methods  = table.methods
  for i in eachindex(methods)
    if method.tree == methods[i].tree
       methods[i]  =  method
       return

    elseif  method.tree ⊆ methods[i].tree
       insert!(methods, i, method)
       @goto finish

    end
  end
  push!(methods, method)
  @label finish; warn_conflicts(table, method)
end

function addlabel!(table, method)
  method.label == unlabeled && return method

  if haskey(table.labels, method.label) && !(method.tree == table.labels[method.label].tree)
    error("$(table.name) has a different method with label :$(method.label)")
  end
  table.labels[method.label] = method
end

#----------------------------------------------------------------------------
# Remove methods from the table
#----------------------------------------------------------------------------

function removemethod!(table, pattern)
  tree    = analyze(pattern)
  methods = table.methods

  for i in eachindex(methods)
    if methods[i].tree == tree
      delete!(table.labels, methods[i].label)
      splice!(methods, i)
      return
    end
  end
  warn("Couldn't remove the method $(tree) from the $(table.name)")
end

function removemethod!(table, label::Symbol)
  if haskey(table.labels, label)
    method  = table.labels[label]
    methods = table.methods
    for i in eachindex(methods)
      if methods[i].tree == method.tree
        splice!(methods, i)
        delete!(table.labels, label)
        return
      end
    end
  end
  warn("Couldn't remove the method [$(label)] from the $(table.name)")
end

#----------------------------------------------------------------------------
# Manipulate preference of methods
#----------------------------------------------------------------------------

function prefermethod!(table, pattern1, pattern2)
  tree1  = analyze(pattern1)
  tree2  = analyze(pattern2)
  prefermethod_impl!(table, tree1, tree2)
end

function prefermethod!(table, label1::Symbol, label2::Symbol)
  haskey(table.labels, label1) || notfounderror(table, "label $label1")
  haskey(table.labels, label2) || notfounderror(table, "label $label2")

  tree1 = table.labels[label1].tree
  tree2 = table.labels[label2].tree
  prefermethod_impl!(table, tree1, tree2)
end

function prefermethod_impl!(table, tree1, tree2)
  if !(conflicts(tree1, tree2))
    warn("Using `prefer` with non-conflicting methods. ($(tree1) and $(tree2) in $(table.name))")
  end

  methods = table.methods
  i = findnext(met->met.tree == tree1, methods, 1)
  j = findnext(met->met.tree == tree2, methods, 1)
  if i != 0 && j != 0
    i < j && return table
    method = methods[i]
    splice!(methods, i)
    insert!(methods, j, method)
    table
  else
    sig = i == 0 ? tree1 : tree2
    notfounderror(table, "signature $(sig)")
  end
end

notfounderror(table, key) =
  throw(ArgumentError("No method with $(key) was found in $(table.name)."))

#----------------------------------------------------------------------------
# which
#----------------------------------------------------------------------------

function whichmethod(table, parameters)
  i = findnext(met->met.matcher(parameters), table.methods, 1)
  i == 0 ? nothing : table.methods[i]
end

#----------------------------------------------------------------------------
# conflicts
#----------------------------------------------------------------------------

function methodconflicts(table)
  result  = []
  methods = table.methods
  for i in eachindex(methods)
    for j in eachindex(methods)

      if i == j
        continue

      elseif methods[j].tree ⊆ methods[i].tree
        break

      elseif  conflicts(methods[i].tree, methods[j].tree) &&
             !((methods[j], methods[i]) in result)

        push!(result, (methods[i], methods[j]))
      end
    end
  end
  result
end

function methodconflicts_with(table, method)
  result  = []
  methods = table.methods
  for i in eachindex(methods)
    if method == methods[i]
      continue

    elseif methods[i].tree ⊆ method.tree
      break

    elseif conflicts(method.tree, methods[i].tree)
      push!(result, (method, methods[i]))

    end
  end
  result
end

function warn_conflicts(table, method)
  if WARN_CONFLICTS == :yes || WARN_CONFLICTS == :interactive && isinteractive()
    conflicts = methodconflicts_with(table, method)
    if !isempty(conflicts)
       warn("Method conflicts found:\n");
       print_conflicts(STDERR, conflicts)
    end
  end
end

function print_conflicts(io, conflicts)
  for c in conflicts
    print_with_color(:red,    io, "$(c[1])")
    print_with_color(:yellow, io, " | ")
    print_with_color(:red,    io, "$(c[2])")
    println(io)
    end
  println(io)
end

function set_conflict_warnings(opt::Symbol)
  if !(opt in [:yes, :interactive, :no])
    throw(ArgumentError("set_conflict_warnings must receive :yes, :no, or :interactive"))
  end
  global WARN_CONFLICTS = opt
  nothing
end

#----------------------------------------------------------------------------
# Utility functions
#----------------------------------------------------------------------------

end


text:
### A Pluto.jl notebook ###
# v0.17.7

using Markdown
using InteractiveUtils

# ╔═╡ 93737264-8d97-11ec-2d60-336b353c2e54
begin
    import Pkg
    Pkg.activate("..")

    import GMT

    using DelimitedFiles
    using STMMRunner
    using STMMRunner.MSTM.V3
end

# ╔═╡ 9e0a299f-9c69-4cb1-8de7-62116eb4e404
begin
    spheres = [
		Sphere(
			r = 0.7 + 0.5 * rand(),
			x = i,
			y = j,
			z = k,
			m = 1.5 + 1.0im * rand()
		) for i = -6.0:3.0:6.0 for j = -6.0:3.0:6.0 for k = -6.0:3.0:6.0
	]

	param = STMMConfig(
		number_processors = Sys.CPU_THREADS ÷ 2,
		sm_number_processors = Sys.CPU_THREADS ÷ 2,
		run_print_file = "",
		working_directory = "",
		orientation = FixedOrientation,
		α = 70.0,
		calculate_near_field = true,
		near_field_plane_position = 0.0,
		near_field_plane_vertices = (5.0, 5.0),
		near_field_plane_coord = 1,
		near_field_step_size = 0.1,
		spheres = spheres,
	)
end

# ╔═╡ 4f69842a-3658-4345-a6ce-8dcd0c20c564
results = run_mstm(param; keep = false)

# ╔═╡ a826a137-7c2c-4c70-9217-4797ca95b593
let
    nf = results.near_field.field
    y = nf.y |> Set |> collect |> sort
    z = nf.z |> Set |> collect |> sort
    sp = results.near_field.spheres

    grd = GMT.xyz2grd(
        [nf.y nf.z real.(nf.Ex)],
        region = (first(y), last(y), first(z), last(z)),
        inc = "$(y[2]-y[1])/$(z[2]-z[1])",
    )
    GMT.grdimage(grd; xaxis = "af+l@[y@[", yaxis = "af+l@[z@[")
    GMT.plot!([sp.y sp.z sp.r * 14 * 2 / (last(nf.y) - first(nf.y))]; symbol = "c")
    GMT.colorbar!(;
        xaxis = "af",
        yaxis = "+l@[\\mathbf{Re}E_x@[",
        nolines = true,
        show = true,
        savefig = "Ex_re.png",
    )
end

# ╔═╡ 048f7096-6da0-445d-b690-69224bc67276
let
    spheres = param.spheres
    x = map(s -> s.x, spheres)
    y = map(s -> s.y, spheres)
    z = map(s -> s.z, spheres)
    r = map(s -> s.r, spheres)
    GMT.plot3d(
        [x y z fill(-20, length(x)) r 2r];
        symbol = "e",
        show = true,
        savefig = "setting.png",
    )
end

# ╔═╡ Cell order:
# ╠═93737264-8d97-11ec-2d60-336b353c2e54
# ╠═9e0a299f-9c69-4cb1-8de7-62116eb4e404
# ╠═4f69842a-3658-4345-a6ce-8dcd0c20c564
# ╠═a826a137-7c2c-4c70-9217-4797ca95b593
# ╠═048f7096-6da0-445d-b690-69224bc67276

ext: jl


text:
using SIIPExamples

using PowerSystems
using PowerSimulations
const PSI = PowerSimulations
using PowerSystemCaseBuilder

using Dates
using DataFrames

using Cbc # solver
solver = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 1, "ratioGap" => 0.05)
odir = mktempdir() #tmpdir for build steps

c_sys5_hy_wk = build_system(SIIPExampleSystems, "5_bus_hydro_wk_sys")
c_sys5_hy_uc = build_system(SIIPExampleSystems, "5_bus_hydro_uc_sys")
c_sys5_hy_ed = build_system(SIIPExampleSystems, "5_bus_hydro_ed_sys")

PSI.JuMP._wrap_in_math_mode(str) = "\$\$ $(replace(str, "__"=>"")) \$\$"

print_tree(HydroGen)

print_tree(PSI.AbstractHydroFormulation)

template = OperationsProblemTemplate()
set_device_model!(template, HydroEnergyReservoir, HydroDispatchRunOfRiver)
set_device_model!(template, HydroDispatch, FixedOutput)
set_device_model!(template, PowerLoad, StaticPowerLoad)

op_problem = OperationsProblem(template, c_sys5_hy_uc, horizon = 2)
build!(op_problem, output_dir = odir)

op_problem.internal.optimization_container.JuMPmodel

template = OperationsProblemTemplate()
set_device_model!(template, HydroEnergyReservoir, HydroDispatchReservoirBudget)
set_device_model!(template, PowerLoad, StaticPowerLoad)

op_problem = PSI.OperationsProblem(template, c_sys5_hy_uc, horizon = 2)
build!(op_problem, output_dir = odir)

op_problem.internal.optimization_container.JuMPmodel

template = OperationsProblemTemplate()
set_device_model!(template, HydroEnergyReservoir, HydroDispatchReservoirStorage)
set_device_model!(template, PowerLoad, StaticPowerLoad)

op_problem = PSI.OperationsProblem(template, c_sys5_hy_uc, horizon = 24)
build!(op_problem, output_dir = odir)

op_problem.internal.optimization_container.JuMPmodel

template_md = OperationsProblemTemplate()
set_device_model!(template_md, ThermalStandard, ThermalDispatch)
set_device_model!(template_md, PowerLoad, StaticPowerLoad)
set_device_model!(template_md, HydroEnergyReservoir, HydroDispatchReservoirStorage)

template_da = OperationsProblemTemplate()
set_device_model!(template_da, ThermalStandard, ThermalDispatch)
set_device_model!(template_da, PowerLoad, StaticPowerLoad)
set_device_model!(template_da, HydroEnergyReservoir, HydroDispatchReservoirStorage)

problems = SimulationProblems(
    MD = OperationsProblem(
        template_md,
        c_sys5_hy_wk,
        optimizer = solver,
        system_to_file = false,
    ),
    DA = OperationsProblem(
        template_da,
        c_sys5_hy_uc,
        optimizer = solver,
        system_to_file = false,
    ),
)

sequence = SimulationSequence(
    problems = problems,
    feedforward_chronologies = Dict(("MD" => "DA") => Synchronize(periods = 2)),
    intervals = Dict("MD" => (Hour(48), Consecutive()), "DA" => (Hour(24), Consecutive())),
    feedforward = Dict(
        ("DA", :devices, :HydroEnergyReservoir) => IntegralLimitFF(
            variable_source_problem = PSI.ACTIVE_POWER,
            affected_variables = [PSI.ACTIVE_POWER],
        ),
    ),
    cache = Dict(("MD", "DA") => StoredEnergy(HydroEnergyReservoir, PSI.ENERGY)),
    ini_cond_chronology = IntraProblemChronology(),
);

sim = Simulation(
    name = "hydro",
    steps = 1,
    problems = problems,
    sequence = sequence,
    simulation_folder = odir,
)

build!(sim)

sim.problems["MD"].internal.optimization_container.JuMPmodel

sim.problems["DA"].internal.optimization_container.JuMPmodel

transform_single_time_series!(c_sys5_hy_wk, 2, Hour(24)) # TODO fix PSI to enable longer intervals of stage 1

problems = SimulationProblems(
    MD = OperationsProblem(
        template_md,
        c_sys5_hy_wk,
        optimizer = solver,
        system_to_file = false,
    ),
    DA = OperationsProblem(
        template_da,
        c_sys5_hy_uc,
        optimizer = solver,
        system_to_file = false,
    ),
    ED = OperationsProblem(
        template_da,
        c_sys5_hy_ed,
        optimizer = solver,
        system_to_file = false,
    ),
)

sequence = SimulationSequence(
    problems = problems,
    feedforward_chronologies = Dict(
        ("MD" => "DA") => Synchronize(periods = 2),
        ("DA" => "ED") => Synchronize(periods = 24),
    ),
    intervals = Dict(
        "MD" => (Hour(24), Consecutive()),
        "DA" => (Hour(24), Consecutive()),
        "ED" => (Hour(1), Consecutive()),
    ),
    feedforward = Dict(
        ("DA", :devices, :HydroEnergyReservoir) => IntegralLimitFF(
            variable_source_problem = PSI.ACTIVE_POWER,
            affected_variables = [PSI.ACTIVE_POWER],
        ),
        ("ED", :devices, :HydroEnergyReservoir) => IntegralLimitFF(
            variable_source_problem = PSI.ACTIVE_POWER,
            affected_variables = [PSI.ACTIVE_POWER],
        ),
    ),
    cache = Dict(("MD", "DA") => StoredEnergy(HydroEnergyReservoir, PSI.ENERGY)),
    ini_cond_chronology = IntraProblemChronology(),
);

sim = Simulation(
    name = "hydro",
    steps = 1,
    problems = problems,
    sequence = sequence,
    simulation_folder = odir,
)

build!(sim)

sim.problems["MD"].internal.optimization_container.JuMPmodel

sim.problems["DA"].internal.optimization_container.JuMPmodel

sim.problems["ED"].internal.optimization_container.JuMPmodel

# This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl


text:
using LazySets

S = Singleton([0.0, 0.0])
B1 = BallInf([0.0, 0.0], 1.0)
B2 = BallInf([1.0, 0.0], 0.5)
S_proj = project(S, [1])
B1_proj = project(B1, [1])
B2_proj = project(B2, [1])

P1 = is_contained_in(B1)
@test P1(S) && P1(B1) && !P1(B2)

P2 = contains(S)
@test P2(S) && P2(B1) && !P2(B2)

# dim is only available for SetAtom types
A1 = Atom(x -> x > 1)
@test_throws ArgumentError dim(A1)

# project is only available for SetAtom (and their Negation) types
@test_throws ArgumentError project(A1, [1])

@test project(Negation(P1), [1]) == Negation(project(P1, [1]))

@test dim(P1) == dim(P2) == 2
P1_proj = project(P1, [1])
P2_proj = project(P2, [1])
@test P1_proj isa SetAtom && dim(P1_proj) == 1 && P1_proj.X == B1_proj
@test P1_proj(S_proj) && P1_proj(B1_proj) && !P1_proj(B2_proj)
@test P2_proj isa SetAtom && dim(P2_proj) == 1 && P2_proj.X == S_proj
@test P2_proj(S_proj) && P2_proj(B1_proj) && !P2_proj(B2_proj)

Pc = Conjunction([P1, P2])
@test Pc(S) && Pc(B1) && !Pc(B2)

Pd = Disjunction([P1, P2])
@test Pd(S) && Pd(B1) && !Pd(B2)

@test project(Pc, [1]) == Conjunction([P1_proj, P2_proj])
@test project(Pd, [1]) == Disjunction([P1_proj, P2_proj])

P1 = is_disjoint_from(S)
P2 = intersects(S)
@test !P1(S) && !P1(B1) && P1(B2)
@test P2(S) && P2(B1) && !P2(B2)


text:
#
# Identity primitive.
#

ItQuery(dom::Domain) =
    Query(ItSig(), Input(dom), Output(dom))

ItQuery(dom) =
    ItQuery(convert(Domain, dom))

immutable ItSig <: AbstractPrimitive
end

describe(io::IO, ::ItSig) = print(io, "it")

ev(::ItSig, vals::AbstractVector) =
    Column(OneTo(length(vals)+1), vals)

max_stars_repo_name: rbt-lang/rbt-proto

max_issues_repo_name: rbt-lang/rbt-proto

max_forks_repo_name: rbt-lang/rbt-proto


text:
using ExprRules
using Test, Random

#=
TESTS NEED TO BE MORE THOROUGHLY DEFINED
=#

include("test_cfg.jl")
include("test_utils.jl")
include("test_constraints.jl")
include("test_operators.jl")


text:
mutable struct Cell
	position::Array{Float64}
	nodes::Set
	l::Int
	x::Int
	y::Int
end

Cell(p,l,x,y) = Cell(p,Set{Node}(),l,x,y)

mutable struct Canvas
	x::Int
	y::Int
	r::Float16
	cells::Vector{Vector{Cell}}
	num_cells::Int
end

Canvas(x,y,r) = Canvas(x,y,r,[],0)

function initialize(canvas::Canvas)
	l = round(Int,sqrt( (canvas.r^2) / 2))

	if canvas.x % l != 0 || canvas.y % l != 0
		return
	end

	x = l / 2;
	r = 1
	while x < canvas.x
		c = 1
		y = l / 2
		cells = Vector{Cell}([])
		while  y < canvas.y
			cell = Cell([x,y],l,r,c)
			push!(cells,cell)
			y += l
			c = c + 1
		end
		x += l
		r = r + 1
		push!(canvas.cells,cells)
	end
	canvas.num_cells = canvas.x / l + canvas.y / l
end

function generate_point(canvas::Canvas)
	while true
		p = [rand(1:canvas.x),rand(1:canvas.y)]
		if !is_occupied(canvas,p)
			return p
		end
	end
end

function is_occupied(canvas::Canvas,p)
	cell = get_cell(canvas,p)
	return length(filter(n -> n.position == p, cell.nodes)) != 0
end

function get_cell(canvas::Canvas,p)
	l = round(Int,sqrt( (canvas.r^2) / 2))
	i = ceil(Int,p[1] / l)
	j = ceil(Int,p[2] / l)
	return canvas.cells[i][j]
end

function get_cell_position(canvas::Canvas,p)
	l = round(Int,sqrt( (canvas.r^2) / 2))
	i = ceil(Int,p[1] / l)
	j = ceil(Int,p[2] / l)
	return [i,j]
end

function get_near_cells(canvas::Canvas,p)
	point = get_cell_position(canvas,p)

	max_x = length(canvas.cells)
	max_y =  length(canvas.cells[1])
	if point[1] > max_x || point[2] > max_y
		return
	end
	near_cells = []
	if point[1] > 1
		push!(near_cells,canvas.cells[point[1] - 1][point[2]])
		if point[2] > 1
			push!(near_cells,canvas.cells[point[1] - 1][point[2] - 1])
		end
		if point[2] < max_y
			push!(near_cells,canvas.cells[point[1] - 1][point[2] + 1])
		end
	end
	if point[1] < max_x
		push!(near_cells,canvas.cells[point[1] + 1][point[2]])
		if point[2] < max_y
			push!(near_cells,canvas.cells[point[1] + 1][point[2] + 1])
		end
	end
	if point[2] > 1
		push!(near_cells,canvas.cells[point[1]][point[2] - 1])
		if point[1] < max_x
			push!(near_cells,canvas.cells[point[1] + 1][point[2] - 1])
		end
	end
	if point[2] < max_y
		push!(near_cells,canvas.cells[point[1]][point[2] + 1])
	end

	return near_cells

end


text:
VERTEX=Int
EDGE=Array{VERTEX,1}
FACE=Array{EDGE,1}
CELL=Array{FACE,1}

function vertices(edge::EDGE)
    return edge
end
function vertices(face::FACE)
    f=copy(face)
    v=union(vcat(f...))
    w=[v[1]]
    for j ∈ 1:(length(v)-1)
        i=findfirst(e->w[end] ∈ e, f)
        push!(w,filter(v->v≠w[end],f[i])[1])
        deleteat!(f,i)
    end
    return w
end
function vertices(cell::CELL)
    return unique(vcat(vcat(cell...)...))
end
function edges(face::FACE)
    return face
end
function edges(cell::CELL)
    return unique(sort.(vcat(cell...)))
end
function faces(cell::CELL)
    return cell
end

import Base.∈
function ∈(vertex::VERTEX, face::FACE)
    return vertex ∈ vertices(face)
end
function ∈(vertex::VERTEX, cell::CELL)
    return vertex ∈ vertices(cell)
end
function ∈(edge::EDGE, cell::CELL)
    return edge ∈ edges(cell)
end

function DualRegularPlolyhedron(POINTS,c)
    fs=copy(c)
    es=edges(fs)
    vs=vertices(fs)
    POINTS_=normalize.([+(POINTS[vertices(f)]...) for f ∈ fs])
    vs_=collect(1:length(faces(fs)))
    es_=[findall(f->e ∈ f, fs) for e ∈ es]
    fs_=[es_[findall(e->issubset(e,findall(f->v ∈ f, c)),es_)] for v ∈ vs]
    return POINTS_, fs_
end

# F₄
𝒑₁=[1,1,1]
𝒑₂=[1,-1,-1]
𝒑₃=[-1,1,-1]
𝒑₄=[-1,-1,1]
POINTS=[𝒑₁,𝒑₂,𝒑₃,𝒑₄]
v₁=1
v₂=2
v₃=3
v₄=4
e₁=[v₁,v₂]
e₂=[v₁,v₃]
e₃=[v₁,v₄]
e₄=[v₂,v₃]
e₅=[v₂,v₄]
e₆=[v₃,v₄]

f₁=[e₄,e₅,e₆]
f₂=[e₂,e₃,e₆]
f₃=[e₁,e₃,e₅]
f₄=[e₁,e₂,e₄]
c₁=[f₁,f₂,f₃,f₄]
F₄=normalize.(POINTS), c₁

# F₆
𝒑₁=[1,1,1]
𝒑₂=[1,1,-1]
𝒑₃=[1,-1,1]
𝒑₄=[1,-1,-1]
𝒑₅=[-1,1,1]
𝒑₆=[-1,1,-1]
𝒑₇=[-1,-1,1]
𝒑₈=[-1,-1,-1]
POINTS=[𝒑₁,𝒑₂,𝒑₃,𝒑₄,𝒑₅,𝒑₆,𝒑₇,𝒑₈]
v₁=1
v₂=2
v₃=3
v₄=4
v₅=5
v₆=6
v₇=7
v₈=8
e₁=[v₁,v₂]
e₂=[v₁,v₃]
e₃=[v₁,v₅]
e₄=[v₂,v₄]
e₅=[v₂,v₆]
e₆=[v₃,v₄]
e₇=[v₃,v₇]
e₈=[v₄,v₈]
e₉=[v₅,v₆]
e₁₀=[v₅,v₇]
e₁₁=[v₆,v₈]
e₁₂=[v₇,v₈]
f₁=[e₁,e₂,e₄,e₆]
f₂=[e₁,e₃,e₅,e₉]
f₃=[e₂,e₃,e₇,e₁₀]
f₄=[e₄,e₅,e₈,e₁₁]
f₅=[e₆,e₇,e₈,e₁₂]
f₆=[e₉,e₁₀,e₁₁,e₁₂]
c₁=[f₁,f₂,f₃,f₄,f₅,f₆]
F₆=normalize.(POINTS), c₁

F₈=DualRegularPlolyhedron(F₆...)

# F₁₂
𝒑₁=[1,1,1]
𝒑₂=[1,1,-1]
𝒑₃=[1,-1,1]
𝒑₄=[1,-1,-1]
𝒑₅=[-1,1,1]
𝒑₆=[-1,1,-1]
𝒑₇=[-1,-1,1]
𝒑₈=[-1,-1,-1]
𝒑₉=[0,1/φ,φ]
𝒑₁₀=[0,1/φ,-φ]
𝒑₁₁=[0,-1/φ,φ]
𝒑₁₂=[0,-1/φ,-φ]
𝒑₁₃=[φ,0,1/φ]
𝒑₁₄=[φ,0,-1/φ]
𝒑₁₅=[-φ,0,1/φ]
𝒑₁₆=[-φ,0,-1/φ]
𝒑₁₇=[1/φ,φ,0]
𝒑₁₈=[1/φ,-φ,0]
𝒑₁₉=[-1/φ,φ,0]
𝒑₂₀=[-1/φ,-φ,0]
POINTS=[𝒑₁,𝒑₂,𝒑₃,𝒑₄,𝒑₅,𝒑₆,𝒑₇,𝒑₈,𝒑₉,𝒑₁₀,𝒑₁₁,𝒑₁₂,𝒑₁₃,𝒑₁₄,𝒑₁₅,𝒑₁₆,𝒑₁₇,𝒑₁₈,𝒑₁₉,𝒑₂₀]
v₁=1
v₂=2
v₃=3
v₄=4
v₅=5
v₆=6
v₇=7
v₈=8
v₉=9
v₁₀=10
v₁₁=11
v₁₂=12
v₁₃=13
v₁₄=14
v₁₅=15
v₁₆=16
v₁₇=17
v₁₈=18
v₁₉=19
v₂₀=20
e₁=[v₁,v₉]
e₂=[v₅,v₉]
e₃=[v₃,v₁₁]
e₄=[v₇,v₁₁]
e₅=[v₉,v₁₁]
e₆=[v₂,v₁₀]
e₇=[v₆,v₁₀]
e₈=[v₄,v₁₂]
e₉=[v₈,v₁₂]
e₁₀=[v₁₀,v₁₂]
e₁₁=[v₁,v₁₃]
e₁₂=[v₃,v₁₃]
e₁₃=[v₂,v₁₄]
e₁₄=[v₄,v₁₄]
e₁₅=[v₁₃,v₁₄]
e₁₆=[v₅,v₁₅]
e₁₇=[v₇,v₁₅]
e₁₈=[v₆,v₁₆]
e₁₉=[v₈,v₁₆]
e₂₀=[v₁₅,v₁₆]
e₂₁=[v₁,v₁₇]
e₂₂=[v₂,v₁₇]
e₂₃=[v₅,v₁₉]
e₂₄=[v₆,v₁₉]
e₂₅=[v₁₇,v₁₉]
e₂₆=[v₃,v₁₈]
e₂₇=[v₄,v₁₈]
e₂₈=[v₇,v₂₀]
e₂₉=[v₈,v₂₀]
e₃₀=[v₁₈,v₂₀]
f₁=[e₁,e₃,e₅,e₁₁,e₁₂]
f₂=[e₂,e₄,e₅,e₁₆,e₁₇]
f₃=[e₆,e₈,e₁₀,e₁₃,e₁₄]
f₄=[e₇,e₉,e₁₀,e₁₈,e₁₉]
f₅=[e₁₁,e₁₃,e₁₅,e₂₁,e₂₂]
f₆=[e₁₂,e₁₄,e₁₅,e₂₆,e₂₇]
f₇=[e₁₆,e₁₈,e₂₀,e₂₃,e₂₄]
f₈=[e₁₇,e₁₉,e₂₀,e₂₈,e₂₉]
f₉=[e₁,e₂,e₂₁,e₂₃,e₂₅]
f₁₀=[e₆,e₇,e₂₂,e₂₄,e₂₅]
f₁₁=[e₃,e₄,e₂₆,e₂₈,e₃₀]
f₁₂=[e₈,e₉,e₂₇,e₂₉,e₃₀]
c₁=[f₁,f₂,f₃,f₄,f₅,f₆,f₇,f₈,f₉,f₁₀,f₁₁,f₁₂]
F₁₂=normalize.(POINTS), c₁

F₂₀=DualRegularPlolyhedron(F₁₂...)

max_stars_repo_name: hyrodium/JuliRay

max_issues_repo_name: hyrodium/JuliRay

max_forks_repo_name: hyrodium/JuliRay


text:
#EasyPlotPlots Defaults control
#-------------------------------------------------------------------------------

#==Constants
===============================================================================#
const DEFAULT_BACKEND = :gr

#==Defaults
===============================================================================#
mutable struct Defaults
	backend::Symbol
end
Defaults() = Defaults(DEFAULT_BACKEND)

#==Data
===============================================================================#
const global defaults = Defaults()

#==Initialization
===============================================================================#
function _initialize(dflt::Defaults)
	dflttool = string(DEFAULT_BACKEND)
	envstr = "EASYPLOTPLOTS_BACKEND"
	val = get(ENV, envstr, dflttool)
	dflt.backend = Symbol(lowercase(val))
	return
end

#Last line


text:
function get_line!(r::Robot, side::HorizonSide)::Nothing
    steps = 0
    while (not(isborder(r,side)))
        move!(r,side)
        putmarker!(r)
        steps += 1
    end
    for i in steps
        move!(r,HorizonSide(((Int(side)+2)%4)))
    end
    steps = 0
end

function where_would_u_like_to_start(x::Integer,y::Integer)::Nothing
    for i in x
        move!(r, Ost)
    end
    for j in y
        move!(r,Nord)
    end
end

function master(r::Robot)::Nothing

    where_would_u_like_to_start(5,6)

    for side in HorizonSide
        get_line!(r,side)
    end
    putmarker!(r)
end

max_stars_repo_name: Igetsuga/AlgorithmicsHomework

max_issues_repo_name: Igetsuga/AlgorithmicsHomework

max_forks_repo_name: Igetsuga/AlgorithmicsHomework


text:
##########################################################################################
######################### Este archivo contiene la función que reúne  ####################
######################### todas las funciones vistas en los otros     ####################
######################### archivos y que ejecuta el juego             ####################
##########################################################################################

function Juego()

    J1 = Jugador(1)                                       # Creación del Jugador 1
    J2 = Jugador(2)                                       # Creación del Jugador 2

    juego = true                                          # Variable para saber si se quiere seguir jugando
    empate = true                                         # Variable para saber si hubo un empate

    while juego == true                                   # Mientras se quiera seguir jugando

        R = Init(empate)                                  # Arreglo con el orden de los jugadores

        Tablero = Gato()                                  # Se crea el tablero

        tiro = 0                                          # Variable para saber en que tiro vamos
        gane = false                                      # Variable para saber si alguien ha ganado

        while tiro < 9 && gane == false                   # Mientras nadie haya ganado y haya espacios vacíos

            gane = Turno(J1, Tablero, tiro, gane, R)      # Tiro del jugador 1
            tiro += 1
            pintar(Tablero)

            if tiro < 9 && gane == false
                gane = Turno(J2, Tablero, tiro, gane, R)  # Tiro del jugador 2
                tiro += 1
                pintar(Tablero)
            end

            if tiro == 9 && gane == false                 # Si llegamos al ultimo tiro y nadie ha ganado
                println("¡Empate! \n")

            end
        end

        empate == !juego

        m1 = J1.marcador; m2 = J2.marcador
        println("Marcador: \n Miau 1: $m1, Miau 2: $m2")  # Imprimimos el marcador

        juego = NuevoJuego()                              # Preguntamos si se quiere seguir jugando
    end
end


text:
@testset "768.max-chunks-to-make-sorted-ii.jl" begin
    @test max_chunks_to_sorted([5, 4, 3, 2, 1]) == 1
    @test max_chunks_to_sorted([2, 1, 3, 4, 4]) == 4
end


text:
############################################################################################
"""
$(SIGNATURES)
Callable struct to make initializing SMC sampler easier in sampling library.

# Examples
```julia
```

"""
struct SMCConstructor{J<:AbstractConstructor,D<:SMCDefault} <: AbstractConstructor
    "Jitter kernel"
    kernel::J
    "SMC Default Arguments"
    default::D
    function SMCConstructor(
        kernel::J, default::D
    ) where {J<:AbstractConstructor,D<:SMCDefault}
        return new{J,D}(kernel, default)
    end
end
function (constructor::SMCConstructor)(
    _rng::Random.AbstractRNG,
    model::ModelWrapper,
    data::D,
    temperature::F,
    info::BaytesCore.SampleDefault
) where {D, F<:AbstractFloat}
    return SMC(
        _rng,
        constructor.kernel,
        Objective(model, data, Tagged(model), temperature),
        constructor.default,
        info
    )
end
function SMC(
    kernel::J; kwargs...
) where {J<:AbstractConstructor}
    return SMCConstructor(kernel, SMCDefault(; kwargs...))
end

function get_sym(constructor::SMCConstructor)
    return get_sym(constructor.kernel)
end

############################################################################################
"""
$(SIGNATURES)
Print diagnostics result of SMC sampler.

# Examples
```julia
```

"""
function results(
    diagnosticsᵛ::AbstractVector{M}, smc::SMC, Ndigits::Int64, quantiles::Vector{T}
) where {T<:Real,M<:SMCDiagnostics}
    ## Print Trace
    println("SMC algorithm with jitter kernel ", Base.nameof(typeof(smc.particles.kernel[begin])), " Diagnostics:")
    println(
        "Sampler finished after ",
        size(diagnosticsᵛ, 1),
        " iterations with average acceptance ratio of ",
        round(
            Statistics.mean(
                !diagnosticsᵛ[iter].resampled for iter in eachindex(diagnosticsᵛ)
            ) * 100;
            digits=Ndigits,
        ),
        "%.",
    )
    println(
        "Initial average ℓlikelihood per particle: ",
        round(Statistics.mean(diagnosticsᵛ[begin].ℓweights); digits=Ndigits),
        ", variance: ",
        round(Statistics.var(diagnosticsᵛ[begin].ℓweights); digits=Ndigits),
    )
    println(
        "Final average ℓlikelihood per particle: ",
        round(Statistics.mean(diagnosticsᵛ[end].ℓweights); digits=Ndigits),
        ", variance: ",
        round(Statistics.var(diagnosticsᵛ[end].ℓweights); digits=Ndigits),
    )
    ## Number of jittering steps
    println("Total number of jittering steps: ",
        Statistics.sum(diagnosticsᵛ[iter].jittersteps for iter in eachindex(diagnosticsᵛ)),
        ".")
    ## Rejuvenation steps
    t = convert(Int64, floor(length(diagnosticsᵛ) / 2))
    if t > 1
        println(
            "Rejuvenations on average every ",
            round(
                (
                    1 / (
                        1 - Statistics.mean(
                            !diagnosticsᵛ[iter].resampled for iter in eachindex(diagnosticsᵛ)
                        )
                    )
                );
                digits=Ndigits,
            ),
            " step, every ",
            round(
                1 / (1 - Statistics.mean(!diagnosticsᵛ[iter].resampled for iter in 1:t));
                digits=Ndigits,
            ),
            " steps in first half, every ",
            round(
                1 / (
                    1 - Statistics.mean(
                        !diagnosticsᵛ[iter].resampled for iter in (t + 1):length(diagnosticsᵛ)
                    )
                );
                digits=Ndigits,
            ),
            " steps in second half.",
        )
    end
    ##Rejuvenation Correlation
    rejuvenations = [diagnosticsᵛ[iter].resampled for iter in eachindex(diagnosticsᵛ)]
    if sum(rejuvenations) > 0
        println(
            "Quantiles for average rejuvenation correlation of parameter: ",
            round.(
                Statistics.quantile(
                    Statistics.mean.(
                        #!NOTE: If pairs[i] are constant (i.e., all resampled initial parameter come from same index), ρ = NaN for index
                        #filter(!isnan, diagnosticsᵛ[rejuvenations][iter].ρ) for
                        diagnosticsᵛ[rejuvenations][iter].ρ for iter in Base.OneTo(sum(rejuvenations))
                    ),
                    quantiles,
                );
                digits=Ndigits,
            ),
            ".",
        )
        println(
            "Quantiles for average number rejuvenation steps: ",
            round.(
                Statistics.quantile(
                    Statistics.mean.(
                        diagnosticsᵛ[rejuvenations][iter].jittersteps for
                        iter in Base.OneTo(sum(rejuvenations))
                    ),
                    quantiles,
                );
                digits=Ndigits,
            ),
            ".",
        )
    end
    ## ESS quantiles
    println(
        "Quantiles for ESS: ",
        round.(
            Statistics.quantile(
                [diagnosticsᵛ[iter].ESS for iter in eachindex(diagnosticsᵛ)], quantiles
            );
            digits=Ndigits,
        ),
        " for ",
        smc.tune.chains.Nchains,
        " chains.",
    )
    ## Return
    return nothing
end

############################################################################################
"""
$(SIGNATURES)
Infer MCMC diagnostics type.

# Examples
```julia
```

"""
function infer(
    _rng::Random.AbstractRNG,
    diagnostics::Type{AbstractDiagnostics},
    smc::SMC,
    model::ModelWrapper,
    data::D,
) where {D}
    #Pick one of the kernels to obtain type for prediction and jittering diagnostics.
    TPrediction = BaytesCore.infer(_rng, smc.particles.kernel[begin], model, data)
    TJitter = BaytesCore.infer(_rng, AbstractDiagnostics, smc.particles.kernel[begin], model, data)
    TTemperature = model.info.reconstruct.default.output
    TGenerated = infer_generated(_rng, smc, model, data)
    return SMCDiagnostics{TPrediction,TJitter,TTemperature,TGenerated}
end

############################################################################################
"""
$(SIGNATURES)
Infer type of generated quantities of PF sampler.

# Examples
```julia
```

"""
function infer_generated(
    _rng::Random.AbstractRNG, smc::SMC, model::ModelWrapper, data::D
) where {D}
    objective = Objective(model, data, smc.tune.tagged)
    return typeof(generate(_rng, objective, smc.tune.generated))
end

############################################################################################
#export
export SMCConstructor, infer