Module ZNone
We provide here some arithmetic on
ZN.t
=
option
Z
- Here
Some
z
represents an integer z. - And
None
represents an unknow integer. This "number" is used to encode intervals. When
None
is involved in comparisons (e.g.
<=
), it can thus be considered as a kind of infinite. Authors: Alexandre Maréchal et Sylvain Boulmé
Require
Export
Sumbool
.
Require
Export
ZArith
.
Require
Export
BinInt
.
Require
Export
OptionMonad
.
Open
Scope
Z_scope
.
Open
Scope
option_scope
.
Program
Definition
Z_isZero
(
z
:
Z
) : {
z
=0 } + {
z
<> 0 } :=
match
z
with
|
Z0
=>
left
_
|
_
=>
right
_
end
.
Program
Definition
Z_isNat
(
z
:
Z
) : { 0 <=
z
} + { ~(0 <=
z
) } :=
match
z
with
|
Z0
=>
left
_
|
Zpos
_
=>
left
_
|
Zneg
_
=>
right
_
end
.
Program
Definition
Z_isNegNat
(
z
:
Z
) : {
z
<= 0 } + { ~(
z
<= 0) } :=
match
z
with
|
Z0
=>
left
_
|
Zpos
_
=>
right
_
|
Zneg
_
=>
left
_
end
.
Hint
Resolve
Z.le_trans
Z.le_max_l
Z.le_max_r
Z.le_min_l
Z.le_min_r
:
zarith
.
Lemma
Zle_max_rew_r
x
y
z
:
x
<= (
Z.max
y
z
) <-> (
x
<=
y
\/
x
<=
z
).
Proof.
intros
;
constructor
1.
apply
Z.max_case_strong
;
intuition
.
intuition
eauto
with
zarith
.
Qed.
Lemma
Zle_max_rew_l
:
forall
x
y
z
, (
Z.max
y
z
) <=
x
<-> (
y
<=
x
/\
z
<=
x
).
Proof.
intros
;
apply
Z.max_case_strong
;
intuition
eauto
with
zarith
.
Qed.
Lemma
Zle_min_rew_r
x
y
z
:
x
<= (
Z.min
y
z
) <-> (
x
<=
y
/\
x
<=
z
).
Proof.
intros
;
apply
Z.min_case_strong
;
intuition
eauto
with
zarith
.
Qed.
Lemma
Zle_min_rew_l
x
y
z
: (
Z.min
y
z
) <=
x
<-> (
y
<=
x
\/
z
<=
x
).
Proof.
intros
;
split
.
apply
Z.min_case_strong
;
intuition
.
intuition
;
(
eapply
Zle_trans
; [
idtac
|
eauto
];
eauto
with
zarith
).
Qed.
Ltac
Zminmax_simplify
:=
repeat
(
rewrite
!
Z.max_id
,
Z.min_id
in
* |- *
||
rewrite
Zle_max_rew_l
||
rewrite
Zle_max_rew_r
||
rewrite
Zle_min_rew_l
||
rewrite
Zle_min_rew_r
);
intuition
(
omega
||
auto
with
zarith
).
Hint
Resolve
Z.mul_le_mono_nonpos_l
Z.mul_le_mono_nonpos_r
:
zarith
.
Lemma
Z_le_trans_r
n
m
p
:
m
<=
p
->
n
<=
m
->
n
<=
p
.
Proof.
omega
.
Qed.
Lemma
Z_not_negnat_isnat
z
: ~(
z
<= 0) -> 0 <=
z
.
Proof.
omega
.
Qed.
Create
HintDb
zle_compat
discriminated
.
Hint
Resolve
Z.mul_le_mono_nonpos_l
Z.mul_le_mono_nonneg_l
Z.mul_le_mono_nonpos_r
Z.mul_le_mono_nonneg_r
Z.le_trans
Z_le_trans_r
Z_not_negnat_isnat
:
zle_compat
.
Delimit
Scope
ZN_scope
with
ZN
.
Module
ZN
.
Definition
t
:
Type
:=
option
Z
.
Bind
Scope
ZN_scope
with
t
.
Open
Scope
ZN
.
Create
HintDb
zn
discriminated
.
Create
HintDb
xzn
discriminated
.
Definition
leZ
(
z1
:
Z
) (
zn2
:
t
):
Prop
:=
WHEN
z2
<-
zn2
THEN
z1
<=
z2
.
Definition
le
(
zn1
zn2
:
t
):
Prop
:=
WHEN
z1
<-
zn1
THEN
leZ
z1
zn2
.
Definition
add
(
zn1
zn2
:
t
) :
t
:=
SOME
z1
<-
zn1
-;
SOME
z2
<-
zn2
-;
Some
(
z1
+
z2
).
Extraction
Inline
add
.
NB: z is required to be not zero ! It is a precondition for precision ! (e.g. not verified in Coq)
Definition
mulZ1
(
z
:
Z
) (
zn
:
t
) :
t
:=
SOME
z2
<-
zn
-;
Some
(
z
*
z2
).
Extraction
Inline
mulZ1
.
Definition
mulZ
(
z
:
Z
) (
zn
:
t
) :
t
:=
if
Z_isZero
z
then
Some
0
else
mulZ1
z
zn
.
Extraction
Inline
mulZ
.
Definition
opp
(
zn
:
t
) :
t
:=
SOME
z
<-
zn
-;
Some
(-
z
).
Extraction
Inline
opp
.
Notation
"
x
+
y
" := (
add
x
y
) :
ZN_scope
.
Notation
"
x
<=
y
" := (
le
x
y
) :
ZN_scope
.
Notation
"
x
<=
y
<=
z
" := (
le
x
y
/\
le
y
z
) :
ZN_scope
.
Open
Scope
ZN_scope
.
Lemma
leZ_le
z1
(
zn2
:
t
):
leZ
z1
zn2
<-> (
Some
z1
) <=
zn2
.
Proof.
unfold
le
;
simpl
;
intuition
.
Qed.
Lemma
mulZ1_Some
a
b
:
mulZ1
a
(
Some
b
)=(
Some
(
a
*
b
)%
Z
).
Proof.
auto
.
Qed.
Lemma
mulZ_Some
a
b
:
mulZ
a
(
Some
b
)=(
Some
(
a
*
b
)%
Z
).
Proof.
unfold
mulZ
.
destruct
(
Z_isZero
a
);
intros
;
try
subst
;
auto
.
Qed.
Lemma
mulZ_mulZ1
a
b
:
a
<> 0 ->
mulZ
a
b
=
mulZ1
a
b
.
Proof.
unfold
mulZ
.
destruct
(
Z_isZero
a
);
intros
;
try
subst
;
auto
.
omega
.
Qed.
Remark
notLe
zn1
zn2
:
~(
zn1
<=
zn2
) <->
EXISTS
z1
<-
zn1
SUCH
EXISTS
z2
<-
zn2
SUCH
(
z2
<
z1
)%
Z
.
Proof.
destruct
zn1
,
zn2
;
simpl
;
intuition
try
omega
.
Qed.
Hint
Resolve
notLe
:
xzn
.
Ltac
simpl_arith
:=
xsimplify
ltac
:(
intuition
eauto
with
xzn
);
intros
;
try
(
rewrite
!
mulZ_Some
in
* |- *);
repeat
(
rewrite
mulZ_mulZ1
in
* |- *; [
idtac
|
omega
|| (
auto
with
zarith
;
fail
) ]);
simpl
in
* |- * ;
try
(
rewrite
!
leZ_le
in
* |- *);
try
(
apply
f_equal
);
omega
||
auto
with
zn
zarith
.
Lemma
le_None
x
:
x
<=
None
.
Proof.
destruct
x
;
simpl
;
auto
.
Qed.
Hint
Resolve
le_None
:
zn
.
Program
Definition
isZero
zn
: {
zn
= (
Some
0) } + {
zn
<> (
Some
0) } :=
match
zn
with
|
None
=>
right
_
|
Some
z
=>
if
Z_isZero
z
then
left
_
else
right
_
end
.
Extraction
Inline
isZero
.
Program
Definition
le_dec
zn1
zn2
: {
zn1
<=
zn2
} + {~
zn1
<=
zn2
} :=
match
zn1
with
|
None
=>
left
_
|
Some
z1
=>
match
zn2
with
|
None
=>
left
_
|
Some
z2
=>
if
Z_le_dec
z1
z2
then
left
_
else
right
_
end
end
.
Extraction
Inline
le_dec
.
Definition
leb
(
x
y
:
t
) :=
if
le_dec
x
y
then
true
else
false
.
Notation
"
x
<=?
y
" := (
leb
x
y
) :
ZN_scope
.
Coercion
Is_true
:
bool
>->
Sortclass
.
Lemma
le_bool_le
x
y
:
x
<=?
y
<->
x
<=
y
.
Proof.
unfold
leb
;
destruct
(
le_dec
x
y
);
simpl
;
intuition
;
omega
||
auto
.
Qed.
Program
Definition
eq_dec
x
y
: {
x
=
y
} + {
x
<>
y
} :=
match
x
with
|
None
=>
match
y
with
|
None
=>
left
_
_
|
Some
zy
=>
right
_
_
end
|
Some
zx
=>
match
y
with
|
None
=>
right
_
_
|
Some
zy
=>
if
Z_eq_dec
zx
zy
then
left
_
else
right
_
end
end
.
Lemma
Some_eq
(
z1
z2
:
Z
):
Some
z1
=
Some
z2
<->
z1
=
z2
.
Proof.
intuition
congruence
.
Qed.
Hint
Rewrite
Some_eq
:
zn
.
Lemma
add_le_compat
(
a
b
c
d
:
t
) :
a
<=
b
->
c
<=
d
->
a
+
c
<=
b
+
d
.
Proof.
unfold
add
;
simpl_arith
.
Qed.
Lemma
opp_le_compat
(
a
b
:
t
) :
a
<=
b
->
opp
b
<=
opp
a
.
Proof.
unfold
opp
;
simpl_arith
.
Qed.
Lemma
le_refl
a
:
a
<=
a
.
Proof.
unfold
le
;
simpl_arith
.
Qed.
Hint
Resolve
le_refl
add_le_compat
opp_le_compat
:
zn
.
Lemma
le_trans
b
(
a
c
:
t
):
a
<=
Some
b
->
Some
b
<=
c
->
a
<=
c
.
Proof.
unfold
le
,
leZ
;
simpl_arith
.
Qed.
Lemma
mulZ1_le_compat_pos_l
a
b
c
:
(0 <=
a
)%
Z
->
b
<=
c
-> (
mulZ1
a
b
) <= (
mulZ1
a
c
).
Proof.
unfold
mulZ1
;
simpl_arith
.
Qed.
Hint
Resolve
mulZ1_le_compat_pos_l
:
zn
.
Lemma
mulZ_le_compat_pos_l
a
b
c
:
(0 <=
a
)%
Z
->
b
<=
c
-> (
mulZ
a
b
) <= (
mulZ
a
c
).
Proof.
unfold
mulZ
;
destruct
(
Z_isZero
a
);
auto
with
zn
.
Qed.
Hint
Resolve
mulZ_le_compat_pos_l
:
zn
.
Lemma
mulZ1_le_compat_opp_l
a
b
c
:
~(0 <=
a
)%
Z
->
b
<=
c
-> (
mulZ1
a
c
) <= (
mulZ1
a
b
).
Proof.
unfold
mulZ1
;
simpl_arith
.
Qed.
Hint
Resolve
mulZ1_le_compat_opp_l
:
zn
.
Lemma
mulZ_le_compat_opp_l
a
b
c
:
~(0 <=
a
)%
Z
->
b
<=
c
-> (
mulZ
a
c
) <= (
mulZ
a
b
).
Proof.
unfold
mulZ
;
destruct
(
Z_isZero
a
);
auto
with
zn
.
Qed.
Hint
Resolve
mulZ_le_compat_opp_l
:
zn
.
Definition
join
(
zn1
zn2
:
t
):
t
:=
SOME
z1
<-
zn1
-;
SOME
z2
<-
zn2
-;
Some
(
Z.max
z1
z2
).
Lemma
join_lowest
x
y
z
:
x
<=
z
->
y
<=
z
->
join
x
y
<=
z
.
Proof.
unfold
join
;
destruct
z
;
simpl_arith
;
Zminmax_simplify
.
Qed.
Lemma
join_le_l
x
y
z
:
z
<=
x
->
z
<=
join
x
y
.
Proof.
unfold
join
;
destruct
z
;
simpl_arith
;
Zminmax_simplify
.
Qed.
Lemma
join_le_r
x
y
z
:
z
<=
y
->
z
<=
join
x
y
.
Proof.
unfold
join
;
destruct
z
;
simpl_arith
;
Zminmax_simplify
.
Qed.
Definition
meet
(
zn1
zn2
:
t
):
t
:=
SOME
z1
<-
zn1
-;
SOME
z2
<-
zn2
-;
Some
(
Z.min
z1
z2
).
Lemma
meet_le_l
x
y
z
:
x
<=
z
->
meet
x
y
<=
z
.
Proof.
unfold
meet
;
destruct
z
;
simpl_arith
;
Zminmax_simplify
.
Qed.
Lemma
meet_le_r
x
y
z
:
y
<=
z
->
meet
x
y
<=
z
.
Proof.
unfold
meet
;
destruct
z
;
simpl_arith
;
Zminmax_simplify
.
Qed.
Lemma
meet_greatest
x
y
z
:
z
<=
x
->
z
<=
y
->
z
<=
meet
x
y
.
Proof.
unfold
meet
;
destruct
z
;
simpl_arith
;
Zminmax_simplify
.
Qed.
Hint
Resolve
join_le_l
join_le_r
join_lowest
meet_le_l
meet_le_r
meet_greatest
:
zn
.
Close
Scope
ZN_scope
.
End
ZN
.
Close
Scope
option_scope
.
Close
Scope
Z_scope
.