Compare commits

..

No commits in common. "8eb1ebb8d2920617d11effd25afb668732b45419" and "58a5c38e6229e6e30b9e468114c4f302140bb2eb" have entirely different histories.

6 changed files with 18 additions and 424 deletions

View File

@ -1,203 +0,0 @@
module Viewer
using Blink
using Colors
using Printf
export ConstructionViewer, display!, opentools!, closetools!
# === Blink utilities ===
append_to_head!(w, type, content) = @js w begin
@var element = document.createElement($type)
element.appendChild(document.createTextNode($content))
document.head.appendChild(element)
end
style!(w, stylesheet) = append_to_head!(w, "style", stylesheet)
script!(w, code) = append_to_head!(w, "script", code)
# === construction viewer ===
mutable struct ConstructionViewer
win::Window
function ConstructionViewer()
# create window and open developer console
win = Window(Blink.Dict(:width => 620, :height => 830))
# set stylesheet
style!(win, """
body {
background-color: #ccc;
}
/* the maximum dimensions keep Ganja from blowing up the canvas */
#view {
display: block;
width: 600px;
height: 600px;
margin-top: 10px;
margin-left: 10px;
border-radius: 10px;
background-color: #f0f0f0;
}
#control-panel {
width: 600px;
height: 200px;
box-sizing: border-box;
padding: 5px 10px 5px 10px;
margin-top: 10px;
margin-left: 10px;
overflow-y: scroll;
border-radius: 10px;
background-color: #f0f0f0;
}
#control-panel > div {
margin-top: 5px;
padding: 4px;
border-radius: 5px;
border: solid;
font-family: monospace;
}
""")
# load Ganja.js
loadjs!(win, "https://unpkg.com/ganja.js")
# create global functions and variables
script!(win, """
// create algebra
var CGA3 = Algebra(4, 1);
// initialize element list and palette
var elements = [];
var palette = [];
// declare handles for the view and its options
var view;
var viewOpt;
// declare handles for the controls
var controlPanel;
var visToggles;
// create scene function
function scene() {
commands = [];
for (let n = 0; n < elements.length; ++n) {
if (visToggles[n].checked) {
commands.push(palette[n], elements[n]);
}
}
return commands;
}
function updateView() {
requestAnimationFrame(view.update.bind(view, scene));
}
""")
@js win begin
# create view
viewOpt = Dict(
:conformal => true,
:gl => true,
:devicePixelRatio => window.devicePixelRatio
)
view = CGA3.graph(scene, viewOpt)
view.setAttribute(:id, "view")
view.removeAttribute(:style)
document.body.replaceChildren(view)
# create control panel
controlPanel = document.createElement(:div)
controlPanel.setAttribute(:id, "control-panel")
document.body.appendChild(controlPanel)
end
new(win)
end
end
function display!(viewer::ConstructionViewer, elements::Matrix)
# load elements
elements_full = [
[0; elt; fill(0, 26)]
for elt in eachcol(elements)
]
@js viewer.win elements = $elements_full.map((elt) -> @new CGA3(elt))
# generate palette. this is Gadfly's `default_discrete_colors` palette,
# available under the MIT license
palette = distinguishable_colors(
length(elements_full),
[LCHab(70, 60, 240)],
transform = c -> deuteranopic(c, 0.5),
lchoices = Float64[65, 70, 75, 80],
cchoices = Float64[0, 50, 60, 70],
hchoices = range(0, stop=330, length=24)
)
palette_packed = [RGB24(c).color for c in palette]
@js viewer.win palette = $palette_packed
# create visibility toggles
@js viewer.win begin
controlPanel.replaceChildren()
visToggles = []
end
for (elt, c) in zip(eachcol(elements), palette)
vec_str = join(map(t -> @sprintf("%.3f", t), elt), ", ")
color_str = "#$(hex(c))"
style_str = "background-color: $color_str; border-color: $color_str;"
@js viewer.win begin
@var toggle = document.createElement(:div)
toggle.setAttribute(:style, $style_str)
toggle.checked = true
toggle.addEventListener(
"click",
() -> begin
toggle.checked = !toggle.checked
toggle.style.backgroundColor = toggle.checked ? $color_str : "inherit";
updateView()
end
)
toggle.appendChild(document.createTextNode($vec_str))
visToggles.push(toggle);
controlPanel.appendChild(toggle);
end
end
# update view
@js viewer.win updateView()
end
function opentools!(viewer::ConstructionViewer)
size(viewer.win, 1240, 830)
opentools(viewer.win)
end
function closetools!(viewer::ConstructionViewer)
closetools(viewer.win)
size(viewer.win, 620, 830)
end
end
# ~~~ sandbox setup ~~~
# in the default view, e4 + e5 is the point at infinity
elements = sqrt(0.5) * BigFloat[
1 1 -1 -1 0;
1 -1 1 -1 0;
1 -1 -1 1 0;
0 0 0 0 -sqrt(6);
1 1 1 1 2
]
# show construction
viewer = Viewer.ConstructionViewer()
Viewer.display!(viewer, elements)

View File

@ -1,76 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-color: #ffe0f0;
}
/* needed to keep Ganja canvas from blowing up */
canvas {
min-width: 600px;
max-width: 600px;
min-height: 600px;
max-height: 600px;
}
</style>
<script src="https://unpkg.com/ganja.js"></script>
</head>
<body>
<p><button onclick="flip()">Flip</button></p>
<script>
// in the default view, e4 + e5 is the point at infinity
let CGA3 = Algebra(4, 1);
let elements = [
CGA3.inline(() => Math.sqrt(0.5)*( 1e1 + 1e2 + 1e3 + 1e5))(),
CGA3.inline(() => Math.sqrt(0.5)*( 1e1 - 1e2 - 1e3 + 1e5))(),
CGA3.inline(() => Math.sqrt(0.5)*(-1e1 + 1e2 - 1e3 + 1e5))(),
CGA3.inline(() => Math.sqrt(0.5)*(-1e1 - 1e2 + 1e3 + 1e5))(),
CGA3.inline(() => -Math.sqrt(3)*1e4 + Math.sqrt(2)*1e5)()
];
// set up palette
var colorIndex;
var palette = [0xff00b0, 0x00ffb0, 0x00b0ff, 0x8040ff, 0xc0c0c0];
function nextColor() {
colorIndex = (colorIndex + 1) % palette.length;
return palette[colorIndex];
}
function resetColorCycle() {
colorIndex = palette.length - 1;
}
resetColorCycle();
// create scene function
function scene() {
commands = [];
resetColorCycle();
elements.forEach((elt) => commands.push(nextColor(), elt));
return commands;
}
// initialize graph
let graph = CGA3.graph(
scene,
{
conformal: true, gl: true, grid: true
}
)
document.body.appendChild(graph);
function flip() {
let last = elements.length - 1;
for (let n = 0; n < last; ++n) {
// reflect
elements[n] = CGA3.Mul(CGA3.Mul(elements[last], elements[n]), elements[last]);
// de-noise
for (let k = 6; k < elements[n].length; ++k) {
elements[n][k] = 0;
}
}
requestAnimationFrame(graph.update.bind(graph, scene));
}
</script>
</body>
</html>

View File

@ -1,127 +0,0 @@
using Blink
using Colors
# === utilities ===
append_to_head!(w, type, content) = @js w begin
@var element = document.createElement($type)
element.appendChild(document.createTextNode($content))
document.head.appendChild(element)
end
style!(w, stylesheet) = append_to_head!(w, "style", stylesheet)
script!(w, code) = append_to_head!(w, "script", code)
function add_element!(vec)
# add element
full_vec = [0; vec; fill(0, 26)]
n = @js win elements.push(@new CGA3($full_vec))
# generate palette. this is Gadfly's `default_discrete_colors` palette,
# available under the MIT license
palette = distinguishable_colors(
n,
[LCHab(70, 60, 240)],
transform = c -> deuteranopic(c, 0.5),
lchoices = Float64[65, 70, 75, 80],
cchoices = Float64[0, 50, 60, 70],
hchoices = range(0, stop=330, length=24)
)
palette_packed = [RGB24(c).color for c in palette]
@js win palette = $palette_packed
end
# === build page ===
# create window and open developer console
win = Window()
opentools(win)
# set stylesheet
style!(win, """
body {
background-color: #ffe0f0;
}
/* needed to keep Ganja canvas from blowing up */
canvas {
min-width: 600px;
max-width: 600px;
min-height: 600px;
max-height: 600px;
}
""")
# load Ganja.js
loadjs!(win, "https://unpkg.com/ganja.js")
# create global functions and variables
script!(win, """
// create algebra
var CGA3 = Algebra(4, 1);
// initialize element list and palette
var elements = [];
var palette = [];
// declare visualization handle
var graph;
// create scene function
function scene() {
commands = [];
for (let n = 0; n < elements.length; ++n) {
commands.push(palette[n], elements[n]);
}
return commands;
}
function flip() {
let last = elements.length - 1;
for (let n = 0; n < last; ++n) {
// reflect
elements[n] = CGA3.Mul(CGA3.Mul(elements[last], elements[n]), elements[last]);
// de-noise
for (let k = 6; k < elements[n].length; ++k) {
elements[n][k] = 0;
}
}
requestAnimationFrame(graph.update.bind(graph, scene));
}
""")
# set up controls
body!(win, """
<p><button id="flip-button" onclick="flip()">Flip</button></p>
""", async = false)
# === set up visualization ===
# list elements. in the default view, e4 + e5 is the point at infinity
elements = sqrt(0.5) * BigFloat[
1 1 -1 -1 0;
1 -1 1 -1 0;
1 -1 -1 1 0;
0 0 0 0 -sqrt(6);
1 1 1 1 2
]
# load elements
for vec in eachcol(elements)
add_element!(vec)
end
# initialize visualization
@js win begin
graph = CGA3.graph(
scene,
Dict(
"conformal" => true,
"gl" => true,
"grid" => true
)
)
document.body.appendChild(graph)
end

View File

@ -10,10 +10,10 @@ using PolynomialRoots
# the difference between the matrices `target` and `attempt`, projected onto the # the difference between the matrices `target` and `attempt`, projected onto the
# subspace of matrices whose entries vanish at each empty index of `target` # subspace of matrices whose entries vanish at each empty index of `target`
function proj_diff(target, attempt) function proj_diff(target, attempt)
J, K, values = findnz(target) I, J, values = findnz(target)
result = zeros(size(target)...) result = zeros(size(target)...)
for (j, k, val) in zip(J, K, values) for (i, j, val) in zip(I, J, values)
result[j, k] = val - attempt[j, k] result[i, j] = val - attempt[i, j]
end end
result result
end end
@ -21,24 +21,24 @@ end
# === example === # === example ===
# the Lorentz form # the Lorentz form
Q = diagm([1, 1, 1, 1, -1]) Q = diagm([-1, 1, 1, 1, 1])
# initialize the partial gram matrix for an arrangement of seven spheres in # initialize the partial gram matrix for an arrangement of seven spheres in
# which spheres 1 through 5 are mutually tangent, and spheres 3 through 7 are # which spheres 1 through 5 are mutually tangent, and spheres 3 through 7 are
# also mutually tangent # also mutually tangent
I = Int64[]
J = Int64[] J = Int64[]
K = Int64[]
values = BigFloat[] values = BigFloat[]
for i in 1:7
for j in 1:7 for j in 1:7
for k in 1:7 if (i <= 5 && j <= 5) || (i >= 3 && j >= 3)
if (j <= 5 && k <= 5) || (j >= 3 && k >= 3) push!(I, i)
push!(J, j) push!(J, j)
push!(K, k) push!(values, i == j ? 1 : -1)
push!(values, j == k ? 1 : -1)
end end
end end
end end
gram = sparse(J, K, values) gram = sparse(I, J, values)
# set the independent variable # set the independent variable
# #
@ -54,11 +54,11 @@ gram[1, 6] = gram[6, 1]
# in this initial guess, the mutual tangency condition is satisfied for spheres # in this initial guess, the mutual tangency condition is satisfied for spheres
# 1 through 5 # 1 through 5
guess = sqrt(0.5) * BigFloat[ guess = sqrt(0.5) * BigFloat[
1 1 1 1 2 0.2 0.1;
0 0 0 0 -sqrt(6) 0.3 -0.2;
1 1 -1 -1 0 -0.1 0.3; 1 1 -1 -1 0 -0.1 0.3;
1 -1 1 -1 0 -0.5 0.4; 1 -1 1 -1 0 -0.5 0.4;
1 -1 -1 1 0 0.1 -0.2; 1 -1 -1 1 0 0.1 -0.2
0 0 0 0 -sqrt(6) 0.3 -0.2;
1 1 1 1 2 0.2 0.1;
] ]
# search parameters # search parameters
@ -108,11 +108,11 @@ println("\nLoss: ", loss, "\n")
# === algebraic check === # === algebraic check ===
R, gens = polynomial_ring(AbstractAlgebra.Rationals{BigInt}(), ["x", "t₁", "t₂", "t₃"]) R, gens = polynomial_ring(Generic.Rationals{BigInt}(), ["x", "t₁", "t₂", "t₃"])
x = gens[1] x = gens[1]
t = gens[2:4] t = gens[2:4]
S, u = polynomial_ring(AbstractAlgebra.Rationals{BigInt}(), "u") S, u = polynomial_ring(Generic.Rationals{BigInt}(), "u")
M = matrix_space(R, 7, 7) M = matrix_space(R, 7, 7)
gram_symb = M(R[ gram_symb = M(R[

View File

@ -11,7 +11,7 @@ function printbad(msg)
println(" ", msg) println(" ", msg)
end end
F, gens = rational_function_field(AbstractAlgebra.Rationals{BigInt}(), ["a₁", "a₂", "b₁", "b₂", "c₁", "c₂"]) F, gens = rational_function_field(Generic.Rationals{BigInt}(), ["a₁", "a₂", "b₁", "b₂", "c₁", "c₂"])
a = gens[1:2] a = gens[1:2]
b = gens[3:4] b = gens[3:4]
c = gens[5:6] c = gens[5:6]

View File

@ -11,7 +11,7 @@ function printbad(msg)
println(" ", msg) println(" ", msg)
end end
F, gens = rational_function_field(AbstractAlgebra.Rationals{BigInt}(), ["x", "t₁", "t₂", "t₃"]) F, gens = rational_function_field(Generic.Rationals{BigInt}(), ["x", "t₁", "t₂", "t₃"])
x = gens[1] x = gens[1]
t = gens[2:4] t = gens[2:4]