Performing double induction in Welder - leon

I'm trying to proof a property by double induction using Welder. The definitions are taken from here. A related question that gives more details of the theory can be found here. Anyways I just need some portion to show my problem:
Basically, I'm working with expressions that take the form of an integer, POP(i,p) and POW(i,p,q). There is a property of normality on them call it n. I want to proof that if n(x) && n(y) then n(x+y).
Let's look at the specific case x = POP(i,p), y = POP(j,q) then x+y is defined as follows:
if i = j then pop(i,p+q)
if i > j then pop(j,POP(i-j,p)+q)
if i < j then pop(i,POP(j-i,q)+p)
where pop is a function that mimics POP constructs with some slight differences.
I perform the proof by double induction in Welder as follows:
def property(x: Expr) = {
forall("y" :: shf){ case (y) =>
(n(x) && n(y)) ==> n(x+y)
}
}
structuralInduction(property _, "x" :: shf) { case (ihs1, goal1) =>
val xi = ihs1.expression
xi match{
...
The relevant case I want to focus is the following:
case C(`POP_ID`,i,pshf) =>
def popproperty(y: Expr) = {
n(y) ==> n(xi+y)
}
structuralInduction(popproperty _, "y" :: shf) { case (ihs2, goal2) =>
val yi = ihs2.expression
implI(n(yi)){ axioms2 =>
yi match{
case C(`constshfID`, fc) => andI(ihs1.hypothesis(pshf),axioms1)
case C(`POP_ID`,j,qshf) =>
andI(
implE(forallE(normpop1Lemma)(i,normadd(pshf,qshf)))( g =>
andI(implE(forallE(ihs1.hypothesis(pshf))(qshf))( g =>
andI(axioms1,axioms2)), axioms1, axioms2)),
implI(i > j){ gt =>
implE(forallE(normpop1Lemma)(i,normadd(POP(i-j,pshf),qshf)))( g =>
andI(implE(ihs2.hypothesis(qshf))(g => axioms2),axioms1,axioms2,gt))
},
implI(i < j){ lt =>
implE(forallE(normpop1Lemma)(i,normadd(POP(j-i,pshf),qshf)))( g =>
andI(implE(ihs2.hypothesis(qshf))(g => axioms2),axioms1,axioms2,lt))
}
)
Here normpop1Lemma states that for having n(pop(i,p)) you need i to be natural and p normal. However, I find that the second case is not proved. In fact I would need to generalize the second property to
def popproperty(y: Expr) = {
forall("x" :: shf){
n(y) ==> n(x+y)
}
}
but then am I not breaking induction? Can I actually solve the cases i > j and i < j by doing so? (more to come while I experiment)
Edit
Currently, I can induct first on y and then on x and for the POP-POP case I can show the cases where i = j and i > j but the i < j is not. I thought it could work by using that POP(j-i,q) + p = p + POP(j-i,q) but it doesn't.
Instead, now I'm trying to proof two different properties assuming in each that the one of the cases cannot hold (either the i < j or the i > j).

Hmm, I would expect your proof to look something more like this:
structuralInduction((x: Expr) =>
forall("y" :: shf)(y => (n(x) && n(y)) ==> n(x+y)), "x" :: shf
) { case (ihs1, g1) =>
structuralInduction((y: Expr) =>
(n(ihs1.expression) && n(y)) ==> n(ihs1.expression+y), "y" :: shf
) { case (ihs2, g2) =>
implI(n(ihs1.expression) && n(ihs2.expression)) { normalXY =>
(ihs1.expression, ihs2.expression) match {
case (C(`POP_ID`,i,pshf), C(`POP_ID`,j,qshf)) => andI(
... // case (i == j)
... // case (i > j)
implI(i < j) { iLtJ =>
andI(
... // stuff using normprop1Lemma
implE(forallE(ihs1.hypothesis(pshf))(normadd(POP(j-i,qshf)) {
g => // the reason why n(normadd(POP(j-i,qshf)) and n(pshf)
},
... // invoke some lemma showing x+y == y+x
)
}
)
}
}
}
}
Here we use the induction hypothesis from the outer induction since we're performing induction on p \in x. I assume normprop1Lemma is telling you that normadd(POP(j-i,qshf)) is in normal form. You will probably need some lemma stating that p \in x is in normal form if x is in normal form.
Hope this helps!

Related

Printing mathematical series concisely in Raku

Mathematical series, take for example the consecutive sequence represented here as an array:
my #seq = my $a=0, {++$a} ... *;
for #seq[^10].kv {state $f=0; ($^k < 4 or $^k > 7) ?? say "a$^k = " ~ $^v !! (say "..." if $f ne 1; $f=1) };
Prints:
a0 = 0
a1 = 1
a2 = 2
...
a8 = 8
a9 = 9
1- Is there a simple way to drop just the first element i.e. a0 = 0 from the printed output?
2- Could this code be made more idiomatic?
This might be a bit more idiomatic:
my #seq = 0, *+1 ... *;
say #seq[^4], #seq[7..10]
You don't need to use a lexical variable within the sequence; either Whatever or placeholder variables can safely be used within sequences. Then you can simply select the elements of the sequence you want printed.
Which returns «(0 1 2 3)(7 8 9 10)␤»
You can skip the first N values on any Iterable or Sequence with skip:
for (^5).skip(3) {
.say
}
# 3
# 4
If you don't specify a number, it will skip only one element.
A barebones solution
Let's start with a very simple solution for printing a gist of a sequence. It doesn't deal with the specifics you've added to your question but it's a good starting point:
sub seq-range-gist ( #seq ) {
my #pairs = #seq.pairs;
join "\n", #pairs.head(3)».gist, '...', #pairs.tail(2)».gist
}
Unlike .kv, which converts its invocant into the form key1, value1, key2, value2, key3, value3, ..., i.e. 6 elements if its invocant contains 3 elements, .pairs converts its invocant into the form key1 => value1, key2 => value2, key3 => value3, ....
I used .pairs instead of .kv partly because it meant I could just use ».gist later on in the code to effortlessly get a nice key1 => value1 display for each element. We'll modify that below but this is a good idiomatic start.
The .head and .tail calls are the idiomatic way to create small lists of the first and last N elements from an invocant list (provided it's not lazy; more about that in a mo).
Given this initial solution, say seq-range-gist (0,1 ... Inf)[^10] displays:
0 => 0
1 => 1
2 => 2
...
8 => 8
9 => 9
Next, we want to be able to "drop just the first element ... from the printed output". Unfortunately say seq-range-gist (0,1 ... Inf)[1..9] displays:
0 => 1
1 => 2
2 => 3
...
7 => 8
8 => 9
We want the number on the left of the => to retain the numbering of the original sequence. To enable this we split the underlying sequence from the range that we want extracted. We add a second parameter/argument #range, and append [#range] to the second line of the sub:
sub seq-range-gist ( #seq, #range ) {
my #pairs = #seq.pairs[#range];
Now we can write say seq-range-gist (0,1 ... Inf), 1..9 to display:
1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9
In your question you used the format aINDEX = VALUE rather than INDEX => VALUE. To allow customization of the gist, we add a third &gist routine parameter/argument and invoke that instead of the built in .gist method:
sub seq-range-gist ( #seq, #range, :&gist ) {
my #pairs = #seq.pairs[#range];
join "\n", #pairs.head(3)».&gist, '...', #pairs.tail(2)».&gist
}
Note how the "method" invocations in the body of seq-range-gist sub are now .&gist, not .gist. The syntax .&foo invokes a sub &foo (which is typically invoked by writing just foo), passing the invocant on the left of the . as a $_ argument to the sub.
Note also that I've made the &gist parameter a named one by preceding it with a :.
So now say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" } displays:
a1 = 1
a2 = 2
a3 = 3
...
a8 = 8
a9 = 9
Adding polish
The rest of this answer is bonus material for readers who care about polish.
say seq-range-gist (0, 1, 2, 3), ^3 displays:
0 => 0
1 => 1
2 => 2
...
1 => 1
2 => 2
Oops. And even if there were more pairs than the head and tail combined, so at least we didn't get repeated lines, it'd still be pointless using the head, ..., tail approach to elide just one or two elements. Let's change the last statement in the sub body to eliminate these issues:
join "\n",
#pairs < $head + $tail + 3 # Of course, the 3 is a bit arbitrary
?? #pairs».&gist
!! (#pairs.head($head)».&gist, '...', #pairs.tail($tail)».&gist)
Next, it would be nice if the sub did something useful if called without a range or gist. We can mostly fix that by giving the #range and &gist parameters suitable defaults:
sub seq-range-gist (
#seq,
#range = #seq.is-lazy ?? ^100 !! ^#seq,
:&gist = { .gist }
) {
If #seq is not lazy, then #range defaults to the full range of #seq. If #seq is infinite (in which case it's also lazy), then the upto 100 default is fine. But what if #seq is lazy but yields less than 100 defined values? To cover this case we append .grep: *.value.defined to the #pairs declaration:
my #pairs = #seq.pairs[#range].grep: *.value.defined;
Another simple improvement would be optional head and tail parameters, leading to a final polished solution:
sub seq-range-gist (
#seq,
#range = #seq.is-lazy ?? ^100 !! ^#seq,
:$head = 3,
:$tail = 2,
:&gist = { .gist }
) {
my #pairs = #seq.pairs[#range].grep: *.value.defined;
join "\n",
#pairs <= $head + $tail + 2
?? #pairs».&gist
!! (#pairs.head($head)».&gist, '...', #pairs.tail($tail)».&gist)
}
my #seq = my $a=0, {++$a} ... *;
my \i = 0;
say( 'a' ~ (i+$_) Z=> (i+$_) ) for #seq[^5];
print "------\n";
my \j = 1;
say( 'a'.succ ~ (j+$_) Z=> (j+$_) ) for #seq[^5];
Output:
(a0 => 0)
(a1 => 1)
(a2 => 2)
(a3 => 3)
(a4 => 4)
------
(b1 => 1)
(b2 => 2)
(b3 => 3)
(b4 => 4)
(b5 => 5)
I recognize the above doesn't include your 'bespoke' gist ellipsis conditional ( ($^k < 4 or $^k > 7) ), but you seem to have come up with a more elegant way of writing that in the comments. Still (if you don't want to use skip), number keys yourself and include an offset such as i or j indicating how many elements of #seq you wish to skip.
Addendum: Below is an attempt at implementing your 'bespoke' gist ellipsis conditional (using grep):
my #seq = my $a=0, {++$a} ... *;
my \i = 0; my \m = 4; my \n = 7;
do for #seq[^10].grep({4 > $_ or $_ > 7 }) {
say 'a' ~ (i+$_) Z=> (i+$_);
if $_ == 3 {print "...\n"};
}
Output when \i = 0:
(a0 => 0)
(a1 => 1)
(a2 => 2)
(a3 => 3)
...
(a8 => 8)
(a9 => 9)
Output when \i = 1:
(a1 => 1)
(a2 => 2)
(a3 => 3)
(a4 => 4)
...
(a9 => 9)
(a10 => 10)

Create and populate an array of Raku objects?

I chose to redesign a portion of the previous code of mine, in this case, a chessboard, in Perl 6. The first two classes went well (or at least worked, I know so little that I can't speak to their correctness), but I'm stuck with the third. Here is the code:
#!/home/hsmyers/rakudo741/bin/perl6
# board.p6 - Beginnings of a PGN toolset. And place to start learning
# Perl 6/Raku.
use v6d;
#!___________________________________________________________
constant $size = 4;
class Piece {
my Str #namesOfPieces[$size] = <
white-rook white-knight white-bishop white-queen
>;
my Str #abrevsOfPieces[$size] = <
R N B Q K B N R
>;
my Str #symbolsOfPieces[$size] = <
♖ ♘ ♗ ♕ ♔ ♗ ♘ ♖
>;
my Str #codeptsOfPieces[$size] = (
"\x2656", "\x2658", "\x2657", "\x2655",
);
has Str $.name;
has Str $.abrev;
has Str $.symbol;
has Uni $.codept;
submethod BUILD( :$i ) {
$!name = #namesOfPieces[$i];
$!abrev = #abrevsOfPieces[$i];
$!symbol = #symbolsOfPieces[$i];
$!codept = #codeptsOfPieces[$i].NFC;
}
}
class Square {
my Int #colors[$size] = <
1 0 1 0 1 0 1 0
>;
my Str #names[$size] = <
a1 b1 c1 d1 e1 f1 g1 h1
>;
has Int $.color;
has Int $.index;
has Str $.name;
has Piece $.piece;
submethod BUILD( :$i ) {
$!color = #colors[$i];
$!index = $i;
$!name = #names[$i];
$!piece = Piece.new(:i($i));
}
}
class Board is Array {
}
my $p = Piece.new(:i(0));
$p.say;
my $s = Square.new(:i(0));
$s.say;
#!___________________________________________________________
my #b := Board.new(
Square.new(:i(0)),
Square.new(:i(1)),
Square.new(:i(2))
);
say #b;
say #b.WHAT;
When run at the cli, results in:
Piece.new(name => "white-rook", abrev => "R", symbol => "♖", codept => Uni.new(0x2656).NFC)
Square.new(color => IntStr.new(1, "1"), index => 0, name => "a1", piece => Piece.new(name => "white-
rook", abrev => "R", symbol => "♖", codept => Uni.new(0x2656).NFC))
[Square.new(color => IntStr.new(1, "1"), index => 0, name => "a1", piece => Piece.new(name =>
"white-rook", abrev => "R", symbol => "♖", codept => Uni.new(0x2656).NFC)) Square.new(color =>
IntStr.new(0, "0"), index => 1, name => "b1", piece => Piece.new(name => "white-knight", abrev =>
"N", symbol => "♘", codept => Uni.new(0x2658).NFC)) Square.new(color => IntStr.new(1, "1"), index =>
2, name => "c1", piece => Piece.new(name => "white-bishop", abrev => "B", symbol => "♗", codept =>
Uni.new(0x2657).NFC))]
(Board)
The Board class (empty as it is) is all that is left from my attempts so far. Amazingly (at least to me), it provides a degree of workability. It has variously had a "new" and a "BUILD," neither provided a working solution. The current approach doesn't work, considering that the actual count will be 64 and not 4.
My current notion is that I need to build an array of 64 Squares, which in turn will create the necessary pieces. I've tried to add to self with nothing working. Suggestions?
Inheriting from Array is probably not the best design choice here; it reveals and commits to the underlying representation of the Board, which will present refactoring challenges as the code evolves. Rather, I'd suggest that a Board has an Array of Square, which is initialized with Square objects.
Assuming the board is meant to have $size squared places, then you could do something like:
class Board {
has #.squares[$size ** 2];
method TWEAK() {
#!squares = map { Square.new(i => $_ % $size) }, ^($size ** 2);
}
}
That is, take the range from 0 up to but excluding $size squared, and then map each value into a Square instance. (We modulo the index to avoid an index out of bounds in one of the other classes.)
A 2D array may be preferable:
class Board {
has #.squares[$size;$size];
method TWEAK() {
#!squares = (map -> $i { Square.new(:$i) }, ^$size) xx $size;
}
}
Here, we map again, but this time since we're just doing one dimension we drop the modulo. The use of a named $i parameter means we can use the :$i convenience, which is short for :i($i) (there's an opportunity to do that in the code you posted also). We then take that expression producing one row, and use xx to run it $size times in order to get data for every column.
Ultimately, it will probably not be quite so simple as this; perhaps Square should take two constructor arguments, both a numeric and a letter, to form its name. That's probably best done as a map of map. Further, the initialization of Piece instances probably wants to happen in Board too; while it's been a quarter of a century since I last played chess, I'm quite sure not every square has a piece on it at the start of the game.

How can I simplify this horribly nested error handling code in Rust?

I'm writing a function to compute a Summed Area Table of a Vec<Vec<isize>> in Rust, without the use of any external crates. I'm trying to learn to do this as idiomatically as possible, but I'm running into some roadblocks with error handling.
Basically all I'm trying to do is this, which is mentioned on the Wikipedia page:
The summed-area table can be computed efficiently in a single pass
over the image, as the value in the summed-area table at (x, y) is
just:
where i provides values from the grid, and I from the previously
computed values of the table. Obviously, if x or y is 0, then some of
these won't exist, in which case they are replaced with 0.
However, of note is the fact that if I(x, y - 1) does not exist even if y - 1 exists, then the grid we're working with is in fact non-rectangular, and we want to return an NonRectError in that case.
With all that background, here's the code: I need to protect against overflow errors from the subtractions, and return the NonRectError in the special case:
fn compute_summed_area_table(grid: &Vec<Vec<isize>>) -> Result<Vec<Vec<isize>>, NonRectError> {
let mut summed_area_table =
vec![Vec::with_capacity(grid[0].len()); grid.len()];
for (yi, row) in grid.iter().enumerate() {
for (xi, &value) in row.iter().enumerate() {
let (prev_row, prev_column_idx) = (
yi.checked_sub(1).and_then(|i| summed_area_table.get(i)),
xi.checked_sub(1)
);
let summed_values =
value +
// I(x, y - 1)
match prev_row {
None => &0,
Some(prev_row_vec) => match prev_row_vec.get(xi) {
Some(v) => v,
None => return Err(NonRectError { xi, yi })
}
} +
// I(x - 1, y)
(prev_column_idx
.and_then(|i| summed_area_table[yi].get(i))
.unwrap_or(&0)) -
// I(x - 1, y - 1)
(prev_row
.map_or(&0, |r| {
prev_column_idx
.and_then(|i| r.get(i))
.unwrap_or(&0)
}));
summed_area_table[yi].push(summed_values);
}
}
Ok(summed_area_table)
}
// Omitted the definition of NonRectError here, but it is defined.
This code is clearly the definition of sin itself, but I'm not sure which angle to approach simplifying this from - there are so many gosh darn edge cases!
Are there any built-in methods that'll allow me to escape this nested error-checking stuff? Can I return the NonRectError in some easier way than this?
Here are some things you can try:
Use an array, not nested Vecs. With an array, you can guarantee that all the rows have the same width, and NonRectError can't happen. (But maybe you have good reasons to use nested Vecs, so the rest of my examples use nested Vecs.)
The block where you calculate summed_value is pretty long. I'd break it up like this:
// I(x, y - 1)
let north = ...;
// I(x - 1, y)
let west = ...;
// I(x - 1, y - 1)
let northwest = ...;
let summed_values = value + north + west - northwest;
Instead of checked subtraction, it's easier to check if xi and yi are nonzero. Also, .ok_or() is a good way to convert None to an error.
let northwest = match (xi, yi) {
(0, _) => 0,
(_, 0) => 0,
(_, _) => {
// We know xi and yi are nonzero, so we can subtract without checks
summed_area_table.get(yi - 1)
.and_then(|row| row.get(xi - 1))
.ok_or(NonRectError { xi, yi })?
}
};
You could also write that with an if/else chain. They're both idiomatic, it's just a matter of preference. I prefer match because it feels more concise.
let northwest = if xi == 0 {
0
} else if yi == 0 {
0
} else {
// same as above
};

How to declare an abstract function in Inox

I'm proving certain properties on elliptic curves and for that I rely on some functions that deal with field operations. However, I don't want Inox to reason about the implementation of these functions but to just assume certain properties on them.
Say for instance I'm proving that the addition of points p1 = (x1,y1) and p2 = (x2,y2) is commutative. For implementing the addition of points I need a function that implements addition over its components (i.e. the elements of a field).
The addition will have the following shape:
val addFunction = mkFunDef(addID)() { case Seq() =>
val args: Seq[ValDef] = Seq("f1" :: F, "f2" :: F)
val retType: Type = F
val body: Seq[Variable] => Expr = { case Seq(f1,f2) =>
//do the addition for this field
}
(args, retType, body)
}
For this function I can state properties such as:
val addAssociative: Expr = forall("x" :: F, "y" :: F, "z" :: F){ case (x, y, z) =>
(x ^+ (y ^+ z)) === ((x ^+ y) ^+ z)
}
where ^+ is just the infix operator corresponding to add as presented in this other question.
What is a proper expression to insert in the body so that Inox does not assume anything on it while unrolling?
There are two ways you can go about this:
Use a choose statement in the body of addFunction:
val body: Seq[Variable] => Expr = {
choose("r" :: F)(_ => E(true))
}
During unrolling, Inox will simply replace the choose with a fresh
variables and assume the specified predicate (in this case true) on
this variable.
Use a first-class function. Instead of using add as a named function,
use a function-typed variables:
val add: Expr = Variable(FreshIdentifier("add"), (F, F) =>: F)
You can then specify your associativity property on add and prove the
relevant theorems.
In your case, it's probably better to go with the second option. The issue with proving things about an addFunction with a choose body is that you can't substitute add with some other function in the theorems you've shown about it. However, since the second option only shows things about a free variable, you can then instantiate your theorems with concrete function implementations.
Your theorem would then look something like:
val thm = forallI("add" :: ((F,F) =>: F)) { add =>
implI(isAssociative(add)) { isAssoc => someProperty }
}
and you can instantiate it through
val isAssocAdd: Theorem = ... /* prove associativity of concreteAdd */
val somePropertyForAdd = implE(
forallE(thm)(\("x" :: F, "y" :: F)((x,y) => E(concreteAdd)()(x, y))),
isAssocAdd
)

How to prove Dafny count < size

I'm currently learning Dafny. I'm totally comfused by lemma and I dont know how to use it. The tutorial is not that helpful. What if I want to prove
count(a) <= |a|
how should I do it. Thanks for helping.
function count(a: seq<bool>): nat
ensures count(a) <= |a|;
{
if |a| == 0 then 0 else
(if a[0] then 1 else 0) + count(a[1..])
}
You've already proved it! You wrote the property you wanted as a postcondition of the function and Dafny verifies it without complaints. That's it.
You can also use a lemma to prove the property. Here's an example:
function count(a: seq<bool>): nat
{
if |a| == 0 then 0 else
(if a[0] then 1 else 0) + count(a[1..])
}
lemma CountProperty(a: seq<bool>)
ensures count(a) <= |a|
{
}
Again, Dafny verifies the lemma without issuing any complaints, so you have proved it!
It is not correct to assume that Dafny will always prove things for you automatically. Therefore, it's a good idea to learn how to write proofs manually, too. Here's a manual proof of this property. Just to make sure Dafny doesn't try to do induction automatically, I used a directive to turn it off (thus making our lives harder than Dafny normally would):
lemma {:induction false} CountProperty(a: seq<bool>)
ensures count(a) <= |a|
{
// Let's consider two cases, just like the definition of "count"
// considers two cases.
if |a| == 0 {
// In this case, we have:
assert count(a) == 0 && |a| == 0;
// so the postcondition follows easily.
} else {
// By the definition of "count", we have:
assert count(a) == (if a[0] then 1 else 0) + count(a[1..]);
// We know an upper bound on the first term of the addition:
assert (if a[0] then 1 else 0) <= 1;
// We can also obtain an upper bound on the second term by
// calling the lemma recursively. We do that here:
CountProperty(a[1..]);
// The call we just did gives us the following property:
assert count(a[1..]) <= |a[1..]|;
// Putting these two upper bounds together, we have:
assert count(a) <= 1 + |a[1..]|;
// We're almost done. We just need to relate |a[1..]| to |a|.
// This is easy:
assert |a[1..]| == |a| - 1;
// By the last two assertions, we now have:
assert count(a) <= 1 + |a| - 1;
// which is the postcondition we have to prove.
}
}
A nicer way to write a proof like this is to use a verified calculation, which Dafny calls "the calc statement":
lemma {:induction false} CountProperty(a: seq<bool>)
ensures count(a) <= |a|
{
if |a| == 0 {
// trivial
} else {
calc {
count(a);
== // def. count
(if a[0] then 1 else 0) + count(a[1..]);
<= // left term is bounded by 1
1 + count(a[1..]);
<= { CountProperty(a[1..]); } // induction hypothesis gives a bound for the right term
1 + |a[1..]|;
== { assert |a[1..]| == |a| - 1; }
|a|;
}
}
}
I hope that this gets you started.
Program safely,
Rustan