# Constriant vs Index
```rust=
#[qualifiers(MyQ1)]
#[sig(fn(&mut {RVec<Particle>[@len] | 1 <= len}))]
pub fn simulation(vec: &mut RVec<Particle>) {
let n = vec.len();
let mut i = 0;
while i < n {
let mut j = i + 1;
let mut idx = VecBorrows::new(vec);
assert(1 + 1 + 1 == 3);
let a = idx.gett(i);
while j < n {
let b = idx.gett(j);
a.collision(b);
j += 1;
}
i += 1;
}
}
```
## Constraint generic
```rust=
// get: forall av. fn(MultiIdx[p], idx: isize{av(idx)}) -> &T
// ensures MultiIdx[|k| av(k) && k != idx]
let idx = MultiIdx::new(...)
// idx: MultiIdx[|k| true]
idx.get(i); // (1)
// idx: MultiIdx[|k| $k0(k)[i, n] && k != i]
simulation_step(idx, i, i + 1, n) // (2)
pub fn simulation_step(
mut idx: MultiIdx[|k| $k1(k)[j, i, n]],
i: usize,
j: usize,
n: usize
) {
if j >= n {
return;
}
let b = idx.get(j); // (3)
// idx: MultiIdx[|k| $k2(k)[j, i, n] && k != j]
simulation_step(idx, a, j + 1, n); // (4)
}
pub fn sim_step(
mut idx: MultiIdx[@av],
i: usize,
j: usize,
n: usize,
)
requires forall k. j <= k => av(k)
{
if j >= n {
return;
}
// idx: MultiIdx[|k| av(k)] ALSO NEED av(j'), forall j <= j'
let b = idx.get(j);
// idx: MultiIdx[|k| av(k) && k != j]
sim_step(idx, a, j + 1, n);
}
fn get<av: int -> bool>(self: &strg Self[av], idx: usize{ av(idx) }) -> &'a mut T
ensures self: Self[|i| av(i) && i != idx];
fn getI(self: &strg Self[@av], idx: usize{ av(idx) }) -> &'a mut T
ensures self: Self[|i| av(i) && i != idx];
fn sim_base(
)
{
let i = ...;
let n = ...;
let idx = MultiIdx::new(...);
// idx: MultiIdx[|k| true]
let _ = idx.getI(i);
// idx: MultiIdx[|k| true && k != i]
sim_step(idx, i, i + 1, n)
// forall k. k != i <=/=> i + 1 <= k
}
pub fn sim_step(
mut idx: MultiIdx[|k| j <= k],
i: usize,
j: usize,
n: usize,
)
{
if j >= n {
return;
}
// idx: MultiIdx[|k| j <= k]
let b = idx.get(j);
// idx: MultiIdx[|k| j <= k && k != j]
sim_step(idx, a, j + 1, n);
}
// forall i,n.
// $k0(i)[i, n] (1)
// forall k. true <=> $k0(k)[i, n] (1)
// forall k. $k0(k)[i, n] && k != i <=> $k1(k)[i + 1, i, n] (2)
// forall j.
// $k2(j)[j, i, n] (3)
// forall k. $k1(k)[j, i, n] <=> $k2(k)[j, i, n] (3)
// forall k. $k2(k)[j, i, n] && k != j <=> $k1(k)[j + 1, i, n] (4)
//
// $k0(k)[j, i, n] = $k1(k)[j, i, n] = (0 <= k && k < i) || (j <= k && k < n)
```
## Index generic (doesn't work)
```rust
let idx = MultiIdx::new(...)
// idx: MultiIdx[|k| true]
idx.get(i); // (1)
// idx: MultiIdx[|k| ?p0(k) && k != i]
simulation_step1(idx, i, i + 1, n) // (2)
pub fn simulation_step(
mut idx: MultiIdx[?p1],
i: usize,
j: usize,
n: usize
) {
if j >= n {
return;
}
let b = idx.get(j); //(3)
// idx: MultiIdx[|k| ?p2(k) && k != j]
simulation_step1(idx, a, j + 1, n); // (4)
}
// forall i,n.
// ?p0(i) (1)
// forall k. true <=> ?p0(k) (1) ?p0 ≡ |k| true
// forall k. ?p0(k) && k != i <=> ?p1(k) (2) ?p1 ≡ |k| ?p0(k) && k != i
// ?p2(j) (3)
// forall k. ?p1(k) <=> ?p2(k) (3) ?p1 ≡ ?p2
// forall k. ?p2(k) && k != j <=> ?p1(k) (4)
```
## Generalize
```rust
let idx = MultiIdx::new(...)
// idx: MultiIdx[|k| true]
idx.get(i);
// idx: MultiIdx[|k| true && k != i]
simulation_step1(idx, i + 1) // (1)
pub fn simulation_step(
// mut idx: MultiIdx[@p],
mut idx: MultiIdx[|k| (0 <= k && k < i) || (j <= k && k < n) ],
i: usize,
j: usize,
n: usize,
)
requires forall k. j <= k => p(k)
{
if j >= n {
return;
}
let b = idx.get(j); // (2)
// idx: MultiIdx[|k| p(k) && k != j]
a.collision(b);
simulation_step1(idx, a, j + 1); // (3)
}
// forall i, n.
// forall k. i + 1 <= k => k != i (1)
// forall p, j.
// H: (forall k. j <= k => p(k))
// p(j) (2) by (H j)
// forall k. j + 1 <= k => p(k) && k != j (3) by (H k)
```
## Mixing Constraint and index
```rust
struct S[p: int -> bool];
fn negate(s: S[@p]) -> S[|x| !p(x)];
fn constraint_generic<refine p : int -> bool>(x: S) -> S[p];
fn require_true(x: S[|x| true]);
let a = constraint_generic(x); // S[|x| $k(x)]
let b = a.negate(); // S[|x| !$k(x)]
require_true(b); // !k(x) <=> true
```
## Index generics cannot be flow sensitive
```rust
struct S[f: int -> int];
fn add(x: i32) -> S[|y| y + x];
fn foo(b: bool) {
let s = if b {
add(2);
} else {
add(1);
};
}
```