17 const mk_Q : (kc : KC_type -> std.result(quiver.quiver#, byte[:]))
18 const mk_Qdv : (kc : KC_type -> std.result(quiver.quiver#, byte[:]))
19 const mk_Qdh : (kc : KC_type -> std.result(quiver.quiver#, byte[:]))
22 /* Cosmetic; can't declare these as constants because they're tuples or something. */
23 const frozen_color = { ; -> (0x4c, 0xe7, 0xff) }
24 const mutable_color = { ; -> (0xad, 0x7f, 0xa8) }
27 var c : weyl_reflection[:] = [][:]
28 var rank : int = get_n(kc)
31 var q1 : quiver.quiver# = auto quiver.mk_with_opts([.use_a_coords = false])
32 var q : quiver.quiver#
33 var dynkin_edges : (weyl_reflection, weyl_reflection)[:] = get_edges(kc)
34 var T : weyl_reflection[:][:] = get_tree_partition(kc)
35 var zero : yakmo.Q# = auto yakmo.QfromZ(0)
36 var one : yakmo.Q# = auto yakmo.QfromZ(1)
37 var half : yakmo.Q# = auto std.try(yakmo.Qfrom(1, 2))
41 -> `std.Err std.fmt("A_{{2n}} is unimplemented at the moment")
47 var node_xshifts = get_node_xshifts(kc)
49 /* Something like [ 1, 2, 3, 4 ] */
50 match get_coxeter_elt(kc)
51 | `std.Err e: -> `std.Err std.fmt("get_coxeter_elt({}): {}", kc, e)
56 /* Should be impossible */
57 -> `std.Err std.fmt("Coxeter number {} must be even", h)
62 Construct the mutable portion. We'll go straight into Q_1,
63 since it makes adding the edges more readable.
65 for var i = 0; i < c.len; ++i
66 for var j = 1; j <= l; ++j
67 var name : byte[:] = vname(c[i],j)
68 match quiver.add_vertex(q1, name, (get_weight(kc, c[i]).0 : uint32))
69 | `std.Err e: -> `std.Err std.fmt("add_vertex: {}", e)
71 q1.v[idx].x_pos = (l - j + 1 : int64) * 100 + std.htgetv(node_xshifts, c[i], 0)
72 q1.v[idx].y_pos = (i + 1 : int64) * (-75)
73 q1.v[idx].color = mutable_color()
80 Construct B and C vertices, as well as dummy A vertices.
82 These are added in a verbose order so that reading the output
85 for var i = 0; i < c.len; ++i
86 var name : byte[:] = std.fmt("B{}", c[i])
87 match quiver.add_vertex(q1, name, (get_weight(kc, c[i]).0 : uint32))
88 | `std.Err e: -> `std.Err std.fmt("add_vertex: {}", e)
90 q1.v[idx].x_pos = 0 - (c.len - i : int64) * 43 + std.htgetv(node_xshifts, c[i], 0)
91 q1.v[idx].y_pos = (i + 1 : int64) * (-75)
92 q1.v[idx].color = frozen_color()
97 var min_mutable_x_pos : int64 = 100
98 var max_mutable_x_pos : int64 = (l * 100 : int64)
99 for var i = 0; i < c.len; ++i
100 var name : byte[:] = std.fmt("C{}", c[i])
101 match quiver.add_vertex(q1, name, (get_weight(kc, c[i]).0 : uint32))
102 | `std.Err e: -> `std.Err std.fmt("add_vertex: {}", e)
104 q1.v[idx].x_pos = max_mutable_x_pos + 100 + (c.len - i : int64) * 43 + std.htgetv(node_xshifts, c[i], 0)
105 q1.v[idx].y_pos = (i + 1 : int64) * (-75)
106 q1.v[idx].color = frozen_color()
111 var c_min_x : int64 = 50
112 var c_max_x : int64 = (l * 100 : int64) + 50
114 for var i = 0; i < c.len; ++i
115 var name : byte[:] = std.fmt("A{}", c[i])
116 match quiver.add_vertex(q1, name, (get_weight(kc, c[i]).0 : uint32))
117 | `std.Err e: -> `std.Err std.fmt("cannot add {}: {}", name, e)
119 q1.v[idx].x_pos = (c_min_x + c_max_x) / 2
121 q1.v[idx].color = frozen_color()
126 for var i = 0; i < c.len; ++i
127 var name : byte[:] = std.fmt("A{}", c[i])
128 var x_pos : int64 = ((c.len - 1 - i : int64) * (c_max_x - c_min_x)) / (c.len - 1) + c_min_x
129 var y_pos : int64 = 0 + std.htgetv(node_xshifts, c[i], 0)
130 match quiver.add_vertex(q1, name, (get_weight(kc, c[i]).0 : uint32))
131 | `std.Err e: -> `std.Err std.fmt("cannot add {}: {}", name, e)
133 q1.v[idx].x_pos = x_pos
134 q1.v[idx].y_pos = y_pos
135 q1.v[idx].color = frozen_color()
141 /* Now, hook up the edges */
143 /* Connect each D-like quiver */
144 for (i1, i2) : dynkin_edges
145 for var j = 1; j <= l; ++j
146 var name_from : byte[:] = vname(i1, j)
147 var name_to : byte[:] = vname(i2, j)
148 match quiver.add_to_edge(q1, name_from, name_to, auto yakmo.QfromZ(1))
149 | `std.Err e: -> `std.Err std.fmt("cannot construct edge {} -> {} in Q_1: {}", name_from, name_to, e)
152 std.slfree(name_from)
156 var name_B_from : byte[:] = std.fmt("B{}", i1)
157 var name_C_from : byte[:] = std.fmt("C{}", i1)
158 var name_B_to : byte[:] = std.fmt("B{}", i2)
159 var name_C_to : byte[:] = std.fmt("C{}", i2)
160 match quiver.add_to_edge(q1, name_B_from, name_B_to, half)
161 | `std.Err e: -> `std.Err std.fmt("cannot construct {} -> {} in Q_1: {}", name_B_from, name_B_to, e)
164 match quiver.add_to_edge(q1, name_C_from, name_C_to, half)
165 | `std.Err e: -> `std.Err std.fmt("cannot construct {} -> {} in Q_1: {}", name_C_from, name_C_to, e)
168 std.slfree(name_B_from)
169 std.slfree(name_C_from)
170 std.slfree(name_B_to)
171 std.slfree(name_C_to)
174 /* Connect each horizontal row */
177 var name_B : byte[:] = std.fmt("B{}", i)
178 var name_C : byte[:] = std.fmt("C{}", i)
179 var name_lmost : byte[:] = vname(i, l)
180 var name_rmost : byte[:] = vname(i, 1)
182 match quiver.add_to_edge(q1, name_B, name_lmost, one)
183 | `std.Err e: -> `std.Err std.fmt("cannot construct {} -> {} in Q_1: {}", name_B, name_lmost, e)
187 match quiver.add_to_edge(q1, name_rmost, name_C, one)
188 | `std.Err e: -> `std.Err std.fmt("cannot construct {} -> {} in Q_1: {}", name_rmost, name_C, e)
194 std.slfree(name_lmost)
195 std.slfree(name_rmost)
197 for var j = 1; j + 1 <= l; ++j
198 var name_from : byte[:] = vname(i, j + 1)
199 var name_to : byte[:] = vname(i, j + 0)
201 match quiver.add_to_edge(q1, name_from, name_to, one)
202 | `std.Err e: -> `std.Err std.fmt("cannot construct {} -> {} in Q_1: {}", name_from, name_to, e)
209 var name_B : byte[:] = std.fmt("B{}", i)
210 var name_C : byte[:] = std.fmt("C{}", i)
212 match quiver.add_to_edge(q1, name_B, name_C, one)
213 | `std.Err e: -> `std.Err std.fmt("cannot construct {} -> {} in Q_1: {}", name_B, name_C, e)
222 /* Now, the diagonals */
223 for (i1, i2) : dynkin_edges
224 var name_B : byte[:] = std.fmt("B{}", i1)
225 var name_lmost : byte[:] = vname(i2, l)
226 var name_C : byte[:] = std.fmt("C{}", i2)
227 var name_rmost : byte[:] = vname(i1, 1)
229 match quiver.add_to_edge(q1, name_lmost, name_B, one)
230 | `std.Err e: -> `std.Err std.fmt("cannot construct {} -> {} in Q_1: {}", name_lmost, name_B, e)
234 match quiver.add_to_edge(q1, name_C, name_rmost, one)
235 | `std.Err e: -> `std.Err std.fmt("cannot construct {} -> {} in Q_1: {}", name_C, name_rmost, e)
241 std.slfree(name_lmost)
242 std.slfree(name_rmost)
244 for var j = 1; j + 1 <= l; ++j
245 var name_from : byte[:] = vname(i2, j + 0)
246 var name_to : byte[:] = vname(i1, j + 1)
248 match quiver.add_to_edge(q1, name_from, name_to, one)
249 | `std.Err e: -> `std.Err std.fmt("cannot construct {} -> {} in Q_1: {}", name_from, name_to, e)
253 std.slfree(name_from)
259 Now, we have Q_1. We need to rotate forwards and backwards,
260 which will give us the edges. There appears to be a more
261 clearly algorithmic construction for this based on ``The
262 first k for which hi shows up in the numerator for
263 w_k^{-1}(h) or something'', but this is easier.
265 var mu : byte[:][:] = [][:]
267 match get_mutwistingrot(kc)
268 | `std.Err e: -> `std.Err std.fmt("murot: {}", e)
269 | `std.Ok mu_: mu = mu_
272 var q1_prime : quiver.quiver# = auto t.dup(q1)
274 match quiver.mutate_ip(q1_prime, vertex)
276 | `std.Err e: -> `std.Err std.fmt("cannot construct Q_1': {}", e)
280 /* Don't mutate Q'' yet -- the renamings need to be done first */
281 var q1_primeprime : quiver.quiver# = auto t.dup(q1)
284 We'll need to permute some vertices according to σG, and to
285 σA_l. The latter is always j <-> l-j+1, the former needs to
286 be calculated. Luckily, both of these things are involutions,
287 so we'll freely use σG as its own inverse when renaming for
291 match get_sigmaG_permutation(kc)
292 | `std.Err e: -> `std.Err std.fmt("cannot calculate σG: {}", e)
293 | `std.Ok sGc: sG = sGc
296 match rename_according_to_twistingrot(kc, q1, q1_prime)
297 | `std.Err e: -> `std.Err std.fmt("renaming Q_1' failed: {}", e)
301 match rename_according_to_twistingrotinv(kc, q1, q1_primeprime)
302 | `std.Err e: -> `std.Err std.fmt("renaming Q_1' failed: {}", e)
306 /* Now finish off the mutation for Q'' */
307 for vertex : iter.byreverse(mu)
308 match quiver.mutate_ip(q1_primeprime, vertex)
310 | `std.Err e: -> `std.Err std.fmt("cannot construct Q_1'': {}", e)
315 Now, we're ready to construct Q_2 = Q. We need to check
316 through all pairs (x, y) of vertices in Q_1 (by name). For
317 each pair, we take the unique non-zero edge weight, and use
318 that as the edge weight for Q_2.
321 /* First, copy over all vertices */
322 var q2 : quiver.quiver# = quiver.mk_with_opts([.use_a_coords = true])
324 match quiver.add_vertex(q2, vertex.name, vertex.d)
325 | `std.Err e: -> `std.Err std.fmt("cannot add {} to Q_2: {}", vertex.name, e)
327 q2.v[idx].x_pos = q1.v[idx].x_pos
328 q2.v[idx].y_pos = q1.v[idx].y_pos
329 q2.v[idx].color = q1.v[idx].color
333 /* Now the long haul of pairs. */
334 for var i = 0; i < q1.v.len; ++i
336 for var j = 0; j < q1.v.len; ++j
339 var eps1 = q1.epsilon[i][j]
340 var eps2 = epsilon_of(q1_prime, x, y, zero)
341 var eps3 = epsilon_of(q1_primeprime, x, y, zero)
344 The lemma is "In the set {eps1, eps2, eps3}, there
345 is at most one non-zero element. Repetitions
346 are allowed." We must check this.
349 var maybe_non_zero : yakmo.Q# = zero
350 for eps : [ eps1, eps2, eps3 ][:]
355 if std.eq(maybe_non_zero, zero)
357 elif !std.eq(maybe_non_zero, eps)
358 std.put("{}", quiver.to_bytes(q1))
359 std.put("=================\n")
360 std.put("{}", quiver.to_bytes(q1_prime))
361 std.put("=================\n")
362 std.put("{}", quiver.to_bytes(q1_primeprime))
363 -> `std.Err std.fmt("Eps uniqueness lemma fails: edge {} -> {}, weights {}, {}", x, y, eps, maybe_non_zero)
367 // TODO: __dispose__(q2.epsilon[i][j])
368 q2.epsilon[i][j] = t.dup(maybe_non_zero)
375 /* Returns exactly epsilon[i][j] or zero. No duping */
376 const epsilon_of = {q, x, y, zero
377 for var i = 0; i < q.v.len; ++i
378 if !std.eq(q.v[i].name, x)
382 for var j = 0; j < q.v.len; ++j
383 if !std.eq(q.v[j].name, y)
394 const bound_quiver_bit = {q : quiver.quiver#, prefix : char
395 var pb : byte = (prefix : byte)
396 var anything : bool = false
402 for var j = 0; j < q.v.len; ++j
403 if q.v[j].name[0] != pb
421 for var j = 0; j < q.v.len; ++j
422 if q.v[j].name[0] != pb
426 min_x = std.min(min_x, q.v[j].x_pos)
427 max_x = std.min(max_x, q.v[j].x_pos)
428 min_y = std.min(min_y, q.v[j].y_pos)
429 max_y = std.min(max_y, q.v[j].y_pos)
432 -> (min_x, max_x, min_y, max_y)
437 match get_coxeter_elt(kc)
438 | `std.Err e: -> `std.Err std.fmt("get_coxeter_elt({}): {}", kc, e)
441 var h = coxeter_num(kc)
444 var Q : quiver.quiver#
445 var min_x, max_x, min_y, max_y
447 | `std.Err e: -> `std.Err std.fmt("mk_Q({}): {}", kc, e)
452 /* Left: a copy of Q, rotated by pi/3, with C-edge centered on (0, 0) */
453 var left_Q : quiver.quiver# = auto t.dup(Q)
454 for var j = 0; j < left_Q.v.len; ++j
455 var x = left_Q.v[j].x_pos
456 var y = left_Q.v[j].y_pos
457 left_Q.v[j].x_pos = (866 * x) / 1000 - y / 2
458 left_Q.v[j].y_pos = x / 2 + (866 * y) / 1000
461 (min_x, max_x, min_y, max_y) = bound_quiver_bit(left_Q, 'C')
462 var c_mid_x = (min_x + max_x) / 2
463 var c_mid_y = (min_y + max_y) / 2
465 for var j = 0; j < left_Q.v.len; ++j
466 left_Q.v[j].x_pos -= c_mid_x
467 left_Q.v[j].y_pos -= c_mid_y
470 /* Right: a copy of Q, rotated by pi/2, adjusted so that the A-edge is centered on (0, 0) */
471 var right_Q : quiver.quiver# = Q
472 for var j = 0; j < right_Q.v.len; ++j
473 var x = right_Q.v[j].x_pos
474 var y = right_Q.v[j].y_pos
475 right_Q.v[j].x_pos = -1 * y
476 right_Q.v[j].y_pos = x
479 (min_x, max_x, min_y, max_y) = bound_quiver_bit(right_Q, 'A')
480 var a_mid_x = (min_x + max_x) / 2
481 var a_mid_y = (min_y + max_y) / 2
483 for var j = 0; j < right_Q.v.len; ++j
484 right_Q.v[j].x_pos -= a_mid_x
485 right_Q.v[j].y_pos -= a_mid_y
488 /* Now embed into Qdv */
489 var Qdv : quiver.quiver# = quiver.mk_with_opts([.use_a_coords = true])
492 FOO_map[BAR] = BAZ means that vertex BAR in Q corresponds to
493 vertex BAZ in the FOO half of Qdv.
495 var left_map : std.htab(byte[:], byte[:])# = std.mkht()
496 var right_map : std.htab(byte[:], byte[:])# = std.mkht()
499 std.htput(left_map, std.fmt("A{}", cc), std.fmt("D{}", cc))
500 std.htput(left_map, std.fmt("B{}", cc), std.fmt("E{}", cc))
501 std.htput(left_map, std.fmt("C{}", cc), wname(cc, l + 1))
503 std.htput(right_map, std.fmt("A{}", cc), wname(cc, l + 1))
504 std.htput(right_map, std.fmt("B{}", cc), std.fmt("F{}", cc))
505 std.htput(right_map, std.fmt("C{}", cc), std.fmt("G{}", cc))
507 for var j = 1; j <= l; ++j
508 std.htput(left_map, vname(cc, j), wname(cc, j + l + 1))
509 std.htput(right_map, vname(cc, j), wname(cc, j))
513 embed_quiver(left_Q, Qdv, left_map)
514 embed_quiver(right_Q, Qdv, right_map)
516 /* Un-freeze the middle vertices */
518 var name = wname(cc, l + 1)
519 match quiver.find_vertex(Qdv, name)
520 | `std.Some (_, vv): vv.color = mutable_color()
526 /* Kill the maps. TODO: bother Ori about integrating disposable tighter here. */
527 for (key, val) : std.byhtkeyvals(left_map)
533 for (key, val) : std.byhtkeyvals(right_map)
537 std.htfree(right_map)
542 const embed_quiver = {q_from, q_to, map
543 for (name_from, name_to) : std.byhtkeyvals(map)
544 match quiver.find_vertex(q_from, name_from)
546 | `std.Some (_, v_from):
547 match quiver.add_vertex(q_to, std.sldup(name_to), v_from.d)
548 | `std.Err e: std.slfree(e)
550 q_to.v[j].color = v_from.color
551 q_to.v[j].x_pos = v_from.x_pos
552 q_to.v[j].y_pos = v_from.y_pos
555 | `std.None: q_to.v[j].acoord = `std.None
556 | `std.Some a: q_to.v[j].acoord = `std.Some t.dup(a)
560 | `std.None: q_to.v[j].xcoord = `std.None
561 | `std.Some x: q_to.v[j].xcoord = `std.Some t.dup(x)
567 for var j1 = 0; j1 < q_from.v.len; ++j1
569 match std.htget(map, q_from.v[j1].name)
570 | `std.None: continue
571 | `std.Some n: name_to1 = n
574 for var j2 = 0; j2 < j1; ++j2
576 match std.htget(map, q_from.v[j2].name)
577 | `std.None: continue
578 | `std.Some n: name_to2 = n
581 match quiver.get_sigma_ii(q_from, j1, j2)
584 match quiver.add_to_edge(q_to, name_to1, name_to2, sigma)
586 | `std.Err e: std.slfree(e)
590 auto (sigma : yakmo.Q#)
598 match get_coxeter_elt(kc)
599 | `std.Err e: -> `std.Err std.fmt("get_coxeter_elt({}): {}", kc, e)
602 var h = coxeter_num(kc)
605 var Q : quiver.quiver#
606 var min_x, max_x, min_y, max_y
608 | `std.Err e: -> `std.Err std.fmt("mk_Q({}): {}", kc, e)
613 /* Bottom: a copy of Q, rotated by pi/3, with B-edge centered on (0, 0) */
614 var bottom_Q : quiver.quiver# = auto t.dup(Q)
615 for var j = 0; j < bottom_Q.v.len; ++j
616 var x = bottom_Q.v[j].x_pos
617 var y = bottom_Q.v[j].y_pos
618 bottom_Q.v[j].x_pos = x / 2 - (866 * y) / 1000
619 bottom_Q.v[j].y_pos = (866 * x) / 1000 + y / 2
622 (min_x, max_x, min_y, max_y) = bound_quiver_bit(bottom_Q, 'B')
623 var b_mid_x = (min_x + max_x) / 2
624 var b_mid_y = (min_y + max_y) / 2
626 for var j = 0; j < bottom_Q.v.len; ++j
627 bottom_Q.v[j].x_pos -= b_mid_x
628 bottom_Q.v[j].y_pos -= b_mid_y
631 /* Top: a copy of Q, rotated by 2pi/3, with C-edge is centered on (0, 0) */
632 var top_Q : quiver.quiver# = Q
633 for var j = 0; j < top_Q.v.len; ++j
634 var x = top_Q.v[j].x_pos
635 var y = top_Q.v[j].y_pos
636 top_Q.v[j].x_pos = -1 * x / 2 - (866 * y) / 1000
637 top_Q.v[j].y_pos = (866 * x) / 1000 - y / 2
640 (min_x, max_x, min_y, max_y) = bound_quiver_bit(top_Q, 'C')
641 var c_mid_x = (min_x + max_x) / 2
642 var c_mid_y = (min_y + max_y) / 2
644 for var j = 0; j < top_Q.v.len; ++j
645 top_Q.v[j].x_pos -= c_mid_x
646 top_Q.v[j].y_pos -= c_mid_y
649 /* Now embed into Qdh */
650 var Qdh : quiver.quiver# = quiver.mk_with_opts([.use_a_coords = true])
652 var bottom_map : std.htab(byte[:], byte[:])# = std.mkht()
653 var top_map : std.htab(byte[:], byte[:])# = std.mkht()
656 std.htput(bottom_map, std.fmt("A{}", cc), std.fmt("D{}", cc))
657 std.htput(bottom_map, std.fmt("B{}", cc), wname(cc, l + 1))
658 std.htput(bottom_map, std.fmt("C{}", cc), std.fmt("G{}", cc))
660 std.htput(top_map, std.fmt("A{}", cc), std.fmt("E{}", cc))
661 std.htput(top_map, std.fmt("B{}", cc), std.fmt("F{}", cc))
662 std.htput(top_map, std.fmt("C{}", cc), wname(cc, l + 1))
664 for var j = 1; j <= l; ++j
665 std.htput(bottom_map, vname(cc, j), wname(cc, j))
666 std.htput(top_map, vname(cc, j), wname(cc, j + l + 1))
670 embed_quiver(top_Q, Qdh, top_map)
671 embed_quiver(bottom_Q, Qdh, bottom_map)
673 /* Un-freeze the middle vertices */
675 var name = wname(cc, l + 1)
676 match quiver.find_vertex(Qdh, name)
677 | `std.Some (_, vv): vv.color = mutable_color()
683 /* Kill the maps. TODO: bother Ori about integrating disposable tighter here. */
684 for (key, val) : std.byhtkeyvals(bottom_map)
688 std.htfree(bottom_map)
690 for (key, val) : std.byhtkeyvals(top_map)