Isabelle: maximum value in a vector - vector

I would like to find the maximum in a vector of natural numbers. Vector (i.e., ‘vec’), however, is a different type than Set or List. I thought about several ideas that did not work, like leveling or lifting the type of vec or the definition of a recursive function.
What solution do you suggest to get the maximum value in a vector?
(*
IMPORTS:
"~~/src/HOL/Algebra/Ring"
"~~/src/HOL/Library/Numeral_Type"
"~~/src/HOL/Library/Permutations"
"~~/src/HOL/Library/Polynomial"
"~~/src/HOL/Big_Operators"
vec (VECTOR) is from Finite_Cartesian_Product
degree is from Polynomial
Max is from Big_Operators
*)
(* The problem is that "Max" from Big_Operators is not working on vectors! *)
definition maxdeg:: "('a::zero poly)^'n ⇒ nat" where "maxdeg v = Max(χ i . degree(v$i))"

The maximum operator Max has type 'a set => 'a, i.e., retrieves the maximum element from a (finite) set. Vectors (type (a, b) vec) are essentially functions from indices to entries with abstraction written as χ i. _ and application as v $ _.
You now want to get the maximum value in the range of a vector. With the above in mind, you can use the range function and spell out the function application on vectors:
maxdeg v = Max (range (%j. (χ i. degree (v $ i)) $ j))
This can be simplified to
maxdeg v = Max (range (%i. degree (v $ i)))
If you just want the maximum entry of a vector without mapping degree over vector first, the following works (where op $ v is the eta-contraction of %j. v $ j):
maxvec v = Max (range (op $ v))

Related

Smallest distance in a list to the number 0 supplies amount of that number with map

I want to create a function absmin which gets a list of floating point numbers and returns the amount of that number which has the smallest distance to 0.
We should do it with the function map. My first idea was that the function abs mentioned the problem with amount, but know my question is, how it is possible to create the point with the smallest distance to 0 and that with the map function, can somebody help me?
absmin :: [Double] -> Int
absmin [] = []
absmin (x:xs) = abs (map (x:xs))
Okay, now i changed to:
absmin xs = map abs xs
But with the specification: absmin :: [Double] -> Double it didn't work, maybe i´m to stupid, but i try and try and it didn't work
If you have a list like [3.14, 2.98, -0.1] and need to find which number is closest to zero, you need to first map abs to that list, and then you need to find the min.
Now min has signature Ord a => a -> a -> a so it only considers two numbers at the same time. Fortunately we can use a fold to fold this function over our list.
Prelude> absmin = foldr1 min . map abs
Prelude> absmin [3.14, 2.98, -0.1]
0.1
The problem with this is that we don't know if the closest number to zero was 0.1 or -0.1.
So let's map each element to a tuple containing its absolute value and the original value. We can define a minBy function that lets us find the minimum of two values based on a function like fst.
After we've folded this function over the list of tuples, we just need to call snd on the result to get the original value.
Prelude> :{
Prelude| minBy f a b
Prelude| | f a <= f b = a
Prelude| | otherwise = b
Prelude| :}
Prelude> absmin' = snd . foldr1 (minBy fst) . map (\x -> (abs x, x))
Prelude> absmin' [3.14, 2.98, -0.1, 0.1]
-0.1
You can use the min() and abs() functions to find the smallest absolute value in a list of numbers, and then use map() to apply this value to each element in the list.

How do I check if the path from a node to another has a depth equal to a given one in a graph in OCaml?

First of all, I'm sorry for how I wrote my question.
Anyway, I'm trying to write a function in OCaml that, given a graph, a max depth, a starting node, and another node, returns the list of the nodes that make the path but only if the depth of it is equal to the given one. However, I can't implement the depth part.
This is what I did:
let m = [(1, 2, "A"); (2, 3, "A");
(3, 1, "A"); (2, 4, "B");
(4, 5, "B"); (4, 6, "C");
(6, 3, "C"); (5, 7, "D");
(6, 7, "D")]
let rec vicini n = function
[] -> []
| (x, y, _)::rest ->
if x = n then y :: vicini n rest
else if y = n then x :: vicini n rest
else vicini n rest
exception NotFound
let raggiungi m maxc start goal =
let rec from_node visited n =
if List.mem n visited then raise NotFound
else if n = goal then [n]
else n :: from_list (n :: visited) (vicini n m)
and from_list visited = function
[] -> raise NotFound
| n::rest ->
try from_node visited n
with NotFound -> from_list visited rest
in start :: from_list [] (vicini start m)
I know I have to add another parameter that increases with every recursion and then check if its the same as the given one, but I don't know where
I am not going to solve your homework, but I will try to teach you how to use recursion.
In programming, especially functional programming, we use recursion to express iteration. In an iterative procedure, there are things that change with each step and things that remain the same on each step. An iteration is well-founded if it has an end, i.e., at some point in time, the thing that changes reaches its foundation and stops. The thing that changes on each step, is usually called an induction variable as the tribute to the mathematical induction. In mathematical induction, we take a complex construct and deconstruct it step by step. For example, consider how we induct over a list to understand its length,
let rec length xs = match xs with
| [] -> 0
| _ :: xs -> 1 + length xs
Since the list is defined inductively, i.e., a list is either an empty list [] or a pair of an element x and a list, x :: list called a cons. So to discover how many elements in the list we follow its recursive definition, and deconstruct it step by step until we reach the foundation, which is, in our case, the empty list.
In the example above, our inductive variable was the list and we didn't introduce any variable that will represent the length itself. We used the program stack to store the length of the list, which resulted in an algorithm that consumes memory equivalent to the size of the list to compute its length. Doesn't sound very efficient, so we can try to devise another version that will use a variable passed to the function, which will track the length of the list, let's call it cnt,
let rec length cnt xs = match xs with
| [] -> cnt
| _ :: xs -> length (cnt+1) xs
Notice, how on each step we deconstruct the list and increment the cnt variable. Here, call to the length (cnt+1) xs is the same as you would see in an English-language explanation of an algorithm that will state something like, increment cnt by one, set xs to the tail xs and goto step 1. The only difference with the imperative implementation is that we use arguments of a function and change them on each call, instead of changing them in place.
As the final example, let's devise a function that checks that there's a letter in the first n letters in the word, which is represented as a list of characters. In this function, we have two parameters, both are inductive (note that a natural number is also an inductive type that is defined much like a list, i.e., a number is zero or the successor of a number). Our recursion is also well-founded, in fact, it even has two foundations, the 0 length and the empty list, whatever comes first. It also has a parameter that doesn't change.
let rec has_letter_in_prefix letter length input =
length > 0 && match input with
| [] -> false
| char :: input ->
char = letter || has_letter_in_prefix letter (length-1) input
I hope that this will help you in understanding how to encode iterations with recursion.

Sum, Average of elements and Count the occurence of elements in Lists in Prolog

how can I write three predicates in Prolog that do the following things:
1) Define the sum (X, N) predicate, which is true when N is the sum of integers from the list X.
2) Define the avg (X, N) predicate that calculates the arithmetic average of all elements of the list X, where N is the number of elements.
3) Define the predicate called count(X, Y, N), which is true if the list Y contains N element instances
X.
Could you give me the examples of them and explain to me why they work the way they do? I know there are dozens of sum and avg predicates here on Stack Overflow, but I can't really understand why they work.
Define the sum(X, N) predicate, which is true when N is the sum of integers from the list X.
You want to calculate the sum of the elements of a list. What would be the simplest instance of the problem? When the list is empty, the sum of its element is 0. How can we break down larger lists to get to the simple case? We can remove the first element of the list, calculate the sum of the remaining list, and then add the first element to the result.
This approach can be implemented with the following code:
% Simple case: Sum of the empty list
sum([], 0).
% Recursive case: Split list into first element X and remaining list XS
sum([X|XS], N) :- sum(XS, M), N is M + X.
Usage:
?- sum([1,2,3],6).
true.
?- sum([1,2,3],X).
X = 6.
The is operator does arithmetic evaluation of its right-hand side (reference), as opposed to treating M + X as a literal term. If you would use = instead of is, M + X would be treated as a literal term. You would then get the following output:
?- sum([1,2,3],6).
false.
?- sum([1,2,3],0+3+2+1).
true.
So for Prolog 6 and 0+3+2+1 are different terms, until you force arithmetic evaluation as done by is.
2) Define the avg (X, N) predicate that calculates the arithmetic average of all elements of the list X, where N is the number of elements.
This is not possible. If X is the list and N the number of elements, then the predicate has no way of outputting the average (unless you count printing the average as a side-effect, I don't think you want). To fix this, add another parameter A that represents the average: avg(X, N, A).
We can calculate the average by taking the sum of the list and dividing it by the length of the list:
avg(X, N, A) :- sum(X, S), length(X, N), A is S / N.
Usage:
?- avg([1,2,3],3,2).
true.
?- avg([1,2,3,4],N,X).
N = 4,
X = 2.5.
3) Define the predicate called count(X, Y, N), which is true if the list Y contains N element instances X.
I understand you want N to be the number of times that the number X occurs in the list Y. We can again break this down into a simple case and then try to break down the general case into smaller steps until we get to the simple case.
For an empty list, we know that X occurs zero times in that list. For a non-empty list, we can remove the first element and check of how often X occurs in the remaining list. If the first element if equal to X, then the total number of occurrences of X is one plus the number of occurrences in the remaining list. If the first element is not equal to X, then the total number of occurrences of X is equal to the number of occurrences in the remaining list.
This approach can be implemented with the following code:
% Simple case: The list is empty.
count(_, [], 0).
% Recursive case: First element is equal to X
count(X, [X|YS], N) :- count(X, YS, M), N is M + 1, !.
% Recursive case: First element is unequal to X
count(X, [Y|YS], N) :- X \= Y, count(X, YS, N).
We use _ for variables we do not care about. We could also write X instead of _, but Prolog would then give us a warning about an unused variable.
Usage:
?- count(1, [1,1,2,3], N).
N = 2.
?- count(2, [1,1,2,3], N).
N = 1.

Isabelle function to find the longest sequence of members of a relation

I have a relation R :: w => w => bool that is both transitive an irreflexive.
I have the axiom Ax1: "finite {x::w. True}". Therefore, for each x there is always a longest sequence of wn R ... R w2 R w1 R x.
I need a function F:: w => nat, that -for a given x - gives back the "lenght" of this sequence (or 0 if there is no y such that xRy). How would I go about building one in isabelle.
Also: Is Ax1 a good way to axiomatize the "finiteness of type w" or is there a better one?
First of all, a more idiomatic way of writing {x::w. True} is UNIV :: w set. I suggest writing finite (UNIV :: w set), or possibly using the finite type class, although that might make your theorem more difficult to apply because you need a finite instance for your type. I think it's not really necessary or helpful for your use case.
I then suggest the following approach:
Define an inductive predicate (using inductive) on lists of type w list stating that the first element is x and for each two successive list elements y and z, R y z holds, i.e. the list is an ascending chain w.r.t. R.
Show that any list that is such a chain must have distinct elements (cf. distinct :: 'a list ⇒ bool).
Show that there are finitely many distinct lists over a finite set.
Use the Max operator to find the biggest n such that there exists a list of length n that is an ascending chain w.r.t. R. That this works should be easy since there is at least one such chain, and you've already shown that there are only finitely many chains.

So: what's the point?

What is the intended purpose of the So type? Transliterating into Agda:
data So : Bool → Set where
oh : So true
So lifts a Boolean proposition up to a logical one. Oury and Swierstra's introductory paper The Power of Pi gives an example of a relational algebra indexed by the tables' columns. Taking the product of two tables requires that they have different columns, for which they use So:
Schema = List (String × U) -- U is the universe of SQL types
-- false iff the schemas share any column names
disjoint : Schema -> Schema -> Bool
disjoint = ...
data RA : Schema → Set where
-- ...
Product : ∀ {s s'} → {So (disjoint s s')} → RA s → RA s' → RA (append s s')
I'm used to constructing evidence terms for the things I want to prove about my programs. It seems more natural to construct a logical relation on Schemas to ensure disjointedness:
Disjoint : Rel Schema _
Disjoint s s' = All (λ x -> x ∉ cols s) (cols s')
where cols = map proj₁
So seems to have serious disadvantages compared to a "proper" proof-term: pattern matching on oh doesn't give you any information with which you could make another term type-check (Does it?) - which would mean So values can't usefully participate in interactive proving. Contrast this with the computational usefulness of Disjoint, which is represented as a list of proofs that each column in s' doesn't appear in s.
I don't really believe that the specification So (disjoint s s') is simpler to write than Disjoint s s' - you have to define the Boolean disjoint function without help from the type-checker - and in any case Disjoint pays for itself when you want to manipulate the evidence contained therein.
I am also sceptical that So saves effort when you're constructing a Product. In order to give a value of So (disjoint s s'), you still have to do enough pattern matching on s and s' to satisfy the type checker that they are in fact disjoint. It seems like a waste to discard the evidence thus generated.
So seems unwieldy for both authors and users of code in which it's deployed. 'So', under what circumstances would I want to use So?
If you already have a b : Bool, you can turn it into proposition: So b, which is a bit shorther than b ≡ true. Sometimes (I don't remember any actual case) there is no need to bother with a proper data type, and this quick solution is enough.
So seems to have serious disadvantages compared to a "proper"
proof-term: pattern matching on oh doesn't give you any information
with which you could make another term type-check. As a corollary,
So values can't usefully participate in interactive proving.
Contrast this with the computational usefulness of Disjoint, which
is represented as a list of proofs that each column in s' doesn't
appear in s.
So does give you the same information as Disjoint — you just need to extract it. Basically, if there is no inconsistency between disjoint and Disjoint, then you should be able to write a function So (disjoint s) -> Disjoint s using pattern matching, recursion and impossible cases elimination.
However, if you tweak the definition a bit:
So : Bool -> Set
So true = ⊤
So false = ⊥
So becomes a really useful data type, because x : So true immediately reduces to tt due to the eta-rule for ⊤. This allows to use So like a constraint: in pseudo-Haskell we could write
forall n. (n <=? 3) => Vec A n
and if n is in canonical form (i.e. suc (suc (suc ... zero))), then n <=? 3 can be checked by the compiler and no proofs are needed. In actual Agda it is
∀ {n} {_ : n <=? 3} -> Vec A n
I used this trick in this answer (it is {_ : False (m ≟ 0)} there). And I guess it would be impossible to write a usable version of the machinery decribed here without this simple definition:
Is-just : ∀ {α} {A : Set α} -> Maybe A -> Set
Is-just = T ∘ isJust
where T is So in the Agda's standard library.
Also, in the presence of instance arguments So-as-a-data-type can be used as So-as-a-constraint:
open import Data.Bool.Base
open import Data.Nat.Base
open import Data.Vec
data So : Bool -> Set where
oh : So true
instance
oh-instance : So true
oh-instance = oh
_<=_ : ℕ -> ℕ -> Bool
0 <= m = true
suc n <= 0 = false
suc n <= suc m = n <= m
vec : ∀ {n} {{_ : So (n <= 3)}} -> Vec ℕ n
vec = replicate 0
ok : Vec ℕ 2
ok = vec
fail : Vec ℕ 4
fail = vec

Resources