Dependently typed bounded range in Lean - lean

Suppose I would like to create a bounded integer Z with bounds a b.
def zbound (x₁ x₂ : ℤ) :=
{ n : ℤ // x₁ ≤ n ∧ n ≤ x₂ }
Is this a reasonable representation of a bounded integer?
Now I would like to create a range of numbers from a to b.
def range : ∀(a b : ℤ), list (zbound a b)
| fro to := if h : fro < to
then ⟨fro, and.intro (le_refl _) (int.le_of_lt h)⟩
:: range (fro + 1) to
else []
I can get this to work with range : ℤ → ℤ → list ℤ, including the proof of termination using using_well_founded. However, I find it impractical in this form, because it doesn't carry a proof that every number within the range is zbound a b.
As such, I would like to get my dependent version. However, I run into the isue that range (fro + 1) to is, naturally, of type list (zbound (fro + 1) to). What I need is list (zbound fro to). How does one get around this issue? I tried approaching the problem by showing that if x is lower bounded by a, then it is also bounded by every number less than a, therefore keeping the bound of form zbound fro to (os this obviously bounds zbound (fro + 1) to). I have however no idea how to use this idea, or even if it makes sense to use it.

I am not sure this is an ideal solution, but it does work for me.
First we need a lemma to weaken the bounded range:
def range_weaken {a b : ℤ} : zbound (a + 1) b → zbound a b
| ⟨i, ⟨lbound, rbound⟩⟩ :=
⟨i, and.intro
(le_of_add_le_left _ 1 _ dec_trivial lbound)
rbound⟩
Then we can redefine range in terms of weakened ranges:
def range : ∀(a b : ℤ), list (zbound a b)
| fro to := if h : fro < to
then ⟨fro, and.intro (le_refl _) h⟩
:: list.map range_weaken (range (fro + 1) to)
else []
using_well_founded { ... }
Note: I couldn't find a lemma I was looking for, so I hand-proved the following:
def le_of_add_le_left (a b c : ℤ) : 0 ≤ b → a + b ≤ c → a ≤ c

Related

How can one represent distinct non-numeric symbols in sympy?

I am experimenting with the representation of a trivial statistics problem in Sympy:
For a sample space S, there are 6 possible distinct outcomes
a,b,c,d,e,f. We can define event A as having occurred if any of
a,b,c have, and event B as having ocurred if any of b,c,d have.
Given a probability mass function pmf defined over S, what is the
probability of event A?
When attempting to implement this symbolically, I receive the following error:
~/project/.envs/dev/lib/python3.6/site-packages/sympy/stats/frv.py in _test(self, elem)
164 elif val.is_Equality:
165 return val.lhs == val.rhs
--> 166 raise ValueError("Undecidable if %s" % str(val))
167
168 def __contains__(self, other):
ValueError: Undecidable if Eq(d, a) | Eq(d, b) | Eq(d, c)
The problem is implemented as follows with comments on the failing lines of code:
from sympy import Eq, Function, symbols
from sympy.logic import Or
from sympy.sets import FiniteSet, Union
from sympy.stats import FiniteRV, P
# 1. Define a sample space S with outcomes: a,b,c,d,e,f; Define events A, B
A = FiniteSet(*symbols('a b c'))
B = FiniteSet(*symbols('b c d'))
S = Union(A, B, FiniteSet(*symbols('e f')))
display("Sample Space", S)
pmfFunc = Function("pmf")
pmfDict = {v: pmfFunc(v) for v in S}
X = FiniteRV('X', pmfDict)
a,b = symbols('a b')
# 2. P(X = a) = pmf(a)
display(P(Eq(X,a)))
# 3. A.as_relational(X) yields `(X=a) \lor (X=b) \lor (X=c)`
display(A.as_relational(X))
# 4. P(X = a \lor X = b) = pmf(a) + pmf(b)
# - Actual Output: ValueError: Undecidable if Eq(c, a) | Eq(c, b)
display(P(Or(Eq(X,a), Eq(X,b)))) # [FAILS]
# 5. P(A) = pmf(a) + pmf(b) + pmf(c)
# - Actual Output: ValueError: Undecidable if Eq(d, a) | Eq(d, b) | Eq(d, c)
display(P(A.as_relational(X))) # [FAILS]
I obtain expected output up to display(A.as_relational(X)):
Interpreting the failure message suggests that Sympy is unable to tell that the set members are distinct. Replacing the symbols with integers resolves the error and I get output similar to what I desire.
A = FiniteSet(1, 2, 3)
B = FiniteSet(2, 3, 4)
S = Union(A, B, FiniteSet(5, 6))
If I am not misunderstanding the error or the fundamental use of the library, is there a way to tell Sympy that a collection of symbols is entirely distinct? I have attempted to replace the symbols with Dummy instances without success, and I have also attempted to leverage the assumptions module without success:
facts = [Eq(a,b) if a is b else Not(Eq(a,b)) for a, b in itertools.product(S, S)]
with assuming(*facts):
I would like to avoid confusing mappings between integers and symbolic forms, as user error may not be apparent when the results are printed as latex. I am willing to adopt some burden in a workaround (e.g., as it would have been maintaining a collection of Dummy instances), but I have yet to find an acceptable workaround.
Interesting question. Maybe it can be done with with assuming(Ne(a,b), ...): context but I take a more pragmatic approach: replace symbols with cos(non-zero integer) which SymPy can easily distinguish as equal or not:
>>> reps = dict(zip(var('a:f'),(cos(i) for i in range(1,7))))
>>> ireps = {v:k for k,v in reps.items()}
>>> a,b,c,d,e,f = [reps[i] for i in var('a:f')]
Then remove your a, b = symbols... line and replace display(x) with display(x.subs(ireps) to get
('Sample Space', FiniteSet(a, b, c, d, e, f))
(pmf(a),)
(Eq(X, a) | Eq(X, b) | Eq(X, c),)
(pmf(a) + pmf(b),)
(I use cos(int) instead of int because I am not sure whether any computation would result in addition of two elements and I want to make sure they stay distinct.)
Another approach would be to define a constant class that derives from Symbol:
class con(Symbol):
def __hash__(self):
return id(self)
def __eq__(a,b):
if isinstance(b, con):
return a.name == b.name
_eval_Eq = __eq__
a,b,c,d,e,f=map(con,'abcdef')
display=lambda*x:print(x)
from sympy import Eq, Function, symbols
from sympy.logic import Or
from sympy.sets import FiniteSet, Union
from sympy.stats import FiniteRV, P
A = FiniteSet(a,b,c)
B = FiniteSet(b,c,d)
S = Union(A, B, FiniteSet(e,f))
pmfFunc = Function("pmf")
pmfDict = {v: pmfFunc(v) for v in S}
X = FiniteRV('X', pmfDict)
display("Sample Space", S)
display(P(Eq(X,a)))
display(A.as_relational(X))
display(P(Or(Eq(X,a), Eq(X,b))))
display(P(A.as_relational(X)))
gives
('Sample Space', FiniteSet(a, b, c, d, e, f))
(pmf(a),)
(Eq(X, a) | Eq(X, b) | Eq(X, c),)
(pmf(a) + pmf(b),)
(pmf(a) + pmf(b) + pmf(c),)

How to build a route from point "A" to point "E" with the condition that the end point is the point "E"?

I need to build all possible routes from point "A" to point "E" with the condition that the end point is a point "B"
Task example:
From : A, To: B
Example result:
A -> E
A -> B -> E
A -> C -> D -> E
A -> B -> C -> D -> E
So far I was able to do so:
FOR v, e, p IN 1..10 OUTBOUND "city/907499" GRAPH 'CityToCity'
FILTER p.edges[*].user ALL == "6609844"
FILTER p.vertices[4]._id == "city/1012911"
RETURN p
But in this example, you must explicitly indicate at what level the endpoint should be located. How to make it simple from A to E without specifying level 4 in this filter "p.vertices [4] ._ id" ???
As the AQL documentation says:
// access last array element
u.friends[-1]
So in your example, specify the constraint on p.vertices[-1]._id
Also specify a very large number for MAX. Unfortunately, currently AQL requires that a specific value be given, but a ridiculously large value can be specified.

construction of state machine in string maching in book algorithm by CLRS

Below is text from Introduction to Algorithms by CLRS. Below is code snippet in string matching using finite state automata. Trnstion function is used to construct state table with pattern to be searched.
Computing the transition function:
The following procedure computes the transition function sigma from a given pattern
P [1: :m].
COMPUTE-TRANSITION-FUNCTION.
1 m = P:length
2 for q = 0 to m
3 for each character a belongs to alphabetset
4 k = min (m + 1, q + 2)
5 repeat
6 k = k - 1
7 until Pk is suffix Pqa
8 sigma(q, a) = k
9 return sigma
This procedure computes sigma(q, a) in a straightforward manner according to its definition
in equation (32.4). The nested loops beginning on lines 2 and 3 consider all states q and all characters a,
and lines 4–8 set sigma(q, a) to be the largest k such
that Pk is suffix Pqa. The code starts with the largest conceivable value of k, which is
min(m, q+1). It then decreases k until Pk is suffix Pqa, which must eventually occur,since P0 is empty string which
is a suffix of every string.
My questions on above code
Why author is selecting k as min(m + 1, q+2) at line 4?
In below explantion text author is mentions that "The code starts with the largest conceivable value of k, which is
min(m, q+1)." Which is not matching with pseudo code above at line 4?
Request to explain with simple example and steps of psudoe code while answering above questions.

How to minimize a string's length by iteratively removing all occurrences of some specified words from the string

This question appeared in a programming contest and we still have no idea how to solve it.
Question:
Given a string S and a list of strings L, we want to keep removing all occurences of substrings that may be in L. And we have to minimize the length of the final string formed. Also note that removal of a string may initiate more removals.
For example,
S=ccdedefcde, L={cde}
then answer = 1. Because we can reduce S by ccdedefcde -> cdefcde -> fcde -> f.
S=aabaab, L={aa, bb} then answer = 0 as reduction can be carried out by aabaab -> aabb -> aa -> ‘Empty String’
S=acmmcacamapapc, L={mca, pa} then answer=6 as reduction can be carried out by acmmcacamapapc-> acmcamapapc -> acmapapc -> acmapc.
The maximum length of S can be 50 and the maximum length of list L can be 50.
My approach is a basic recursive traversal in which I return the minimum length that I can get by removing different sub-strings. Unfortunately this recursive approach will time out in the worst case input as we have 50 options at each step and the recursion depth is 50.
Please suggest an efficient algorithm that may solve this problem.
Here's a polynomial-time algorithm that yields optimal results. Since it's convenient for me, I'm going to use the polynomial-time CYK algorithm as a subroutine, specifically the extension that computes a minimum-weight parse of a string according to a context-free grammar with weighted productions.
Now we just have to formalize this problem with a context-free grammar. The start symbol is A (usually S, but that's taken already), with the following productions.
A -> N (weight 0)
A -> A C N (weight 0)
I'll explain N shortly. If N and C were terminals, then A would accept the regular language N (C N)*. The nonterminal C matches a single terminal (character).
C -> a (weight 1)
C -> b (weight 1)
C -> c (weight 1)
...
The nonterminal N matches strings that are nullable, that is, strings that can be reduced to the empty string by deleting strings in L. The base case is obvious.
N -> (weight 0)
We also have a production for each element of L. When L = {mca, pa}, for example, we have the following productions.
N -> N m N c N a N (weight 0)
N -> N p N a N (weight 0)
I hope that it's clear how to construct the one-to-one correspondence between iterative removals and parses, where the parse weight is equal to the length of the residual string.
Note: this is not an optimal solution, since it doesn't work for the example S=ABAABABAA, L={ABA}
Algorithm
RECURSIVE_FUNCTION ( STRING STR, STRING PATTERN) :
1. STRING LEFT = STR.SUBSTR (0, STR.FIND(PATTERN))
2. STRING RIGHT = STR.SUBSTR(STR.FIND(PATTERN), STR.LENGTH)
3. IF (RIGHT is empty) THEN RETURN LEFT
4. STRING FIN = RECUR(LEFT) + RECUR(RIGHT)
5. RETURN RECUR(FIN)
function SUBSTR(A,B) will return substring of the string, from index A inclusive to index B exclusive
Operation A + B is concatenation of string A and B
function RECUR(A) call the same function, aka recurrence
Example: ccdedefcde
First it will branch down with RECUR(LEFT) + RECUR(RIGHT):
c[cde]defcde
/ \
c def[cde]
/
def
Then it will RECUR(FIN) on merge:
cdef*
/ \
c def
/
def
* will RECUR to do the following before that MERGE completes:
[cde]f
\
f
and finally the ROOT call returns f

Constraint programming boolean solver

Huey, Dewey and Louie are being questioned by their uncle. These are the statements they make:
• Huey: “Dewey and Louie had equal share in it; if one is guilty, so is the other.”
• Dewey: “If Huey is guilty, then so am I.”
• Louie: “Dewey and I are not both guilty.”
Their uncle, knowing that they are scouts realizes that they cannot tell a lie.
My solution.
var bool :D; var bool :L; var bool :H;
constraint D <->L;
constraint H -> D;
constraint D!=L;
solve satisfy;
output[show(D), "\n", show(L),"\n", show(H)];
Minizinc can't solve it.
Here's my (old) version of this problem: http://www.hakank.org/minizinc/huey_dewey_louie.mzn
var bool: huey;
var bool: dewey;
var bool: louie;
constraint
% Huey: Dewey and Louie has equal share in it; if one is quitly, so is the other.
(dewey <-> louie)
% Dewey: If Huey is guilty, then so am I.
/\
(huey -> dewey)
% Louie: Dewey and I are not both quilty.
/\
(not (dewey /\ louie))
;
For this kind of problems I prefer to use Boolean Satisfiability (SAT) directly. Your problem can obviously be formulated as a propositional logic formula as follows (using the DIMACS format) :
Atom 1 : Dewey is guilty (i.e. will be associated to the literals -1 and 1 in the CNF)
Atom 2 : Louie is guilty (i.e. will be associated to the literals -2 and 2 in the CNF)
Atom 3 : Huey is guilty (i.e. will be associated to the literals -3 and 3 in the CNF)
The CNF file is then :
p cnf 4 3
-1 2 0
-2 1 0
-3 1 0
-1 -2 0
And here the solution using an 'online' SAT Solver : http://boolsat.com/show/5320e18a0148a30002000002
Yet another solution, using CLP(B) (constraint logic programming over Boolean variables) with SICStus Prolog or SWI:
:- use_module(library(clpb)).
guilty(H, D, L) :-
sat(D =:= L), % Huey
sat(H =< D), % Dewey
sat(~(D*L)). % Louie
Example query and its result:
?- guilty(H, D, L).
D = H, H = L, L = 0.
Another option is to ask WolframAlpha:
not (L xor D) and (H implies D) and not (L and D)
As suggested by Hakan, the following equivalent expression is also possible:
(L equivalent D) and (H implies D) and not (L and D)
Result is a truth table which has only (!D !H !L) as solution.

Resources