mathlib documentation

testing.slim_check.functions

slim_check: generators for functions

This file defines sampleable instances for α → β functions and ℤ → ℤ injective functions.

Functions are generated by creating a list of pairs and one more value using the list as a lookup table and resorting to the additional value when a value is not found in the table.

Injective functions are generated by creating a list of numbers and a permutation of that list. The permutation insures that every input is mapped to a unique output. When an input is not found in the list the input itself is used as an output.

Injective functions f : α → α could be generated easily instead of ℤ → ℤ by generating a list α, removing duplicates and creating a permutations. One has to be careful when generating the domain to make if vast enough that, when generating arguments to apply f to, they argument should be likely to lie in the domain of f. This is the reason that injective functions f : ℤ → ℤ are generated by fixing the domain to the range [-2*size .. -2*size], with size the size parameter of the gen monad.

Much of the machinery provided in this file is applicable to generate injective functions of type α → α and new instances should be easy to define.

Other classes of functions such as monotone functions can generated using similar techniques. For monotone functions, generating two lists, sorting them and matching them should suffice, with appropriate default values. Some care must be taken for shrinking such functions to make sure their defining property is invariant through shrinking. Injective functions are an example of how complicated it can get.

inductive slim_check.total_function (α : Type u) (β : Type v) :
Type (max u v)

Data structure specifying a total function using a list of pairs and a default value returned when the input is not in the domain of the partial function.

with_default f y encodes x ↦ f x when x ∈ f and x ↦ y otherwise.

We use Σ to encode mappings instead of × because we rely on the association list API defined in data.list.sigma.

def slim_check.total_function.apply {α : Type u_1} {β : Type u_2} [decidable_eq α] :
slim_check.total_function α βα → β

Apply a total function to an argument.

Equations
def slim_check.total_function.repr_aux {α : Type u} [has_repr α] {β : Type v} [has_repr β] (m : list (Σ (_x : α), β)) :

Implementation of has_repr (total_function α β).

Creates a string for a given finmap and output, x₀ ↦ y₀, .. xₙ ↦ yₙ for each of the entries. The brackets are provided by the calling function.

Equations
def slim_check.total_function.repr {α : Type u} [has_repr α] {β : Type v} [has_repr β] :

Produce a string for a given total_function. The output is of the form [x₀ ↦ f x₀, .. xₙ ↦ f xₙ, _ ↦ y].

Equations
def slim_check.total_function.list.to_finmap' {α : Type u_1} {β : Type u_2} (xs : list × β)) :
list (Σ (_x : α), β)

Create a finmap from a list of pairs.

Equations

Redefine sizeof to follow the structure of sampleable instances.

Equations

Shrink a total function by shrinking the lists that represent it.

Equations
@[instance]

Equations
@[instance]
def slim_check.total_function.pi_uncurry.sampleable_ext {α : Type u} {β : Type v} {γ : Sort w} [slim_check.sampleable_ext × β → γ)] :
slim_check.sampleable_ext (α → β → γ)

Equations
inductive slim_check.injective_function (α : Type u) :
Type u

Data structure specifying a total function using a list of pairs and a default value returned when the input is not in the domain of the partial function.

map_to_self f encodes x ↦ f x when x ∈ f and x ↦ x, i.e. x to itself, otherwise.

We use Σ to encode mappings instead of × because we rely on the association list API defined in data.list.sigma.

Apply a total function to an argument.

Equations

Produce a string for a given total_function. The output is of the form [x₀ ↦ f x₀, .. xₙ ↦ f xₙ, x ↦ x]. Unlike for total_function, the default value is not a constant but the identity function.

Equations
def slim_check.injective_function.list.apply_id {α : Type u} [decidable_eq α] (xs : list × α)) (x : α) :
α

Interpret a list of pairs as a total function, defaulting to the identity function when no entries are found for a given function

Equations
theorem slim_check.injective_function.list.apply_id_zip_eq {α : Type u} [decidable_eq α] {xs ys : list α} (h₀ : xs.nodup) (h₁ : xs.length = ys.length) (x y : α) (i : ) (h₂ : xs.nth i = some x) :

theorem slim_check.injective_function.apply_id_mem_iff {α : Type u} [decidable_eq α] {xs ys : list α} (h₀ : xs.nodup) (h₁ : xs ~ ys) (x : α) :

theorem slim_check.injective_function.list.apply_id_eq_self {α : Type u} [decidable_eq α] {xs ys : list α} (x : α) :

def slim_check.injective_function.perm.slice {α : Type u_1} [decidable_eq α] (n m : ) :
(Σ' (xs ys : list α), xs ~ ys ys.nodup)(Σ' (xs ys : list α), xs ~ ys ys.nodup)

Remove a slice of length m at index n in a list and a permutation, maintaining the property that it is a permutation.

Equations

A lazy list, in decreasing order, of sizes that should be sliced off a list of length n

Equations
def slim_check.injective_function.shrink_perm {α : Type} [decidable_eq α] [has_sizeof α] :
slim_check.shrink_fn (Σ' (xs ys : list α), xs ~ ys ys.nodup)

Shrink a permutation of a list, slicing a segment in the middle.

The sizes of the slice being removed start at n (with n the length of the list) and then n / 2, then n / 4, etc down to 1. The slices will be taken at index 0, n / k, 2n / k, 3n / k, etc.

Equations
@[instance]

Equations

Shrink an injective function slicing a segment in the middle of the domain and removing the corresponding elements in the codomain, hence maintaining the property that one is a permutation of the other.

Equations
def slim_check.injective_function.mk {α : Type (max u_1 u_2)} (xs ys : list α) (h : xs ~ ys) (h' : ys.nodup) :

Create an injective function from one list and a permutation of that list.

Equations
@[instance]
def slim_check.injective.testable {α : Sort u_1} {β : Sort u_2} (f : α → β) [I : slim_check.testable (slim_check.named_binder "x" (∀ (x : α), slim_check.named_binder "y" (∀ (y : α), slim_check.named_binder "H" (f x = f yx = y))))] :

Equations
@[instance]
def slim_check.monotone.testable {α : Type u_1} {β : Type u_2} [preorder α] [preorder β] (f : α → β) [I : slim_check.testable (slim_check.named_binder "x" (∀ (x : α), slim_check.named_binder "y" (∀ (y : α), slim_check.named_binder "H" (x yf x f y))))] :

Equations