Prove that ¬P → ( P → ( P → Q)) is a tautology without using truth tables - first-order-logic

I can't find a proper formula for this considering it's almost exclusively made up of implications. Can somebody help me?
EDIT: Sorry, I'm new to this site and still learning to use it. I've tried writing (P → Q) as (¬P ∨ Q) and then applying the distibutive laws but I feel like I've reached a dead end.

P -> q is the same as no(p) OR q
If you replace, in your expression :
P -> (P -> Q) is the same as no(P) OR (no(P) OR Q)
no(P) -> P (P -> (P -> Q)) is the same as no(no(p)) OR (no(P) OR (no(P) OR Q))
which is the same as p OR no(P) OR no(P) OR Q which is always true ( because p or no(p) is always true)

Simply:
!P -> (P -> (P -> Q)) apply implication
P v (!P v (P -> Q))) P v !P is T
T v (...) T v anything is T
T

Related

Prove (p → ¬ q) → ¬ (p ∧ q) in Lean4

I get as far as this
theorem problem_2 : (p → ¬ q) → ¬ (p ∧ q) := by
intro hp
intro hpw
which gets me to ⊢ False
Not p, or ¬p, is the negation of p. It is defined to be p → False, so if your goal is ¬p you can use intro h to turn the goal into h : p ⊢ False, and if you have hn : ¬p and h : p then hn h : False and (hn h).elim will prove anything. For more information: Propositional Logic.
de Moura, Leonardo, Mario Carneiro et al. “Init.Prelude.” Mathlib4 Docs. Accessed Feb 10, 2023. https://leanprover-community.github.io/mathlib4_docs/Init/Prelude.html#Not.
We can solve the problem as follows:
theorem problem_2 : (p → ¬q) → ¬(p ∧ q) := by
intro hpnq hpq
have hp : p := hpq.1
have hnq : ¬q := hpnq hp
have hq : q := hpq.2
exact hnq hq

How to write bigvee and big wedge in Isabelle

I'm trying to use Isabelle to do auto-prove. However, I got a problem of specifying formulas in Isabelle. For example, I have a formulas like this
Then, I define sets and use big_wedge and big_vee symbols in Isabelle as follows:
And the result is "Inner lexical error⌂ Failed to parse prop".
Could you explain what is wrong here, please?
Thank you very much.
Not all symbols shown in Isabelle/jEdit's Symbol tabs have a meaning. These are the symbols you can use in your code.
Based on the corresponding code for sums, I started the setup, but I did not finish it (in particular, the syntax ⋀t!=l. P t is not supported).
context comm_monoid_add
begin
sublocale bigvee: comm_monoid_set HOL.disj False
defines bigvee = bigvee.F and bigvee' = bigvee.G
by standard auto
abbreviation bigvee'' :: ‹bool set ⇒ bool› ("⋁")
where "⋁ ≡ bigvee (λx. x)"
sublocale bigwedge: comm_monoid_set HOL.conj True
defines bigwedge = bigwedge.F and bigwedge' = bigwedge.G
by standard auto
abbreviation bigwedge'' :: ‹bool set ⇒ bool› ("⋀")
where "⋀ ≡ bigwedge (λx. x)"
end
syntax
"_bigwedge" :: "pttrn ⇒ 'a set ⇒ 'b ⇒ 'b::comm_monoid_add" ("(2⋀(_/∈_)./ _)" [0, 51, 10] 10)
translations ― ‹Beware of argument permutation!›
"⋀i∈A. b" ⇌ "CONST bigwedge (λi. b) A"
syntax
"_bigvee" :: "pttrn ⇒ 'a set ⇒ 'b ⇒ 'b::comm_monoid_add" ("(2⋁(_/∈_)./ _)" [0, 51, 10] 10)
translations ― ‹Beware of argument permutation!›
"⋁i∈A. b" ⇌ "CONST bigvee (λi. b) A"
instantiation bool :: comm_monoid_add
begin
definition zero_bool where
[simp]: ‹zero_bool = False›
definition plus_bool where
[simp]: ‹plus_bool = (∨)›
instance
by standard auto
end
thm bigvee_def
lemma ‹finite A ⟹ (⋁i∈A. f i) ⟷ (∃i ∈ A. f i)›
apply (induction rule: finite_induct)
apply (auto simp: )
done
lemma ‹finite A ⟹ (⋀i∈A. f i) ⟷ A = {} ∨ (∀i ∈ A. f i)›
apply (induction rule: finite_induct)
apply (auto simp: )[2]
done
lemma ‹infinite A ⟹ (⋀i∈A. f i) ⟷ True›
by auto
lemma test1:
‹(⋀j∈L. ⋀u∈U. ⋀t∈T. ⋀l∈L. ⋀l⇩1∈L⇩1. ¬P j u t l⇩1) ∨
(⋁i∈I. ⋁v∈V. ⋀k∈K. ⋁h∈H. Q i ∨ k h) ⟹
(⋁i∈I. ⋁v∈V. ⋀k∈K. ⋁h∈H. Q i ∨ k h) ∨ (⋀j∈J. ⋀u∈U. ⋀t∈T. ⋀l⇩1∈L⇩1. ¬P j u t l⇩1)›
apply auto
The full setup is possible. But I am not certain that this is a good idea... You will need a lot of lemmas to make things work nicely and I am not certain the behaviour for infinite sets is the right one.

How to substract TRUE and TRUE in lambda calculus correctly?

I am trying to understand the lambda calculus. However, I am a bit stuck on this expression: TRUE and TRUE. I can't figure out how you can get from
((\T F -> T) (\T F -> T))
to
(\F T F -> T)
, not
(\F -> (\T F -> T))
\ is lambda-signature
(\F T F -> T)
and
(\F -> (\T F -> T))
are the same thing.
https://en.wikipedia.org/wiki/Lambda_calculus_definition#Notation:
Outermost parentheses are dropped: M N instead of (M N)
[...]
The body of an abstraction extends as far right as possible: λx. M N means λx. (M N) and not (λx. M) N
A sequence of abstractions is contracted: λx. λy. λz. N is abbreviated as λxyz. N
In particular,
(\F -> (\T F -> T))
can be written
(\F -> \T F -> T)
because we can drop redundant parentheses and the body of the outer lambda extends as far right as possible, which can then be written
(\F -> \T -> \F -> T)
or
(\F T F -> T)
by the last rule (contraction).

Is it possible to make `foldrRanges` as fast as `foldrRange2D`?

This:
foldrRange :: (Int -> t -> t) -> t -> Int -> Int -> t
foldrRange cons nil a b = foldr cons nil [a..b-1]
Defines a function that folds over a list from a til b. This:
foldrRange :: (Int -> t -> t) -> t -> Int -> Int -> t
foldrRange cons nil a b = go (b-1) nil where
go b !r | b < a = r
| otherwise = go (b-1) (cons b r)
{-# INLINE foldrRange #-}
is a ~50x faster version due to proper strictness usage (we know the last element, so we can roll like foldl').
This:
foldrRange2D cons nil (ax,ay) (bx,by)
= foldr cons nil
$ do
y <- [ay..by-1]
x <- [ax..bx-1]
return (x,y)
Is a 2D version of foldrRange, i.e., it works over 2D rectangles so that foldrRange2d (:) [] (0,0) (2,2) == [(0,0),(1,0),(0,1),(1,1)]. This:
foldrRange2D :: ((Int,Int) -> t -> t) -> t -> (Int,Int) -> (Int,Int) -> t
foldrRange2D cons nil (ax,ay) (bx,by) = go (by-1) nil where
go by !r
| by < ay = r
| otherwise = go (by-1) (foldrRange (\ ax -> cons (ax,by)) r ax bx)
Is, again, an ~50x faster definition due to better strictness usage. Writing foldrRange3D, foldrRange4D, etc., would be cumbersome, so one can generalize it like so:
foldrRangeND :: forall t . ([Int] -> t -> t) -> t -> [Int] -> [Int] -> t
foldrRangeND cons nil as bs = foldr co ni (zip as bs) [] nil where
co (a,b) tail lis = foldrRange (\ h t -> tail (h:lis) . t) id a b
ni lis = cons lis
Unfortunately this definition is at around 120 times slower than foldrRange2D, as one can verify with this test:
main = do
let n = 2000
print $ foldrRange2D (\ (a,b) c -> a+b+c) 0 (0,0) (n,n)
print $ foldrRanges (\ [a,b] c -> a+b+c) 0 [0,0] [n,n]
I could probably use ST to get a faster foldrRanges, but is it possible to do so with recursion alone?
You have an efficient implementation of your algorithm which is inductive on the dimension of the input. Fortunately, you can do that in Haskell!
First, replace lists with type level Nat indexed vectors. This gives us a type to do induction on (it could probably be done with lists ... but this is much safer).
data Nat = Z | S Nat
infixl 5 :<
data Vec (n :: Nat) (a :: *) where
Nil :: Vec Z a
(:<) :: Vec n a -> a -> Vec (S n) a
instance Functor (Vec n) where
fmap _ Nil = Nil
fmap f (xs :< x) = fmap f xs :< f x
Then your desired function is just the same as the 2D case - just generalize the recursive call:
{-# INLINE foldrRangeN #-}
foldrRangeN :: (Vec n Int -> t -> t) -> t -> Vec n Int -> Vec n Int -> t
foldrRangeN f x Nil Nil = f Nil x
foldrRangeN cons nil (ax :< ay) (bx :< by) = go (by-1) nil where
go by !r
| by < ay = r
| otherwise = go (by-1) (foldrRangeN (\ ax -> cons (ax :< by)) r ax bx)
Although when I tested the performance, I was disappointed to see it couldn't keep up with the 2D version. The trick seems to be more inlining. By putting the function in a class, you can get it to inline at each 'dimension' (there must be a better way to do this...)
class FoldrRange n where
foldrRangeN' :: (Vec n Int -> t -> t) -> t -> Vec n Int -> Vec n Int -> t
instance FoldrRange Z where
{-# INLINE foldrRangeN' #-}
foldrRangeN' f x Nil Nil = f Nil x
instance FoldrRange n => FoldrRange (S n) where
{-# INLINE foldrRangeN' #-}
foldrRangeN' cons nil (ax :< ay) (bx :< by) = go (by-1) nil where
go by !r
| by < ay = r
| otherwise = go (by-1) (foldrRangeN' (\ ax -> cons (ax :< by)) r ax bx)
Tested as follows:
main = do
i:n':_ <- getArgs
let n = read n' :: Int
rs = [ foldrRange2D (\ (a,b) c -> a+b+c) 0 (0,0) (n,n)
, foldrRangeND (\ [a,b] c -> a+b+c) 0 [0,0] [n,n]
, foldrRangeN (\ (Nil :< a :< b) c -> a+b+c) 0 (Nil :< 0 :< 0) (Nil :< n :< n)
, foldrRangeN' (\ (Nil :< a :< b) c -> a+b+c) 0 (Nil :< 0 :< 0) (Nil :< n :< n)
]
print $ rs !! read i
and the results on my system
./test 0 4000 +RTS -s : 0.02s
./test 1 4000 +RTS -s : 7.63s
./test 2 4000 +RTS -s : 0.59s
./test 3 4000 +RTS -s : 0.03s

How to formalize the definition of likeness/similarity between relations in Coq?

I am reading the book Introduction to Mathematics Philosophy by B.Russell and trying to formalize the definitions. Whereas I got stuck on proving the equivalence between the two definitions of similarity posed in the book.
Here are the text quoted from the book. (context)
1) Defining similarity directly:
We may define two relations P and Q as “similar,” or as having
“likeness,” when there is a one-one relation S whose domain is the
field of P and whose converse domain is the field of Q, and which is
such that, if one term has the relation P to another, the correlate of
the one has the relation Q to the correlate of the other, and vice
versa.
Here's my comprehension of the above text:
Inductive similar {X} (P : relation X) (Q : relation X) : Prop :=
| similar_intro : forall (S : relation X),
one_one S ->
(forall x, field P x <-> domain S x) ->
(forall x y z w, P x y -> S x z -> S y w -> Q z w) ->
(forall x y z w, Q z w -> S x z -> S y w -> P x y) ->
similar P Q.
2) Defining similarity through the concept of 'correlator':
A relation S is said to be a “correlator” or an “ordinal correlator”
of two relations P and Q if S is one-one, has the field of Q for its
converse domain, and is such that P is the relative product of S and Q
and the converse of S.
Two relations P and Q are said to be “similar,” or to have “likeness,”
when there is at least one correlator of P and Q.
My definition to this is:
Inductive correlator {X} (P Q : relation X) : relation X -> Prop :=
| correlator_intro : forall (S : relation X),
one_one S ->
(forall x, field P x <-> domain S x) ->
(forall x y, relative_product (relative_product S Q) (converse S) x y <-> P x y) ->
correlator P Q S.
Inductive similar' {X} (P Q : relation X) : Prop :=
| similar'_intro : forall S, correlator P Q S -> similar' P Q.
But I couldn't prove that similar is equivalent to similar', where did I make the mistake? Thanks a lot.

Resources