Pixel Arrays
using AlgebraicInference
using Catlab
using UnicodePlots
using Catlab.CategoricalAlgebra.FinRelations: BoolRig
A pixel array is an array with entries in the boolean semiring. The function defined below constructs a pixel array by discretizing a relation of the form
\[xRy \iff f(x, y) = 0.\]
References:
- Spivak, David I. et al. "Pixel Arrays: A fast and elementary method for solving nonlinear systems." arXiv: Numerical Analysis (2016): n. pag.
const PixelArray{N} = Array{BoolRig, N}
function PixelArray(f::Function, xdim::NamedTuple, ydim::NamedTuple, tol::Real)
rows = xdim.resolution
cols = ydim.resolution
result = PixelArray{2}(undef, rows, cols)
xstep = (xdim.upper - xdim.lower) / xdim.resolution
ystep = (ydim.upper - ydim.lower) / ydim.resolution
for i in 1:rows, j in 1:cols
xval = xdim.lower + (i - 0.5) * xstep
yval = ydim.lower + (j - 0.5) * ystep
try
result[i, j] = -tol < f(xval, yval) < tol
catch
result[i, j] = false
end
end
result
end;
For plotting:
function Base.isless(x::Int, y::BoolRig)
x < y.value
end;
Example 2.4.1 in Spivak et al.
\[\begin{align*} & \text{Solve relations:} && \cos(\ln(z^2 + 10^{-3}x)) - x + 10^{-5}z^{-1} = 0 && \text{(Equation 1)} \\ & && \cosh(w + 10^{-3}y) + y + 10^{-4}w = 2 && \text{(Equation 2)} \\ & && \tan(x + y)(x - 2)^{-1}(x + 3)^{-1}y^{-2} = 1 && \text{(Equation 3)} \\ & \text{Range and resolution:} && w, x, y, z \in [-3, 3)@125 && \\ & \text{Expose variables:} && (w, z) && \\ & \end{align*}\]
function f₁(x::Real, z::Real)
0 - (cos(log(z^2 + x / 10^3)) − x + 1 / z / 10^5)
end
function f₂(w::Real, y::Real)
2 - (cosh(w + y / 10^3) + y + w / 10^4)
end
function f₃(x::Real, y::Real)
1 - (tan(x + y) / (x - 2) / (x + 3) / y^2)
end
w = x = y = z = (lower = -3, upper = 3, resolution = 125)
tol = .2
R₁ = PixelArray(f₁, x, z, tol)
R₂ = PixelArray(f₂, w, y, tol)
R₃ = PixelArray(f₃, x, y, tol);
spy(R₁; title="Equation 1", xlabel="x", ylabel="z")
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀Equation 1⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
┌──────────────────────────────┐
1 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ > 0
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ < 0
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡄⢠⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⡇⢸⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠│
│⠿⣿⣶⣄⠀⠀⠀⠀⠀⠀⠀⠀⢀⡇⠁⠈⢸⡀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣶⣿⠿│
z │⠀⠈⠛⠿⣷⣄⠀⠀⠀⠀⠀⠀⣼⠁⢸⡇⠈⣧⠀⠀⠀⠀⠀⠀⣠⣾⠿⠛⠁⠀│
│⠀⠀⠀⠀⠈⢿⣷⣄⠀⠀⠀⢠⡏⠀⠀⠀⠀⢹⡄⠀⠀⠀⣠⣾⡿⠃⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠙⢿⣿⣦⣴⡿⠁⠀⢰⡆⠀⠈⢿⣦⣴⣿⡿⠋⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠛⠁⠀⠀⠈⠁⠀⠀⠈⠛⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
125 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
└──────────────────────────────┘
⠀1⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀125⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀x⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
spy(R₂; title="Equation 2", xlabel="w", ylabel="y")
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀Equation 2⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
┌──────────────────────────────┐
1 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ > 0
│⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ < 0
│⠀⠉⠉⠛⠓⠲⠶⢤⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠷⢶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢿⣦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⢻⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀│
y │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣾⠟⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⡶⠾⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⣀⣀⣤⡤⠴⠶⠚⠛⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
125 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
└──────────────────────────────┘
⠀1⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀125⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀w⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
spy(R₃; title="Equation 3", xlabel="x", ylabel="y")
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀Equation 3⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
┌──────────────────────────────┐
1 │⠀⠀⠀⠀⠀⣀⡤⠤⠖⠒⠒⠒⠒⠂⠀⠀⠀⠀⠀⠀⠀⢀⡤⠖⠊⠁⠈⠁⠀⠀│ > 0
│⠀⠀⠀⡠⠚⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡴⠋⠀⠀⠀⠀⠀⠀⠀⠀│ < 0
│⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠞⠛⠻⣆⠀⢰⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
y │⠀⠀⠀⠀⠀⠀⠀⠴⠋⠀⠀⠀⠀⠙⠦⠁⠀⠀⠀⠀⠀⠀⠠⠞⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠞⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⢀⠔⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠠⠞⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
│⠒⠂⠀⠀⠀⠀⠄⠠⢤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⠂⠄⠀⠠⠤⠤⣄⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⠃⠀⠀⠀│
125 │⠀⠀⠀⠀⠀⠀⠀⢀⠞⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠞⠀⠀⠀⠀⠀│
└──────────────────────────────┘
⠀1⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀125⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀x⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
diagram = @relation (w, z) where (w::n, x::n, y::n, z::n) begin
R₁(x, z)
R₂(w, y)
R₃(x, y)
end
to_graphviz(diagram; box_labels=:name, junction_labels=:variable)
hom_map = Dict{Symbol, PixelArray}(
:R₁ => R₁,
:R₂ => R₂,
:R₃ => R₃)
ob_map = Dict(
:n => 125)
problem = InferenceProblem(diagram, hom_map, ob_map)
R = solve(problem)
spy(R; title="Solution", xlabel="w", ylabel="z")
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀Solution⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
┌──────────────────────────────┐
1 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ > 0
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ < 0
│⣀⣠⣤⣤⣤⡄⠘⠛⠛⠛⠛⠛⢤⡄⢸⡇⢠⡤⠛⠛⠛⠛⠛⠃⠠⣤⣤⣤⣄⣀│
│⣿⣿⣿⣭⣤⡀⠀⠀⠀⠀⠀⠀⢨⡇⣧⣼⢸⡅⠀⠀⠀⠀⠀⠀⢀⣤⣭⣿⣿⣿│
│⣾⣿⣿⣿⠟⠃⠀⠀⠀⠀⠀⠀⢸⣷⡾⢷⣾⡇⠀⠀⠀⠀⠀⠀⠘⠻⣿⣿⣿⣷│
│⠁⠀⠀⠀⠀⠀⠀⣠⣤⣶⣶⣄⠀⠙⢣⡜⠋⠀⣠⣶⣶⣤⣄⠀⠀⠀⠀⠀⠀⠈│
│⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⡆⠀⢸⡇⠀⢰⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀│
z │⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⡇⠀⢸⡇⠀⢸⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣿⠇⠀⢸⡇⠀⠸⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀│
│⠀⠀⠀⠀⠀⠀⠀⠙⠛⠿⠿⠋⠀⢠⡜⢣⡄⠀⠙⠿⠿⠛⠋⠀⠀⠀⠀⠀⠀⠀│
│⠿⣿⣿⣿⣦⡄⠀⠀⠀⠀⠀⠀⢸⡿⢷⡾⢿⡇⠀⠀⠀⠀⠀⠀⢠⣴⣿⣿⣿⠿│
│⣿⣿⣿⣛⠛⠁⠀⠀⠀⠀⠀⠀⢘⡇⡟⢻⢸⡃⠀⠀⠀⠀⠀⠀⠈⠛⣛⣿⣿⣿│
│⠉⠙⠛⠛⠛⠃⢠⣤⣤⣤⣤⣤⠚⠃⢸⡇⠘⠓⣤⣤⣤⣤⣤⡄⠐⠛⠛⠛⠋⠉│
│⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀│
125 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
└──────────────────────────────┘
⠀1⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀125⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀w⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀