1use crate::expr::{Expr, Names, VarRange};
4use crate::flag::Flag;
5use crate::operator::*;
6use ndarray::{Array1, ScalarOperand};
7use num::{pow::Pow, FromPrimitive, Integer, Num};
8use sprs::{CsMat, CsMatView, CsVec, MulAcc, TriMat};
9use std::fmt::*;
10use std::ops::*;
11
12#[derive(Clone, Debug)]
14pub struct QFlag<N, F: Flag> {
15 pub basis: Basis<F>,
17 pub data: Array1<N>,
19 pub scale: u64,
21 pub expr: Expr<N, F>,
23}
24
25impl<N, F> PartialEq for QFlag<N, F>
27where
28 N: Num + FromPrimitive + Clone,
29 F: Flag,
30{
31 fn eq(&self, other: &Self) -> bool {
32 assert_eq!(self.basis, other.basis);
33 assert_eq!(self.data.len(), other.data.len());
34 let s1 = N::from_u64(self.scale).unwrap();
36 let s2 = N::from_u64(other.scale).unwrap();
37 self.data
38 .iter()
39 .zip(other.data.iter())
40 .all(|(x, y)| x.clone() * s2.clone() == y.clone() * s1.clone())
41 }
42}
43
44fn matching_scales<N>(scale1: u64, scale2: u64) -> (N, N, u64)
52where
53 N: FromPrimitive,
54{
55 let gcd = scale1.gcd(&scale2);
56 let c1 = N::from_u64(scale2 / gcd).unwrap();
57 let c2 = N::from_u64(scale1 / gcd).unwrap();
58 let scale = (scale1 / gcd) * scale2;
59 (c1, c2, scale)
60}
61
62impl<N, F> Add<&Self> for QFlag<N, F>
63where
64 N: Clone + FromPrimitive + Num + ScalarOperand,
65 F: Flag,
66{
67 type Output = Self;
68
69 fn add(self, other: &Self) -> Self::Output {
70 assert_eq!(self.basis, other.basis);
71 assert_eq!(self.data.len(), other.data.len());
72 let (a1, a2, scale) = matching_scales::<N>(self.scale, other.scale);
73 QFlag {
74 basis: self.basis,
75 data: self.data * a1 + &other.data * a2,
76 scale,
77 expr: self.expr + other.expr.clone(),
78 }
79 }
80}
81
82impl<N, F> Add for QFlag<N, F>
83where
84 N: Clone + Num + FromPrimitive + ScalarOperand,
85 F: Flag,
86{
87 type Output = Self;
88
89 fn add(self, other: Self) -> Self::Output {
90 self + &other
91 }
92}
93
94impl<'a, N, F> Sub for &'a QFlag<N, F>
95where
96 N: Clone + Num + FromPrimitive + ScalarOperand,
97 F: Flag,
98{
99 type Output = QFlag<N, F>;
100
101 fn sub(self, other: Self) -> Self::Output {
102 assert_eq!(self.basis, other.basis);
103 assert_eq!(self.data.len(), other.data.len());
104 let (a1, a2, scale) = matching_scales::<N>(self.scale, other.scale);
105 QFlag {
106 basis: self.basis,
107 data: &self.data * a1 - &other.data * a2,
108 scale,
109 expr: self.expr.clone() - other.expr.clone(),
110 }
111 }
112}
113
114impl<N, F> Sub for QFlag<N, F>
115where
116 N: Clone + Num + FromPrimitive + ScalarOperand,
117 F: Flag,
118{
119 type Output = Self;
120
121 fn sub(self, other: Self) -> Self::Output {
122 &self - &other
123 }
124}
125
126impl<N, F: Flag> Neg for QFlag<N, F>
127where
128 N: Clone + Neg<Output = N>,
129{
130 type Output = Self;
131
132 fn neg(self) -> Self::Output {
133 Self {
134 basis: self.basis,
135 data: -self.data,
136 scale: self.scale,
137 expr: -self.expr,
138 }
139 }
140}
141
142impl<'a, N, F> Neg for &'a QFlag<N, F>
143where
144 N: Clone + Neg<Output = N>,
145 F: Flag,
146{
147 type Output = QFlag<N, F>;
148
149 fn neg(self) -> Self::Output {
150 QFlag {
151 basis: self.basis,
152 data: -self.data.clone(),
153 scale: self.scale,
154 expr: -self.expr.clone(),
155 }
156 }
157}
158
159impl<N, F> Mul<N> for QFlag<N, F>
161where
162 N: Num + ScalarOperand + Display,
163 F: Flag,
164{
165 type Output = Self;
166
167 fn mul(self, rhs: N) -> Self::Output {
168 Self {
169 expr: Expr::num(&rhs) * self.expr.clone(),
170 basis: self.basis,
171 data: self.data * rhs,
172 scale: self.scale,
173 }
174 }
175}
176
177impl<N, F> Pow<usize> for &QFlag<N, F>
178where
179 N: Num + Clone + FromPrimitive + Display,
180 F: Flag,
181{
182 type Output = QFlag<N, F>;
183
184 fn pow(self, n: usize) -> QFlag<N, F> {
185 match n {
186 0 => self.basis.with_size(self.basis.t.size).one(),
187 1 => self.clone(),
188 n => {
189 let mut res = self * self;
190 for _ in 2..n {
191 res = &res * self
192 }
193 res
194 }
195 }
196 }
197}
198
199impl<N, F: Flag> Display for IneqMeta<N, F>
200where
201 N: Display,
202{
203 fn fmt(&self, f: &mut Formatter) -> Result {
204 write!(
205 f,
206 "{}\t{} {}",
207 self.flag_expr,
208 if self.equality { '=' } else { '≥' },
209 self.bound_expr
210 )
211 }
212}
213
214impl<N, F: Flag> Display for Ineq<N, F>
215where
216 N: Display,
217{
218 fn fmt(&self, f: &mut Formatter) -> Result {
219 self.meta.fmt(f)
220 }
221}
222
223fn quadratic_form<N>(lhs: &Array1<N>, matrix: &CsMat<u32>, rhs: &Array1<N>) -> N
225where
226 N: Num + Clone + FromPrimitive,
227{
228 assert_eq!(lhs.len(), matrix.rows());
229 assert_eq!(rhs.len(), matrix.cols());
230 let mut res = N::zero();
231 for (v, (i, j)) in matrix {
232 res = res + (N::from_u32(*v).unwrap() * lhs[i].clone() * rhs[j].clone());
233 }
234 res
235}
236
237fn vector_matrix_mul<N>(matrix: &CsMatView<u32>, vec: &Array1<N>) -> Array1<N>
238where
239 N: Num + Clone + FromPrimitive,
240{
241 assert_eq!(vec.len(), matrix.cols());
242 let mut res: Array1<N> = Array1::zeros(matrix.rows());
243 for (&v, (i, j)) in matrix {
244 res[i] = res[i].clone() + N::from_u32(v).unwrap() * vec[j].clone();
245 }
246 res
247}
248
249fn multiply<N>(lhs: &Array1<N>, table: &[CsMat<u32>], rhs: &Array1<N>) -> Array1<N>
250where
251 N: Num + Clone + FromPrimitive,
252{
253 let mut res = Array1::<N>::zeros(table.len());
254 for (i, matrix) in table.iter().enumerate() {
255 res[i] = quadratic_form(lhs, matrix, rhs);
256 }
257 res
258}
259
260fn csvec_from_array<N>(array: &Array1<N>) -> CsVec<N>
263where
264 N: Num + Clone,
265{
266 let mut res = CsVec::empty(array.len());
267 for (i, val) in array.iter().enumerate() {
268 if val != &N::zero() {
269 res.append(i, val.clone())
270 }
271 }
272 res
273}
274
275fn array_from_csvec<N>(csvec: &CsVec<N>) -> Array1<N>
277where
278 N: Num + Clone,
279{
280 let mut res = vec![N::zero(); csvec.dim()];
281 csvec.scatter(&mut res);
282 Array1::from(res)
283}
284
285impl<N, F> QFlag<N, F>
287where
288 N: Num + Clone + FromPrimitive,
289 F: Flag,
290{
291 fn raw_expand(&self, operator: &CsMat<u32>, outbasis: Basis<F>, denom: u32) -> Self {
292 Self {
293 basis: outbasis,
294 data: vector_matrix_mul(&operator.view(), &self.data),
295 scale: self.scale * denom as u64,
296 expr: self.expr.clone(),
297 }
298 }
299 fn raw_multiply(&self, table: &[CsMat<u32>], other: &Self, denom: u32) -> Self {
300 assert_eq!(self.basis.t, other.basis.t);
301 Self {
302 basis: self.basis * other.basis,
303 data: multiply(&self.data, table, &other.data),
304 scale: self.scale * denom as u64 * other.scale,
305 expr: Expr::mul(self.expr.clone(), other.expr.clone()),
306 }
307 }
308 fn raw_untype(
309 &self,
310 untype_flag: &[usize],
311 untype_count: &[u32],
312 outbasis: Basis<F>,
313 outbasis_size: usize,
314 denom: u32,
315 ) -> Self {
316 assert_eq!(untype_flag.len(), untype_count.len());
317 let mut data = Array1::<N>::zeros(outbasis_size);
318 for (i, v) in self.data.iter().enumerate() {
319 data[untype_flag[i]] =
320 data[untype_flag[i]].clone() + v.clone() * N::from_u32(untype_count[i]).unwrap()
321 }
322 Self {
323 basis: outbasis,
324 data,
325 scale: self.scale * denom as u64,
326 expr: self.expr.clone().unlab(),
327 }
328 }
329}
330
331fn untype_matrix<N>(untype_flag: &[usize], untype_count: &[u32], outbasis_size: usize) -> CsMat<N>
332where
333 N: Num + FromPrimitive + Clone,
334{
335 let inbasis_size = untype_flag.len();
336 let shape = (outbasis_size, inbasis_size);
337 let mut trimat = TriMat::with_capacity(shape, inbasis_size);
338 for i in 0..untype_flag.len() {
339 trimat.add_triplet(untype_flag[i], i, N::from_u32(untype_count[i]).unwrap())
340 }
341 trimat.to_csr()
342}
343
344impl<'a, N, F> Mul for &'a QFlag<N, F>
347where
348 N: Num + Clone + FromPrimitive,
349 F: Flag,
350{
351 type Output = QFlag<N, F>;
352
353 fn mul(self, other: Self) -> QFlag<N, F> {
354 let split = SplitCount::from_input(&self.basis, &other.basis);
355 self.raw_multiply(&split.get(), other, split.denom())
356 }
357}
358
359impl<N, F> Mul for QFlag<N, F>
360where
361 N: Num + Clone + FromPrimitive,
362 F: Flag,
363{
364 type Output = Self;
365
366 fn mul(self, other: Self) -> Self {
367 &self * &other
368 }
369}
370
371impl<N, F: Flag> QFlag<N, F> {
372 pub fn expand(&self, outbasis: Basis<F>) -> Self
374 where
375 N: Num + Clone + FromPrimitive,
376 {
377 let subflag = SubflagCount::from_to(self.basis, outbasis);
378 self.raw_expand(&subflag.get(), outbasis, subflag.denom())
379 }
380 pub fn untype(&self) -> Self
382 where
383 N: Num + Clone + FromPrimitive,
384 {
385 let unlabeling = Unlabeling::<F>::total(self.basis.t);
386 let size = self.basis.size;
387 let outbasis = self.basis.with_type(Type::empty());
388 let unlabel = Unlabel { unlabeling, size };
389 let (unlab_flag, unlab_count) = unlabel.get();
390 self.raw_untype(
391 &unlab_flag,
392 &unlab_count,
393 outbasis,
394 outbasis.get().len(),
395 unlabel.denom(),
396 )
397 }
398 pub fn with_expr(mut self, expr: Expr<N, F>) -> Self {
400 self.expr = expr;
401 self
402 }
403 pub fn named(mut self, name: String) -> Self {
405 self.expr = self.expr.named(name);
406 self
407 }
408 pub fn no_scale(mut self) -> Self
410 where
411 N: FromPrimitive + DivAssign<N> + ScalarOperand,
412 {
413 self.data /= N::from_u64(self.scale).unwrap();
414 self.scale = 1;
415 self
416 }
417 pub fn map<G, M>(&self, g: G) -> QFlag<M, F>
418 where
419 G: Fn(&N) -> M,
420 {
421 QFlag {
422 basis: self.basis,
423 data: self.data.map(&g),
424 scale: self.scale,
425 expr: self.expr.map(&g),
426 }
427 }
428}
429
430impl<N, F> QFlag<N, F>
432where
433 N: Num + FromPrimitive + Clone + Display,
434 F: Flag,
435{
436 pub fn at_least(&self, x: N) -> Ineq<N, F> {
438 Ineq {
439 meta: IneqMeta {
440 basis: self.basis,
441 flag_expr: self.expr.clone(),
442 bound_expr: Expr::num(&x),
443 equality: false,
444 forall: None,
445 scale: self.scale,
446 },
447 data: vec![IneqData {
448 flag: csvec_from_array(&self.data),
449 bound: x * N::from_u64(self.scale).unwrap(),
450 }],
451 }
452 }
453 pub fn at_most(&self, x: N) -> Ineq<N, F>
455 where
456 N: Clone + Neg<Output = N>,
457 {
458 (-self.clone()).at_least(-x)
459 }
460 pub fn non_negative(&self) -> Ineq<N, F>
462 where
463 N: Num,
464 {
465 self.at_least(N::zero())
466 }
467 pub fn equal(self, n: N) -> Ineq<N, F>
469 where
470 N: Clone + Neg<Output = N>,
471 {
472 self.at_least(n).equality()
473 }
474}
475
476pub fn total_sum_is_one<N, F>(basis: Basis<F>) -> Ineq<N, F>
479where
480 F: Flag,
481 N: Num + Clone + Neg<Output = N> + FromPrimitive + Display,
482{
483 basis.one().equal(N::one())
484}
485
486pub fn flags_are_nonnegative<N, F>(basis: Basis<F>) -> Ineq<N, F>
489where
490 F: Flag,
491 N: Num + Clone + Neg<Output = N>,
492{
493 let n = basis.get().len();
494 let mut data = Vec::with_capacity(n);
495 for i in 0..n {
496 let mut flag = CsVec::empty(n);
497 flag.append(i, N::one());
498 data.push(IneqData {
499 flag,
500 bound: N::zero(),
501 })
502 }
503 let meta = IneqMeta {
504 basis,
505 flag_expr: Expr::Var(0).named(format!("flag(:{})", basis.print_concise())),
506 bound_expr: Expr::Zero,
507 equality: false,
508 forall: Some(VarRange::InBasis(basis)),
509 scale: 1,
510 };
511 Ineq { meta, data }
512}
513
514#[derive(Clone, Debug)]
516pub(crate) struct IneqMeta<N, F: Flag> {
518 pub basis: Basis<F>,
521 pub flag_expr: Expr<N, F>,
523 forall: Option<VarRange<F>>,
524 pub bound_expr: Expr<N, F>,
526 pub equality: bool,
528 scale: u64,
529}
530
531impl<N: Clone, F: Flag> IneqMeta<N, F> {
532 fn opposite(self) -> Self {
533 Self {
534 basis: self.basis,
535 flag_expr: self.flag_expr.neg(),
536 bound_expr: self.bound_expr.neg(),
537 equality: self.equality,
538 forall: self.forall,
539 scale: self.scale,
540 }
541 }
542 fn one_sided_expr(&self) -> Expr<N, F> {
543 Expr::sub(self.flag_expr.clone(), self.bound_expr.clone())
544 }
545
546 fn multiply(&self, rhs_basis: Basis<F>, rhs_expr: Expr<N, F>) -> Self {
547 let forall = if let Expr::Var(_) = rhs_expr {
548 match self.forall {
549 None => Some(VarRange::InBasis(rhs_basis)),
550 Some(_) => unimplemented!(),
551 }
552 } else {
553 self.forall.clone()
554 };
555 Self {
556 basis: self.basis * rhs_basis,
557 flag_expr: Expr::mul(self.one_sided_expr(), rhs_expr),
558 bound_expr: Expr::Zero,
559 equality: self.equality,
560 forall,
561 scale: self.scale * SplitCount::from_input(&self.basis, &rhs_basis).denom() as u64,
562 }
563 }
564
565 fn untype(&self) -> Self {
566 Self {
567 basis: self.basis.with_type(Type::empty()),
568 flag_expr: Expr::unlab(self.flag_expr.clone()),
569 bound_expr: self.bound_expr.clone(),
570 equality: self.equality,
571 forall: self.forall.clone(),
572 scale: self.scale * Unlabel::total(self.basis).denom() as u64,
573 }
574 }
575
576 pub(crate) fn latex(&self, names: &mut Names<N, F>) -> String
577 where
578 N: Display,
579 {
580 format!(
581 "{}{} {} {}",
582 if let Some(ref range) = self.forall {
583 range.latex(names)
584 } else {
585 String::new()
586 },
587 self.flag_expr.latex(names),
588 if self.equality { "=" } else { "\\geq" },
589 self.bound_expr.latex(names),
590 )
591 }
592}
593
594#[derive(Clone, Debug)]
595pub(crate) struct IneqData<N> {
599 pub flag: CsVec<N>,
601 pub bound: N,
603}
604
605impl<N> IneqData<N>
606where
607 N: Num + Clone,
608{
609 fn opposite(self) -> Self
610 where
611 N: Neg<Output = N>,
612 {
613 let mut flag = self.flag;
614 flag.map_inplace(|x| -x.clone());
615 Self {
616 flag,
617 bound: -self.bound,
618 }
619 }
620 fn one_sided(self) -> Self
621 where
622 N: Neg<Output = N>,
623 {
624 if self.bound == N::zero() {
625 self
626 } else {
627 let n = self.flag.dim();
630 let mut flag = CsVec::empty(n);
631 flag.reserve(n);
632 let mut next_j = 0;
633 for (i, val) in self.flag.iter() {
634 for j in next_j..i {
635 flag.append(j, -self.bound.clone())
636 }
637 flag.append(i, val.clone() - self.bound.clone());
638 next_j = i + 1;
639 }
640 for j in next_j..n {
641 flag.append(j, -self.bound.clone())
642 }
643 Self {
644 flag,
645 bound: N::zero(),
646 }
647 }
648 }
649 fn untype(&self, untype_matrix: &CsMat<N>, denom: u32) -> Self
650 where
651 N: Clone + Num + Default + MulAcc + Send + Sync + FromPrimitive,
652 {
653 Self {
654 flag: untype_matrix * &self.flag,
655 bound: self.bound.clone() * N::from_u32(denom).unwrap(),
656 }
657 }
658 fn multiply_by_all(self, table: &[CsMat<N>], acc: &mut Vec<Self>)
660 where
661 N: Num + Clone + Send + Sync + MulAcc + Default + Neg<Output = N>,
662 {
663 if let Some(other_size) = table.first().map(|mat| mat.cols()) {
664 let one_sided = self.one_sided();
665 let mut flags: Vec<CsVec<N>> = vec![CsVec::empty(table.len()); other_size];
666 for (i, mat) in table.iter().enumerate() {
667 let vec: CsVec<N> = &mat.transpose_view() * &one_sided.flag.view();
668 for (j, val) in vec.iter() {
669 flags[j].append(i, val.clone())
670 }
671 }
672 for flag in flags {
673 let ineq_data = Self {
674 flag,
675 bound: N::zero(),
676 };
677 acc.push(ineq_data)
678 }
679 }
680 }
681}
682
683#[derive(Clone, Debug)]
684pub struct Ineq<N, F: Flag> {
688 pub(crate) meta: IneqMeta<N, F>,
690 pub(crate) data: Vec<IneqData<N>>,
692}
693
694impl<N, F> Ineq<N, F>
695where
696 N: Clone + Num,
697 F: Flag,
698{
699 pub fn opposite(self) -> Self
701 where
702 N: Neg<Output = N>,
703 {
704 Self {
705 meta: self.meta.opposite(),
706 data: self.data.into_iter().map(|x| x.opposite()).collect(),
707 }
708 }
709 pub fn equality(mut self) -> Self {
711 self.meta.equality = true;
712 self
713 }
714
715 pub fn relaxed(mut self, eps: N) -> Self
717 where
718 N: SubAssign,
719 {
720 for ineq in &mut self.data {
721 ineq.bound -= eps.clone()
722 }
723 self
724 }
725 pub fn lhs(&self, i: usize) -> QFlag<N, F> {
727 assert!(i < self.data.len());
728 QFlag {
729 basis: self.meta.basis,
730 data: array_from_csvec(&self.data[i].flag),
731 scale: self.meta.scale,
732 expr: self.meta.flag_expr.substitute_option(&self.meta.forall, i),
733 }
734 }
735 pub fn check(&self)
736 where
737 N: Debug + Neg<Output = N> + Clone + FromPrimitive + ScalarOperand + Display,
738 {
739 for i in 0..self.data.len() {
740 let x = self.lhs(i);
741 assert_eq!(x, x.expr.eval());
742 }
743 }
744}
745
746impl<N, F> Ineq<N, F>
747where
748 N: Num + Clone + Send + Sync + Default + FromPrimitive + AddAssign + std::iter::Sum + MulAcc,
749 F: Flag,
750{
751 pub fn untype(&self) -> Self {
753 let unlabeling = Unlabeling::<F>::total(self.meta.basis.t);
754 let size = self.meta.basis.size;
755 let unlabel = Unlabel { unlabeling, size };
756 let (unlab_f, unlab_c) = unlabel.get();
757 let outbasis_size = unlabel.output_basis().get().len();
758 let unlab_matrix = untype_matrix(&unlab_f, &unlab_c, outbasis_size);
759 let denom = unlabel.denom();
760 let mut data = Vec::new();
762 for i in &self.data {
763 let f = i.untype(&unlab_matrix, denom);
764 data.push(f)
765 }
766 Self {
767 meta: self.meta.untype(),
768 data,
769 }
770 }
771 pub fn multiply_by_all(self, outbasis: Basis<F>) -> Self
774 where
775 N: Neg<Output = N>,
776 {
777 let b = outbasis / self.meta.basis;
778 let splitcount = SplitCount::from_input(&self.meta.basis, &b);
779 let table: Vec<CsMat<N>> = splitcount
780 .get()
781 .iter()
782 .map(|m| m.map(|&x| N::from_u32(x).unwrap()))
783 .collect();
784 let mut data = Vec::new();
786 for ineq in self.data {
787 ineq.multiply_by_all(&table, &mut data)
788 }
789 Self {
791 data,
792 meta: self.meta.multiply(b, Expr::Var(0)),
793 }
794 }
795 pub fn multiply_and_unlabel(self, outbasis: Basis<F>) -> Self
798 where
799 N: Neg<Output = N>,
800 {
801 assert_eq!(outbasis.t, Type::empty());
802 let unlabeling = Unlabeling::total(self.meta.basis.t);
803 let other = outbasis.with_type(self.meta.basis.t) / self.meta.basis;
804 let splitcount = SplitCount::from_input(&self.meta.basis, &other);
805 let operator = MulAndUnlabel {
806 split: splitcount,
807 unlabeling,
808 };
809 let table: Vec<CsMat<N>> = operator
811 .get()
812 .iter()
813 .map(|m| m.map(|&x| N::from_i64(x).unwrap()))
814 .collect();
815 let mut data = Vec::new();
817 for ineq in self.data {
819 ineq.multiply_by_all(&table, &mut data)
820 }
821 Self {
822 data,
823 meta: self.meta.multiply(other, Expr::Var(0)).untype(),
824 }
825 }
826}
827
828pub fn flag<N, F>(f: &F) -> QFlag<N, F>
830where
831 N: Num + Clone,
832 F: Flag,
833{
834 Basis::new(f.size()).flag(f)
835}
836
837pub fn flag_typed<N, F>(f: &F, type_size: usize) -> QFlag<N, F>
840where
841 N: Num + Clone,
842 F: Flag,
843{
844 let flag = f.canonical_typed(type_size);
845 let type_flag = flag.induce(&(0..type_size).collect::<Vec<_>>()); let t = Type::from_flag(&type_flag);
847 let basis = Basis::new(f.size()).with_type(t);
848 basis.flag(&flag)
849}
850
851#[cfg(test)]
852mod tests {
853 use super::*;
854 use crate::flags::Graph;
855 use ndarray::array;
856 #[test]
857 fn test_internals() {
858 assert_eq!(matching_scales(15, 12), (4, 5, 60));
860 assert_eq!(matching_scales(2, 24), (12, 1, 24));
861 let (c1, c2, scale): (u64, u64, _) = matching_scales(1788, 2444);
862 let big = 1788 * 2444 * 1048;
863 assert_eq!((big * c1) / scale, big / 1788);
864 assert_eq!((big * c2) / scale, big / 2444);
865 }
866 #[test]
867 fn test_qflags() {
868 let qflag = QFlag {
869 basis: Basis::<Graph>::new(1),
870 data: array![3., 2., -5., 45.14],
871 scale: 42,
872 expr: Expr::Zero,
873 };
874 assert_eq!(qflag.clone().no_scale(), qflag)
875 }
876 #[test]
877 fn test_qflag_pows() {
878 let b = Basis::new(2).with_type(Type::new(1, 0));
879 let v: QFlag<i128, Graph> = b.random();
880 assert_eq!(v.pow(0), b.with_size(1).one());
881 assert_eq!(v.pow(1), v);
882 assert_eq!(v.pow(2), &v * &v);
883 assert_eq!(v.pow(3), &v * &(&v * &v));
884 }
885}