The Hilbert epsilon operator - operator-keyword

Why you can use the Hilbert epsilon operator in a method and in a function, but not in a "function method"?
method choose<T>(s:set<T>) returns (x:T)
requires s != {}
{
var z :| z in s;
return z;
}
function choose'<T>(s:set<T>):T
// function method choose'<T>(s:set<T>):T // Activate this line and comment the previous line to see the error
requires s != {}
{
var z :| z in s;
z
}

In order for the Hilbert epsilon operator, also known in Dafny as the let-such-that expression,
var z :| P; E
to be compilable, the constraint P must determine z uniquely. In your case, the constraint P is z in s, which does not determine z uniquely except for singleton sets.
If s were of type set<int>, you can (inefficiently) live up to this requirement by changing your choose' function to:
function method choose'<T>(s:set<int>):int
requires s != {}
{
var z :| z in s && forall y :: y in s ==> z <= y;
z
}
Almost. You need to convince Dafny there is such a z. You can do that in a lemma. Here's a probably-longer-than-necessary-but-the-first-thing-I-got-working lemma that does that. Note that the lemma also uses the Hilbert operator, but in a statement context, so the uniqueness requirement does not apply.
function method choose'<T>(s:set<int>):int
requires s != {}
{
HasMinimum(s);
var z :| z in s && forall y :: y in s ==> z <= y;
z
}
lemma HasMinimum(s: set<int>)
requires s != {}
ensures exists z :: z in s && forall y :: y in s ==> z <= y
{
var z :| z in s;
if s == {z} {
// the mimimum of a singleton set is its only element
} else if forall y :: y in s ==> z <= y {
// we happened to pick the minimum of s
} else {
// s-{z} is a smaller, nonempty set and it has a minimum
var s' := s - {z};
HasMinimum(s');
var z' :| z' in s' && forall y :: y in s' ==> z' <= y;
// the minimum of s' is the same as the miminum of s
forall y | y in s
ensures z' <= y
{
if
case y in s' =>
assert z' <= y; // because z' in minimum in s'
case y == z =>
var k :| k in s && k < z; // because z is not minimum in s
assert k in s'; // because k != z
}
}
}
Unfortunately, the type of your s is not set<int>. I don't know how to get a unique value from a general set. :(
For information about why the uniqueness requirement is important in compiled expressions see this paper.
Rustan

Related

N-Queens problem using answer set programming

trying to learn answer set programming and decided to give the n-queens problem a go. This is what I have so far:-
% Queens are placed on an n x n chess board.
% Each queens must not attack each other.
% Represent the chess board squares.
square(1..n, 1..n).
% Place a Queen on one chess square.
queen(1..n).
5 { on(Q, X, Y) : queen(Q), square(X, Y) } 5.
:- queen(Q), on(Q, X, Y), on(Q, X', Y'), X != X', Y != Y'.
% Make sure each square only has one queen.
:- queen(Q), queen(Q'), on(Q, X, Y), on(Q', X, Y), Q != Q'.
% A Queen attacks another if both are on the same vertical, horizontal or diagonal.
:- on(Q, X, Y), on(Q', X, Y'), Q != Q', Y != Y'.
:- on(Q, X, Y), on(Q', X', Y), Q != Q', X != X'.
:- on(Q, X, Y), on(Q', X', Y'), Q != Q', |X-X'| = |Y-Y'|.
I am using clingo with the command - clingo n-queens.lp --const n=5 --models 2. The output that I get is:-
As you can see, despite stating that the queens should not be in the same column or row, the output contains some. What is wrong with the program?
Do you guys have some tips in general for getting better at ASP? I feel like I always get stuck when trying to describe the knowledge in ASP syntax.
There are 2 issues with your program:
5 { on(Q, X, Y) : queen(Q), square(X, Y) } 5.
should be
n { on(Q, X, Y) : queen(Q), square(X, Y) } n.
if you want it for anything else than n=5 and
:- queen(Q), on(Q, X, Y), on(Q, X', Y'), X != X', Y != Y'.
should be
:- queen(Q), on(Q, X, Y), on(Q, X', Y'), X != X'.
:- queen(Q), on(Q, X, Y), on(Q, X', Y'), Y != Y'.
This is because you want to write :- ..., X != X' OR Y != Y' and not :- ..., X != X' AND Y != Y' - causing this constraint to take effect only if both values differ.
For the output I added also:
#show on/3.
tested with the online version of clingo (added #const n=5. to the code):
clingo version 5.5.0
Reading from stdin
Solving...
Answer: 1
on(2,3,3) on(4,4,5) on(5,2,1) on(1,1,4) on(3,5,2)
SATISFIABLE
Please note that the online version provides a very neat example of n-queens.
Your program works but there is room for improvement. If you want to implement efficient code, a first hint would be to reduce the size of the ground logic program. This can be done - for example - by reducing the arity of predicates.

How to convert logical conditions to a variable of a function

I would like to achieve the above for the following:
Rn = 0.009; % Resolution of simulation (in m^3)
Xs = -1 : Rn : 1;
Ys = -1 : Rn : 1;
Zs = 0 : Rn : 1;
[X Y Z] = meshgrid(Xs, Ys, Zs);
alpha = atan2(Z,X);
ze = x.^2 + y.^2; % define some condition
m = 0.59; % manual input
cond = (pi/3 <= alpha) & ...
(alpha <= (2*pi/3)) & ...
(m <= Z) & ...
(Z <= ze); % more conditions
xl = nnz(cond); % the number of non-zero elements
f = abs(xl*1000 - 90) % guessing m to get f as low as possible
How do I turn m into a variable for some f function so I can call fminsearch to quickly find the corresponding m for f ≈ 0?
In order to use m as a variable, you need to define a function handle. So you need to write:
cond = #(m) ((pi/3) <= alpha) & (alpha <= (2*pi/3)) & (m <= Z) & (Z <= ze);
However, you cannot use a function handle in the nnz routine, since it only accepts matrices as inputs. But, the solution to the problem is that you only have Boolean variables in cond. This means, you can simply sum over cond and get the same result as with nnz.
The only issue I see is how to implement the sum in fminsearch. Unfortunately, I do not have access to fminsearch, however I would assume that you can do something with reshape and then multiply with dot (i.e. .*) with the unity vector to get a sum. But you'll have to try that one out, not sure about it.

Isabelle: degree of polynomial multiplied with constant

I am working with the library HOL/Library/Polynomial.thy.
A simple property didn't work. E.g., the degree of 2x *2 is equal to the degree of 2x-
How can I prove the lemmas (i.e., remove "sorry"):
lemma mylemma:
fixes y :: "('a::comm_ring_1 poly)" and x :: "('a::comm_ring_1)"
shows "1 = 1" (* dummy *)
proof-
have "⋀ x. degree [: x :] = 0" by simp
from this have "⋀ x y. degree (y * [: x :] ) = degree y" sorry
(* different notation: *)
from this have "⋀ x y. degree (y * (CONST pCons x 0)) = degree y" sorry
.
From Manuel's answer, the solution I was looking for:
have 1: "⋀ x. degree [: x :] = 0" by simp
{
fix y :: "('a::comm_ring_1 poly)" and x :: "('a::comm_ring_1)"
from 1 have "degree (y * [: x :]) ≤ degree y"
by (metis Nat.add_0_right degree_mult_le)
}
There are a number of issues here.
First of all, the statement you are trying to show simply does not hold for all x. If x = 0 and y is nonconstant, e.g. y = [:0,1:], you have
degree (y * [: x :]) = degree 0 = 0 ≠ 1 = degree y
The obvious way to fix this is to assume x ≠ 0.
However, this is not sufficient either, since you only assumed 'a to be a commutative ring. However, in a commutative ring, in general, you can have zero divisors. Consider the commutative ring ℤ/4ℤ. Let x = 2 and y = [:0,2:].
Then y * [:x:] = [:0,4:], but 4 = 0 in ℤ/4ℤ. Therefore y * [:x:] = 0, and therefore, again,
degree (y * [: x :]) = degree 0 = 0 ≠ 1 = degree y
So, what you really need is one of the following two:
the assumption x ≠ 0 and 'a::idom instead of 'a::comm_ring. idom stands for “integral domain” and, that is simply a commutative ring with a 1 and without zero divisors
more generally, the assumption that x is not a zero divisor
even more generally, the assumption that x * y ≠ 0 or, equivalently, x times the leading coefficient of y is not 0
Also, the usage of ⋀ in Isar proofs is somewhat problematic at times. The “proper“ Isar way of doing this would be:
fix x :: "'a::idom" and y :: "'a poly"
assume "x ≠ 0"
hence "degree (y * [:x:]) = degree y" by simp
The relevant lemmas are degree_mult_eq and degree_smult_eq, you will see that they require the coefficient type to be an idom. This works for the first case I described above, the other two will require some more manual reasoning, I think.
EDIT: just a small hint: you can find theorems like this by typing
find_theorems "degree (_ * _)"
If you try to apply the degree_mult_eq it shows to your situation (with comm_ring), you will find that it fails, even though the terms seem to match. If that is the case, it is usually a type issue, so you can write something like
from [[show_sorts]] degree_mult_eq
to see what the types and sorts required by the lemma are, and it says idom.

Combining functions with boundaries in matlab

I have a function like this:
f(x) = { x if 0 < x < n
{ n-x if n < x < 2*n
How to enter this function in MATLAB?
Best way is to put this in a sub-function or nested function, or in a separate m-file:
function y = f(x)
n = 4; %// Or whatever your N is
if x <= 0 || x >= 2*n
y = 0;
elseif x < n
y = x;
else
y = n-x;
end
end
or, more generally, when x is a vector/matrix,
function y = f(x)
y = x;
y(x >= n) = n-x(x >= n);
y(x <= 0 | x >= 2*n) = 0;
end
Alternatively, you can of course pass the n as an argument:
function y = f(x, n)
...
end
Alternatively, you can use this anonymous function:
f = #(x) (x>0 & x<n).*x + (x>=n & x<=2*n).*(n-x);
again, optionally, pass the n:
f = #(x,n) ...

How to implement an assignment algorithm

Given a vector y(d x 1) and matrix Z(d x n), I would like to implement the optimal matlab code for the below algorithm.
Initialization:
Let z* be the nearest point from y in Z.
A={z*} (A is the list of assignment for y)
Z = Z \ {z*} (z* point is removed from matrix Z)
do
Let p denotes the center of gravity of A:
Let z* be the nearest center from y in Z(updated Z)
Let q denotes the center of gravity of A U {z*}
if distance(y,q) < distance(y,p) then
A = A U {z*} and Z = Z \ {z*}
else
NOP
endif
while a new assignment is performed
return A(list of assignments)
function A = Assign(x,Z)
%
% x - 1 x N
% Z - k x N
%
OriginalZ = Z;
[~,index]=sort(pdist2(x,Z));
A = index(1);
Z(A,:)=inf;
loop =1;
while(loop)
loop =0;
p=mean(OriginalZ(A,:),1);
[~,index]=sort(pdist2(x,Z));
Ad = [A index(1)];
q = mean(OriginalZ(Ad,:),1);
if pdist([x;q]) < pdist([x;p])
A = Ad; Z(Ad,:)=inf;
loop = 1;
end
end
end