1use super::super::grid::{CellState, MappingGrid};
8use super::super::traits::{apply_gadget, pattern_matches, Pattern, PatternCell};
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11
12type PatternFactory = Box<dyn Fn() -> Box<dyn KsgPatternBoxed>>;
14
15pub type SourceGraph = (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>);
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
27pub struct KsgCross<const CON: bool>;
28
29impl Pattern for KsgCross<true> {
30 fn size(&self) -> (usize, usize) {
31 (3, 3)
32 }
33
34 fn cross_location(&self) -> (usize, usize) {
35 (2, 2)
36 }
37
38 fn is_connected(&self) -> bool {
39 true
40 }
41
42 fn is_cross_gadget(&self) -> bool {
43 true
44 }
45
46 fn connected_nodes(&self) -> Vec<usize> {
47 vec![0, 5]
48 }
49
50 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
51 let locs = vec![(2, 1), (2, 2), (2, 3), (1, 2), (2, 2), (3, 2)];
52 let edges = vec![(0, 1), (1, 2), (3, 4), (4, 5), (0, 5)];
53 let pins = vec![0, 3, 5, 2];
54 (locs, edges, pins)
55 }
56
57 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
58 let locs = vec![(2, 1), (2, 2), (2, 3), (1, 2), (3, 2)];
59 let pins = vec![0, 3, 4, 2];
60 (locs, pins)
61 }
62
63 fn mis_overhead(&self) -> i32 {
64 -1
65 }
66
67 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
68 [
69 (5, 5),
70 (12, 12),
71 (8, 0),
72 (1, 0),
73 (0, 0),
74 (6, 6),
75 (11, 11),
76 (9, 9),
77 (14, 14),
78 (3, 3),
79 (7, 7),
80 (4, 0),
81 (13, 13),
82 (15, 15),
83 (2, 0),
84 (10, 10),
85 ]
86 .into_iter()
87 .collect()
88 }
89
90 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
91 let mut map = HashMap::new();
92 map.insert(0, vec![vec![false, true, false, false, true, false]]);
93 map.insert(1, vec![vec![true, false, false, false, true, false]]);
94 map.insert(3, vec![vec![true, false, false, true, false, false]]);
95 map.insert(4, vec![vec![false, true, false, false, false, true]]);
96 map.insert(6, vec![vec![false, true, false, true, false, true]]);
97 map.insert(8, vec![vec![false, false, true, false, true, false]]);
98 map.insert(9, vec![vec![true, false, true, false, true, false]]);
99 map.insert(10, vec![vec![false, false, true, true, false, false]]);
100 map.insert(11, vec![vec![true, false, true, true, false, false]]);
101 map.insert(12, vec![vec![false, false, true, false, false, true]]);
102 map.insert(14, vec![vec![false, false, true, true, false, true]]);
103 map.insert(5, vec![]);
104 map.insert(7, vec![]);
105 map.insert(13, vec![]);
106 map.insert(15, vec![]);
107 map.insert(2, vec![vec![false, true, false, true, false, false]]);
108 map
109 }
110}
111
112impl Pattern for KsgCross<false> {
113 fn size(&self) -> (usize, usize) {
114 (4, 5)
115 }
116
117 fn cross_location(&self) -> (usize, usize) {
118 (2, 3)
119 }
120
121 fn is_connected(&self) -> bool {
122 false
123 }
124
125 fn is_cross_gadget(&self) -> bool {
126 true
127 }
128
129 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
130 let locs = vec![
131 (2, 1),
132 (2, 2),
133 (2, 3),
134 (2, 4),
135 (2, 5),
136 (1, 3),
137 (2, 3),
138 (3, 3),
139 (4, 3),
140 ];
141 let edges = vec![(0, 1), (1, 2), (2, 3), (3, 4), (5, 6), (6, 7), (7, 8)];
142 let pins = vec![0, 5, 8, 4];
143 (locs, edges, pins)
144 }
145
146 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
147 let locs = vec![
148 (2, 1),
149 (2, 2),
150 (2, 3),
151 (2, 4),
152 (2, 5),
153 (1, 3),
154 (3, 3),
155 (4, 3),
156 (3, 2),
157 (3, 4),
158 ];
159 let pins = vec![0, 5, 7, 4];
160 (locs, pins)
161 }
162
163 fn mis_overhead(&self) -> i32 {
164 -1
165 }
166
167 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
168 [
169 (5, 4),
170 (12, 4),
171 (8, 0),
172 (1, 0),
173 (0, 0),
174 (6, 0),
175 (11, 11),
176 (9, 9),
177 (14, 2),
178 (3, 2),
179 (7, 2),
180 (4, 4),
181 (13, 13),
182 (15, 11),
183 (2, 2),
184 (10, 2),
185 ]
186 .into_iter()
187 .collect()
188 }
189
190 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
191 let mut map = HashMap::new();
192 map.insert(
193 0,
194 vec![
195 vec![false, true, false, true, false, false, false, true, false],
196 vec![false, true, false, true, false, false, true, false, false],
197 ],
198 );
199 map.insert(
200 2,
201 vec![vec![
202 false, true, false, true, false, true, false, true, false,
203 ]],
204 );
205 map.insert(
206 4,
207 vec![vec![
208 false, true, false, true, false, false, true, false, true,
209 ]],
210 );
211 map.insert(
212 9,
213 vec![
214 vec![true, false, true, false, true, false, false, true, false],
215 vec![true, false, true, false, true, false, true, false, false],
216 ],
217 );
218 map.insert(
219 11,
220 vec![vec![
221 true, false, true, false, true, true, false, true, false,
222 ]],
223 );
224 map.insert(
225 13,
226 vec![vec![
227 true, false, true, false, true, false, true, false, true,
228 ]],
229 );
230 for i in [1, 3, 5, 6, 7, 8, 10, 12, 14, 15] {
231 map.entry(i).or_insert_with(Vec::new);
232 }
233 map
234 }
235}
236
237#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
239pub struct KsgTurn;
240
241impl Pattern for KsgTurn {
242 fn size(&self) -> (usize, usize) {
243 (4, 4)
244 }
245 fn cross_location(&self) -> (usize, usize) {
246 (3, 2)
247 }
248 fn is_connected(&self) -> bool {
249 false
250 }
251
252 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
253 let locs = vec![(1, 2), (2, 2), (3, 2), (3, 3), (3, 4)];
254 let edges = vec![(0, 1), (1, 2), (2, 3), (3, 4)];
255 let pins = vec![0, 4];
256 (locs, edges, pins)
257 }
258
259 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
260 let locs = vec![(1, 2), (2, 3), (3, 4)];
261 let pins = vec![0, 2];
262 (locs, pins)
263 }
264
265 fn mis_overhead(&self) -> i32 {
266 -1
267 }
268
269 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
270 [(0, 0), (2, 0), (3, 3), (1, 0)].into_iter().collect()
271 }
272
273 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
274 let mut map = HashMap::new();
275 map.insert(0, vec![vec![false, true, false, true, false]]);
276 map.insert(
277 1,
278 vec![
279 vec![true, false, true, false, false],
280 vec![true, false, false, true, false],
281 ],
282 );
283 map.insert(
284 2,
285 vec![
286 vec![false, true, false, false, true],
287 vec![false, false, true, false, true],
288 ],
289 );
290 map.insert(3, vec![vec![true, false, true, false, true]]);
291 map
292 }
293}
294
295#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
297pub struct KsgWTurn;
298
299impl Pattern for KsgWTurn {
300 fn size(&self) -> (usize, usize) {
301 (4, 4)
302 }
303 fn cross_location(&self) -> (usize, usize) {
304 (2, 2)
305 }
306 fn is_connected(&self) -> bool {
307 false
308 }
309
310 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
311 let locs = vec![(2, 3), (2, 4), (3, 2), (3, 3), (4, 2)];
312 let edges = vec![(0, 1), (0, 3), (2, 3), (2, 4)];
313 let pins = vec![1, 4];
314 (locs, edges, pins)
315 }
316
317 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
318 let locs = vec![(2, 4), (3, 3), (4, 2)];
319 let pins = vec![0, 2];
320 (locs, pins)
321 }
322
323 fn mis_overhead(&self) -> i32 {
324 -1
325 }
326
327 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
328 [(0, 0), (2, 0), (3, 3), (1, 0)].into_iter().collect()
329 }
330
331 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
332 let mut map = HashMap::new();
333 map.insert(0, vec![vec![true, false, true, false, false]]);
334 map.insert(
335 1,
336 vec![
337 vec![false, true, false, true, false],
338 vec![false, true, true, false, false],
339 ],
340 );
341 map.insert(
342 2,
343 vec![
344 vec![false, false, false, true, true],
345 vec![true, false, false, false, true],
346 ],
347 );
348 map.insert(3, vec![vec![false, true, false, true, true]]);
349 map
350 }
351}
352
353#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
355pub struct KsgBranch;
356
357impl Pattern for KsgBranch {
358 fn size(&self) -> (usize, usize) {
359 (5, 4)
360 }
361 fn cross_location(&self) -> (usize, usize) {
362 (3, 2)
363 }
364 fn is_connected(&self) -> bool {
365 false
366 }
367
368 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
369 let locs = vec![
370 (1, 2),
371 (2, 2),
372 (3, 2),
373 (3, 3),
374 (3, 4),
375 (4, 3),
376 (4, 2),
377 (5, 2),
378 ];
379 let edges = vec![(0, 1), (1, 2), (2, 3), (3, 4), (3, 5), (5, 6), (6, 7)];
380 let pins = vec![0, 4, 7];
381 (locs, edges, pins)
382 }
383
384 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
385 let locs = vec![(1, 2), (2, 3), (3, 2), (3, 4), (4, 3), (5, 2)];
386 let pins = vec![0, 3, 5];
387 (locs, pins)
388 }
389
390 fn mis_overhead(&self) -> i32 {
391 -1
392 }
393
394 fn source_weights(&self) -> Vec<i32> {
396 vec![2, 2, 2, 3, 2, 2, 2, 2]
397 }
398 fn mapped_weights(&self) -> Vec<i32> {
400 vec![2, 3, 2, 2, 2, 2]
401 }
402
403 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
404 [
405 (0, 0),
406 (4, 0),
407 (5, 5),
408 (6, 6),
409 (2, 0),
410 (7, 7),
411 (3, 3),
412 (1, 0),
413 ]
414 .into_iter()
415 .collect()
416 }
417
418 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
419 let mut map = HashMap::new();
420 map.insert(
421 0,
422 vec![vec![false, true, false, true, false, false, true, false]],
423 );
424 map.insert(
425 3,
426 vec![
427 vec![true, false, true, false, true, false, true, false],
428 vec![true, false, true, false, true, true, false, false],
429 ],
430 );
431 map.insert(
432 5,
433 vec![vec![true, false, true, false, false, true, false, true]],
434 );
435 map.insert(
436 6,
437 vec![
438 vec![false, false, true, false, true, true, false, true],
439 vec![false, true, false, false, true, true, false, true],
440 ],
441 );
442 map.insert(
443 7,
444 vec![vec![true, false, true, false, true, true, false, true]],
445 );
446 for i in [1, 2, 4] {
447 map.insert(i, vec![]);
448 }
449 map
450 }
451}
452
453#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
455pub struct KsgBranchFix;
456
457impl Pattern for KsgBranchFix {
458 fn size(&self) -> (usize, usize) {
459 (4, 4)
460 }
461 fn cross_location(&self) -> (usize, usize) {
462 (2, 2)
463 }
464 fn is_connected(&self) -> bool {
465 false
466 }
467
468 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
469 let locs = vec![(1, 2), (2, 2), (2, 3), (3, 3), (3, 2), (4, 2)];
470 let edges = vec![(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)];
471 let pins = vec![0, 5];
472 (locs, edges, pins)
473 }
474
475 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
476 let locs = vec![(1, 2), (2, 2), (3, 2), (4, 2)];
477 let pins = vec![0, 3];
478 (locs, pins)
479 }
480
481 fn mis_overhead(&self) -> i32 {
482 -1
483 }
484
485 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
486 [(0, 0), (2, 2), (3, 1), (1, 1)].into_iter().collect()
487 }
488
489 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
490 let mut map = HashMap::new();
491 map.insert(
492 0,
493 vec![
494 vec![false, true, false, true, false, false],
495 vec![false, true, false, false, true, false],
496 vec![false, false, true, false, true, false],
497 ],
498 );
499 map.insert(1, vec![vec![true, false, true, false, true, false]]);
500 map.insert(2, vec![vec![false, true, false, true, false, true]]);
501 map.insert(
502 3,
503 vec![
504 vec![true, false, false, true, false, true],
505 vec![true, false, true, false, false, true],
506 ],
507 );
508 map
509 }
510}
511
512#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
514pub struct KsgTCon;
515
516impl Pattern for KsgTCon {
517 fn size(&self) -> (usize, usize) {
518 (3, 4)
519 }
520 fn cross_location(&self) -> (usize, usize) {
521 (2, 2)
522 }
523 fn is_connected(&self) -> bool {
524 true
525 }
526 fn connected_nodes(&self) -> Vec<usize> {
527 vec![0, 1]
528 }
529
530 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
531 let locs = vec![(1, 2), (2, 1), (2, 2), (3, 2)];
532 let edges = vec![(0, 1), (0, 2), (2, 3)];
533 let pins = vec![0, 1, 3];
534 (locs, edges, pins)
535 }
536
537 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
538 let locs = vec![(1, 2), (2, 1), (2, 3), (3, 2)];
539 let pins = vec![0, 1, 3];
540 (locs, pins)
541 }
542
543 fn mis_overhead(&self) -> i32 {
544 0
545 }
546
547 fn source_weights(&self) -> Vec<i32> {
549 vec![2, 1, 2, 2]
550 }
551 fn mapped_weights(&self) -> Vec<i32> {
553 vec![2, 1, 2, 2]
554 }
555
556 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
557 [
558 (0, 0),
559 (4, 0),
560 (5, 5),
561 (6, 6),
562 (2, 2),
563 (7, 7),
564 (3, 3),
565 (1, 0),
566 ]
567 .into_iter()
568 .collect()
569 }
570
571 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
572 let mut map = HashMap::new();
573 map.insert(0, vec![vec![false, false, true, false]]);
574 map.insert(1, vec![vec![true, false, false, false]]);
575 map.insert(2, vec![vec![false, true, true, false]]);
576 map.insert(4, vec![vec![false, false, false, true]]);
577 map.insert(5, vec![vec![true, false, false, true]]);
578 map.insert(6, vec![vec![false, true, false, true]]);
579 map.insert(3, vec![]);
580 map.insert(7, vec![]);
581 map
582 }
583}
584
585#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
587pub struct KsgTrivialTurn;
588
589impl Pattern for KsgTrivialTurn {
590 fn size(&self) -> (usize, usize) {
591 (2, 2)
592 }
593 fn cross_location(&self) -> (usize, usize) {
594 (2, 2)
595 }
596 fn is_connected(&self) -> bool {
597 true
598 }
599 fn connected_nodes(&self) -> Vec<usize> {
600 vec![0, 1]
601 }
602
603 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
604 let locs = vec![(1, 2), (2, 1)];
605 let edges = vec![(0, 1)];
606 let pins = vec![0, 1];
607 (locs, edges, pins)
608 }
609
610 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
611 let locs = vec![(1, 2), (2, 1)];
612 let pins = vec![0, 1];
613 (locs, pins)
614 }
615
616 fn mis_overhead(&self) -> i32 {
617 0
618 }
619
620 fn source_weights(&self) -> Vec<i32> {
622 vec![1, 1]
623 }
624 fn mapped_weights(&self) -> Vec<i32> {
626 vec![1, 1]
627 }
628
629 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
630 [(0, 0), (2, 2), (3, 3), (1, 1)].into_iter().collect()
631 }
632
633 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
634 let mut map = HashMap::new();
635 map.insert(0, vec![vec![false, false]]);
636 map.insert(1, vec![vec![true, false]]);
637 map.insert(2, vec![vec![false, true]]);
638 map.insert(3, vec![]);
639 map
640 }
641}
642
643#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
645pub struct KsgEndTurn;
646
647impl Pattern for KsgEndTurn {
648 fn size(&self) -> (usize, usize) {
649 (3, 4)
650 }
651 fn cross_location(&self) -> (usize, usize) {
652 (2, 2)
653 }
654 fn is_connected(&self) -> bool {
655 false
656 }
657
658 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
659 let locs = vec![(1, 2), (2, 2), (2, 3)];
660 let edges = vec![(0, 1), (1, 2)];
661 let pins = vec![0];
662 (locs, edges, pins)
663 }
664
665 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
666 let locs = vec![(1, 2)];
667 let pins = vec![0];
668 (locs, pins)
669 }
670
671 fn mis_overhead(&self) -> i32 {
672 -1
673 }
674
675 fn source_weights(&self) -> Vec<i32> {
677 vec![2, 2, 1]
678 }
679 fn mapped_weights(&self) -> Vec<i32> {
681 vec![1]
682 }
683
684 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
685 [(0, 0), (1, 1)].into_iter().collect()
686 }
687
688 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
689 let mut map = HashMap::new();
690 map.insert(0, vec![vec![false, false, true], vec![false, true, false]]);
691 map.insert(1, vec![vec![true, false, true]]);
692 map
693 }
694}
695
696#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
698pub struct KsgBranchFixB;
699
700impl Pattern for KsgBranchFixB {
701 fn size(&self) -> (usize, usize) {
702 (4, 4)
703 }
704 fn cross_location(&self) -> (usize, usize) {
705 (2, 2)
706 }
707 fn is_connected(&self) -> bool {
708 false
709 }
710
711 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
712 let locs = vec![(2, 3), (3, 2), (3, 3), (4, 2)];
713 let edges = vec![(0, 2), (1, 2), (1, 3)];
714 let pins = vec![0, 3];
715 (locs, edges, pins)
716 }
717
718 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
719 let locs = vec![(3, 2), (4, 2)];
720 let pins = vec![0, 1];
721 (locs, pins)
722 }
723
724 fn mis_overhead(&self) -> i32 {
725 -1
726 }
727
728 fn source_weights(&self) -> Vec<i32> {
730 vec![1, 2, 2, 2]
731 }
732 fn mapped_weights(&self) -> Vec<i32> {
734 vec![1, 2]
735 }
736
737 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
738 [(0, 0), (2, 2), (3, 3), (1, 1)].into_iter().collect()
739 }
740
741 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
742 let mut map = HashMap::new();
743 map.insert(
744 0,
745 vec![
746 vec![false, false, true, false],
747 vec![false, true, false, false],
748 ],
749 );
750 map.insert(1, vec![vec![true, true, false, false]]);
751 map.insert(2, vec![vec![false, false, true, true]]);
752 map.insert(3, vec![vec![true, false, false, true]]);
753 map
754 }
755}
756
757#[derive(Debug, Clone)]
763pub struct KsgRotatedGadget<G: Pattern> {
764 pub gadget: G,
765 pub n: usize,
767}
768
769impl<G: Pattern> KsgRotatedGadget<G> {
770 pub fn new(gadget: G, n: usize) -> Self {
771 Self { gadget, n: n % 4 }
772 }
773}
774
775fn rotate90(loc: (i32, i32)) -> (i32, i32) {
776 (-loc.1, loc.0)
777}
778
779fn rotate_around_center(loc: (usize, usize), center: (usize, usize), n: usize) -> (i32, i32) {
780 let mut dx = loc.0 as i32 - center.0 as i32;
781 let mut dy = loc.1 as i32 - center.1 as i32;
782 for _ in 0..n {
783 let (nx, ny) = rotate90((dx, dy));
784 dx = nx;
785 dy = ny;
786 }
787 (center.0 as i32 + dx, center.1 as i32 + dy)
788}
789
790impl<G: Pattern> Pattern for KsgRotatedGadget<G> {
791 fn size(&self) -> (usize, usize) {
792 let (m, n) = self.gadget.size();
793 if self.n.is_multiple_of(2) {
794 (m, n)
795 } else {
796 (n, m)
797 }
798 }
799
800 fn cross_location(&self) -> (usize, usize) {
801 let center = self.gadget.cross_location();
802 let (m, n) = self.gadget.size();
803 let rotated = rotate_around_center(center, center, self.n);
804 let corners = [(1, 1), (m, n)];
805 let rotated_corners: Vec<_> = corners
806 .iter()
807 .map(|&c| rotate_around_center(c, center, self.n))
808 .collect();
809 let min_r = rotated_corners.iter().map(|c| c.0).min().unwrap();
810 let min_c = rotated_corners.iter().map(|c| c.1).min().unwrap();
811 let offset_r = 1 - min_r;
812 let offset_c = 1 - min_c;
813 (
814 (rotated.0 + offset_r) as usize,
815 (rotated.1 + offset_c) as usize,
816 )
817 }
818
819 fn is_connected(&self) -> bool {
820 self.gadget.is_connected()
821 }
822 fn is_cross_gadget(&self) -> bool {
823 self.gadget.is_cross_gadget()
824 }
825 fn connected_nodes(&self) -> Vec<usize> {
826 self.gadget.connected_nodes()
827 }
828
829 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
830 let (locs, edges, pins) = self.gadget.source_graph();
831 let center = self.gadget.cross_location();
832 let (m, n) = self.gadget.size();
833 let corners = [(1usize, 1usize), (m, n)];
834 let rotated_corners: Vec<_> = corners
835 .iter()
836 .map(|&c| rotate_around_center(c, center, self.n))
837 .collect();
838 let min_r = rotated_corners.iter().map(|c| c.0).min().unwrap();
839 let min_c = rotated_corners.iter().map(|c| c.1).min().unwrap();
840 let offset_r = 1 - min_r;
841 let offset_c = 1 - min_c;
842 let new_locs: Vec<_> = locs
843 .into_iter()
844 .map(|loc| {
845 let rotated = rotate_around_center(loc, center, self.n);
846 (
847 (rotated.0 + offset_r) as usize,
848 (rotated.1 + offset_c) as usize,
849 )
850 })
851 .collect();
852 (new_locs, edges, pins)
853 }
854
855 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
856 let (locs, pins) = self.gadget.mapped_graph();
857 let center = self.gadget.cross_location();
858 let (m, n) = self.gadget.size();
859 let corners = [(1usize, 1usize), (m, n)];
860 let rotated_corners: Vec<_> = corners
861 .iter()
862 .map(|&c| rotate_around_center(c, center, self.n))
863 .collect();
864 let min_r = rotated_corners.iter().map(|c| c.0).min().unwrap();
865 let min_c = rotated_corners.iter().map(|c| c.1).min().unwrap();
866 let offset_r = 1 - min_r;
867 let offset_c = 1 - min_c;
868 let new_locs: Vec<_> = locs
869 .into_iter()
870 .map(|loc| {
871 let rotated = rotate_around_center(loc, center, self.n);
872 (
873 (rotated.0 + offset_r) as usize,
874 (rotated.1 + offset_c) as usize,
875 )
876 })
877 .collect();
878 (new_locs, pins)
879 }
880
881 fn mis_overhead(&self) -> i32 {
882 self.gadget.mis_overhead()
883 }
884 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
885 self.gadget.mapped_entry_to_compact()
886 }
887 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
888 self.gadget.source_entry_to_configs()
889 }
890
891 fn source_weights(&self) -> Vec<i32> {
893 self.gadget.source_weights()
894 }
895 fn mapped_weights(&self) -> Vec<i32> {
896 self.gadget.mapped_weights()
897 }
898}
899
900#[derive(Debug, Clone, Copy, PartialEq, Eq)]
902pub enum Mirror {
903 X,
904 Y,
905 Diag,
906 OffDiag,
907}
908
909#[derive(Debug, Clone)]
911pub struct KsgReflectedGadget<G: Pattern> {
912 pub gadget: G,
913 pub mirror: Mirror,
914}
915
916impl<G: Pattern> KsgReflectedGadget<G> {
917 pub fn new(gadget: G, mirror: Mirror) -> Self {
918 Self { gadget, mirror }
919 }
920}
921
922fn reflect(loc: (i32, i32), mirror: Mirror) -> (i32, i32) {
923 match mirror {
924 Mirror::X => (loc.0, -loc.1),
925 Mirror::Y => (-loc.0, loc.1),
926 Mirror::Diag => (-loc.1, -loc.0),
927 Mirror::OffDiag => (loc.1, loc.0),
928 }
929}
930
931fn reflect_around_center(
932 loc: (usize, usize),
933 center: (usize, usize),
934 mirror: Mirror,
935) -> (i32, i32) {
936 let dx = loc.0 as i32 - center.0 as i32;
937 let dy = loc.1 as i32 - center.1 as i32;
938 let (nx, ny) = reflect((dx, dy), mirror);
939 (center.0 as i32 + nx, center.1 as i32 + ny)
940}
941
942impl<G: Pattern> Pattern for KsgReflectedGadget<G> {
943 fn size(&self) -> (usize, usize) {
944 let (m, n) = self.gadget.size();
945 match self.mirror {
946 Mirror::X | Mirror::Y => (m, n),
947 Mirror::Diag | Mirror::OffDiag => (n, m),
948 }
949 }
950
951 fn cross_location(&self) -> (usize, usize) {
952 let center = self.gadget.cross_location();
953 let (m, n) = self.gadget.size();
954 let reflected = reflect_around_center(center, center, self.mirror);
955 let corners = [(1, 1), (m, n)];
956 let reflected_corners: Vec<_> = corners
957 .iter()
958 .map(|&c| reflect_around_center(c, center, self.mirror))
959 .collect();
960 let min_r = reflected_corners.iter().map(|c| c.0).min().unwrap();
961 let min_c = reflected_corners.iter().map(|c| c.1).min().unwrap();
962 let offset_r = 1 - min_r;
963 let offset_c = 1 - min_c;
964 (
965 (reflected.0 + offset_r) as usize,
966 (reflected.1 + offset_c) as usize,
967 )
968 }
969
970 fn is_connected(&self) -> bool {
971 self.gadget.is_connected()
972 }
973 fn is_cross_gadget(&self) -> bool {
974 self.gadget.is_cross_gadget()
975 }
976 fn connected_nodes(&self) -> Vec<usize> {
977 self.gadget.connected_nodes()
978 }
979
980 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
981 let (locs, edges, pins) = self.gadget.source_graph();
982 let center = self.gadget.cross_location();
983 let (m, n) = self.gadget.size();
984 let corners = [(1usize, 1usize), (m, n)];
985 let reflected_corners: Vec<_> = corners
986 .iter()
987 .map(|&c| reflect_around_center(c, center, self.mirror))
988 .collect();
989 let min_r = reflected_corners.iter().map(|c| c.0).min().unwrap();
990 let min_c = reflected_corners.iter().map(|c| c.1).min().unwrap();
991 let offset_r = 1 - min_r;
992 let offset_c = 1 - min_c;
993 let new_locs: Vec<_> = locs
994 .into_iter()
995 .map(|loc| {
996 let reflected = reflect_around_center(loc, center, self.mirror);
997 (
998 (reflected.0 + offset_r) as usize,
999 (reflected.1 + offset_c) as usize,
1000 )
1001 })
1002 .collect();
1003 (new_locs, edges, pins)
1004 }
1005
1006 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
1007 let (locs, pins) = self.gadget.mapped_graph();
1008 let center = self.gadget.cross_location();
1009 let (m, n) = self.gadget.size();
1010 let corners = [(1usize, 1usize), (m, n)];
1011 let reflected_corners: Vec<_> = corners
1012 .iter()
1013 .map(|&c| reflect_around_center(c, center, self.mirror))
1014 .collect();
1015 let min_r = reflected_corners.iter().map(|c| c.0).min().unwrap();
1016 let min_c = reflected_corners.iter().map(|c| c.1).min().unwrap();
1017 let offset_r = 1 - min_r;
1018 let offset_c = 1 - min_c;
1019 let new_locs: Vec<_> = locs
1020 .into_iter()
1021 .map(|loc| {
1022 let reflected = reflect_around_center(loc, center, self.mirror);
1023 (
1024 (reflected.0 + offset_r) as usize,
1025 (reflected.1 + offset_c) as usize,
1026 )
1027 })
1028 .collect();
1029 (new_locs, pins)
1030 }
1031
1032 fn mis_overhead(&self) -> i32 {
1033 self.gadget.mis_overhead()
1034 }
1035 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
1036 self.gadget.mapped_entry_to_compact()
1037 }
1038 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
1039 self.gadget.source_entry_to_configs()
1040 }
1041
1042 fn source_weights(&self) -> Vec<i32> {
1044 self.gadget.source_weights()
1045 }
1046 fn mapped_weights(&self) -> Vec<i32> {
1047 self.gadget.mapped_weights()
1048 }
1049}
1050
1051#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1067pub struct KsgDanglingLeg;
1068
1069impl Pattern for KsgDanglingLeg {
1070 fn size(&self) -> (usize, usize) {
1071 (4, 3)
1072 }
1073 fn cross_location(&self) -> (usize, usize) {
1075 (2, 1)
1076 }
1077 fn is_connected(&self) -> bool {
1078 false
1079 }
1080
1081 fn source_graph(&self) -> (Vec<(usize, usize)>, Vec<(usize, usize)>, Vec<usize>) {
1082 let locs = vec![(2, 2), (3, 2), (4, 2)];
1084 let edges = vec![(0, 1), (1, 2)];
1085 let pins = vec![2];
1087 (locs, edges, pins)
1088 }
1089
1090 fn mapped_graph(&self) -> (Vec<(usize, usize)>, Vec<usize>) {
1091 let locs = vec![(4, 2)];
1093 let pins = vec![0];
1094 (locs, pins)
1095 }
1096
1097 fn mis_overhead(&self) -> i32 {
1098 -1
1099 }
1100
1101 fn source_weights(&self) -> Vec<i32> {
1103 vec![1, 2, 2]
1104 }
1105 fn mapped_weights(&self) -> Vec<i32> {
1107 vec![1]
1108 }
1109
1110 fn mapped_entry_to_compact(&self) -> HashMap<usize, usize> {
1111 [(0, 0), (1, 1)].into_iter().collect()
1113 }
1114
1115 fn source_entry_to_configs(&self) -> HashMap<usize, Vec<Vec<bool>>> {
1116 let mut map = HashMap::new();
1120 map.insert(0, vec![vec![true, false, false], vec![false, true, false]]);
1121 map.insert(1, vec![vec![true, false, true]]);
1122 map
1123 }
1124}
1125
1126#[derive(Debug, Clone)]
1132pub enum KsgPattern {
1133 CrossFalse(KsgCross<false>),
1134 CrossTrue(KsgCross<true>),
1135 Turn(KsgTurn),
1136 WTurn(KsgWTurn),
1137 Branch(KsgBranch),
1138 BranchFix(KsgBranchFix),
1139 TCon(KsgTCon),
1140 TrivialTurn(KsgTrivialTurn),
1141 EndTurn(KsgEndTurn),
1142 BranchFixB(KsgBranchFixB),
1143 DanglingLeg(KsgDanglingLeg),
1144 RotatedTCon1(KsgRotatedGadget<KsgTCon>),
1145 ReflectedCrossTrue(KsgReflectedGadget<KsgCross<true>>),
1146 ReflectedTrivialTurn(KsgReflectedGadget<KsgTrivialTurn>),
1147 ReflectedRotatedTCon1(KsgReflectedGadget<KsgRotatedGadget<KsgTCon>>),
1148 DanglingLegRot1(KsgRotatedGadget<KsgDanglingLeg>),
1149 DanglingLegRot2(KsgRotatedGadget<KsgRotatedGadget<KsgDanglingLeg>>),
1150 DanglingLegRot3(KsgRotatedGadget<KsgRotatedGadget<KsgRotatedGadget<KsgDanglingLeg>>>),
1151 DanglingLegReflX(KsgReflectedGadget<KsgDanglingLeg>),
1152 DanglingLegReflY(KsgReflectedGadget<KsgDanglingLeg>),
1153}
1154
1155impl KsgPattern {
1156 pub fn from_tape_idx(idx: usize) -> Option<Self> {
1158 match idx {
1159 0 => Some(Self::CrossFalse(KsgCross::<false>)),
1160 1 => Some(Self::Turn(KsgTurn)),
1161 2 => Some(Self::WTurn(KsgWTurn)),
1162 3 => Some(Self::Branch(KsgBranch)),
1163 4 => Some(Self::BranchFix(KsgBranchFix)),
1164 5 => Some(Self::TCon(KsgTCon)),
1165 6 => Some(Self::TrivialTurn(KsgTrivialTurn)),
1166 7 => Some(Self::RotatedTCon1(KsgRotatedGadget::new(KsgTCon, 1))),
1167 8 => Some(Self::ReflectedCrossTrue(KsgReflectedGadget::new(
1168 KsgCross::<true>,
1169 Mirror::Y,
1170 ))),
1171 9 => Some(Self::ReflectedTrivialTurn(KsgReflectedGadget::new(
1172 KsgTrivialTurn,
1173 Mirror::Y,
1174 ))),
1175 10 => Some(Self::BranchFixB(KsgBranchFixB)),
1176 11 => Some(Self::EndTurn(KsgEndTurn)),
1177 12 => Some(Self::ReflectedRotatedTCon1(KsgReflectedGadget::new(
1178 KsgRotatedGadget::new(KsgTCon, 1),
1179 Mirror::Y,
1180 ))),
1181 100 => Some(Self::DanglingLeg(KsgDanglingLeg)),
1182 101 => Some(Self::DanglingLegRot1(KsgRotatedGadget::new(
1183 KsgDanglingLeg,
1184 1,
1185 ))),
1186 102 => Some(Self::DanglingLegRot2(KsgRotatedGadget::new(
1187 KsgRotatedGadget::new(KsgDanglingLeg, 1),
1188 1,
1189 ))),
1190 103 => Some(Self::DanglingLegRot3(KsgRotatedGadget::new(
1191 KsgRotatedGadget::new(KsgRotatedGadget::new(KsgDanglingLeg, 1), 1),
1192 1,
1193 ))),
1194 104 => Some(Self::DanglingLegReflX(KsgReflectedGadget::new(
1195 KsgDanglingLeg,
1196 Mirror::X,
1197 ))),
1198 105 => Some(Self::DanglingLegReflY(KsgReflectedGadget::new(
1199 KsgDanglingLeg,
1200 Mirror::Y,
1201 ))),
1202 _ => None,
1203 }
1204 }
1205
1206 pub fn map_config_back(&self, gi: usize, gj: usize, config: &mut [Vec<usize>]) {
1208 match self {
1209 Self::CrossFalse(p) => map_config_back_pattern(p, gi, gj, config),
1210 Self::CrossTrue(p) => map_config_back_pattern(p, gi, gj, config),
1211 Self::Turn(p) => map_config_back_pattern(p, gi, gj, config),
1212 Self::WTurn(p) => map_config_back_pattern(p, gi, gj, config),
1213 Self::Branch(p) => map_config_back_pattern(p, gi, gj, config),
1214 Self::BranchFix(p) => map_config_back_pattern(p, gi, gj, config),
1215 Self::TCon(p) => map_config_back_pattern(p, gi, gj, config),
1216 Self::TrivialTurn(p) => map_config_back_pattern(p, gi, gj, config),
1217 Self::EndTurn(p) => map_config_back_pattern(p, gi, gj, config),
1218 Self::BranchFixB(p) => map_config_back_pattern(p, gi, gj, config),
1219 Self::DanglingLeg(p) => map_config_back_pattern(p, gi, gj, config),
1220 Self::RotatedTCon1(p) => map_config_back_pattern(p, gi, gj, config),
1221 Self::ReflectedCrossTrue(p) => map_config_back_pattern(p, gi, gj, config),
1222 Self::ReflectedTrivialTurn(p) => map_config_back_pattern(p, gi, gj, config),
1223 Self::ReflectedRotatedTCon1(p) => map_config_back_pattern(p, gi, gj, config),
1224 Self::DanglingLegRot1(p) => map_config_back_pattern(p, gi, gj, config),
1225 Self::DanglingLegRot2(p) => map_config_back_pattern(p, gi, gj, config),
1226 Self::DanglingLegRot3(p) => map_config_back_pattern(p, gi, gj, config),
1227 Self::DanglingLegReflX(p) => map_config_back_pattern(p, gi, gj, config),
1228 Self::DanglingLegReflY(p) => map_config_back_pattern(p, gi, gj, config),
1229 }
1230 }
1231}
1232
1233#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
1239pub struct KsgTapeEntry {
1240 pub pattern_idx: usize,
1241 pub row: usize,
1242 pub col: usize,
1243}
1244
1245pub fn tape_entry_mis_overhead(entry: &KsgTapeEntry) -> i32 {
1247 match entry.pattern_idx {
1248 0 => KsgCross::<false>.mis_overhead(),
1249 1 => KsgTurn.mis_overhead(),
1250 2 => KsgWTurn.mis_overhead(),
1251 3 => KsgBranch.mis_overhead(),
1252 4 => KsgBranchFix.mis_overhead(),
1253 5 => KsgTCon.mis_overhead(),
1254 6 => KsgTrivialTurn.mis_overhead(),
1255 7 => KsgRotatedGadget::new(KsgTCon, 1).mis_overhead(),
1256 8 => KsgReflectedGadget::new(KsgCross::<true>, Mirror::Y).mis_overhead(),
1257 9 => KsgReflectedGadget::new(KsgTrivialTurn, Mirror::Y).mis_overhead(),
1258 10 => KsgBranchFixB.mis_overhead(),
1259 11 => KsgEndTurn.mis_overhead(),
1260 12 => KsgReflectedGadget::new(KsgRotatedGadget::new(KsgTCon, 1), Mirror::Y).mis_overhead(),
1261 100..=105 => KsgDanglingLeg.mis_overhead(),
1262 _ => 0,
1263 }
1264}
1265
1266#[allow(dead_code)]
1268pub fn crossing_ruleset_indices() -> Vec<usize> {
1269 (0..13).collect()
1270}
1271
1272pub fn apply_crossing_gadgets(
1278 grid: &mut MappingGrid,
1279 copylines: &[super::super::copyline::CopyLine],
1280) -> Vec<KsgTapeEntry> {
1281 let mut tape = Vec::new();
1282 let n = copylines.len();
1283
1284 for j in 0..n {
1285 for i in 0..n {
1286 let (cross_row, cross_col) = crossat(grid, copylines, i, j);
1287 if let Some((pattern_idx, row, col)) =
1288 try_match_and_apply_crossing(grid, cross_row, cross_col)
1289 {
1290 tape.push(KsgTapeEntry {
1291 pattern_idx,
1292 row,
1293 col,
1294 });
1295 }
1296 }
1297 }
1298 tape
1299}
1300
1301fn crossat(
1304 grid: &MappingGrid,
1305 copylines: &[super::super::copyline::CopyLine],
1306 v: usize,
1307 w: usize,
1308) -> (usize, usize) {
1309 let line_v = copylines.get(v);
1310 let line_w = copylines.get(w);
1311
1312 match (line_v, line_w) {
1313 (Some(lv), Some(lw)) => {
1314 let (line_first, line_second) = if lv.vslot < lw.vslot {
1315 (lv, lw)
1316 } else {
1317 (lw, lv)
1318 };
1319 grid.cross_at(line_first.vslot, line_second.vslot, line_first.hslot)
1321 }
1322 _ => (0, 0),
1323 }
1324}
1325
1326fn try_match_and_apply_crossing(
1327 grid: &mut MappingGrid,
1328 cross_row: usize,
1329 cross_col: usize,
1330) -> Option<(usize, usize, usize)> {
1331 let patterns: Vec<(usize, PatternFactory)> = vec![
1333 (0, Box::new(|| Box::new(KsgCross::<false>))),
1334 (1, Box::new(|| Box::new(KsgTurn))),
1335 (2, Box::new(|| Box::new(KsgWTurn))),
1336 (3, Box::new(|| Box::new(KsgBranch))),
1337 (4, Box::new(|| Box::new(KsgBranchFix))),
1338 (5, Box::new(|| Box::new(KsgTCon))),
1339 (6, Box::new(|| Box::new(KsgTrivialTurn))),
1340 (7, Box::new(|| Box::new(KsgRotatedGadget::new(KsgTCon, 1)))),
1341 (
1342 8,
1343 Box::new(|| Box::new(KsgReflectedGadget::new(KsgCross::<true>, Mirror::Y))),
1344 ),
1345 (
1346 9,
1347 Box::new(|| Box::new(KsgReflectedGadget::new(KsgTrivialTurn, Mirror::Y))),
1348 ),
1349 (10, Box::new(|| Box::new(KsgBranchFixB))),
1350 (11, Box::new(|| Box::new(KsgEndTurn))),
1351 (
1352 12,
1353 Box::new(|| {
1354 Box::new(KsgReflectedGadget::new(
1355 KsgRotatedGadget::new(KsgTCon, 1),
1356 Mirror::Y,
1357 ))
1358 }),
1359 ),
1360 ];
1361
1362 for (idx, make_pattern) in patterns {
1363 let pattern = make_pattern();
1364 let cl = pattern.cross_location();
1365 if cross_row + 1 >= cl.0 && cross_col + 1 >= cl.1 {
1368 let x = cross_row + 1 - cl.0;
1369 let y = cross_col + 1 - cl.1;
1370 if pattern.pattern_matches_boxed(grid, x, y) {
1371 pattern.apply_gadget_boxed(grid, x, y);
1372 return Some((idx, x, y));
1373 }
1374 }
1375 }
1376 None
1377}
1378
1379pub fn apply_weighted_crossing_gadgets(
1382 grid: &mut MappingGrid,
1383 copylines: &[super::super::copyline::CopyLine],
1384) -> Vec<KsgTapeEntry> {
1385 let mut tape = Vec::new();
1386 let n = copylines.len();
1387
1388 for j in 0..n {
1389 for i in 0..n {
1390 let (cross_row, cross_col) = crossat(grid, copylines, i, j);
1391 if let Some((pattern_idx, row, col)) =
1392 try_match_and_apply_weighted_crossing(grid, cross_row, cross_col)
1393 {
1394 tape.push(KsgTapeEntry {
1395 pattern_idx,
1396 row,
1397 col,
1398 });
1399 }
1400 }
1401 }
1402 tape
1403}
1404
1405fn try_match_and_apply_weighted_crossing(
1406 grid: &mut MappingGrid,
1407 cross_row: usize,
1408 cross_col: usize,
1409) -> Option<(usize, usize, usize)> {
1410 let patterns: Vec<(usize, PatternFactory)> = vec![
1412 (0, Box::new(|| Box::new(KsgCross::<false>))),
1413 (1, Box::new(|| Box::new(KsgTurn))),
1414 (2, Box::new(|| Box::new(KsgWTurn))),
1415 (3, Box::new(|| Box::new(KsgBranch))),
1416 (4, Box::new(|| Box::new(KsgBranchFix))),
1417 (5, Box::new(|| Box::new(KsgTCon))),
1418 (6, Box::new(|| Box::new(KsgTrivialTurn))),
1419 (7, Box::new(|| Box::new(KsgRotatedGadget::new(KsgTCon, 1)))),
1420 (
1421 8,
1422 Box::new(|| Box::new(KsgReflectedGadget::new(KsgCross::<true>, Mirror::Y))),
1423 ),
1424 (
1425 9,
1426 Box::new(|| Box::new(KsgReflectedGadget::new(KsgTrivialTurn, Mirror::Y))),
1427 ),
1428 (10, Box::new(|| Box::new(KsgBranchFixB))),
1429 (11, Box::new(|| Box::new(KsgEndTurn))),
1430 (
1431 12,
1432 Box::new(|| {
1433 Box::new(KsgReflectedGadget::new(
1434 KsgRotatedGadget::new(KsgTCon, 1),
1435 Mirror::Y,
1436 ))
1437 }),
1438 ),
1439 ];
1440
1441 for (idx, make_pattern) in patterns {
1442 let pattern = make_pattern();
1443 let cl = pattern.cross_location();
1444 if cross_row + 1 >= cl.0 && cross_col + 1 >= cl.1 {
1445 let x = cross_row + 1 - cl.0;
1446 let y = cross_col + 1 - cl.1;
1447 let matches = pattern.pattern_matches_boxed(grid, x, y);
1448 if matches {
1449 pattern.apply_weighted_gadget_boxed(grid, x, y);
1450 return Some((idx, x, y));
1451 }
1452 }
1453 }
1454 None
1455}
1456
1457pub fn apply_simplifier_gadgets(grid: &mut MappingGrid, nrepeat: usize) -> Vec<KsgTapeEntry> {
1460 let mut tape = Vec::new();
1461 let (rows, cols) = grid.size();
1462
1463 let patterns = rotated_and_reflected_danglinleg();
1465
1466 for _ in 0..nrepeat {
1467 for (pattern_idx, pattern) in patterns.iter().enumerate() {
1468 for j in 0..cols {
1469 for i in 0..rows {
1470 if pattern_matches_boxed(pattern.as_ref(), grid, i, j) {
1471 apply_gadget_boxed(pattern.as_ref(), grid, i, j);
1472 tape.push(KsgTapeEntry {
1473 pattern_idx: 100 + pattern_idx, row: i,
1475 col: j,
1476 });
1477 }
1478 }
1479 }
1480 }
1481 }
1482
1483 tape
1484}
1485
1486pub fn apply_weighted_simplifier_gadgets(
1490 grid: &mut MappingGrid,
1491 nrepeat: usize,
1492) -> Vec<KsgTapeEntry> {
1493 let mut tape = Vec::new();
1494 let (rows, cols) = grid.size();
1495
1496 let patterns = rotated_and_reflected_danglinleg();
1497
1498 for _ in 0..nrepeat {
1499 for (pattern_idx, pattern) in patterns.iter().enumerate() {
1500 for j in 0..cols {
1501 for i in 0..rows {
1502 if pattern_matches_weighted(pattern.as_ref(), grid, i, j) {
1503 pattern.apply_weighted_gadget_boxed(grid, i, j);
1504 tape.push(KsgTapeEntry {
1505 pattern_idx: 100 + pattern_idx,
1506 row: i,
1507 col: j,
1508 });
1509 }
1510 }
1511 }
1512 }
1513 }
1514
1515 tape
1516}
1517
1518fn pattern_matches_weighted(
1522 pattern: &dyn KsgPatternBoxed,
1523 grid: &MappingGrid,
1524 i: usize,
1525 j: usize,
1526) -> bool {
1527 if !pattern_matches_boxed(pattern, grid, i, j) {
1529 return false;
1530 }
1531
1532 let (locs, _, _) = pattern.source_graph_boxed();
1536 if let Some((loc_r, loc_c)) = locs.first() {
1539 let grid_r = i + loc_r - 1;
1540 let grid_c = j + loc_c - 1;
1541 if let Some(cell) = grid.get(grid_r, grid_c) {
1542 if cell.weight() != 1 {
1544 return false;
1545 }
1546 }
1547 }
1548
1549 for (_idx, (loc_r, loc_c)) in locs.iter().enumerate().skip(1) {
1551 let grid_r = i + loc_r - 1;
1552 let grid_c = j + loc_c - 1;
1553 if let Some(cell) = grid.get(grid_r, grid_c) {
1554 if cell.weight() != 2 {
1555 return false;
1556 }
1557 }
1558 }
1559
1560 true
1561}
1562
1563fn rotated_and_reflected_danglinleg() -> Vec<Box<dyn KsgPatternBoxed>> {
1564 vec![
1565 Box::new(KsgDanglingLeg),
1566 Box::new(KsgRotatedGadget::new(KsgDanglingLeg, 1)),
1567 Box::new(KsgRotatedGadget::new(KsgDanglingLeg, 2)),
1568 Box::new(KsgRotatedGadget::new(KsgDanglingLeg, 3)),
1569 Box::new(KsgReflectedGadget::new(KsgDanglingLeg, Mirror::X)),
1570 Box::new(KsgReflectedGadget::new(KsgDanglingLeg, Mirror::Y)),
1571 ]
1572}
1573
1574#[allow(clippy::needless_range_loop)]
1576fn pattern_matches_boxed(
1577 pattern: &dyn KsgPatternBoxed,
1578 grid: &MappingGrid,
1579 i: usize,
1580 j: usize,
1581) -> bool {
1582 let source = pattern.source_matrix();
1583 let (m, n) = pattern.size_boxed();
1584
1585 for r in 0..m {
1586 for c in 0..n {
1587 let grid_r = i + r;
1588 let grid_c = j + c;
1589
1590 let expected = source[r][c];
1591 let actual = safe_get_pattern_cell(grid, grid_r, grid_c);
1592
1593 let matches = match (expected, actual) {
1596 (a, b) if a == b => true,
1597 (PatternCell::Connected, PatternCell::Occupied) => true,
1598 (PatternCell::Occupied, PatternCell::Connected) => true,
1599 _ => false,
1600 };
1601 if !matches {
1602 return false;
1603 }
1604 }
1605 }
1606 true
1607}
1608
1609fn safe_get_pattern_cell(grid: &MappingGrid, row: usize, col: usize) -> PatternCell {
1610 let (rows, cols) = grid.size();
1611 if row >= rows || col >= cols {
1612 return PatternCell::Empty;
1613 }
1614 match grid.get(row, col) {
1615 Some(CellState::Empty) => PatternCell::Empty,
1616 Some(CellState::Occupied { .. }) => PatternCell::Occupied,
1617 Some(CellState::Doubled { .. }) => PatternCell::Doubled,
1618 Some(CellState::Connected { .. }) => PatternCell::Connected,
1619 None => PatternCell::Empty,
1620 }
1621}
1622
1623#[allow(clippy::needless_range_loop)]
1625fn apply_gadget_boxed(pattern: &dyn KsgPatternBoxed, grid: &mut MappingGrid, i: usize, j: usize) {
1626 let mapped = pattern.mapped_matrix();
1627 let (m, n) = pattern.size_boxed();
1628
1629 for r in 0..m {
1630 for c in 0..n {
1631 let grid_r = i + r;
1632 let grid_c = j + c;
1633
1634 let cell = mapped[r][c];
1635 let state = match cell {
1636 PatternCell::Empty => CellState::Empty,
1637 PatternCell::Occupied => CellState::Occupied { weight: 1 },
1638 PatternCell::Doubled => CellState::Doubled { weight: 1 },
1639 PatternCell::Connected => CellState::Connected { weight: 1 },
1640 };
1641 grid.set(grid_r, grid_c, state);
1642 }
1643 }
1644}
1645
1646#[allow(dead_code)]
1648fn apply_weighted_gadget_boxed_fn(
1649 pattern: &dyn KsgPatternBoxed,
1650 grid: &mut MappingGrid,
1651 i: usize,
1652 j: usize,
1653) {
1654 pattern.apply_weighted_gadget_boxed(grid, i, j);
1655}
1656
1657pub trait KsgPatternBoxed {
1659 fn size_boxed(&self) -> (usize, usize);
1660 fn cross_location(&self) -> (usize, usize);
1661 fn source_matrix(&self) -> Vec<Vec<PatternCell>>;
1662 fn mapped_matrix(&self) -> Vec<Vec<PatternCell>>;
1663 fn source_graph_boxed(&self) -> SourceGraph;
1664 fn pattern_matches_boxed(&self, grid: &MappingGrid, i: usize, j: usize) -> bool;
1665 fn apply_gadget_boxed(&self, grid: &mut MappingGrid, i: usize, j: usize);
1666 fn apply_weighted_gadget_boxed(&self, grid: &mut MappingGrid, i: usize, j: usize);
1667}
1668
1669impl<P: Pattern> KsgPatternBoxed for P {
1670 fn size_boxed(&self) -> (usize, usize) {
1671 self.size()
1672 }
1673 fn cross_location(&self) -> (usize, usize) {
1674 Pattern::cross_location(self)
1675 }
1676 fn source_matrix(&self) -> Vec<Vec<PatternCell>> {
1677 Pattern::source_matrix(self)
1678 }
1679 fn mapped_matrix(&self) -> Vec<Vec<PatternCell>> {
1680 Pattern::mapped_matrix(self)
1681 }
1682 fn source_graph_boxed(&self) -> SourceGraph {
1683 Pattern::source_graph(self)
1684 }
1685 fn pattern_matches_boxed(&self, grid: &MappingGrid, i: usize, j: usize) -> bool {
1686 pattern_matches(self, grid, i, j)
1687 }
1688 fn apply_gadget_boxed(&self, grid: &mut MappingGrid, i: usize, j: usize) {
1689 apply_gadget(self, grid, i, j);
1690 }
1691 fn apply_weighted_gadget_boxed(&self, grid: &mut MappingGrid, i: usize, j: usize) {
1692 apply_weighted_gadget(self, grid, i, j);
1693 }
1694}
1695
1696#[allow(clippy::needless_range_loop)]
1699pub fn apply_weighted_gadget<P: Pattern>(pattern: &P, grid: &mut MappingGrid, i: usize, j: usize) {
1700 let (m, n) = pattern.size();
1701 let (mapped_locs, _) = pattern.mapped_graph();
1702 let mapped_weights = pattern.mapped_weights();
1703
1704 for r in 0..m {
1706 for c in 0..n {
1707 let grid_r = i + r;
1708 let grid_c = j + c;
1709 grid.set(grid_r, grid_c, CellState::Empty);
1710 }
1711 }
1712
1713 let mut weight_map: HashMap<(usize, usize), i32> = HashMap::new();
1715 for (idx, &(r, c)) in mapped_locs.iter().enumerate() {
1716 let weight = mapped_weights.get(idx).copied().unwrap_or(2);
1717 *weight_map.entry((r, c)).or_insert(0) += weight;
1718 }
1719
1720 let mut count_map: HashMap<(usize, usize), usize> = HashMap::new();
1722 for &(r, c) in &mapped_locs {
1723 *count_map.entry((r, c)).or_insert(0) += 1;
1724 }
1725
1726 for (&(r, c), &total_weight) in &weight_map {
1728 let grid_r = i + r - 1; let grid_c = j + c - 1;
1730 let count = count_map.get(&(r, c)).copied().unwrap_or(1);
1731
1732 let state = if count > 1 {
1733 CellState::Doubled {
1734 weight: total_weight,
1735 }
1736 } else {
1737 CellState::Occupied {
1738 weight: total_weight,
1739 }
1740 };
1741 grid.set(grid_r, grid_c, state);
1742 }
1743}
1744
1745pub fn map_config_back_pattern<P: Pattern>(
1747 pattern: &P,
1748 gi: usize,
1749 gj: usize,
1750 config: &mut [Vec<usize>],
1751) {
1752 let (m, n) = pattern.size();
1753 let (mapped_locs, mapped_pins) = pattern.mapped_graph();
1754 let (source_locs, _, _) = pattern.source_graph();
1755
1756 let mapped_config: Vec<usize> = mapped_locs
1758 .iter()
1759 .map(|&(r, c)| {
1760 let row = gi + r - 1;
1761 let col = gj + c - 1;
1762 config
1763 .get(row)
1764 .and_then(|row_vec| row_vec.get(col))
1765 .copied()
1766 .unwrap_or(0)
1767 })
1768 .collect();
1769
1770 let bc = {
1772 let mut result = 0usize;
1773 for (i, &pin_idx) in mapped_pins.iter().enumerate() {
1774 if pin_idx < mapped_config.len() && mapped_config[pin_idx] > 0 {
1775 result |= 1 << i;
1776 }
1777 }
1778 result
1779 };
1780
1781 let d1 = pattern.mapped_entry_to_compact();
1783 let d2 = pattern.source_entry_to_configs();
1784
1785 let compact = d1.get(&bc).copied();
1786 debug_assert!(
1787 compact.is_some(),
1788 "Boundary config {} not found in mapped_entry_to_compact",
1789 bc
1790 );
1791 let compact = compact.unwrap_or(0);
1792
1793 let source_configs = d2.get(&compact).cloned();
1794 debug_assert!(
1795 source_configs.is_some(),
1796 "Compact {} not found in source_entry_to_configs",
1797 compact
1798 );
1799 let source_configs = source_configs.unwrap_or_default();
1800
1801 debug_assert!(
1802 !source_configs.is_empty(),
1803 "Empty source configs for compact {}.",
1804 compact
1805 );
1806 let new_config = if source_configs.is_empty() {
1807 vec![false; source_locs.len()]
1808 } else {
1809 source_configs[0].clone()
1810 };
1811
1812 for row in gi..gi + m {
1814 for col in gj..gj + n {
1815 if let Some(row_vec) = config.get_mut(row) {
1816 if let Some(cell) = row_vec.get_mut(col) {
1817 *cell = 0;
1818 }
1819 }
1820 }
1821 }
1822
1823 for (k, &(r, c)) in source_locs.iter().enumerate() {
1825 let row = gi + r - 1;
1826 let col = gj + c - 1;
1827 if let Some(rv) = config.get_mut(row) {
1828 if let Some(cv) = rv.get_mut(col) {
1829 *cv += if new_config.get(k).copied().unwrap_or(false) {
1830 1
1831 } else {
1832 0
1833 };
1834 }
1835 }
1836 }
1837}