diff --git a/.github/workflows/docker-action.yml b/.github/workflows/docker-action.yml index 69e39c5..052158a 100644 --- a/.github/workflows/docker-action.yml +++ b/.github/workflows/docker-action.yml @@ -6,13 +6,9 @@ on: push: branches: - master - paths-ignore: - - 'documents/**' pull_request: branches: - '**' - paths-ignore: - - 'documents/**' jobs: build: @@ -21,8 +17,7 @@ jobs: strategy: matrix: image: - - 'mathcomp/mathcomp:1.16.0-coq-8.15' - - 'mathcomp/mathcomp:1.16.0-coq-8.16' + - 'mathcomp/mathcomp:2.2.0-coq-8.19' fail-fast: false steps: - uses: actions/checkout@v3 diff --git a/.gitignore b/.gitignore index c4e0fb6..1935569 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ Makefile.coq Makefile.coq.conf .Makefile.coq.d -html/*.cmo -html/*.cmi -html/*.bytes -html/*.js \ No newline at end of file +www/*.cmo +www/*.cmi +www/*.bytes +www/*.js diff --git a/README.md b/README.md index 2e27acb..06103b0 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ Follow the instructions on https://github.com/coq-community/templates to regener [![Docker CI][docker-action-shield]][docker-action-link] -[docker-action-shield]: https://github.com/math-comp/trajectories/workflows/Docker%20CI/badge.svg?branch=master -[docker-action-link]: https://github.com/math-comp/trajectories/actions?query=workflow:"Docker%20CI" +[docker-action-shield]: https://github.com/math-comp/trajectories/actions/workflows/docker-action.yml/badge.svg?branch=master +[docker-action-link]: https://github.com/math-comp/trajectories/actions/workflows/docker-action.yml @@ -20,20 +20,20 @@ TODO - Reynald Affeldt (initial) - Yves Bertot (initial) - License: [CeCILL-C](LICENSE) -- Compatible Coq versions: Coq >= 8.15, MathComp >= 1.16 +- Compatible Coq versions: Coq >= 8.17, MathComp >= 2.2.0 - Additional dependencies: - - [MathComp ssreflect 1.15 or later](https://math-comp.github.io) - - [MathComp fingroup 1.15 or later](https://math-comp.github.io) - - [MathComp algebra 1.15 or later](https://math-comp.github.io) - - [MathComp solvable 1.15 or later](https://math-comp.github.io) - - [MathComp field 1.16 or later](https://math-comp.github.io) - - [Mathcomp real closed 1.1.3 or later](https://github.com/math-comp/real-closed/) - - [Algebra tactics 1.0.0](https://github.com/math-comp/algebra-tactics) - - [MathComp analysis](https://github.com/math-comp/analysis) - - [Infotheo](https://github.com/affeldt-aist/infotheo) + - [MathComp ssreflect 2.2.0 or later](https://math-comp.github.io) + - [MathComp fingroup 2.2.0 or later](https://math-comp.github.io) + - [MathComp algebra 2.2.0 or later](https://math-comp.github.io) + - [MathComp solvable 2.2.0 or later](https://math-comp.github.io) + - [MathComp field 2.2.0 or later](https://math-comp.github.io) + - [Mathcomp real closed 2.0.0 or later](https://github.com/math-comp/real-closed/) + - [Algebra tactics 1.2.0 or later](https://github.com/math-comp/algebra-tactics) + - [MathComp analysis 1.0.0 or later](https://github.com/math-comp/analysis) + - [Infotheo 0.7.0 of later](https://github.com/affeldt-aist/infotheo) - Coq namespace: `mathcomp.trajectories` - Related publication(s): - - [TODO](TODO) doi:[TODO](https://doi.org/TODO) + - [Safe Smooth Paths between Straight Line Obstacles](https://inria.hal.science/hal-04312815) doi:[https://doi.org/10.1007/978-3-031-61716-4_3](https://doi.org/https://doi.org/10.1007/978-3-031-61716-4_3) ## Building and installation instructions @@ -70,6 +70,9 @@ references: https://hal.inria.fr/inria-00503017v2/document - Theorem of three circles in Coq (2013) https://arxiv.org/abs/1306.0783 +- Safe Smooth Paths between straight line obstacles + https://inria.hal.science/hal-04312815 + https://link.springer.com/chapter/10.1007/978-3-031-61716-4_3 ## Development information diff --git a/_CoqProject b/_CoqProject index 8dcf076..517d550 100644 --- a/_CoqProject +++ b/_CoqProject @@ -1,3 +1,4 @@ +theories/shortest_path.v theories/generic_trajectories.v theories/smooth_trajectories.v theories/convex.v @@ -22,6 +23,16 @@ theories/encompass.v theories/counterclockwise.v theories/axiomsKnuth.v theories/preliminaries_hull.v +theories/cells.v +theories/cells_alg.v +theories/door_crossing.v +theories/events.v +theories/extraction_command.v +theories/math_comp_complements.v +theories/no_crossing.v +theories/opening_cells.v +theories/points_and_edges.v +theories/safe_cells.v -R theories trajectories diff --git a/coq-mathcomp-trajectories.opam b/coq-mathcomp-trajectories.opam index 6badeca..db76215 100644 --- a/coq-mathcomp-trajectories.opam +++ b/coq-mathcomp-trajectories.opam @@ -17,16 +17,16 @@ TODO""" build: [make "-j%{jobs}%"] install: [make "install"] depends: [ - "coq" { (>= "8.14" & < "8.17~") | (= "dev") } - "coq-mathcomp-ssreflect" { (>= "1.16.0" & < "1.17~") | (= "dev") } - "coq-mathcomp-fingroup" { (>= "1.16.0" & < "1.17~") | (= "dev") } - "coq-mathcomp-algebra" { (>= "1.16.0" & < "1.17~") | (= "dev") } - "coq-mathcomp-solvable" { (>= "1.16.0" & < "1.17~") | (= "dev") } - "coq-mathcomp-field" { (>= "1.16.0" & < "1.17~") | (= "dev") } - "coq-mathcomp-real-closed" { (>= "1.1.3") | (= "dev") } - "coq-mathcomp-algebra-tactics" { (>= "1.0.0") | (= "dev") } - "coq-mathcomp-analysis" { (>= "0.6.1") & (< "0.7~")} - "coq-infotheo" { >= "0.5.1" & < "0.6~"} + "coq" { (>= "8.17" & < "8.20~") | (= "dev") } + "coq-mathcomp-ssreflect" { (>= "2.2.0") | (= "dev") } + "coq-mathcomp-fingroup" { (>= "2.2.0") | (= "dev") } + "coq-mathcomp-algebra" { (>= "2.2.0") | (= "dev") } + "coq-mathcomp-solvable" { (>= "2.2.0") | (= "dev") } + "coq-mathcomp-field" { (>= "2.2.0") | (= "dev") } + "coq-mathcomp-real-closed" { (>= "2.0.0") | (= "dev") } + "coq-mathcomp-algebra-tactics" { (>= "1.2.0") | (= "dev") } + "coq-mathcomp-analysis" { (>= "1.0.0") } + "coq-infotheo" { >= "0.7.0"} ] tags: [ diff --git a/documents/FHG_slides.tex b/documents/FHG_slides.tex new file mode 100644 index 0000000..d9394f2 --- /dev/null +++ b/documents/FHG_slides.tex @@ -0,0 +1,192 @@ +\documentclass[compress]{beamer} +\usepackage[latin1]{inputenc} +\usepackage{alltt} +\newdimen\topcrop +\topcrop=10cm %alternatively 8cm if the pdf inclusions are in letter format +\newdimen\topcropBezier +\topcropBezier=19cm %alternatively 16cm if the inclusions are in letter format + +\setbeamertemplate{footline}[frame number] +\title{Smooth trajectories in straight line mazes} +\author{Yves Bertot\\ +Joint work with Thomas Portet, Quentin Vermande} +\date{April 2023} +\mode +\begin{document} + +\maketitle +\begin{frame} +\frametitle{The game} +\begin{itemize} +\item Apply Type Theory-based verification to a problem understood by a + wide audience +\item Find a smooth path in a maze +\item Decompose the problem +\begin{itemize} +\item Find a discrete approximation of the problem +\item Construct a piece-wise linear path +\item smoothen the angles +\end{itemize} +\item Prove the correctness of the algorithm +\begin{itemize} +\item Safety: absence of collision +\item work in progress +\end{itemize} +\end{itemize} +\end{frame} +\begin{frame} +\frametitle{Example} +\includegraphics[trim={0 0 0 \topcrop}, clip, width=\textwidth]{empty_spiral.pdf} +\end{frame} +\begin{frame} +\frametitle{Cell decomposition} +\begin{itemize} +\item Decompose the space into simple cells +\item Each cell is convex +\item Each cell is free of obstacles +\item Each cell may have safely reachable neighbors +\end{itemize} +\end{frame} +\begin{frame} +\frametitle{Vertical cell decomposition example} +\includegraphics[trim={0 0 0 \topcrop}, clip, width=\textwidth]{cells_spiral.pdf} +\end{frame} +\begin{frame} +\frametitle{Cell properties} +\begin{itemize} +\item Vertical edges are safe passages between two cells +\item Moving directly from a left-edge to a right-edge is safe +\begin{itemize} +\item and vice-versa +\end{itemize} +\item Moving from a left-edge to the cell center is safe +\begin{itemize} +\item similarly for a right-edge +\item moving from left-edge to left-edge is safe by going through the + cell center +\end{itemize} +\end{itemize} +\end{frame} +\begin{frame} +\frametitle{Finding a path in the cell graph} +\begin{itemize} +\item A discrete path from cell to cell is found by breadth-first search +\item Connected components of the graph are defined by polygons +\item Special care for points that are already on the common edge of two cells +\item Recent improvement: take distances into account +\begin{itemize} +\item Use a graph of doors instead of cells +\item Easier to associate a distance between pairs of doors +\item Dijkstra shortest path algorithm +\end{itemize} +\item In the end, a path from door to door +\end{itemize} +\end{frame} +\begin{frame} +\frametitle{Two examples of elementary safe paths} +\includegraphics[trim={0 0 0 \topcrop}, clip, width=\textwidth]{spiral_safe2.pdf} +\end{frame} +\begin{frame} +\frametitle{piecewise linear path} +\label{broken-line} +\includegraphics[trim={0 0 0 \topcrop}, clip, width=\textwidth]{spiral_bline.pdf} +\end{frame} +\begin{frame} +\frametitle{Making corners smooth} +\begin{itemize} +\item Using quadratic Bezier curves +\item Bezier curves are given by a set of control points + (3 for a quadratic curve) +\item Points on the curves are obtained by computing weighted barycenters +\begin{itemize} +\item The curve is enclosed in the convex hull of the control points +\end{itemize} +\item Given control points \(a_0, a_1, \ldots, a_{n-1}, a_n\), \(a_0, a_1\) +is tangent to the curve in \(a_0\) +\begin{itemize} +\item same for \(a_{n-1}, a_n\) in \(a_n\) +\end{itemize} +\end{itemize} +\end{frame} +\begin{frame} +\frametitle{Bezier curve illustration} +\begin{itemize} +\item How the point for ratio \(4/9\) is computed +\item Control points for the two subcurves are given by the new point, +the initial starting and end points, and the solid green straight edge tip +\end{itemize} +\includegraphics[trim={0 6cm 0 \topcropBezier}, clip, width=\textwidth]{bezier_example2.pdf} +\end{frame} +\begin{frame} +\frametitle{Using Bezier curves for smoothing} +\begin{itemize} +\item Add extra points in the middle of each straight line segment +\item Uses these extra points as first and last control points for Bezier curves +\item Use the angle point as the middle control point +\item Check the Bezier curve for collision and repair if need be +\end{itemize} +\end{frame} +\begin{frame} +\frametitle{Collision checking, graphically} +\includegraphics[trim={0 4cm 0 17cm}, clip, width=\textwidth]{collision.pdf} +\end{frame} +\begin{frame} +\frametitle{Not passing in the top door} +\includegraphics[trim={0 4cm 0 17cm}, clip, width=\textwidth]{collision2.pdf} +\end{frame} +\begin{frame} +\frametitle{Final trajectories} +\label{final-spiral} +\includegraphics[trim={0 0 0 \topcrop}, clip, width=\textwidth]{smooth_spiral2.pdf} +\end{frame} +\begin{frame} +\frametitle{Proof tools} +\begin{itemize} +\item Convex hulls (Pichardie \& B. 2001) +\begin{itemize} +\item Orientation predicate +\item point below or above edge +\end{itemize} +\item Linear arithmetic +\begin{itemize} +\item Algorithms only use rational numbers +\item Bezier curve intersections rely on algebraic numbers +\end{itemize} +\item Convex spaces and Bezier Curve +\begin{itemize} +\item Internship by Q. Vermande +\item Using {\tt infotheo}, especially convex and conical spaces + (Affeldt \& Garrigue \& Saikawa 2020) +\end{itemize} +\end{itemize} +\end{frame} +\begin{frame} +\frametitle{Vertical cell decomposition proofs} +\begin{itemize} +\item Use of semi-closed vertical cells +\item Show disjoint property +\item Show that obstacles are covered by cell tops +\end{itemize} +\end{frame} +\begin{frame} +\frametitle{Future work} +\begin{itemize} +\item Intend to prove only safety +\item Produce concrete code from abstract models +\begin{itemize} +\item Move from exact computation to approximations +\item Efficient implementation of graphs +\end{itemize} +\item Already usable in \textcolor{blue}{\href{https://stamp.gitlabpages.inria.fr/trajectories.html}{web-base demonstration}.} +\begin{itemize} +\item Extracted code to Ocaml, then compile to JavaScript +\end{itemize} +\end{itemize} +\end{frame} +\end{document} + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: diff --git a/documents/Makefile b/documents/Makefile index 3038b9a..60dd236 100644 --- a/documents/Makefile +++ b/documents/Makefile @@ -1,4 +1,4 @@ -all : intro_slides.pdf FHG_paper.pdf +all : intro_slides.pdf FHG_paper.pdf FHG_slides.pdf PSFILES=bezier_example.ps bezier_example2.ps cells_spiral.ps \ collision.ps collision2.ps empty_spiral.ps polygon.ps repair2.ps \ @@ -16,5 +16,8 @@ FHG_paper.pdf : FHG_paper.tex FHG_paper.bib $(PDFFILES) illustration.png pdflatex FHG_paper.tex; bibtex FHG_paper; pdflatex FHG_paper.tex \ FHG_paper.tex +FHG_slides.pdf : FHG_slides.tex $(PDFFILES) + PDFLATEX FHG_slides.tex; pdflatex FHG_slides.tex + $(PDFFILES): %.pdf: %.ps ps2pdf -sPAPERSIZE=a4 $< diff --git a/documents/collision.ps b/documents/collision.ps index 03beb13..ff64f80 100644 Binary files a/documents/collision.ps and b/documents/collision.ps differ diff --git a/documents/collision2.ps b/documents/collision2.ps index ddf615f..9ddbf9f 100644 Binary files a/documents/collision2.ps and b/documents/collision2.ps differ diff --git a/html/Add.html b/html/Add.html deleted file mode 100755 index aefc4fa..0000000 --- a/html/Add.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - Add - - - -

Add

- -

- - - -

- -

- -

- -

- - - - diff --git a/html/Add.ml b/html/Add.ml deleted file mode 100644 index c94be3b..0000000 --- a/html/Add.ml +++ /dev/null @@ -1,403 +0,0 @@ - -type nat = -| O -| S of nat - -type ('a, 'b) prod = -| Pair of 'a * 'b - -(** val snd : ('a1, 'a2) prod -> 'a2 **) - -let snd = function -| Pair (_, y) -> y - -type 'a list = -| Nil -| Cons of 'a * 'a list - -type comparison = -| Eq -| Lt -| Gt - -module Coq__1 = struct - (** val add : nat -> nat -> nat **) - let rec add n m = - match n with - | O -> m - | S p -> S (add p m) -end -include Coq__1 - -type positive = -| XI of positive -| XO of positive -| XH - -type z = -| Z0 -| Zpos of positive -| Zneg of positive - -module Pos = - struct - type mask = - | IsNul - | IsPos of positive - | IsNeg - end - -module Coq_Pos = - struct - (** val succ : positive -> positive **) - - let rec succ = function - | XI p -> XO (succ p) - | XO p -> XI p - | XH -> XO XH - - (** val add : positive -> positive -> positive **) - - let rec add x y = - match x with - | XI p -> - (match y with - | XI q0 -> XO (add_carry p q0) - | XO q0 -> XI (add p q0) - | XH -> XO (succ p)) - | XO p -> - (match y with - | XI q0 -> XI (add p q0) - | XO q0 -> XO (add p q0) - | XH -> XI p) - | XH -> (match y with - | XI q0 -> XO (succ q0) - | XO q0 -> XI q0 - | XH -> XO XH) - - (** val add_carry : positive -> positive -> positive **) - - and add_carry x y = - match x with - | XI p -> - (match y with - | XI q0 -> XI (add_carry p q0) - | XO q0 -> XO (add_carry p q0) - | XH -> XI (succ p)) - | XO p -> - (match y with - | XI q0 -> XO (add_carry p q0) - | XO q0 -> XI (add p q0) - | XH -> XO (succ p)) - | XH -> - (match y with - | XI q0 -> XI (succ q0) - | XO q0 -> XO (succ q0) - | XH -> XI XH) - - (** val pred_double : positive -> positive **) - - let rec pred_double = function - | XI p -> XI (XO p) - | XO p -> XI (pred_double p) - | XH -> XH - - type mask = Pos.mask = - | IsNul - | IsPos of positive - | IsNeg - - (** val succ_double_mask : mask -> mask **) - - let succ_double_mask = function - | IsNul -> IsPos XH - | IsPos p -> IsPos (XI p) - | IsNeg -> IsNeg - - (** val double_mask : mask -> mask **) - - let double_mask = function - | IsPos p -> IsPos (XO p) - | x0 -> x0 - - (** val double_pred_mask : positive -> mask **) - - let double_pred_mask = function - | XI p -> IsPos (XO (XO p)) - | XO p -> IsPos (XO (pred_double p)) - | XH -> IsNul - - (** val sub_mask : positive -> positive -> mask **) - - let rec sub_mask x y = - match x with - | XI p -> - (match y with - | XI q0 -> double_mask (sub_mask p q0) - | XO q0 -> succ_double_mask (sub_mask p q0) - | XH -> IsPos (XO p)) - | XO p -> - (match y with - | XI q0 -> succ_double_mask (sub_mask_carry p q0) - | XO q0 -> double_mask (sub_mask p q0) - | XH -> IsPos (pred_double p)) - | XH -> (match y with - | XH -> IsNul - | _ -> IsNeg) - - (** val sub_mask_carry : positive -> positive -> mask **) - - and sub_mask_carry x y = - match x with - | XI p -> - (match y with - | XI q0 -> succ_double_mask (sub_mask_carry p q0) - | XO q0 -> double_mask (sub_mask p q0) - | XH -> IsPos (pred_double p)) - | XO p -> - (match y with - | XI q0 -> double_mask (sub_mask_carry p q0) - | XO q0 -> succ_double_mask (sub_mask_carry p q0) - | XH -> double_pred_mask p) - | XH -> IsNeg - - (** val sub : positive -> positive -> positive **) - - let sub x y = - match sub_mask x y with - | IsPos z0 -> z0 - | _ -> XH - - (** val mul : positive -> positive -> positive **) - - let rec mul x y = - match x with - | XI p -> add y (XO (mul p y)) - | XO p -> XO (mul p y) - | XH -> y - - (** val size_nat : positive -> nat **) - - let rec size_nat = function - | XI p0 -> S (size_nat p0) - | XO p0 -> S (size_nat p0) - | XH -> S O - - (** val compare_cont : comparison -> positive -> positive -> comparison **) - - let rec compare_cont r x y = - match x with - | XI p -> - (match y with - | XI q0 -> compare_cont r p q0 - | XO q0 -> compare_cont Gt p q0 - | XH -> Gt) - | XO p -> - (match y with - | XI q0 -> compare_cont Lt p q0 - | XO q0 -> compare_cont r p q0 - | XH -> Gt) - | XH -> (match y with - | XH -> r - | _ -> Lt) - - (** val compare : positive -> positive -> comparison **) - - let compare = - compare_cont Eq - - (** val ggcdn : - nat -> positive -> positive -> (positive, (positive, positive) prod) - prod **) - - let rec ggcdn n a b = - match n with - | O -> Pair (XH, (Pair (a, b))) - | S n0 -> - (match a with - | XI a' -> - (match b with - | XI b' -> - (match compare a' b' with - | Eq -> Pair (a, (Pair (XH, XH))) - | Lt -> - let Pair (g, p) = ggcdn n0 (sub b' a') a in - let Pair (ba, aa) = p in - Pair (g, (Pair (aa, (add aa (XO ba))))) - | Gt -> - let Pair (g, p) = ggcdn n0 (sub a' b') b in - let Pair (ab, bb) = p in - Pair (g, (Pair ((add bb (XO ab)), bb)))) - | XO b0 -> - let Pair (g, p) = ggcdn n0 a b0 in - let Pair (aa, bb) = p in Pair (g, (Pair (aa, (XO bb)))) - | XH -> Pair (XH, (Pair (a, XH)))) - | XO a0 -> - (match b with - | XI _ -> - let Pair (g, p) = ggcdn n0 a0 b in - let Pair (aa, bb) = p in Pair (g, (Pair ((XO aa), bb))) - | XO b0 -> let Pair (g, p) = ggcdn n0 a0 b0 in Pair ((XO g), p) - | XH -> Pair (XH, (Pair (a, XH)))) - | XH -> Pair (XH, (Pair (XH, b)))) - - (** val ggcd : - positive -> positive -> (positive, (positive, positive) prod) prod **) - - let ggcd a b = - ggcdn (Coq__1.add (size_nat a) (size_nat b)) a b - end - -module Z = - struct - (** val double : z -> z **) - - let double = function - | Z0 -> Z0 - | Zpos p -> Zpos (XO p) - | Zneg p -> Zneg (XO p) - - (** val succ_double : z -> z **) - - let succ_double = function - | Z0 -> Zpos XH - | Zpos p -> Zpos (XI p) - | Zneg p -> Zneg (Coq_Pos.pred_double p) - - (** val pred_double : z -> z **) - - let pred_double = function - | Z0 -> Zneg XH - | Zpos p -> Zpos (Coq_Pos.pred_double p) - | Zneg p -> Zneg (XI p) - - (** val pos_sub : positive -> positive -> z **) - - let rec pos_sub x y = - match x with - | XI p -> - (match y with - | XI q0 -> double (pos_sub p q0) - | XO q0 -> succ_double (pos_sub p q0) - | XH -> Zpos (XO p)) - | XO p -> - (match y with - | XI q0 -> pred_double (pos_sub p q0) - | XO q0 -> double (pos_sub p q0) - | XH -> Zpos (Coq_Pos.pred_double p)) - | XH -> - (match y with - | XI q0 -> Zneg (XO q0) - | XO q0 -> Zneg (Coq_Pos.pred_double q0) - | XH -> Z0) - - (** val add : z -> z -> z **) - - let add x y = - match x with - | Z0 -> y - | Zpos x' -> - (match y with - | Z0 -> x - | Zpos y' -> Zpos (Coq_Pos.add x' y') - | Zneg y' -> pos_sub x' y') - | Zneg x' -> - (match y with - | Z0 -> x - | Zpos y' -> pos_sub y' x' - | Zneg y' -> Zneg (Coq_Pos.add x' y')) - - (** val mul : z -> z -> z **) - - let mul x y = - match x with - | Z0 -> Z0 - | Zpos x' -> - (match y with - | Z0 -> Z0 - | Zpos y' -> Zpos (Coq_Pos.mul x' y') - | Zneg y' -> Zneg (Coq_Pos.mul x' y')) - | Zneg x' -> - (match y with - | Z0 -> Z0 - | Zpos y' -> Zneg (Coq_Pos.mul x' y') - | Zneg y' -> Zpos (Coq_Pos.mul x' y')) - - (** val sgn : z -> z **) - - let sgn = function - | Z0 -> Z0 - | Zpos _ -> Zpos XH - | Zneg _ -> Zneg XH - - (** val abs : z -> z **) - - let abs = function - | Zneg p -> Zpos p - | x -> x - - (** val to_pos : z -> positive **) - - let to_pos = function - | Zpos p -> p - | _ -> XH - - (** val ggcd : z -> z -> (z, (z, z) prod) prod **) - - let ggcd a b = - match a with - | Z0 -> Pair ((abs b), (Pair (Z0, (sgn b)))) - | Zpos a0 -> - (match b with - | Z0 -> Pair ((abs a), (Pair ((sgn a), Z0))) - | Zpos b0 -> - let Pair (g, p) = Coq_Pos.ggcd a0 b0 in - let Pair (aa, bb) = p in - Pair ((Zpos g), (Pair ((Zpos aa), (Zpos bb)))) - | Zneg b0 -> - let Pair (g, p) = Coq_Pos.ggcd a0 b0 in - let Pair (aa, bb) = p in - Pair ((Zpos g), (Pair ((Zpos aa), (Zneg bb))))) - | Zneg a0 -> - (match b with - | Z0 -> Pair ((abs a), (Pair ((sgn a), Z0))) - | Zpos b0 -> - let Pair (g, p) = Coq_Pos.ggcd a0 b0 in - let Pair (aa, bb) = p in - Pair ((Zpos g), (Pair ((Zneg aa), (Zpos bb)))) - | Zneg b0 -> - let Pair (g, p) = Coq_Pos.ggcd a0 b0 in - let Pair (aa, bb) = p in - Pair ((Zpos g), (Pair ((Zneg aa), (Zneg bb))))) - end - -type q = { qnum : z; qden : positive } - -(** val qplus : q -> q -> q **) - -let qplus x y = - { qnum = (Z.add (Z.mul x.qnum (Zpos y.qden)) (Z.mul y.qnum (Zpos x.qden))); - qden = (Coq_Pos.mul x.qden y.qden) } - -(** val qred : q -> q **) - -let qred q0 = - let { qnum = q1; qden = q2 } = q0 in - let Pair (r1, r2) = snd (Z.ggcd q1 (Zpos q2)) in - { qnum = r1; qden = (Z.to_pos r2) } - -(** val a_val : q list **) - -let a_val = - Cons ({ qnum = (Zpos XH); qden = XH }, Nil) - -(** val sum_val_rec : q list -> q **) - -let rec sum_val_rec = function -| Nil -> { qnum = Z0; qden = XH } -| Cons (a, l0) -> qred (qplus a (sum_val_rec l0)) - -(** val sum_val : q list -> q list **) - -let sum_val l = - Cons ((sum_val_rec l), Nil) diff --git a/html/AddScript.js b/html/AddScript.js deleted file mode 100644 index eee5860..0000000 --- a/html/AddScript.js +++ /dev/null @@ -1,4 +0,0 @@ -function myadd() { - let v = document.getElementById("text").value; - window.alert(add(v)); -} diff --git a/html/Makefile.coq.local b/html/Makefile.coq.local deleted file mode 100644 index 7083bfd..0000000 --- a/html/Makefile.coq.local +++ /dev/null @@ -1,62 +0,0 @@ -post-all:: - $(MAKE) -f $(SELF) Add.mli SmoothTrajectories.mli -clean:: - rm -f Add.mli - -Add.mli : add.vo - echo "mli" -post-all:: - $(MAKE) -f $(SELF) Add.ml -clean:: - rm -f Add.ml -Add.ml : add.vo - echo "ml" - -post-all:: - $(MAKE) -f $(SELF) Add.cmi SmoothTrajectories.cmi - -clean:: - rm -f Add.cmi Add.cmo jAdd.cmi jAdd.cmo SmoothTrajectories.cmi SmoothTrajectories.cmo jSmoothTrajectories.cmi jSmoothTrajectories.cmo - -Add.cmi : Add.mli - ocamlfind ocamlc Add.mli - -SmoothTrajectories.ml SmoothTrajectories.mli : ../theories/smooth_trajectories.vo - cd ../theories; echo 'Require Import QArith smooth_trajectories. Extraction "SmoothTrajectories.ml" Qsmooth_point_to_point Qedges_to_cells Qreduction.Qred.' | coqtop -R . trajectories - cp ../theories/SmoothTrajectories.ml ../theories/SmoothTrajectories.mli . - -SmoothTrajectories.cmi : SmoothTrajectories.mli - ocamlfind ocamlc SmoothTrajectories.mli - -post-all:: - $(MAKE) -f $(SELF) jAdd.cmi jSmoothTrajectories.cmi -clean:: - rm -f jAdd.cmi jSmoothTrajectories.cmi - -jAdd.cmi : jAdd.ml - ocamlfind ocamlc jAdd.mli - -jSmoothTrajectories.cmi : jSmoothTrajectories.ml - ocamlfind ocamlc jSmoothTrajectories.mli - -post-all:: - $(MAKE) -f $(SELF) Add.bytes SmoothTrajectories.bytes -clean:: - rm -f Add.bytes SmoothTrajectories.bytes - -Add.bytes : jAdd.cmi jAdd.ml Add.ml Add.cmi - ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml-ppx -linkpkg -o Add.bytes Add.ml jAdd.ml - -SmoothTrajectories.bytes : jSmoothTrajectories.cmi jSmoothTrajectories.ml SmoothTrajectories.ml SmoothTrajectories.cmi - ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml-ppx -linkpkg -o SmoothTrajectories.bytes SmoothTrajectories.ml jSmoothTrajectories.ml - -post-all:: - $(MAKE) -f $(SELF) Add.js SmoothTrajectories.js -clean:: - rm -f Add.js SmoothTrajectories.js - -Add.js : Add.bytes - js_of_ocaml Add.bytes - -SmoothTrajectories.js : SmoothTrajectories.bytes - js_of_ocaml --opt=3 SmoothTrajectories.bytes diff --git a/html/add.v b/html/add.v deleted file mode 100644 index 0d36de6..0000000 --- a/html/add.v +++ /dev/null @@ -1,14 +0,0 @@ -Require Import List QArith Extraction. - - -Definition a_val := 1%Q :: nil. - -Fixpoint sum_val_rec l := - match l with a :: l => Qred (a + sum_val_rec l)%Q | _ => 0%Q end. - -Definition sum_val l := (sum_val_rec l) :: nil. - -Compute sum_val ((1#2)%Q :: (1#2)%Q :: nil). - -Extraction "Add.ml" a_val sum_val. - diff --git a/html/curve.html b/html/curve.html deleted file mode 100755 index 6de55e6..0000000 --- a/html/curve.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - Curve - - - - - - - - - \ No newline at end of file diff --git a/html/jAdd.ml b/html/jAdd.ml deleted file mode 100644 index a57188e..0000000 --- a/html/jAdd.ml +++ /dev/null @@ -1,57 +0,0 @@ -(** link code **) - -open Js_of_ocaml -open Add - -let rec n2pos n = if n < 2 then XH else - if n mod 2 == 0 then - XO (n2pos (n / 2)) else XI (n2pos (n / 2)) - -let rec pos2n n = - match n with XH -> 1 | XO n -> 2 * (pos2n n) | XI n -> 2 * (pos2n n) + 1 - -let n2z n = if n = 0 then Z0 else - if 0 < n then Zpos (n2pos n) - else Zneg (n2pos n) - -let z2n n = match n with -| Z0 -> 0 -| Zpos n -> pos2n n -| Zneg n -> - pos2n n - -let string2lr s = - let le = String.length s in - let rec iter i si vi = if i = le then Nil else - let v = String.get s i in - if (v == '-') then iter (i + 1) (-1) vi else - if (v == '+') then iter (i + 1) (1) vi else - if (v == ' ') then Cons (n2z (si * vi), iter (i + 1) 1 0) else - iter (i + 1) si (vi * 10 + (Char.code v - 48)) in - iter 0 1 0 - -let rec string2lr1 l = -match l with -| Cons (n , Cons (Z0, l)) -> Cons ({qnum = n; qden = XH}, (string2lr1 l)) -| Cons (n, Cons (Zpos d, l)) -> Cons ({qnum = n; qden = d}, (string2lr1 l)) -| _ -> Nil - -let string2l s = string2lr1 (string2lr s) - -let rec l2stringr s l = - match l with - Nil -> s - | Cons (n,l) -> l2stringr (s ^ (string_of_int (z2n n.qnum)) ^ " " ^ - (string_of_int (pos2n n.qden)) ^ " ") - l - -let l2string l = l2stringr "" l - -let main s = - let l = string2l s in l2string (sum_val l) - -let _ = - Js.export_all - (object%js - method add s = Js.string (main (Js.to_string s)) - end) - diff --git a/html/jAdd.mli b/html/jAdd.mli deleted file mode 100644 index 2fe4da4..0000000 --- a/html/jAdd.mli +++ /dev/null @@ -1,6 +0,0 @@ -open Add - -val n2pos : int -> positive -val pos2n : positive -> int -val n2z : int -> z -val z2n : z -> int diff --git a/html/script.js b/html/script.js deleted file mode 100644 index a0e24cb..0000000 --- a/html/script.js +++ /dev/null @@ -1,171 +0,0 @@ -import * as THREE from 'three'; -import { FontLoader } from 'three/addons/loaders/FontLoader.js'; -import { TextGeometry } from 'three/addons/geometries/TextGeometry.js'; - -const renderer = new THREE.WebGLRenderer(); -renderer.setSize( window.innerWidth, window.innerHeight ); -document.body.appendChild( renderer.domElement ); - -const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 500 ); -camera.position.set( 0, 0, 10 ); -camera.lookAt( 0, 0, 0 ); - -const scene = new THREE.Scene(); -scene.background = new THREE.Color( 'lightgrey' ); - -//create a blue LineBasicMaterial -const material = new THREE.LineBasicMaterial( { color: 'black' } ); -const cmaterial = new THREE.LineBasicMaterial( { color: 'red' } ); - -/* -BOTTOM - ({| left_pt := {| p_x := -4; p_y := -4|}; - right_pt := {| p_x := 4; p_y := -4|}|}). - -*/ - -const bpoints = []; -bpoints.push( new THREE.Vector3( - 4, - 4, 0 ) ); -bpoints.push( new THREE.Vector3( 4, - 4, 0 ) ); - -const bgeometry = new THREE.BufferGeometry().setFromPoints( bpoints ); - -const bline = new THREE.Line( bgeometry, material ); - -scene.add( bline ); - -/* -Notation TOP := - ({| left_pt := {| p_x := -4; p_y := 2|}; - right_pt := {| p_x := 4; p_y := 2|}|}). - -*/ - -const tpoints = []; -tpoints.push( new THREE.Vector3( - 4, 2, 0 ) ); -tpoints.push( new THREE.Vector3( 4, 2, 0 ) ); - -const tgeometry = new THREE.BufferGeometry().setFromPoints( tpoints ); - -const tline = new THREE.Line( tgeometry, material ); - -scene.add( tline ); - -/* -Definition example_edge_list : seq edge := - Bedge (Bpt (-3) 0) (Bpt (-2) 1) :: - Bedge (Bpt (-3) 0) (Bpt 0 (-3)) :: - Bedge (Bpt 0 (-3)) (Bpt 3 0) :: - Bedge (Bpt (-2) 1) (Bpt 0 1) :: - Bedge (Bpt 0 1) (Bpt 1 0) :: - Bedge (Bpt (-1) 0) (Bpt 0 (-1)) :: - Bedge (Bpt 0 (-1)) (Bpt 1 0) :: nil. -*/ - -const edge_list = [ - {fx : -3, fy : 0, tx : -2, ty : 1}, - {fx : -3, fy : 0, tx : 0, ty : -3}, - {fx : 0, fy : -3, tx : 3, ty : 0}, - {fx : -2, fy : 1, tx : 0, ty : 1}, - {fx : 0, fy : 1, tx : 1, ty : 0}, - {fx : -1, fy : 0, tx : 0, ty : -1}, - {fx : 0, fy : -1, tx : 1, ty : 0} -]; - -edge_list.forEach(add_edge); - -function add_edge(edge) { - let epoints = []; - epoints.push( new THREE.Vector3(edge.fx, edge.fy, 0 ) ); - epoints.push( new THREE.Vector3(edge.tx, edge.ty, 0 ) ); - let egeometry = new THREE.BufferGeometry().setFromPoints( epoints ); - let eline = new THREE.Line( egeometry, material ); - scene.add( eline ); -} - -/* curve - = straight {| p_x := -1.9; p_y := -3 # 2 |}; - {| p_x := -19 # 20; p_y := -480 # 192 |} :: - bezier {| p_x := -19 # 20; p_y := -480 # 192 |}; - {| p_x := 0; p_y := -168 # 48 |} - {| p_x := 3 # 2; p_y := -12672 # 4608 |}; :: - bezier {| p_x := 3 # 2; p_y := -12672 # 4608 |}; - {| p_x := 3; p_y := -96 # 48 |} - {| p_x := 0x3.4%xQ; p_y := -589824 # 393216 |} :: - bezier {| p_x := 0x3.4%xQ; p_y := -589824 # 393216 |} - {| p_x := 28 # 8; p_y := (-0x1.000)%xQ |} - {| p_x := 0x3.4%xQ; p_y := 0 # 131072 |} :: - bezier {| p_x := 0x3.4%xQ; p_y := 0 # 131072 |} - {| p_x := 3; p_y := 0x1.0%xQ |} - {| p_x := 4 # 2; p_y := 0 # 192 |} :: - bezier {| p_x := 4 # 2; p_y := 0 # 192 |} - {| p_x := 1; p_y := -6 # 6 |} - {| p_x := 1 # 2; p_y := -36 # 24 |} :: - bezier {| p_x := 1 # 2; p_y := -36 # 24 |} - {| p_x := 0; p_y := -4 # 2 |} - {| p_x := -1 # 2; p_y := -36 # 24 |} - bezier {| p_x := -1 # 2; p_y := -36 # 24 |} - {| p_x := -1; p_y := -6 # 6 |} - {| p_x := (-0x1.4)%xQ; p_y := -1080 # 1728 |} :: - bezier {| p_x := (-0x1.4)%xQ; p_y := -1080 # 1728 |} - {| p_x := -12 # 8; p_y := -36 # 144 |} - {| p_x := (-0x1.4)%xQ; p_y := 144 # 1152 |} :: - bezier {| p_x := (-0x1.4)%xQ; p_y := 144 # 1152 |} - {| p_x := -1; p_y := 2 # 4 |} - {| p_x := -1 # 2; p_y := 8 # 32 |} :: - bezier {| p_x := -1 # 2; p_y := 8 # 32 |}; - ({| p_x := 0; p_y := 0|}). - {| p_x := 1 # 6; p_y := 0 # 8 |} :: - straight {| p_x := 1 # 6; p_y := 0 # 8 |}; - {| p_x := 1 # 3; p_y := 0 |}; -*/ - -const curve_list = [ - {b : false, fx : -1.9, fy : -(3/2), tx : -(19/20), ty : - (480 / 192)}, - {b : true, fx : -(19/20), fy : -(480/192), - cx : 0, cy : -(168/48), tx : (3/2), ty : -(12672/4608)}, - {b : true, fx : (3/2), fy : -(12672/4608), - cx : 3, cy : -(96/48), tx : (3 + 4/16), ty : -(589824/393216)}, - {b : true, fx : (3 + 4 /16), fy : -(589824/393216), - cx : (28/8), cy : -(1), tx : (3 + 4/16), ty : 0}, - {b : true, fx : (3 + 4/16), fy : 0, - cx : 3, cy : 1.0, tx : (4/2), ty : 0}, - {b : true, fx : (4/2), fy : 0, - cx : 1, cy : -(6/6), tx : (1/2), ty : -(36/24)}, - {b : true, fx : (1/2), fy : -(36/24), - cx : 0, cy : -(4/2), tx : -(1/2), ty : -(36/24)}, - {b : true, fx : -(1/2), fy : -(36/24), - cx : -1, cy : -(6/6), tx : -(1 + 4 / 16), ty : -(1080/1728)}, - {b : true, fx : -(1 + 4 / 16), fy : -(1080/1728), - cx : -(12/8), cy : -(36/144), tx : -(1 + 4/16), ty : (144/1152)}, - {b : true, fx : -(1 + 4 / 16), fy : (144/1152), - cx : -1, cy : (2/4), tx : -(1/2), ty : (8/32)}, - {b : true, fx : -(1/2), fy : (8/32), - cx : 0, cy : 0, tx : (1/6), ty : 0}, - {b : false, fx : (1/6), fy : 0, tx : (1/3), ty : 0} -]; - -curve_list.forEach(add_curve); - -function add_curve(curve) { - if (curve.b) { - let ccurve = new THREE.QuadraticBezierCurve3( - new THREE.Vector3(curve.fx, curve.fy, 0 ), - new THREE.Vector3(curve.cx, curve.cy, 0 ), - new THREE.Vector3(curve.tx, curve.ty, 0 ) - ); - let cpoints = ccurve.getPoints( 50 ); - let cgeometry = new THREE.BufferGeometry().setFromPoints( cpoints ); - let cline = new THREE.Line( cgeometry, cmaterial ); - scene.add( cline ); - } else { - let epoints = []; - epoints.push( new THREE.Vector3(curve.fx, curve.fy, 0 ) ); - epoints.push( new THREE.Vector3(curve.tx, curve.ty, 0 ) ); - let egeometry = new THREE.BufferGeometry().setFromPoints( epoints ); - let sline = new THREE.Line( egeometry, cmaterial ); - scene.add( sline ); - } -} - -renderer.render( scene, camera ); diff --git a/meta.yml b/meta.yml index 0ae1a2f..60a7716 100644 --- a/meta.yml +++ b/meta.yml @@ -27,61 +27,59 @@ license: file: LICENSE supported_coq_versions: - text: Coq >= 8.15, MathComp >= 1.16 - opam: '{ (>= "8.14" & < "8.17~") | (= "dev") }' + text: Coq >= 8.17, MathComp >= 2.2.0 + opam: '{ (>= "8.17" & < "8.20~") | (= "dev") }' tested_coq_opam_versions: -- version: '1.16.0-coq-8.15' - repo: 'mathcomp/mathcomp' -- version: '1.16.0-coq-8.16' +- version: '2.2.0-coq-8.19' repo: 'mathcomp/mathcomp' dependencies: - opam: name: coq-mathcomp-ssreflect - version: '{ (>= "1.16.0" & < "1.17~") | (= "dev") }' + version: '{ (>= "2.2.0") | (= "dev") }' description: |- - [MathComp ssreflect 1.15 or later](https://math-comp.github.io) + [MathComp ssreflect 2.2.0 or later](https://math-comp.github.io) - opam: name: coq-mathcomp-fingroup - version: '{ (>= "1.16.0" & < "1.17~") | (= "dev") }' + version: '{ (>= "2.2.0") | (= "dev") }' description: |- - [MathComp fingroup 1.15 or later](https://math-comp.github.io) + [MathComp fingroup 2.2.0 or later](https://math-comp.github.io) - opam: name: coq-mathcomp-algebra - version: '{ (>= "1.16.0" & < "1.17~") | (= "dev") }' + version: '{ (>= "2.2.0") | (= "dev") }' description: |- - [MathComp algebra 1.15 or later](https://math-comp.github.io) + [MathComp algebra 2.2.0 or later](https://math-comp.github.io) - opam: name: coq-mathcomp-solvable - version: '{ (>= "1.16.0" & < "1.17~") | (= "dev") }' + version: '{ (>= "2.2.0") | (= "dev") }' description: |- - [MathComp solvable 1.15 or later](https://math-comp.github.io) + [MathComp solvable 2.2.0 or later](https://math-comp.github.io) - opam: name: coq-mathcomp-field - version: '{ (>= "1.16.0" & < "1.17~") | (= "dev") }' + version: '{ (>= "2.2.0") | (= "dev") }' description: |- - [MathComp field 1.16 or later](https://math-comp.github.io) + [MathComp field 2.2.0 or later](https://math-comp.github.io) - opam: name: coq-mathcomp-real-closed - version: '{ (>= "1.1.3") | (= "dev") }' + version: '{ (>= "2.0.0") | (= "dev") }' description: |- - [Mathcomp real closed 1.1.3 or later](https://github.com/math-comp/real-closed/) + [Mathcomp real closed 2.0.0 or later](https://github.com/math-comp/real-closed/) - opam: name: coq-mathcomp-algebra-tactics - version: '{ (>= "1.0.0") | (= "dev") }' + version: '{ (>= "1.2.0") | (= "dev") }' description: |- - [Algebra tactics 1.0.0](https://github.com/math-comp/algebra-tactics) + [Algebra tactics 1.2.0 or later](https://github.com/math-comp/algebra-tactics) - opam: name: coq-mathcomp-analysis - version: '{ (>= "0.6.1") & (< "0.7~")}' + version: '{ (>= "1.0.0") }' description: |- - [MathComp analysis](https://github.com/math-comp/analysis) + [MathComp analysis 1.0.0 or later](https://github.com/math-comp/analysis) - opam: name: coq-infotheo - version: '{ >= "0.5.1" & < "0.6~"}' + version: '{ >= "0.7.0"}' description: |- - [Infotheo](https://github.com/affeldt-aist/infotheo) + [Infotheo 0.7.0 of later](https://github.com/affeldt-aist/infotheo) namespace: mathcomp.trajectories @@ -92,9 +90,9 @@ categories: - name: Mathematics/Real Calculus and Topology publications: -- pub_url: TODO - pub_title: TODO - pub_doi: TODO +- pub_url: https://inria.hal.science/hal-04312815 + pub_title: Safe Smooth Paths between Straight Line Obstacles + pub_doi: https://doi.org/10.1007/978-3-031-61716-4_3 documentation: |- ## Disclaimer @@ -112,6 +110,9 @@ documentation: |- https://hal.inria.fr/inria-00503017v2/document - Theorem of three circles in Coq (2013) https://arxiv.org/abs/1306.0783 + - Safe Smooth Paths between straight line obstacles + https://inria.hal.science/hal-04312815 + https://link.springer.com/chapter/10.1007/978-3-031-61716-4_3 ## Development information diff --git a/theories/axiomsKnuth.v b/theories/axiomsKnuth.v index 7937f36..6812757 100644 --- a/theories/axiomsKnuth.v +++ b/theories/axiomsKnuth.v @@ -7,7 +7,7 @@ Module Type KnuthAxioms. Section Dummy. Variable R : realType. -Definition Plane := pair_vectType (regular_vectType R) (regular_vectType R). +Definition Plane : vectType _ := (R^o * R^o)%type. Parameter OT : Plane -> Plane -> Plane -> bool. (*Knuth's axioms are given by the following variables. But axiom 4 is not used in Jarvis' algorithm and axiom 3 is a property of the data, not of the diff --git a/theories/bern.v b/theories/bern.v index a71af14..4e0d1bc 100644 --- a/theories/bern.v +++ b/theories/bern.v @@ -1,4 +1,4 @@ -From mathcomp Require Import all_ssreflect all_algebra. +From mathcomp Require Import all_ssreflect all_algebra archimedean. (*Require Import QArith ZArith Zwf Omega. From mathcomp Require Import ssreflect eqtype ssrbool ssrnat div fintype seq ssrfun order. From mathcomp Require Import bigop fingroup choice binomial poly. @@ -64,15 +64,15 @@ Lemma one_root2_translate {R : archiFieldType} (l : {poly R}) a b : one_root2 (translate_pol l a) b -> one_root2 l (a + b). Proof. move=> [x1 [k [x1a kp neg sl]]]; exists (a + x1), k; split => //. -- by rewrite ltr_add2l. +- by rewrite ltrD2l. - move=> x abx xax1; rewrite (_ : x = x - a + a); last by rewrite addrNK. - by rewrite -translate_polq; apply: neg; rewrite ?ltr_subr_addl ?ler_subl_addl. + by rewrite -translate_polq; apply: neg; rewrite ?ltrBrDl ?lerBlDl. - move=> x y ax1x xy. have t z : z = (z - a) + a by rewrite addrNK. rewrite {2}(t y) {2}(t x). rewrite -!(translate_polq l) (_ : y - x = y - a - (x - a)); last first. by rewrite [x + _]addrC opprD opprK addrA addrNK. - by apply: sl; rewrite ?ler_subr_addl ?ltr_le_sub. + by apply: sl; rewrite ?lerBrDl ?ltr_leD. Qed. Lemma one_root1_translate {R : archiFieldType} (l : {poly R}) a b c : @@ -80,21 +80,21 @@ Lemma one_root1_translate {R : archiFieldType} (l : {poly R}) a b c : Proof. move=> [x1 [x2 [k [[ax1 x1x2 x2b kp] pos neg sl]]]]. exists (c + x1), (c + x2), k; split. -- by rewrite !ltr_add2l. +- by rewrite !ltrD2l. - move=> x cax xcx1; rewrite (_ : x = x - c + c); last by rewrite addrNK. - by rewrite -translate_polq; apply pos; rewrite ?ltr_subr_addl ?ler_subl_addl. + by rewrite -translate_polq; apply pos; rewrite ?ltrBrDl ?lerBlDl. - move=> x cx2x xcb; rewrite (_ : x = x - c + c); last by rewrite addrNK. rewrite -translate_polq; apply: neg; rewrite -?ler_addlA //. - by rewrite ltr_subr_addl. - by rewrite ltr_subl_addl. + by rewrite ltrBrDl. + by rewrite ltrBlDl. - move=> x y cx1x xy ycx2. have t z : z = (z - c) + c by rewrite addrNK. rewrite {2}(t x) {2}(t y) (_ : y - x = y - c - (x - c)); last first. by rewrite [x + _]addrC opprD opprK addrA addrNK. - rewrite -!(translate_polq l); apply: sl; rewrite ?ler_add2l. - + by rewrite ltr_subr_addl. - + by rewrite ler_sub. - + by rewrite ltr_subl_addl. + rewrite -!(translate_polq l); apply: sl; rewrite ?lerD2l. + + by rewrite ltrBrDl. + + by rewrite lerB. + + by rewrite ltrBlDl. Qed. Lemma diff_xn_ub {R : archiFieldType} (n : nat) : @@ -110,12 +110,12 @@ exists (z * k + z ^+ n) => [| x y x0 xy yz]. rewrite !exprS. rewrite (_: _ * _ - _ = y * (y ^+ n - x ^+ n) + (y - x) * x ^+ n); last first. by rewrite mulrDr mulrDl addrA mulrN mulNr addrNK. -rewrite [_ * (y-x)]mulrDl ler_add //=. +rewrite [_ * (y-x)]mulrDl lerD //=. rewrite -mulrA (@le_trans _ _ (y * (k * (y - x))))//. - rewrite (ler_wpmul2l (le_trans (ltW x0) xy))//. + rewrite (ler_wpM2l (le_trans (ltW x0) xy))//. exact: kp. - by rewrite !(mulrCA _ k) ler_wpmul2l// ler_wpmul2r// subr_ge0. -rewrite (mulrC (_ - _)) ler_wpmul2r ?subr_ge0// ler_expn2r//. + by rewrite !(mulrCA _ k) ler_wpM2l// ler_wpM2r// subr_ge0. +rewrite (mulrC (_ - _)) ler_wpM2r ?subr_ge0// lerXn2r//. - by rewrite nnegrE ltW. - by rewrite nnegrE ltW. - exact: le_trans yz. @@ -133,9 +133,9 @@ Proof. move=> p; exists (eps / 2%:R), (eps / 2%:R). have p1 : (0 < eps / 2%:R)%R by rewrite divr_gt0// ltr0n. have cmp : eps / 2%:R < eps. - by rewrite ltr_pdivr_mulr// ?ltr0n// ltr_pmulr// ltr1n. + by rewrite ltr_pdivrMr// ?ltr0n// ltr_pMr// ltr1n. split => //. -by rewrite -mulrDr ger_pmulr// -mulr2n -mulr_natr mulVf// pnatr_eq0. +by rewrite -splitr. Qed. Lemma ler_horner_norm_pol {R : realFieldType} (l : {poly R}) x : @@ -149,16 +149,16 @@ have [->|ln0] := eqVneq l 0%R. have [->|an0] := eqVneq a 0%R; first by rewrite normr0 big_ord0. by rewrite big_ord1 /= expr0 mulr1 coefC eqxx. rewrite size_MXaddC (negbTE ln0) /= big_ord_recl expr0 mulr1. -rewrite (le_trans (ler_norm_add _ _))//. +rewrite (le_trans (ler_normD _ _))//. rewrite coefD coefMX eqxx add0r coefC eqxx hornerE [X in X <= _]addrC. -rewrite ler_add// !hornerE. +rewrite lerD// !hornerE. have exteq (i : 'I_(size l)) : true -> `|(l * 'X + a%:P)`_(lift ord0 i)| * x ^+ lift ord0 i = (`|l`_i| * x ^+ i) * x. move=> _; rewrite lift0 coefD coefC /= addr0 coefMX /=. by rewrite exprS (mulrC x) mulrA. rewrite normrM (ger0_norm xge0). -by rewrite (eq_bigr _ exteq) -mulr_suml ler_wpmul2r. +by rewrite (eq_bigr _ exteq) -mulr_suml ler_wpM2r. Qed. Lemma cm3 {R : realFieldType} (b : R) : @@ -174,14 +174,14 @@ rewrite [A in `|A|](_ : _ = l.[y] * y - l.[y] * x + l.[y] * x - l.[x] * x); last by rewrite -[_ - _ + _]addrA addNr addr0. have py : (0 <= y)%R by rewrite (le_trans xge0). have psyx : (0 <= y - x)%R by rewrite subr_ge0. -rewrite -addrA (le_trans (ler_norm_add _ _)) //. +rewrite -addrA (le_trans (ler_normD _ _)) //. rewrite -mulrBr -mulrBl !normrM (ger0_norm xge0) (ger0_norm psyx). -rewrite [X in _ <= X]mulrDl ler_add//. - rewrite ler_wpmul2r// (le_trans (ler_horner_norm_pol l y py))//. +rewrite [X in _ <= X]mulrDl lerD//. + rewrite ler_wpM2r// (le_trans (ler_horner_norm_pol l y py))//. apply: ler_sum => i _. - rewrite ler_wpmul2l ?normr_ge0//. - by rewrite ler_expn2r// nnegrE (le_trans _ yb). -rewrite mulrAC ler_pmul//; first exact: cp. + rewrite ler_wpM2l ?normr_ge0//. + by rewrite lerXn2r// nnegrE (le_trans _ yb). +rewrite mulrAC ler_pM//; first exact: cp. by rewrite (le_trans xy). Qed. @@ -192,7 +192,7 @@ move=> [x1 [k [x1gt1 kp neg sl]]]. have x10 : (0 < x1)%R by rewrite (lt_trans _ x1gt1)// ltr01. set y' := x1 - (reciprocal_pol l).[x1] / k. have y'1 : x1 < y'. - rewrite /y' -(ltr_add2l (-x1)) addNr addrA addNr add0r -mulNr. + rewrite /y' -(ltrD2l (-x1)) addNr addrA addNr add0r -mulNr. by rewrite divr_gt0 // oppr_gt0; exact: neg. have nx1 : (reciprocal_pol l).[x1] < 0%R by apply: neg; rewrite // ltxx. have y'pos : (0 <= (reciprocal_pol l).[y'])%R. @@ -207,10 +207,10 @@ have [u' u1 u'u] : exists2 u', (1 <= u')%R & (u <= u')%R. by exists 1%R; rewrite ?lexx // ltW // ltNge cmp. have u'0 : (0 < u')%R by apply: lt_le_trans u1. have divu_ltr (x : R) : (0 <= x)%R -> (x / u' <= x)%R. - by move=> x0; rewrite ler_pdivr_mulr// ler_pemulr. + by move=> x0; rewrite ler_pdivrMr// ler_peMr. have y'0 : (0 < y')%R by apply: lt_trans y'1. pose y := y' + 1. -have y'y : y' < y by rewrite /y ltr_addl ltr01. +have y'y : y' < y by rewrite /y ltrDl ltr01. have y1 : x1 < y by apply: lt_trans y'1 _. have ypos : (0 < (reciprocal_pol l).[y])%R. apply: le_lt_trans y'pos _=> /=. @@ -245,28 +245,28 @@ have [b [b'b clb blty]] : exists b, [/\ b' < b, c * (b - b') < e2 & b <= y]. have [e3 [e4 [e3p e4p e3e4e2 e3e2 e4e2]]] := cut_epsilon _ e2p. case cmp : (b' + e2 / c <= y). exists (b' + e3 / c); split. - - by rewrite ltr_addl// divr_gt0. + - by rewrite ltrDl// divr_gt0. - by rewrite (addrC b') addrK mulrA (mulrC c) mulfK // gt_eqF. - - apply: le_trans cmp; rewrite ler_add2l//. - by rewrite ler_pmul// ltW// invr_gt0. + - apply: le_trans cmp; rewrite lerD2l//. + by rewrite ler_pM// ltW// invr_gt0. exists y; split => //. - by rewrite (le_lt_trans b'y'). - - by rewrite mulrC -ltr_pdivl_mulr// ltr_subl_addl ltNge cmp. + - by rewrite mulrC -ltr_pdivlMr// ltrBlDl ltNge cmp. pose n := ((size l))%:R - 1. have b'0 : (0 < b')%R by apply: lt_trans ab. have b0 : (0 < b)%R by apply: lt_trans b'b. have b'v0 : (0 < b'^-1)%R by rewrite invr_gte0. have bv0 : (0 < b^-1)%R by rewrite invr_gte0. -have bb'v : b^-1 < b'^-1 by rewrite ltf_pinv. +have bb'v : b^-1 < b'^-1 by rewrite ltf_pV2. exists b^-1, a^-1, k'; split => //. - split => //. - + by rewrite (lt_le_trans bb'v)// lef_pinv// ltW. + + by rewrite (lt_le_trans bb'v)// lef_pV2// ltW. + by rewrite invf_lt1// (lt_le_trans _ x1a). - move => x x0 xb. have xv0 : (0 < x^-1)%R by rewrite invr_gt0. have xexp0 : (0 < x^-1 ^+ (size l - 1))%R by rewrite exprn_gt0. have b'x : b' < x^-1. - by rewrite -(invrK b')// ltf_pinv// (le_lt_trans _ bb'v). + by rewrite -(invrK b')// ltf_pV2// (le_lt_trans _ bb'v). rewrite -(pmulr_rgt0 _ xexp0) -{2}[x]invrK -horner_reciprocal; last first. by rewrite unitfE gt_eqF. apply: (le_lt_trans posb'); rewrite -subr_gte0 /=. @@ -276,12 +276,12 @@ exists b^-1, a^-1, k'; split => //. - move => x a1x xlt1. have x0 : (0 < x)%R by apply: lt_trans a1x; rewrite invr_gt0. have xv0 : (0 < x^-1)%R by rewrite invr_gt0. - have x1a0 : (x^-1 < a)%R by rewrite -[a]invrK ltf_pinv// posrE// invr_gt0. + have x1a0 : (x^-1 < a)%R by rewrite -[a]invrK ltf_pV2// posrE// invr_gt0. have xexp0 : (0 < x^-1 ^+ (size l - 1))%R by apply: exprn_gt0. rewrite -(pmulr_rlt0 _ xexp0) -{2}[x]invrK -horner_reciprocal//; last first. by rewrite unitfE gt_eqF. case cmp: (x^-1 <= x1); last (move/negbT:cmp => cmp). - by apply: neg => //; rewrite -invr1 ltf_pinv// ?posrE ltr01//. + by apply: neg => //; rewrite -invr1 ltf_pV2// ?posrE ltr01//. apply: lt_trans nega; rewrite -subr_gte0. apply: lt_le_trans (_ : k * (a - x^-1) <= _). by rewrite mulr_gt0// subr_gt0. @@ -313,34 +313,34 @@ exists b^-1, a^-1, k'; split => //. by rewrite gt_eqF// ltr0n. rewrite (_ : k' = k1 + k2); last by rewrite /k1 /k2 addrA addNr add0r. have x1ltvz : x1 < z ^-1. - by rewrite (le_lt_trans x1a) // -[a]invrK ltef_pinv ?posrE ?invr_gt0 ?ltW. - rewrite mulrDl; apply: ler_add; last first. + by rewrite (le_lt_trans x1a) // -[a]invrK ltef_pV2 ?posrE ?invr_gt0 ?ltW. + rewrite mulrDl; apply: lerD; last first. have maj' : t3 * y^-1 ^+ (size l - 1) <= t3 * z^+ (size l - 1). have maj : y^-1 ^+(size l - 1) <= z ^+ (size l - 1). case: (size l - 1)%N => [ | n']; first by rewrite !expr0 lexx. have /pow_monotone : (0 <= y ^-1 <= z)%R. rewrite ltW /=; last by rewrite invr_gt0 (lt_trans x10). apply: ltW (le_lt_trans _ xz); apply: ltW (le_lt_trans _ bvx). - by rewrite lef_pinv ?posrE. + by rewrite lef_pV2 ?posrE. by move=> /(_ n'.+1) /andP[]. - rewrite lter_pmul2l // /t3. + rewrite lter_pM2l // /t3. apply: (lt_le_trans _ (_ : k * (x ^-1 - z ^-1) <= _)); last first. apply: sl; first by apply: ltW. - by rewrite ltf_pinv. - by rewrite mulr_gt0 // subr_gt0 ltf_pinv. + by rewrite ltf_pV2. + by rewrite mulr_gt0 // subr_gt0 ltf_pV2. apply: le_trans maj'; rewrite /t3 k2p mulrAC. - rewrite lter_pmul2r; last by apply: exprn_gt0; rewrite invr_gt0. + rewrite lter_pM2r; last by apply: exprn_gt0; rewrite invr_gt0. apply: ltW (lt_le_trans _ (_ :k * (x ^-1 - z ^-1) <= _)). - rewrite ![k * _]mulrC mulrAC lter_pmul2r; last by []. + rewrite ![k * _]mulrC mulrAC lter_pM2r; last by []. rewrite -[x ^-1](mulrK (unitf_gt0 z0)). rewrite -[X in _ < _ - X](mulrK (unitf_gt0 x0)) -(mulrC x) -(mulrC z). rewrite (mulrAC x) -!(mulrA _ (x^-1)) -mulrBl (mulrC (z - x)). - rewrite lter_pmul2r; last by rewrite subr_gte0. - apply: lt_le_trans (_ : x1 / z <= _); first by rewrite lter_pmul2l. - rewrite lter_pmul2r; last by rewrite invr_gte0. - by apply: ltW (lt_trans x1ltvz _); rewrite ltef_pinv ?posrE. + rewrite lter_pM2r; last by rewrite subr_gte0. + apply: lt_le_trans (_ : x1 / z <= _); first by rewrite lter_pM2l. + rewrite lter_pM2r; last by rewrite invr_gte0. + by apply: ltW (lt_trans x1ltvz _); rewrite ltef_pV2 ?posrE. apply: sl; first by apply: ltW. - by rewrite ltef_pinv ?posrE. + by rewrite ltef_pV2 ?posrE. rewrite /t1/k1/k' {t2 t3}. have xzexp : (x ^+ (size l - 1) <= z ^+ (size l - 1)). case sizep : (size l - 1)%N => [ | n']. @@ -350,39 +350,39 @@ exists b^-1, a^-1, k'; split => //. by move=>/(_ n'.+1)=> /andP[]. case: (lerP 0 ((reciprocal_pol l).[x^-1])) => sign; last first. apply: le_trans (_ : 0 <= _)%R. - rewrite mulNr lter_oppl oppr0; apply: mulr_ge0; last first. + rewrite mulNr lterNl oppr0; apply: mulr_ge0; last first. by rewrite subr_gte0 ltW. exact (ltW k'p). by rewrite nmulr_lge0 // subr_lte0. - rewrite mulNr lter_oppl -mulNr opprB. + rewrite mulNr lterNl -mulNr opprB. have rpxe : (reciprocal_pol l).[x^-1] <= e. apply:le_trans (_ : (reciprocal_pol l).[b] <= _) => /=. rewrite -subr_gte0 /= ; apply: le_trans (_ : k * (b - x^-1) <= _). rewrite mulr_ge0 //. exact: ltW. - by rewrite subr_ge0 ltW // -(invrK b) ltef_pinv ?posrE. + by rewrite subr_ge0 ltW // -(invrK b) ltef_pV2 ?posrE. apply: sl. - by apply: (ltW (lt_trans x1ltvz _)); rewrite ltef_pinv ?posrE. - by rewrite -(invrK b) ltef_pinv ?posrE. + by apply: (ltW (lt_trans x1ltvz _)); rewrite ltef_pV2 ?posrE. + by rewrite -(invrK b) ltef_pV2 ?posrE. rewrite -[_ _ b]addr0 -(addrN ((reciprocal_pol l).[b'])) addrA. rewrite (addrC (_.[b])) -addrA; apply: le_trans e1e2e. - apply: ler_add; first by []. + apply: lerD; first by []. apply: (le_trans (ler_norm _)). by apply/ltW/(le_lt_trans _ clb)/cp=> //; apply/ltW. apply: le_trans (_ : (z^+ (size l - 1) - x ^+ (size l - 1)) * e <= _). move: xzexp; rewrite -subr_gte0 le_eqVlt => /predU1P[<-|xzexp] /=. by rewrite !mul0r. - by rewrite lter_pmul2l. + by rewrite lter_pM2l. rewrite [_ * e]mulrC; apply: le_trans (_ : e * (u' * (z - x)) <= _)=> /=. - rewrite ler_pmul2l//. + rewrite ler_pM2l//. apply: le_trans (_ : u * (z - x) <= _). apply: up => //. by apply: ltW. apply: ltW (lt_trans zav _). by rewrite invf_lt1 //; by apply: lt_le_trans x1a. - by rewrite ler_pmul2r// subr_gt0. + by rewrite ler_pM2r// subr_gt0. rewrite mulrA. -rewrite ler_pmul2r// ?subr_gt0//. +rewrite ler_pM2r// ?subr_gt0//. by rewrite /e divrK// unitfE gt_eqF. Qed. diff --git a/theories/casteljau.v b/theories/casteljau.v index 5016c64..6f1c6bb 100644 --- a/theories/casteljau.v +++ b/theories/casteljau.v @@ -1,5 +1,5 @@ From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat binomial seq choice order. -From mathcomp Require Import fintype bigop ssralg poly ssrnum ssrint rat ssrnum. +From mathcomp Require Import fintype bigop ssralg poly ssrnum ssrint rat ssrnum archimedean. From mathcomp Require Import polyrcf qe_rcf_th realalg. Require Import pol poly_normal desc. @@ -43,15 +43,15 @@ Lemma normr_sum : forall m (G : nat -> F), `|\sum_(i < m) G i| <= \sum_(i < m) `|G i|. Proof. elim=> [|m ihm] G; first by rewrite !big_ord0 normr0. -rewrite !big_ord_recr /=; apply: le_trans (ler_norm_add _ _) _=> /=. -by rewrite ler_add2r; apply: ihm. +rewrite !big_ord_recr /=; apply: le_trans (ler_normD _ _) _=> /=. +by rewrite lerD2r; exact: ihm. Qed. Lemma expf_gt1 : forall m (x : F), x > 1 -> x^+m.+1 > 1. Proof. elim => [|m ihm] x hx; first by rewrite expr1. apply: lt_trans (hx) _ => /=; rewrite exprS -{1}(mulr1 x). -rewrite ltr_pmul2l; first exact: ihm. +rewrite ltr_pM2l; first exact: ihm. apply: lt_trans hx; exact: ltr01. Qed. @@ -59,7 +59,7 @@ Lemma expf_ge1 : forall m (x : F), x >= 1 -> x^+m >= 1. Proof. elim => [|m ihm] x hx; first by rewrite expr0 lexx. apply: le_trans (hx) _ => /=; rewrite exprS. (* -{1}(mulr1 x). *) -rewrite ler_pmulr; first exact: ihm. +rewrite ler_pMr; first exact: ihm. apply: lt_le_trans hx; exact: ltr01. Qed. @@ -125,8 +125,8 @@ Proof. move=> px0; case: (lerP `|x| 1)=> cx1. set C := _ * _; suff leC1 : 1 <= C by apply: le_trans leC1. have h1 : `|E n| > 0 by rewrite normr_gt0. - rewrite -(ler_pmul2l h1) /= mulr1 /C mulrA mulfV ?normr_eq0 // mul1r. - by rewrite big_ord_recr /= -{1}(add0r `|E n|) ler_add2r sumr_ge0. + rewrite -(ler_pM2l h1) /= mulr1 /C mulrA mulfV ?normr_eq0 // mul1r. + by rewrite big_ord_recr /= -{1}(add0r `|E n|) lerD2r sumr_ge0. case e: n=> [| m]. move: pnz; rewrite -px0 e horner_poly big_ord_recl big_ord0 /=. by rewrite addr0 expr0 mulr1 /= eqxx. @@ -145,13 +145,13 @@ have xmn0 : ~~ (x^+m == 0) by rewrite expf_eq0 x0 andbF. have h3 : `|\sum_(i < m.+1) E i / x ^+ (m - i) | <= \sum_(i < m.+2) `|E i|. apply: le_trans (normr_sum m.+1 (fun i => E i / x ^+ (m - i))) _. apply: (@le_trans _ _ (\sum_(i < m.+1) `|E i|)); last first. - by rewrite (big_ord_recr m.+1) /= ler_addl /= normr_ge0. + by rewrite (big_ord_recr m.+1) /= lerDl /= normr_ge0. suff h: forall i, (i < m.+1)%N -> `|E i/x^+(m-i)| <= `|E i|. by apply: ler_sum => //= i _; exact: h. - move=> i lti; rewrite normrM -{2}(mulr1 (`|E i|)) ler_wpmul2l ?normr_ge0 //. + move=> i lti; rewrite normrM -{2}(mulr1 (`|E i|)) ler_wpM2l ?normr_ge0 //. rewrite normfV normrX invf_le1; first by rewrite exprn_cp1 // ltW. by rewrite exprn_gt0 // (lt_trans ltr01). -rewrite lter_pdivl_mull; last by rewrite normr_gt0 -e. +rewrite lter_pdivlMl; last by rewrite normr_gt0 -e. by apply: le_trans h3=> /=; rewrite -normrM h2 normrN lexx. Qed. @@ -724,7 +724,7 @@ have -> // : forall c : R, c != 0 -> move=> c hc; rewrite scaleX_polyE size_factor_expr. rewrite [(_ * _ + _) ^+ _]exprDn. rewrite (reindex_inj rev_ord_inj) /=. - rewrite power_monom poly_def; apply: eq_bigr => j _. + rewrite power_monom [LHS]poly_def; apply: eq_bigr => j _. rewrite coef_poly subSS; have -> : (j < i.+1)%N by case j. rewrite subKn; last by case j. rewrite exprMn_comm; last by exact: mulrC. @@ -753,7 +753,7 @@ Qed. Lemma scaleD (p q : {poly R}) u : (p + q) \shift u = p \shift u + (q \shift u). Proof. -by rewrite /scaleX_poly linearD. +by apply: linearD. Qed. (* TODO : move to another section and abstract over deg a b, maybe *) @@ -894,11 +894,15 @@ rewrite [_ \shift 0]/shift_poly addr0 comp_polyXr. and lemma about composing scale operations. *) rewrite recip_scale_swap // recipK // /sc mul_polyC /scaleX_poly linearZ /=. rewrite -comp_polyA comp_polyM comp_polyX comp_polyC -mulrA -polyCM. -by rewrite mulVf // mulr1 comp_polyXr linearZ /= shift_polyDK. +rewrite mulVf // mulr1 comp_polyXr. +transitivity ((b - a) ^+ deg *: ((q \shift a) \shift - a)). + exact: linearZ. +by rewrite /= shift_polyDK. Qed. Lemma relocate0 (p : {poly R}) : (size p <= deg.+1)%N -> (relocate p == 0) = (p == 0). +Proof. move=> s; apply/idP/idP; last first. move/eqP=> ->; rewrite /relocate /shift_poly /scaleX_poly !linear0. by rewrite size_poly0 ltn0 recip0 linear0. @@ -1047,7 +1051,7 @@ have -> : bernp a b p k = by rewrite -invfM -exprD subnKC // !mulrA [_ %:P * _]mulrC. have -> : (('X - a%:P) ^+ k * ((b - a) ^- k)%:P) = (beta^+k)%:P * (('X - a%:P) ^+ k * ((m - a) ^- k)%:P). - rewrite /beta expr_div_n polyCM !mulrA -[_ * (_ ^+k)]mulrC !mulrA mulrAC. + rewrite /beta expr_div_n polyCM !mulrA -[_ * (_ ^+k)]mulrC !mulrA (mulrAC _ (((m - a) ^+ k)%:P)). rewrite -!mulrA -polyCM mulfV ?polyC1 ?mulr1 ?expf_eq0 ?subr_eq0 //. by move/negPf: dma => ->; rewrite andbF. rewrite -(exprVn (b - a)) [(_ ^-1 ^+ _)%:P]polyC_exp. @@ -1280,24 +1284,24 @@ set q := \poly_(_ < _) _; move=> pq. have [ub pu] := (poly_itv_bound (q \Po ('X - a%:P)) a b). have ub0 : 0 <= ub by rewrite (le_trans _ (pu a _)) // lexx andTb ltW. set ub' := ub + 1. -have ub'0 : 0 < ub' by rewrite ltr_paddl. -have ublt : ub < ub' by rewrite ltr_spaddr // ltr01. +have ub'0 : 0 < ub' by rewrite ltr_wpDl. +have ublt : ub < ub' by rewrite ltr_pwDr // ltr01. pose x := minr (a - p.[a]/ub') (half (a + b)). have xitv2 : a < x < b. - by case/andP: (mid_between ab)=> A B; rewrite lt_minr ltr_spaddr ?A //= - ?lt_minl ?B ?orbT // -mulNr mulr_gt0 // ?invr_gt0 // oppr_gt0. + by case/andP: (mid_between ab)=> A B; rewrite lt_min ltr_pwDr ?A //= + ?gt_min ?B ?orbT // -mulNr mulr_gt0 // ?invr_gt0 // oppr_gt0. have xitv : a <= x <= b by case/andP: xitv2 => *; rewrite !ltW //. have := cp _ xitv2. rewrite [X in X.[x]]pq hornerD hornerC hornerM hornerXsubC. rewrite -[X in 0 < _ + X]opprK subr_gt0 => abs. -have : x - a <= -p.[a] / ub' by rewrite ler_subl_addl le_minl mulNr lexx. -rewrite -(ler_pmul2r ub'0) mulfVK; last first. +have : x - a <= -p.[a] / ub' by rewrite lerBlDl ge_min mulNr lexx. +rewrite -(ler_pM2r ub'0) mulfVK; last first. by move:ub'0; rewrite lt0r=>/andP=>[[]]. have xma :0 < x - a by rewrite subr_gt0; case/andP: xitv2. move: (pu _ xitv); rewrite lter_norml; case/andP => _ {pu}. -rewrite -[_ <= ub](ler_pmul2r xma) => pu2. +rewrite -[_ <= ub](ler_pM2r xma) => pu2. rewrite mulrC; have := (lt_le_trans abs pu2) => {pu2} {}abs ab'. -have := (le_lt_trans ab' abs); rewrite ltr_pmul2r // ltNge;case/negP. +have := (le_lt_trans ab' abs); rewrite ltr_pM2r // ltNge;case/negP. by rewrite ltW. Qed. @@ -1310,10 +1314,10 @@ move=> itv1 itv2 sl. case/andP: itv=> ac; case/andP=> cd; case/andP=> db k0. have qd0 : q.[d] <= 0. have : (0 <= (-q).[d]). - by apply: (poly_border db) => x xitv; rewrite hornerN lter_oppE itv2. - by rewrite hornerN lter_oppE. + by apply: (poly_border db) => x xitv; rewrite hornerN lterNE itv2. + by rewrite hornerN lterNE. have qc0 : 0 <= q.[c] by apply/ltW/itv1; rewrite ac lexx. -have qcd0 : (-q).[c] <= 0 <= (-q).[d] by rewrite !hornerN !lter_oppE qd0 qc0. +have qcd0 : (-q).[c] <= 0 <= (-q).[d] by rewrite !hornerN !lterNE qd0 qc0. have [x xin] := (poly_ivt (ltW cd) qcd0). rewrite /root hornerN oppr_eq0 =>/eqP => xr. exists x; split. @@ -1333,12 +1337,12 @@ exists x; split. case/andP: xin=> cx xd. case ux : (u <= x). have := (sl _ _ cu' ux xd). - rewrite qu0 xr subrr -(mulr0 k) ler_pmul2l // subr_le0 => xu. + rewrite qu0 xr subrr -(mulr0 k) ler_pM2l // subr_le0 => xu. by apply/eqP; rewrite eq_le ux. have xu : x <= u. by apply: ltW; rewrite ltNge ux. have := (sl _ _ cx xu ud'). - rewrite qu0 xr subrr -(mulr0 k) ler_pmul2l // subr_le0 => ux'. + rewrite qu0 xr subrr -(mulr0 k) ler_pM2l // subr_le0 => ux'. by apply/eqP; rewrite eq_le ux'. Qed. @@ -1416,7 +1420,7 @@ case h0: (head 0 (seqn0 l) == 0); move: (h0). by move: al0; apply: sub_all => x x0; rewrite (eqP x0) lexx. move=> _ /eqP; rewrite (ltW hsn0) addn_eq0 /= => /andP [p1]/eqP. apply: IH. -rewrite lt_neqAle h0 /= -(ler_nmul2l hsn0) mulr0. +rewrite lt_neqAle h0 /= -(ler_nM2l hsn0) mulr0. by move: p1; rewrite eqb0 ltNge negbK. Qed. @@ -1431,7 +1435,7 @@ case h0: (head 0 (seqn0 l) == 0); move: (h0). move=> _ /eqP; rewrite hsn0 addn_eq0 /= => /andP [p1]/eqP. apply: IH. have hsn0' : 0 < a by rewrite lt_neqAle eq_sym a0. -rewrite -(ler_pmul2l hsn0') mulr0. +rewrite -(ler_pM2l hsn0') mulr0. by move: p1; rewrite eqb0 ltNge negbK. Qed. @@ -1463,7 +1467,7 @@ case alt: (a * head 0 (seqn0 l) < 0)%R; last first. have alt' : alternate (\sum_(i < d.+1) (l`_i * f i.+1) *: 'X^(d - i)). apply: (IH l (fun i => f i.+1)) => //. have agt0 : 0 < a by rewrite lt_neqAle eq_sym (negbTE h). - rewrite -(ler_pmul2l agt0) mulr0 leNgt; apply: negbT; exact alt. + rewrite -(ler_pM2l agt0) mulr0 leNgt; apply: negbT; exact alt. rewrite big_ord_recl subn0 nth0 /= addrC; apply: alternate_r => //. rewrite pmulr_lgt0; first by rewrite lt_neqAle eq_sym h h4. by apply: h2. @@ -1474,7 +1478,7 @@ case alt: (a * head 0 (seqn0 l) < 0)%R; last first. rewrite add1n; move=> sl cf [c0] ap. have negl : head 0 (seqn0 l) < 0. have ap' : 0 < a by rewrite lt_neqAle eq_sym h ap. - by rewrite -(ltr_pmul2l ap') mulr0 alt. + by rewrite -(ltr_pM2l ap') mulr0 alt. have int: head 0 (seqn0 l) != 0 by rewrite neq_lt negl. move/seqn0_last: (int) => [l1 [x [l2 /andP [/eqP p1 /andP[p2 p3]]]]]. apply/alternate_P; rewrite /= -/R. @@ -1636,7 +1640,7 @@ wlog : l q / (0 <= (seqn0 l)`_0). have ur : unique_root_for (horner (-q)) a b. apply: (main (map (fun x => -x) l) (-q)) => //. rewrite seqn0_oppr (nth_map 0). - by rewrite ler_oppr oppr0 ltW // ltNge sg. + by rewrite lerNr oppr0 ltW // ltNge sg. rewrite lt0n; apply/negP; move/eqP=>abs; move: sg. by rewrite nth_default ?abs ?lexx. by rewrite size_map. @@ -1813,10 +1817,10 @@ have qh : ((half (a + b) - a)/(b - a)) d [eta nth 0 l] i *: bernp ((a + b) / 2%:R) b d i. by move => [i ci] _; rewrite -help -help2 /= nth_mkseq. - rewrite (eq_bigr _ qt); apply: dicho_correct => //. + rewrite (eq_bigr _ qt); apply: dicho_correct; [exact: anb| |exact: qq]. rewrite -[X in _ == X]double_half half_lin; apply/negP. by move/eqP/half_inj/addIr/eqP; apply/negP. -apply: (IH) => //. +apply: (IH); [|exact: dn0|exact: qn0| |exact: qh'| |]. by case/andP : (mid_between altb) => it _; exact it. by rewrite size_mkseq. case ts0: (dicho 2%:R^-1 2%:R^-1 d [eta nth 0 l] 0 == 0). diff --git a/theories/cells.v b/theories/cells.v new file mode 100644 index 0000000..a376596 --- /dev/null +++ b/theories/cells.v @@ -0,0 +1,1404 @@ +From HB Require Import structures. +From mathcomp Require Import all_ssreflect all_algebra. +Require Export Field. +Require Import math_comp_complements generic_trajectories points_and_edges + events. + + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Require Import NArithRing. +Import Order.TTheory GRing.Theory Num.Theory Num.ExtraDef Num. + +Open Scope ring_scope. + +Section working_environment. + +Variable R : realFieldType. + +Notation pt := (pt R). +Notation Bpt := (Bpt R). +Notation p_x := (p_x R). +Notation p_y := (p_y R). +Notation edge := (edge R). +Notation event := (event R edge). +Notation point := (point R edge). +Notation outgoing := (outgoing R edge). + +Notation cell := (cell R edge). +Notation Bcell := (Bcell R edge). +Notation low := (low R edge). +Notation high := (high R edge). +Notation left_pts := (left_pts R edge). +Notation right_pts := (right_pts R edge). + +Definition cell_eqb (ca cb : cell) : bool := + let: generic_trajectories.Bcell lptsa rptsa lowa higha := ca in + let: generic_trajectories.Bcell lptsb rptsb lowb highb:= cb in + (lptsa == lptsb :> seq pt) && (rptsa == rptsb :> seq pt) && + (lowa == lowb) && (higha == highb). + +Lemma cell_eqP : Equality.axiom cell_eqb. +Proof. +rewrite /Equality.axiom. +move => [lptsa rptsa lowa higha] [lptsb rptsb lowb highb] /=. +have [/eqP <-|/eqP anb] := boolP(lptsa == lptsb :> seq pt). + have [/eqP <-|/eqP anb] := boolP(rptsa == rptsb :> seq pt). + have [/eqP <-|/eqP anb] := boolP(lowa == lowb). + have [/eqP <-|/eqP anb] := boolP(higha == highb). + by apply:ReflectT. + by apply : ReflectF => [][]. + by apply : ReflectF => [][]. + by apply: ReflectF=> [][]. +by apply: ReflectF=> [][]. +Qed. + +HB.instance Definition _ := hasDecEq.Build _ cell_eqP. + +Definition valid_cell c x := valid_edge (low c) x /\ valid_edge (high c) x. + +Lemma order_edges_viz_point c p : +valid_edge (low c) p -> valid_edge (high c) p -> +(low c) <| (high c) -> +p <<= (low c) -> p <<= (high c). +Proof. apply : order_edges_viz_point'. Qed. + +Lemma order_edges_strict_viz_point c p : +valid_edge (low c) p -> valid_edge (high c) p -> +(low c) <| (high c) -> +p <<< (low c) -> p <<< (high c). +Proof. apply: order_edges_strict_viz_point'. Qed. + +Definition unsafe_Bedge (a b : pt) := + if (ltrP (p_x a) (p_x b)) is LtrNotGe h then Bedge h else + Bedge (ltr01 : p_x (Bpt 0 0) < p_x (Bpt 1 0)). + +Notation dummy_pt := (generic_trajectories.dummy_pt R 1). +Notation dummy_event := (generic_trajectories.dummy_event R 1 edge). +Notation dummy_edge := (generic_trajectories.dummy_edge R 1 edge unsafe_Bedge). +Notation dummy_cell := (dummy_cell R 1 edge unsafe_Bedge). + +Definition head_cell (s : seq cell) := head dummy_cell s. +Definition last_cell (s : seq cell) := last dummy_cell s. + +Definition contains_point := + contains_point R eq_op le +%R (fun x y => x - y) *%R 1 edge + (@left_pt R) (@right_pt R). + +Lemma contains_pointE p c : + contains_point p c = (p >>= low c) && (p <<= high c). +Proof. by []. Qed. + +Definition contains_point' (p : pt) (c : cell) : bool := + (p >>> low c) && (p <<= (high c)). + +Lemma contains_point'W p c : + contains_point' p c -> contains_point p c. +by move=> /andP[] /underWC A B; rewrite contains_pointE A B. +Qed. + +Definition open_limit c := + min (p_x (right_pt (low c))) (p_x (right_pt (high c))). + +Definition bottom_left_corner (c : cell) := last dummy_pt (left_pts c). + +Definition bottom_left_cells_lex (open : seq cell) p := + {in open, forall c, lexPt (bottom_left_corner c) p}. + +(* TODO: these should be at the head. *) +Definition left_limit (c : cell) := + p_x (last dummy_pt (left_pts c)). + +Definition right_limit c := p_x (last dummy_pt (right_pts c)). + +Lemma add_point_left_limit (c : cell) (p : pt) : + (1 < size (left_pts c))%N -> + left_limit (set_left_pts _ _ c + (head dummy_pt (left_pts c) :: p :: behead (left_pts c))) = + left_limit c. +Proof. +rewrite /left_limit. +by case lptsq : (left_pts c) => [ | p1 [ | p2 ps]]. +Qed. + +Definition inside_open_cell p c := + [&& contains_point p c & left_limit c <= p_x p <= open_limit c]. + +Definition inside_open' p c := + [&& inside_open_cell p c, p >>> low c & left_limit c < p_x p] . + +Lemma inside_open'E p c : + inside_open' p c = + [&& p <<= high c, p >>> low c, left_limit c < p_x p & + p_x p <= open_limit c]. +Proof. +rewrite /inside_open' /inside_open_cell contains_pointE. +rewrite strictE -leNgt !le_eqVlt. +rewrite [in _ >>> low c]/point_under_edge -ltNge subrr. +by case: (0 < _); case: (_ < p_x p); rewrite ?andbF ?orbT ?andbT. +Qed. + +Definition inside_closed_cell p c := + contains_point p c && (left_limit c <= p_x p <= right_limit c). + +Definition inside_closed' p c := + [&& inside_closed_cell p c, p >>> low c & left_limit c < p_x p]. + +Lemma inside_closed'E p c : + inside_closed' p c = + [&& p <<= high c, p >>> low c, left_limit c < p_x p & + p_x p <= right_limit c]. +Proof. +rewrite /inside_closed' /inside_closed_cell contains_pointE. +rewrite strictE -leNgt !le_eqVlt. +rewrite [in _ >>> low c]/point_under_edge -ltNge subrr. +by case: (0 < _); case: (_ < p_x p); rewrite ?andbF ?orbT ?andbT. +Qed. + +Definition in_safe_side_left p c := + [&& p_x p == left_limit c, p <<< high c, p >>> low c & + p \notin (left_pts c : seq pt)]. + +Definition in_safe_side_right p c := + [&& p_x p == right_limit c, p <<< high c, p >>> low c & + p \notin (right_pts c : seq pt)]. + +Section proof_environment. +Variable bottom top : edge. + +Definition between_edges (l h : edge) (p : pt) := + (p >>> l) && (p <<< h). + +Definition inside_box p := +(~~ (p <<= bottom) && (p <<< top) ) && + ((p_x (left_pt bottom) < p_x p < p_x (right_pt bottom)) && + (p_x (left_pt top) < p_x p < p_x (right_pt top))). + +(* this function removes consecutives duplicates, meaning the seq needs + to be sorted first if we want to remove all duplicates *) +Fixpoint no_dup_seq (A : eqType) (s : seq A) : (seq A) := + match s with + | [::] => [::] + | a::q => match q with + | [::] => s + | b::r => if a == b then no_dup_seq q else a::(no_dup_seq q) + end + end. + +Lemma no_dup_seq_aux_eq {A : eqType} (s : seq A) : + no_dup_seq s = no_dup_seq_aux eq_op s. +Proof. by elim: s => [ | a s /= ->]. Qed. + +(* TODO : remove duplication with generic_trajectories *) +Definition close_cell (p : pt) (c : cell) := + match vertical_intersection_point p (low c), + vertical_intersection_point p (high c) with + | None, _ | _, None => c + | Some p1, Some p2 => + Bcell (left_pts c) (no_dup_seq [:: p2; p; p1]) (low c) (high c) + end. + +Definition closing_cells (p : pt) (contact_cells: seq cell) : seq cell := + [seq close_cell p c | c <- contact_cells]. + +Lemma close_cell_preserve_3sides p c : + [/\ low (close_cell p c) = low c, + high (close_cell p c) = high c & + left_pts (close_cell p c) = left_pts c]. +Proof. +rewrite /close_cell. +case: (vertical_intersection_point p (low c))=> [p1 | ] //. +by case: (vertical_intersection_point p (high c))=> [p2 | ]. +Qed. + +Lemma right_limit_close_cell p1 c : + valid_edge (low c) p1 -> valid_edge (high c) p1 -> + right_limit (close_cell p1 c) = p_x p1. +Proof. +move=> vlc vhc; rewrite /close_cell /right_limit. +rewrite !pvertE //=. +by case: ifP; case: ifP. +Qed. + +Lemma left_limit_close_cell p1 c : + left_limit (close_cell p1 c) = left_limit c. +Proof. +rewrite /close_cell. +by do 2 (case: (vertical_intersection_point _ _) => //). +Qed. + +Lemma inside_box_between p : inside_box p -> between_edges bottom top p. +Proof. by move=> /andP[]. Qed. + +Lemma inside_box_valid_bottom_top p g : + inside_box p -> + g \in [:: bottom; top] -> valid_edge g p. +Proof. +move=>/andP[] _ /andP[] /andP[] /ltW a /ltW b /andP[] /ltW c /ltW d. +rewrite /valid_edge/generic_trajectories.valid_edge. +by rewrite !inE=> /orP[] /eqP ->; rewrite ?(a, b, c, d). +Qed. + +Definition end_edge_ext (g : edge) (evs : seq event) := + (g \in [:: bottom; top]) || end_edge g evs. + +Lemma end_edgeW g evs : end_edge g evs -> end_edge_ext g evs. +Proof. by rewrite /end_edge_ext=> ->; rewrite orbT. Qed. + +Definition close_alive_edges open future_events : bool := +all (fun c => (end_edge_ext (low c) future_events) && + (end_edge_ext (high c) future_events)) open. + +Lemma insert_opening_all (first_cells new_open_cells last_cells : seq cell) p : +all p first_cells -> all p new_open_cells -> + all p last_cells -> all p (first_cells++new_open_cells++ last_cells). +Proof. +move => C_first C_new C_last. + rewrite all_cat all_cat. +apply /andP. +split. + by []. +apply /andP. +split. + by []. +by []. +Qed. + +Lemma insert_opening_closeness first_cells new_open_cells last_cells events : + close_alive_edges first_cells events -> close_alive_edges new_open_cells events -> + close_alive_edges last_cells events -> close_alive_edges (first_cells++new_open_cells++ last_cells) events. +Proof. +apply insert_opening_all. +Qed. + +Definition adj_rel := [rel x y : cell | high x == low y]. + +Definition adjacent_cells := sorted adj_rel. + +Lemma adjacent_catW s1 s2 : + adjacent_cells (s1 ++ s2) -> adjacent_cells s1 /\ adjacent_cells s2. +Proof. +case: s1 => [ // | cs1 s1 /=]; rewrite /adjacent_cells. +rewrite cat_path => /andP[] -> ps2; split=> //. +by move/path_sorted: ps2. +Qed. + +Lemma adjacent_cut l2 a lc : +l2 != nil -> +((high (last dummy_cell l2) == low a) && +adjacent_cells l2 && +adjacent_cells (a::lc) ) = +adjacent_cells (l2 ++ a::lc). +Proof. +case : l2 => [//= | c2 q2 _]. +elim : q2 c2 => [ | c3 q3 IH] c2 //=. +by rewrite andbT. +have /= IH' := IH c3. +rewrite andbCA. +rewrite -IH'. +by rewrite !andbA. +Qed. + +Definition bottom_edge_seq_above (s : seq cell) (p : pt) := + if s is c :: _ then (p) <<= (low c) else true. + +Definition bottom_edge_seq_below (s : seq cell) (p : pt) := + if s is c :: _ then ~~ (p <<< low c) else true. + +Lemma strict_under_cell (c : cell) (p : pt) : + valid_cell c p -> + low c <| high c -> p <<= (low c) -> ~~ contains_point p c -> + p <<< (low c). +Proof. +move=> valcp rfc. +move: (valcp)=> [vallp valhp]. +rewrite (under_onVstrict vallp) => /orP [] //. +move=> ponl; rewrite /contains_point negb_and negbK=> /orP[] //. +case/negP. +apply: (order_edges_viz_point vallp) => //. +by rewrite under_onVstrict // ponl. +Qed. + +Definition s_right_form (s : seq cell) : bool := + all (fun c => low c <| high c ) s. + +Definition seq_valid (s : seq cell) (p : pt) : bool := + all (fun c => (valid_edge (low c) p) && (valid_edge (high c) p)) s. + +Lemma seq_valid_high (s : seq cell) (p : pt) : + seq_valid s p -> {in [seq high i | i <- s], forall g, valid_edge g p}. +Proof. +by move=> sval g /mapP [c cin ->]; move: (allP sval c cin)=> /andP[]. +Qed. + +Lemma seq_valid_low (s : seq cell) (p : pt) : + seq_valid s p -> {in [seq low i | i <- s], forall g, valid_edge g p}. +Proof. +by move=> sval g /mapP [c cin ->]; move: (allP sval c cin)=> /andP[]. +Qed. + +Lemma insert_opening_valid fc nc lc p : + [&& seq_valid fc p, seq_valid nc p & seq_valid lc p] = + seq_valid (fc ++ nc ++ lc) p. +Proof. +by rewrite /seq_valid !all_cat. +Qed. + +Lemma strict_under_seq p c q : + adjacent_cells (c :: q) -> + seq_valid (c :: q) p -> + s_right_form (c :: q) -> + p <<< (low c) -> + forall c1, c1 \in q -> p <<< (low c1). +Proof. +elim: q c => [// | c' q Ih] c adj vals rfs plow c1 c1in. +move: adj; rewrite /adjacent_cells /= => /andP[/eqP eq_edges adj']. +move: vals; rewrite /seq_valid /= => /andP[/andP[vallc valhc] valc'q]. +move: rfs; rewrite /s_right_form /= => /andP[lowhigh rfc'q]. +have pc' : p <<< (low c'). + by rewrite -eq_edges; apply: (order_edges_strict_viz_point vallc). +have [/eqP c1c' | c1nc'] := boolP (c1 == c'). + by rewrite c1c'. +apply: (Ih c')=> //. + by move: c1in; rewrite !inE (negbTE c1nc'). +Qed. + +Lemma strict_under_seq' p c q : + adjacent_cells (c :: q) -> + seq_valid (c :: q) p -> + s_right_form (c :: q) -> + p <<< (low c) -> + forall c1, c1 \in (c :: q) -> p <<< (low c1). +Proof. +move=> adj sv rf pl c1; rewrite inE=> /orP[/eqP -> // | ]. +by apply: (strict_under_seq adj sv rf pl). +Qed. + +Lemma close_imp_cont c e : +low c <| high c -> +valid_edge (low c) (point e) /\ valid_edge (high c) (point e) -> +event_close_edge (low c) e \/ event_close_edge (high c) e -> +contains_point (point e) c. +Proof. +rewrite contains_pointE /event_close_edge . +move => rf val [/eqP rlc | /eqP rhc]. +move : rf val. + rewrite !strictE -rlc {rlc e}. + have := area3_two_points (right_pt (low c)) (left_pt (low c)) => [][] _ [] -> _. + rewrite ltxx /= /edge_below. + move => /orP [] /andP [] //= => pablhlow pabrhlow [] _ validrlhigh. + apply: not_strictly_above pablhlow pabrhlow validrlhigh. + move : rf val. +rewrite underE -rhc {rhc}. +have := area3_two_points (right_pt (high c)) (left_pt (high c)) => [] [] _ [] -> _ /=. +rewrite le_refl /edge_below /= andbT=> /orP [] /andP [] //= => pablhlow pabrhlow [] valrhlow _ . +apply : not_strictly_under pablhlow pabrhlow valrhlow. +Qed. + +Lemma contrapositive_close_imp_cont c e : +low c <| high c-> +valid_edge (low c) (point e) /\ valid_edge (high c) (point e) -> +~ contains_point (point e) c -> +~ event_close_edge (low c) e /\ ~ event_close_edge (high c) e. +Proof. + move => rf val ev. +have aimpb := (close_imp_cont rf val). +have := (@contra_not ( contains_point (point e) c) (event_close_edge (low c) e \/ event_close_edge (high c) e) aimpb ev) . +move => /orP /= . +rewrite negb_or. +by move => /andP [] /negP a /negP. +Qed. + +Lemma adjacent_cons a q : adjacent_cells (a :: q) -> adjacent_cells q. +Proof. +by rewrite /=; case: q => [// | b q]; rewrite /= => /andP[]. +Qed. + + +(* this lemma below is not true, see the counter example below. +Lemma lowest_above_all_above (s : seq cell) p : +s != [::] -> +adjacent_cells s -> +s_right_form s -> + p <<< (low (head dummy_cell s)) -> +forall c, (c \in s) -> p<<< (low c) /\ p <<< (high c) . +Proof. +case: s => [// | c q]. +*) + +Lemma lowest_above_all_above_counterexample : + ~(forall (s : seq cell) p, + s != [::] -> adjacent_cells s -> + s_right_form s -> p <<< (low (head dummy_cell s)) -> + forall c, (c \in s) -> p<<< (low c) /\ p <<< (high c)). +Proof. +move=> abs. +set e1 := @Bedge R (Bpt 0 1) (Bpt 1 1) ltr01. +set e2 := @Bedge R (Bpt 0 2) (Bpt 1 1) ltr01. +set p := (Bpt 3%:R 0). +set c := Bcell [::] [::] e1 e2. +have exrf : s_right_form [:: c]. + rewrite /= andbT /e1 /e2 /edge_below /=. + rewrite /generic_trajectories.point_under_edge !underE /=. + rewrite /generic_trajectories.point_under_edge !strictE /=. + rewrite !(mul0r, subrr, mul1r, subr0, add0r, addr0, oppr0, opprK, addrK). + rewrite le_refl lt_irreflexive /= !andbT. + rewrite -[X in X - 2%:R]/(1%:R) -opprB -natrB // -[(2-1)%N]/1%N. + by rewrite lerN10. +have plow : p <<< low (head dummy_cell [:: c]). + rewrite strictE /=. + by rewrite !(mul0r, subrr, mul1r, subr0, add0r, addr0, oppr0, opprK) ltrN10. +have := abs [::c] p isT isT exrf plow c. +rewrite inE=> /(_ (eqxx _))=> [][] _. +rewrite strictE /=. +rewrite + !(mul0r, subrr, mul1r, subr0, add0r, addr0, oppr0, opprK, mulr1, addrK). +rewrite -natrM -!natrB // -[X in X%:R]/(1%N). +by rewrite ltNge ler0n. +Qed. + +Definition cells_low_e_top cells low_e : bool := + (cells != nil) && (low (head dummy_cell cells) == low_e) && (high (last dummy_cell cells) == top). + +Definition cells_bottom_top cells : bool := + cells_low_e_top cells bottom. + +Lemma bottom_imp_seq_below s p : +cells_bottom_top s -> inside_box p -> bottom_edge_seq_below s p. +Proof. +case s=> [// | c q]. +rewrite /cells_bottom_top /cells_low_e_top => /andP []/andP [] _ /eqP /= loweq _. +rewrite /bottom_edge_seq_below /inside_box loweq => /andP [] /andP [] /negP nsab _ _ /=. +by apply /underWC/negP. +Qed. + +Lemma exists_cell_aux low_e p open : +cells_low_e_top open low_e -> adjacent_cells open -> +p >>> low_e -> p <<< top -> +exists2 c : cell, c \in open & contains_point' p c. +Proof. +elim : open low_e => [//= | c0 q IH ]. +case cont : (contains_point' p c0). + by exists c0; rewrite ?cont ?inE ?eqxx. +have := (IH (high c0)). +move => IH' low_e {IH}. +rewrite /cells_low_e_top => /andP[] /andP [] _ /= /eqP <- hightop. +move=> adj lowunder topabove. + have : cells_low_e_top q (high c0). + rewrite /cells_low_e_top /=. + have qnnil: q!= nil. + move : hightop lowunder topabove cont {IH'} adj. + case : q => //=. + rewrite /contains_point' /=. + by move=> /eqP -> -> /underW ->. + rewrite qnnil /=. + move : hightop qnnil adj IH'. + case : q => [ // | a q /=]. + move => hightop. + by rewrite hightop eq_sym => _ /andP [] ->. +move => lowtop /=. +rewrite /contains_point' in cont. +move : lowunder cont => -> /= /negbT phc. +have := (IH' lowtop (path_sorted adj) phc topabove) . +move => [] x xinq cpx. +by exists x; rewrite ?in_cons ?xinq /= ?orbT ?cpx. +Qed. + +Lemma exists_cell p open : +cells_bottom_top open -> adjacent_cells open -> +between_edges bottom top p -> +exists2 c : cell, c \in open & contains_point' p c. +Proof. +move=> cbtom adj /[dup] inbox_e /andP[] pa pu. +by apply: (exists_cell_aux cbtom adj). +Qed. + +Definition cell_edges cells := map low cells ++ map high cells. + +Lemma head_not_end q e future_events : +close_alive_edges q (e :: future_events) -> +(forall c, (c \in q) -> +~ event_close_edge (low c) e /\ ~ event_close_edge (high c) e) -> +close_alive_edges q (future_events). +Proof. +elim q => [//| c' q' IH cae]. +have cae': close_alive_edges q' (e :: future_events). + move : cae. + by rewrite /close_alive_edges /all => /andP [] /andP [] _ _. +move=> condition. +rewrite /=. +apply/andP; split; last first. + apply: IH=> //. + by move=> c cin; apply condition; rewrite inE cin orbT. +move: cae; rewrite /= /end_edge_ext /= => /andP[] /andP[] /orP[]. + move=> -> +; rewrite orTb=> /orP[]. + by move=> ->. + move=> /orP [abs | ]. + case: (condition c'). + by rewrite inE eqxx. + by rewrite abs. + by move=> ->; rewrite orbT. + move=> /orP [abs | ]. + case: (condition c'). + by rewrite inE eqxx. + by rewrite abs. +move=> ->; rewrite orbT. +move=> /orP[] . + by move=> ->. + move=> /orP [abs | ]. + case: (condition c'). + by rewrite inE eqxx. + by rewrite abs. +by move=> ->; rewrite orbT. +Qed. + +Lemma valid_between_events g e p future : +lexePt e p -> +(forall e', e' \in future -> lexePt p (point e')) -> +valid_edge g e -> inside_box p -> end_edge_ext g future -> +valid_edge g p. +Proof. +move => einfp pinffut vale. +rewrite /inside_box => /andP [] _ /andP [] botv topv. +rewrite /end_edge => /orP []. + rewrite !inE /valid_edge/generic_trajectories.valid_edge. + by move=> /orP [] /eqP ->; rewrite !ltW; + move: botv topv=> /andP[] a b /andP[] c d; rewrite ?(a,b,c,d). +move => /hasP [] e' e'in e'c. +have pinfe' := pinffut e' e'in. +rewrite /valid_edge; apply /andP; split. + move : vale. + rewrite /valid_edge => /andP [] ginfe _. + move : einfp. + rewrite /lexPt => /orP [esinfp | /andP [] /eqP <- //]. + by rewrite ltW // (le_lt_trans ginfe esinfp). +move : e'c. +rewrite /event_close_edge => /eqP ->. +move : pinfe'. +rewrite /lexPt => /orP [ | /andP [] /eqP -> //]. +apply ltW . +Qed. + +Lemma replacing_seq_adjacent l1 l2 fc lc : +l1 != nil -> l2 != nil -> +low (head dummy_cell l1) = low (head dummy_cell l2) -> +high (last dummy_cell l1) = high (last dummy_cell l2) -> +adjacent_cells (fc ++ l1 ++ lc) -> +adjacent_cells l2 -> +adjacent_cells (fc ++ l2 ++ lc). +Proof. +rewrite /adjacent_cells; case: fc => [ | a0 fc] /=; case: l1 => //=; + case: l2 => //=; move=> a2 l2 a1 l1 _ _ a1a2 l1l2. + rewrite cat_path => /andP[] pl1 plc pl2; rewrite cat_path pl2. + by move: plc; case: lc => [// | a3 l3 /=]; rewrite -l1l2. +rewrite cat_path /= cat_path => /andP[] pfc /andP[] jfca1 /andP[] pl1 plc pl2. +rewrite cat_path /= cat_path; rewrite pfc -a1a2 jfca1 pl2. +by move: plc; case: lc => [// | a3 l3 /=]; rewrite -l1l2. +Qed. + +Lemma replacing_seq_cells_bottom_top l1 l2 fc lc : + l1 != nil -> l2 != nil -> + low (head dummy_cell l1) = low (head dummy_cell l2) -> + high (last dummy_cell l1) = high (last dummy_cell l2) -> + cells_bottom_top (fc ++ l1 ++ lc) = cells_bottom_top (fc ++ l2 ++ lc). +Proof. +move=> l1n0 l2n0 hds tls. +case: fc => [ | c1 fc]; case: lc => [ | c2 lc]; + rewrite /cells_bottom_top /cells_low_e_top /= ?cats0. +- by rewrite l1n0 l2n0 hds tls. +- case : l1 l1n0 hds tls => [ // | c1 l1] _; case: l2 l2n0 => [ | c3 l2] //= _. + by move=> -> lts; rewrite !last_cat /=. +- case: l1 l1n0 tls {hds} => [ | c1' l1] //= _; case: l2 l2n0 => [ | c2' l2] //. + by move=> _ /=; rewrite !last_cat /= => ->. +by rewrite !last_cat /=. +Qed. + +Definition all_edges cells events := + cell_edges cells ++ events_to_edges events. + +Lemma mono_cell_edges s1 s2 : {subset s1 <= s2} -> + {subset cell_edges s1 <= cell_edges s2}. +Proof. +by move=> Sub g; rewrite mem_cat => /orP[] /mapP[c cin geq]; + rewrite /cell_edges geq mem_cat map_f ?orbT // Sub. +Qed. + +Lemma cell_edges_catC s1 s2 : + cell_edges (s1 ++ s2) =i cell_edges (s2 ++ s1). +Proof. +move=> g. +by apply/idP/idP; apply: mono_cell_edges => {}g; rewrite !mem_cat orbC. +Qed. + +Lemma cell_edges_cat (s1 s2 : seq cell) : + cell_edges (s1 ++ s2) =i cell_edges s1 ++ cell_edges s2. +Proof. +move=> g; rewrite /cell_edges !(mem_cat, map_cat) !orbA; congr (_ || _). +by rewrite -!orbA; congr (_ || _); rewrite orbC. +Qed. + +Lemma cell_edges_cons c s : cell_edges (c :: s) =i + (low c :: high c :: cell_edges s). +Proof. by move=> g; rewrite -[c :: s]/([:: c] ++ s) cell_edges_cat. Qed. + +Lemma cell_edges_catCA s1 s2 s3 : + cell_edges (s1 ++ s2 ++ s3) =i cell_edges (s2 ++ s1 ++ s3). +Proof. +move=> g; rewrite 2!catA [in LHS]cell_edges_cat [in RHS]cell_edges_cat. +rewrite [in LHS]mem_cat [in RHS]mem_cat; congr (_ || _). +by rewrite cell_edges_catC. +Qed. + +Definition cover_left_of p s1 s2 := + forall q, inside_box q -> lexePt q p -> + has (inside_open' q) s1 || has (inside_closed' q) s2. + +Lemma contains_to_inside_open' open evs c p : + seq_valid open p -> close_alive_edges open evs -> + inside_box p -> + p_x (last dummy_pt (left_pts c)) < p_x p -> + all (lexePt p) [seq point e | e <- evs] -> + c \in open -> contains_point' p c -> inside_open' p c. +Proof. +rewrite inside_open'E /contains_point'. +move=> val clae inbox_p leftb rightb cin /andP[] -> ->. +rewrite leftb. +have cledge g : (g \in [:: bottom; top]) || end_edge g evs -> + p_x p <= p_x (right_pt g). + have [/ltW pbot /ltW ptop] : p_x p < p_x (right_pt bottom) /\ + p_x p < p_x (right_pt top). + by apply/andP; move:inbox_p=> /andP[] _ /andP[] /andP[] _ -> /andP[] _ ->. + move=>/orP[]; [by rewrite !inE => /orP[]/eqP -> | ]. + move/hasP=> [ev' ev'in /eqP ->]. + apply: lexePt_xW. + by apply/(allP rightb)/map_f. +have /andP [cmp1 cmp2] : (p_x p <= p_x (right_pt (low c))) && + (p_x p <= p_x (right_pt (high c))). + by apply/andP; split; apply/cledge; move/allP: clae=> /(_ _ cin)/andP[]. +rewrite /open_limit. +by case: (ltrP (p_x (right_pt (low c))) (p_x (right_pt (high c))))=> //. +Qed. + +Lemma contact_middle_at_point p cc s1 s2 c : + adjacent_cells cc -> + seq_valid cc p -> + all (contains_point p) cc -> + cc = s1 ++ c :: s2 -> + (s1 != nil -> p === low c) /\ (s2 != nil -> p === high c). +Proof. +move=> adj sv ctps dec. +have cin : c \in cc by rewrite dec !(inE, mem_cat) eqxx ?orbT. +have [vlc vhc] : valid_cell c p by move: (allP sv _ cin) => /andP. +have /andP[plc phc] := (allP ctps _ cin). +split. +elim/last_ind: s1 dec => [// | s1 a _] dec _. + have /eqP ac : high a == low c. + case: s1 dec adj => [ | b s1] -> /=; first by move => /andP[] ->. + by rewrite cat_path last_rcons /= => /andP[] _ /andP[]. + have ain : a \in cc by rewrite dec -cats1 !(mem_cat, inE) eqxx ?orbT. + apply: (under_above_on vlc _ plc). + by rewrite -ac; move: (allP ctps _ ain)=> /andP[]. +case: s2 dec => [// | a s2] + _. +rewrite -[ c :: _]/([:: c] ++ _) catA => dec. +have /eqP ca : high c == low a. + case: s1 dec adj => [ | b s1] -> /=; first by move=> /andP[] ->. + by rewrite cats1 cat_path last_rcons /= => /andP[] _/andP[]. +have ain : a \in cc by rewrite dec !(mem_cat, inE) eqxx ?orbT. +apply: (under_above_on vhc phc). +by rewrite ca; move: (allP ctps _ ain)=> /andP[]. +Qed. + +Definition strict_inside_open (p : pt) (c : cell) := + (p <<< high c) && (~~(p <<= low c)) && + (left_limit c < p_x p < open_limit c). + +Definition strict_inside_closed (p : pt) (c : cell) := + (p <<< high c) && (~~(p <<= low c)) && + (left_limit c < p_x p < right_limit c). + +Definition o_disjoint (c1 c2 : cell) := + forall p, ~~(inside_open' p c1 && inside_open' p c2). + +Definition o_disjoint_e (c1 c2 : cell) := + c1 = c2 \/ o_disjoint c1 c2. + +Lemma o_disjointC c1 c2 : o_disjoint c1 c2 -> o_disjoint c2 c1. +Proof. by move=> c1c2 p; rewrite andbC; apply: c1c2. Qed. + +Definition disjoint_open_cells := + forall c1 c2 : cell, o_disjoint_e c1 c2. + + +Lemma seq_edge_below s c : + adjacent_cells (rcons s c) -> s_right_form (rcons s c) -> + path (@edge_below R) (head dummy_edge [seq low i | i <- rcons s c]) + [seq high i | i <- rcons s c]. +Proof. +elim: s => [ | c0 s Ih] // /[dup]/= /adjacent_cons adj' adj /andP[] rfc rfo. +apply/andP;split;[exact: rfc | ]. +have -> : high c0 = head dummy_edge [seq low i | i <- rcons s c]. + by move: adj; case: (s) => [ | c1 q]; rewrite //= => /andP[] /eqP -> _. +by apply: Ih. +Qed. + +Lemma seq_edge_below' s : + adjacent_cells s -> s_right_form s -> + path (@edge_below R) (head dummy_edge [seq low i | i <- s]) + [seq high i | i <- s]. +Proof. +elim: s => [ | c0 s Ih] // /[dup]/= /adjacent_cons adj' adj /andP[] rfc rfo. +apply/andP;split;[exact: rfc | ]. +case sq : s => [// | c1 s']. +have -> : high c0 = head dummy_edge [seq low i | i <- c1 :: s']. + by move: adj; rewrite sq /= => /andP[] /eqP. +by rewrite -sq; apply: Ih. +Qed. + +Lemma below_seq_higher_edge_aux s g e p : + {in rcons s g & &, transitive (@edge_below R)} -> + all (fun g' => valid_edge g' p) (rcons s g) -> + sorted (@edge_below R) (rcons s g) -> + all (fun g' => valid_edge g' e) (rcons s g) -> + {in rcons s g &, no_crossing R} -> + {in rcons s g, forall g', p <<< g' -> p <<< g}. +Proof. +elim: s => [ | g0 s Ih]. + rewrite /=?andbT => /= _ _ _ sval noc g1. + by rewrite inE=> /eqP ->. +rewrite -[rcons _ _]/(g0 :: rcons s g)=> e_trans svp. +move/[dup]/path_sorted=> adj' adj /= sval noc. +move=> g1 g1in puc1. +have v0p : valid_edge g0 p by apply: (allP svp); rewrite inE eqxx. +have vedge g2 : g2 \in rcons s g -> valid_edge g2 p. + by move=> g2in; apply: (allP svp); rewrite inE g2in orbT. +have vgp : valid_edge g p by apply: vedge; rewrite mem_rcons inE eqxx. +have g0below : g0 <| g. + move: adj; rewrite /= (path_sorted_inE e_trans); last by apply/allP. + by move=> /andP[]/allP + _; apply; rewrite mem_rcons inE eqxx. +move:g1in; rewrite /= inE => /orP[/eqP g1g0 | intail]. + by apply: (order_edges_strict_viz_point' v0p vgp g0below); rewrite -g1g0. +have tr' : {in rcons s g & &, transitive (@edge_below R)}. + move=> g1' g2' g3' g1in g2in g3in. + by apply: e_trans; rewrite inE ?g1in ?g2in ?g3in orbT. +have svp' : all (fun x => valid_edge x p) (rcons s g) by case/andP: svp. +have sval' : all (fun x => valid_edge x e) (rcons s g) by case/andP: sval. +have noc' : {in rcons s g &, no_crossing R}. + by move=> g1' g2' g1in g2in; apply: noc; rewrite !inE ?g1in ?g2in orbT. +by apply: (Ih tr' svp' adj' sval' noc' g1 intail puc1). +Qed. + +Definition open_cell_side_limit_ok c := + [&& left_pts c != [::] :> seq pt, + all (fun (p : pt) => p_x p == left_limit c) (left_pts c), + sorted >%R [seq p_y p | p <- left_pts c], + (head dummy_pt (left_pts c) === high c) & + (last dummy_pt (left_pts c) === low c)]. + +Lemma strict_inside_open_valid c (p : pt) : + open_cell_side_limit_ok c -> + strict_inside_open p c -> + valid_edge (low c) p && valid_edge (high c) p. +Proof. +move=> /andP[]; rewrite /strict_inside_open /left_limit /open_limit. +case: (left_pts c) => [// | w tl _] /andP[] allxl /andP[] _ /andP[]. +rewrite /=; move=> /andP[] _ /andP[] lh _ /andP[] _ /andP[] ll _. +move=> /andP[] _ /andP[] ls rs. +rewrite /valid_edge/generic_trajectories.valid_edge ltW; last first. + by apply: (le_lt_trans ll). +rewrite ltW; last first. + apply: (lt_le_trans rs). + by case: (lerP (p_x (right_pt (low c))) (p_x (right_pt (high c)))) => // /ltW. +rewrite ltW; last first. + apply: (le_lt_trans lh). + by rewrite (eqP (allP allxl w _)) //= inE eqxx. +apply: ltW. +apply: (lt_le_trans rs). +by case: (lerP (p_x (right_pt (low c))) (p_x (right_pt (high c)))) => // /ltW. +Qed. + +Lemma valid_high_limits c p : + open_cell_side_limit_ok c -> + left_limit c < p_x p <= open_limit c -> valid_edge (high c) p. +Proof. +move=>/andP[] wn0 /andP[] /allP allx /andP[] _ /andP[] /andP[] _ /andP[] + _ _. +rewrite (eqP (allx _ (head_in_not_nil _ wn0))) // => onh. +rewrite /left_limit=> /andP[] /ltW llim. +rewrite /valid_edge/generic_trajectories.valid_edge (le_trans onh llim) /=. +rewrite /open_limit. +case: (lerP (p_x (right_pt (low c))) (p_x (right_pt (high c))))=> // /[swap]. +by apply: le_trans. +Qed. + +Lemma valid_low_limits c p : + open_cell_side_limit_ok c -> + left_limit c < p_x p <= open_limit c -> valid_edge (low c) p. +Proof. +move=>/andP[] wn0 /andP[] /allP ax /andP[] _ /andP[] _ /andP[] _ /andP[] onl _. +rewrite /left_limit=> /andP[] /ltW llim. +rewrite /valid_edge/generic_trajectories.valid_edge (le_trans onl llim) /=. +rewrite /open_limit. +case: (lerP (p_x (right_pt (low c))) (p_x (right_pt (high c))))=> // /[swap]. +by move=> ph hl; apply/ltW/(le_lt_trans ph hl). +Qed. + +Lemma inside_openP p c : + open_cell_side_limit_ok c -> + strict_inside_open p c = + [&& inside_open' p c, p_x p < open_limit c & p <<< high c]. +Proof. +move=> cok. +rewrite /strict_inside_open/inside_open'/inside_open_cell contains_pointE. +have [pin | ] := boolP (left_limit c < p_x p <= open_limit c); last first. + rewrite (lt_neqAle _ (open_limit _)). + by rewrite negb_and => /orP[] /negbTE /[dup] A ->; rewrite !andbF. +have vh : valid_edge (high c) p. + by move: (pin) => /(valid_high_limits cok). +have vl : valid_edge (low c) p. + by move: (pin) => /(valid_low_limits cok). +rewrite [in RHS](under_onVstrict) // [in RHS] strict_nonAunder // negb_and. +rewrite !le_eqVlt !negbK. +by have [uh //= | nuh] := boolP(p <<< high c); + have [al //= | nal] := boolP(p >>> low c); + have [lfp | nlfp] := boolP (left_limit c < p_x p); + have [rhp | nrhp] := boolP (p_x p < open_limit c); + rewrite ?orbT ?andbT ?orbF ?andbF. +Qed. + +Lemma below_seq_higher_edge s c e p : + {in [seq high i | i <- rcons s c] & & ,transitive (@edge_below R)} -> + adjacent_cells (rcons s c) -> s_right_form (rcons s c) -> + seq_valid (rcons s c) e -> + {in [seq high i | i <- rcons s c] &, no_crossing R} -> + {in rcons s c, forall g, open_cell_side_limit_ok g} -> + {in rcons s c, forall c1, strict_inside_open p c1 -> + valid_edge (high c) p-> p <<< high c}. +Proof. +move=> e_trans adj rf sval noc csok c1 c1in /[dup]/andP[] /andP[] puc1 _ pp2. +move=> inpc1. +set g := high c => vgp. +set sg := [seq high i | i <- s & valid_edge (high i) p]. +have subp : {subset rcons sg g <= [seq high i | i <- rcons s c]}. + move=> g1; rewrite map_rcons 2!mem_rcons 2!inE=>/orP[-> //| ]. + rewrite /sg=> /mapP[c1' + c1'eq]; rewrite mem_filter=>/andP[] _ c1'in. + by apply/orP; right; apply/mapP; exists c1'. +have e_trans' : {in rcons sg g & &, transitive (@edge_below R)}. + move=> g1 g2 g3 g1in g2in g3in. + by apply: e_trans; apply: subp. +have svp : all (fun g' => valid_edge g' p) (rcons sg g). + apply/allP=> g'; rewrite -map_rcons => /mapP [c' + ->]. + by rewrite mem_rcons inE mem_filter => /orP[/eqP -> | /andP[] + _]. +have adj' : sorted (@edge_below R) (rcons sg g). + have sggq : rcons sg g = + [seq i <- [seq high j | j <- rcons s c] | valid_edge i p]. + by rewrite (@filter_map _ _ high) filter_rcons /= vgp map_rcons. + rewrite sggq. + apply: (sorted_filter_in e_trans). + apply/allP=> g1 /mapP[c' + g'eq]. + rewrite topredE !mem_rcons !inE. + rewrite /g=>/orP[/eqP <- | c'in]. + by rewrite map_rcons mem_rcons inE g'eq eqxx. + by rewrite map_rcons mem_rcons inE; apply/orP/or_intror/mapP; exists c'. + have := seq_edge_below' adj rf. + by case s_eq : s => [ // | a s' /=] /andP[] _. +have noc' : {in rcons sg g &, no_crossing R}. + by move=> g1 g2 /subp g1in /subp g2in; apply: noc. +apply: (below_seq_higher_edge_aux e_trans' svp adj' svp noc' _ puc1). +rewrite -map_rcons; apply/mapP; exists c1 => //. +move: c1in; rewrite !mem_rcons !inE=>/orP[-> // | c1in]. +rewrite mem_filter c1in andbT; apply/orP/or_intror. +apply: (proj2 (andP (strict_inside_open_valid _ inpc1))). +by apply: csok; rewrite mem_rcons inE c1in orbT. +Qed. + +Lemma left_side_below_seq_higher_edge s c e p : + adjacent_cells (rcons s c) -> s_right_form (rcons s c) -> + seq_valid (rcons s c) e -> + {in [seq high i | i <- rcons s c], forall g, p_x (left_pt g) < p_x e} -> + {in [seq high i | i <- rcons s c] &, no_crossing R} -> + {in rcons s c, forall c1, open_cell_side_limit_ok c1} -> + {in rcons s c, forall c1, strict_inside_open p c1 -> + valid_edge (high c) p -> p <<< high c}. +Proof. +move => adj rfs svals llim noc csok. +apply: (below_seq_higher_edge _ adj rfs svals) => //. +have vale' : {in [seq high i | i <- rcons s c], forall g, valid_edge g e}. + by apply: seq_valid_high. +apply: (edge_below_trans _ vale' noc); right; exact: llim. +Qed. + +Lemma right_side_below_seq_higher_edge s c e p : + adjacent_cells (rcons s c) -> s_right_form (rcons s c) -> + seq_valid (rcons s c) e -> + {in [seq high i | i <- rcons s c], forall g, p_x e < p_x (right_pt g)} -> + {in [seq high i | i <- rcons s c] &, no_crossing R} -> + {in rcons s c, forall c1, open_cell_side_limit_ok c1} -> + {in rcons s c, forall c1, strict_inside_open p c1 -> + valid_edge (high c) p -> p <<< high c}. +Proof. +move => adj rfs svals rlim noc csok. +apply: (below_seq_higher_edge _ adj rfs svals) => //. +have vale' : {in [seq high i | i <- rcons s c], forall g, valid_edge g e}. + by apply: seq_valid_high. +apply: (edge_below_trans _ vale' noc); left; exact: rlim. +Qed. + +Lemma o_disjoint_eC (c1 c2 : cell) : + o_disjoint_e c1 c2 -> o_disjoint_e c2 c1. +Proof. +move=> [-> // |]; first by left. +by move=> disj; right=> p; rewrite andbC; apply: disj. +Qed. + +Definition closed_cell_side_limit_ok c := + [&& left_pts c != [::] :> seq pt, + all (fun p : pt => p_x p == left_limit c) (left_pts c), + sorted >%R [seq p_y p | p <- left_pts c], + head dummy_pt (left_pts c) === high c, + last dummy_pt (left_pts c) === low c, + right_pts c != [::] :> seq pt, + all (fun p : pt => p_x p == right_limit c) (right_pts c), + sorted >%R [seq p_y p | p <- right_pts c], + head dummy_pt (right_pts c) === high c & + last dummy_pt (right_pts c) === low c]. + +Lemma closed_right_imp_open c: + closed_cell_side_limit_ok c -> right_limit c <= open_limit c. +Proof. +move=> /andP[] _ /andP[] _ /andP[] _ /andP[] _ /andP[] _. +move=> /andP[] ln0 /andP[] eqs /andP[] _ /andP[] /andP[] _ /andP[] _ /[swap]. +move=> /andP[] _ /andP[] _. +rewrite (eqP (allP eqs (head dummy_pt (right_pts c)) (head_in_not_nil _ ln0))). +rewrite /right_limit /open_limit. +by case : (lerP (p_x (right_pt (low c))) (p_x (right_pt (high c)))). +Qed. + +Definition any_edge (b : bool) (c : cell) : edge := + if b then low c else high c. + +(* This is not used (yet?) *) +Lemma fc_lc_right_pt s ev events : + close_alive_edges s events -> + inside_box (point ev) -> + all (fun x => lexPtEv ev x) events -> + {in s, forall c b, lexPt (point ev) (right_pt (any_edge b c))}. +Proof. +move=> /allP clae inbox_e /allP lexev c cin b. +have : ((any_edge b c) \in [:: bottom; top]) || end_edge (any_edge b c) events. + by have := clae _ cin; rewrite /end_edge /any_edge; case: b=> /= /andP[]. +move=> /orP[ | ]. + move: inbox_e => /andP[] _ /andP[]/andP[] _ botP /andP[] _ topP. + by rewrite !inE => /orP[]/eqP ->; rewrite /lexPt ?botP ?topP. +by move=>/hasP[ev' ev'in /eqP ->]; apply: lexev. +Qed. + +Lemma seq_low_high_shift s : + s != nil -> adjacent_cells s -> + rcons [seq low i | i <- s] (high (last dummy_cell s)) = + (low (head dummy_cell s) :: [seq high i | i <- s]). +Proof. +elim: s => [ // | c s +] _ /=. + case: s => [// | c' s]. +rewrite /=; move=> /(_ isT) Ih => /andP[] /eqP -> adj; congr (_ :: _). +by apply: Ih. +Qed. + +Lemma cell_edges_high s : + s != [::] -> adjacent_cells s -> + cell_edges s =i low (head dummy_cell s) :: [seq high i | i <- s]. +Proof. +move=> sn0 adj g; rewrite mem_cat; apply/idP/idP. + move=>/orP[]. + by rewrite -(seq_low_high_shift sn0 adj) mem_rcons inE orbC => ->. + by rewrite inE orbC => ->. +rewrite inE => /orP[/eqP -> | ]. + by rewrite map_f // head_in_not_nil. +by move=> ->; rewrite orbT. +Qed. + +Lemma pvert_y_bottom p : inside_box p -> pvert_y p bottom < p_y p. +Proof. +have tmp : bottom \in [:: bottom; top] by rewrite inE eqxx. +move=> /[dup]/inside_box_valid_bottom_top=> /(_ _ tmp) val. +move=> /andP[] /andP[] + _ _. +by rewrite (under_pvert_y val) -ltNge. +Qed. + +Lemma adjacent_right_form_sorted_le_y s p : + seq_valid s p -> + adjacent_cells s -> + s_right_form s -> + sorted <=%R [seq pvert_y p (high c) | c <- s]. +Proof. +elim: s => [ // | a s Ih] /=. +move=> /andP[] _ vs /[dup]/adjacent_cons adj + /andP[] _ rfs. +case s_eq : s => [ // | b s'] /= /andP[]/eqP hl _. +rewrite hl. +have bin : b \in s by rewrite s_eq inE eqxx. +have rfb := (allP rfs b bin). +have := (allP vs b bin)=> /andP[] vl vh. +have := order_below_viz_vertical vl vh. +rewrite (pvertE vl) (pvertE vh) => /(_ _ _ erefl erefl rfb) /= => -> /=. +by move: Ih; rewrite s_eq; apply; rewrite -s_eq. +Qed. + +Definition edge_side_prop (ev : event) (g : edge) := + if valid_edge g (point ev) then + if pvert_y (point ev) g < p_y (point ev) then + p_x (point ev) < p_x (right_pt g) + else + if p_y (point ev) < pvert_y (point ev) g then + p_x (left_pt g) < p_x (point ev) + else + true + else + true. + +Definition edge_side (evs : seq event) (open : seq cell) := + if evs is ev :: _ then + all (edge_side_prop ev) [seq high c | c <- open] + else true. + +Definition extra_bot := Bcell nil nil bottom bottom. + +Definition oc_disjoint (c1 c2 : cell) := + forall p, ~~ (inside_open' p c1 && inside_closed' p c2). + +Definition disjoint_open_closed_cells := + forall c1 c2, oc_disjoint c1 c2. + +Definition c_disjoint (c1 c2 : cell) := + forall p, ~~ (inside_closed' p c1 && inside_closed' p c2). + +Lemma c_disjointC (c1 c2 : cell) : + c_disjoint c1 c2 -> c_disjoint c2 c1. +Proof. by move=> cnd p; rewrite andbC; apply: cnd. Qed. + +Definition c_disjoint_e (c1 c2 : cell) := + c1 = c2 \/ c_disjoint c1 c2. + +Lemma c_disjoint_eC (c1 c2 : cell) : + c_disjoint_e c1 c2 -> c_disjoint_e c2 c1. +Proof. +move=> cnd; have [/eqP -> | c1nc2] := boolP(c1 == c2). + by left. +case: cnd => [/eqP | cnd ]; first by rewrite (negbTE c1nc2). +by right; apply: c_disjointC. +Qed. + +Definition disjoint_closed_cells := + forall c1 c2, c_disjoint_e c1 c2. + +Definition pt_at_end (p : pt) (e : edge) := + p === e -> p \in [:: left_pt e; right_pt e]. + +Definition connect_limits (s : seq cell) := + sorted [rel c1 c2 | right_limit c1 == left_limit c2] s. + +Definition edge_covered (e : edge) (os : seq cell) (cs : seq cell) := + (exists (opc : cell) (pcc : seq cell), {subset pcc <= cs} /\ + {in rcons pcc opc, forall c, high c = e} /\ + connect_limits (rcons pcc opc) /\ + opc \in os /\ + left_limit (head_cell (rcons pcc opc)) = p_x (left_pt e)) \/ + (exists pcc, pcc != [::] /\ + {subset pcc <= cs} /\ + {in pcc, forall c, high c = e} /\ + connect_limits pcc /\ + left_limit (head_cell pcc) = p_x (left_pt e) /\ + right_limit (last_cell pcc) = p_x (right_pt e)). + +Lemma connect_limits_rcons (s : seq cell) (lc : cell) : + s != nil -> connect_limits (rcons s lc) = + connect_limits s && (right_limit (last dummy_cell s) == left_limit lc). +Proof. +elim: s => [// | c0 s Ih] _ /=. +by rewrite rcons_path. +Qed. + +Lemma left_limit_max c: + open_cell_side_limit_ok c -> + max (p_x (left_pt (high c))) (p_x (left_pt (low c))) <= left_limit c. +Proof. +move=>/andP[] + /andP[] + /andP[] _ /andP[] /andP[] _ + /andP[] _ +. +rewrite /left_limit ge_max. +case: (left_pts c) => [ // | p tl] /=. +by move => _ /andP[] /eqP + _ /andP[] + _ /andP[] + _ => <- -> ->. +Qed. + +Lemma bottom_left_x c : left_limit c = p_x (bottom_left_corner c). +Proof. by[]. Qed. + +Lemma bottom_left_lex_to_high s p: +cells_bottom_top s -> +adjacent_cells s -> +s_right_form s -> +all open_cell_side_limit_ok s -> +inside_box p -> +bottom_left_cells_lex s p -> +{in s, forall c, lexPt (left_pt (high c)) p}. +Proof. +move=> cbtom adj rfo sok inboxp btm_left c cin. +have /mem_seq_split [s1 [s2 s12q]] := cin. +case s2q : s2 => [ | c' s2']. + move: cbtom=> /andP[] /andP[] _ _; rewrite s12q s2q last_cat /=. + move=> /eqP ctop. + move: inboxp=> /andP[] _ /andP[] _ /andP[] + _. + by rewrite /lexPt ctop=> ->. +have c'in : c' \in s. + by rewrite s12q s2q !mem_cat !inE eqxx ?orbT. +move: adj; rewrite s12q s2q=> /adjacent_catW[] _ /= /andP[] /eqP cc' _. +have c'ok : open_cell_side_limit_ok c'. + by apply: (allP sok c'). +have lexbtme := btm_left c' c'in. +have btmon : bottom_left_corner c' === low c'. + by move: c'ok=> /andP[] _ /andP[] _ /andP[] _ /andP[] _. +have := lexePt_lexPt_trans (on_edge_lexePt_left_pt btmon) lexbtme. +by rewrite cc'. +Qed. + +Lemma inside_box_valid_bottom x : inside_box x -> valid_edge bottom x. +Proof. +move=> /andP[] _ /andP[] /andP[] /ltW + /ltW + _. +rewrite /valid_edge/generic_trajectories.valid_edge. +by move=> -> ->. +Qed. + +Section open_cells_decomposition. + +Variables open fc cc : seq cell. +Variable lcc : cell. +Variable lc : seq cell. +Variable p : pt. + +Hypothesis cbtom : cells_bottom_top open. +Hypothesis adj : adjacent_cells open. +Hypothesis rfo : s_right_form open. +Hypothesis sval : seq_valid open p. +Hypothesis inbox_p : between_edges bottom top p. + +Hypothesis ocd : open = fc ++ cc ++ lcc :: lc. +Hypothesis allnct : {in fc, forall c, ~~ contains_point p c}. +Hypothesis allct : {in cc, forall c, contains_point p c}. +Hypothesis lcc_ctn : contains_point p lcc. +Hypothesis head_nct : lc != [::] -> ~~ contains_point p (head lcc lc). +Hypothesis noc : {in cell_edges open &, no_crossing R}. + +Let le := low (head lcc cc). +Let he := high lcc. + +#[clearbody] +Let headin : head lcc cc \in open. +Proof. +by rewrite ocd; case: cc => [ | a cc'] /=; rewrite !(mem_cat, inE) eqxx ?orbT. +Defined. + +#[clearbody] +Let vle : valid_edge le p. +Proof. by have /andP[] := (allP sval _ headin). Defined. + +#[clearbody] +Let lccin : lcc \in open. +Proof. by rewrite ocd !(mem_cat, inE) eqxx !orbT. Defined. + +#[clearbody] +Let lein : le \in cell_edges open. +Proof. by rewrite mem_cat /le map_f // headin. Defined. + +#[clearbody] +Let hein : he \in cell_edges open. +Proof. by rewrite mem_cat /he map_f ?orbT // lccin. Defined. + +#[clearbody] +Let vhe : valid_edge he p. +Proof. by have /andP[] := (allP sval _ lccin). Defined. + +#[clearbody] +Let pal : p >>> le. +Proof. +elim/last_ind : {-1}(fc) (erefl fc) => [ | fc' c1 _] fc_eq. + suff -> : le = bottom. + by move: inbox_p=> /andP[]. + move: cbtom=> /andP[] /andP[] _ /eqP <- _; rewrite ocd fc_eq /le. + by case: (cc). +have c1in : c1 \in open. + by rewrite ocd fc_eq !(mem_cat, mem_rcons, inE) eqxx. +have /andP[vlc1 vhc1] : valid_edge (low c1) p && valid_edge (high c1) p. + by apply: (allP sval). +have /order_edges_strict_viz_point' : low c1 <| high c1 by apply: (allP rfo). +move=> /(_ _ vlc1 vhc1) oc1. +have ctfc : contains_point p (head lcc cc). + case cc_eq : (cc) => [ // | c2 cc']. + by apply: allct; rewrite /= cc_eq inE eqxx. +have hc1q : high c1 = low (head lcc cc). + move: adj; rewrite ocd fc_eq -cats1 -!catA=> /adjacent_catW[] _ /=. + by case: (cc) => [ | ? ?] /= /andP[] /eqP. +have palc1 : p >>= low c1. + apply/negP=> /oc1 abs. + by move: ctfc; rewrite contains_pointE -hc1q abs. +have nctc1 : ~~ contains_point p c1. + by apply: allnct; rewrite fc_eq mem_rcons inE eqxx. +by move: nctc1; rewrite contains_pointE palc1 /= hc1q. +Defined. + +#[clearbody] +Let puh : p <<< he. +Proof. +case lc_eq : lc => [ | c1 lc']. + move: inbox_p => /andP[] _ +. + by case/andP : cbtom=> _; rewrite ocd lc_eq !last_cat /= /he => /eqP ->. +have c1in : c1 \in open. + by rewrite ocd lc_eq /= !(mem_cat, inE) eqxx !orbT. +have /andP[vlc1 vhc1] : valid_edge (low c1) p && valid_edge (high c1) p. + by apply: (allP sval). +have /order_edges_viz_point' := allP rfo _ c1in => /(_ _ vlc1 vhc1) oc1. +have hlcclc1 : high lcc = low c1. + move: adj; rewrite ocd lc_eq=> /adjacent_catW[] _ /adjacent_catW[] _. + by move=> /andP[] /eqP. +have pulc1 : p <<= low c1. + by rewrite -hlcclc1; move: lcc_ctn => /andP[]. +move: head_nct; rewrite lc_eq /= contains_pointE negb_and. +rewrite (oc1 pulc1) orbF negbK -hlcclc1. +by apply. +Defined. + +Lemma fclc_not_contain c : (c \in fc) || (c \in lc) -> + ~~ contains_point p c. +Proof. +move=> /orP[ | cl]; first by apply: allnct. +case lc_eq : lc => [ | c2 lc']; first by move: cl; rewrite lc_eq. +have adjlc : adjacent_cells (lcc :: lc). + by move: adj; rewrite ocd => /adjacent_catW[] _ /adjacent_catW[]. +have adjlc' : adjacent_cells (c2 :: lc'). + by move: adjlc; rewrite lc_eq=> /andP[] _. +have sval' : seq_valid (c2 :: lc') p. + apply/allP=> x xin; apply: (allP sval); rewrite ocd !(mem_cat, inE). + by rewrite lc_eq xin !orbT. +have lc2_eq : low c2 = he. + by move: adjlc; rewrite lc_eq /= /he => /andP[] /eqP ->. +have rfolc : s_right_form (c2 :: lc'). + apply/allP=> x xin; apply: (allP rfo). + by rewrite ocd !mem_cat inE lc_eq xin ?orbT. +have pulc2 : p <<< low c2 by rewrite lc2_eq. +move: cl; rewrite lc_eq inE => /orP[/eqP -> | cinlc' ]. + by apply/negP; rewrite contains_pointE pulc2. +have pulc : p <<< low c. + by apply: (strict_under_seq adjlc' sval' rfolc pulc2 cinlc'). +by apply/negP; rewrite contains_pointE pulc. +Qed. + +Lemma above_all_cells (s : seq cell) : + seq_valid s p -> + adjacent_cells s -> + s_right_form s -> + p >>> high (last dummy_cell s) -> + p >>> low (head dummy_cell s) /\ {in s, forall c, p >>> high c}. +Proof. +elim: s => [ | c0 s Ih]; first by move=> _ _ _ ->. +move=> /= /andP[] /andP[] vl0 vh0 svals adjs /andP[] lbh rfos pah. +have pal0 : p >>> high c0 -> p >>> low c0. + move=> {}pah. + rewrite under_pvert_y // -ltNge. + apply: (le_lt_trans (edge_below_pvert_y vl0 vh0 lbh)). + by rewrite ltNge -under_pvert_y. +elim/last_ind : {-1}s (erefl s) svals adjs rfos pah => [ | s' c1 _] + /= s_eq svals adjs rfos pah. + split; last by move=> x; rewrite inE => /eqP ->. + by apply: pal0. +have adjs1 : adjacent_cells (rcons s' c1) by apply: (path_sorted adjs). +rewrite last_rcons in pah. +rewrite s_eq last_rcons in Ih; have := Ih svals adjs1 rfos pah. +move=> [] palh {}Ih. +have hc0q : high c0 = low (head dummy_cell (rcons s' c1)). + by move: adjs; case: (s') => [ | ? ?] /= /andP[] /eqP. +split; first by apply pal0; rewrite hc0q. +move=> x; rewrite inE=> /orP[ /eqP -> |]; last by apply: Ih. +by rewrite hc0q. +Qed. + +Lemma below_all_cells (s : seq cell) : + seq_valid s p -> + adjacent_cells s -> + s_right_form s -> + p <<< low (head dummy_cell s) -> {in s, forall c, p <<< high c}. +Proof. +elim: s => [ | c0 s Ih]; first by []. +move=> /= /andP[] /andP[] vl0 vh0 svals adjs /andP[] lbh rfos pah. +have puh0 : p <<< low c0 -> p <<< high c0. + move=> {}pul. + rewrite strict_under_pvert_y //. + apply: (lt_le_trans _ (edge_below_pvert_y vl0 vh0 lbh)). + by rewrite -strict_under_pvert_y. +have adjs1 : adjacent_cells s by apply: (path_sorted adjs). +move=> x; rewrite inE => /orP[/eqP -> | ]; first by apply: puh0. +case s_eq: s => [ // | c1 s']. +have h0lc1 : high c0 = low c1 by move: adjs; rewrite s_eq /= => /andP[] /eqP. +by rewrite -s_eq; apply: (Ih) => //; rewrite s_eq /= -h0lc1 (puh0 pah). +Qed. + +Lemma connect_properties : + [/\ p >>> le, p <<< he, valid_edge le p, valid_edge he p & + forall c, (c \in fc) || (c \in lc) -> ~~contains_point p c]. +Proof. by split; last exact fclc_not_contain. Qed. + +Lemma fclc_not_end_aux c e : + point e = p -> + (c \in fc) || (c \in lc) -> + (~ event_close_edge (low c) e) /\ (~ event_close_edge (high c) e). +Proof. +move=> pq /[dup] cin /fclc_not_contain/negP. +have cino : c \in open. + by rewrite ocd !(mem_cat, inE); move:cin=> /orP[] ->; rewrite ?orbT. +rewrite -pq=>/contrapositive_close_imp_cont; apply. + by apply: (allP rfo). +by rewrite pq; apply/andP/(allP sval). +Qed. + +Lemma low_under_high : le <| he. +Proof. +have [// | abs_he_under_le] := noc lein hein; case/negP: pal. +by have /underW := (order_edges_strict_viz_point' vhe vle abs_he_under_le puh). +Qed. + +Lemma in_cc_on_high c : c \in cc -> p === high c. +Proof. +move=> cin. +have cino : c \in open by rewrite ocd !mem_cat cin !orbT. +have vhc : valid_edge (high c) p by apply/(seq_valid_high sval)/map_f. +apply: under_above_on => //; first by apply: (proj2 (andP (allct cin))). +have [s1 [[ | c2 s2] cceq]] := mem_seq_split cin. + move: adj; rewrite ocd cceq -catA /= => /adjacent_catW[] _ /adjacent_catW[]. + move=> _ /= /andP[] /eqP -> _. + by move: lcc_ctn=> /andP[]. +have c2in : c2 \in cc by rewrite cceq !(mem_cat, inE) eqxx !orbT. +move: adj; rewrite ocd cceq -!catA; do 2 move => /adjacent_catW[] _. +rewrite /= => /andP[] /eqP -> _. +by apply: (proj1 (andP (allct c2in))). +Qed. + +End open_cells_decomposition. + +Lemma inside_open_cell_valid c p1 : + open_cell_side_limit_ok c -> + inside_open_cell p1 c -> + valid_edge (low c) p1 && valid_edge (high c) p1. +Proof. +move=> /andP[] ne /andP[] sxl /andP[] _ /andP[] /andP[] _ onh /andP[] _ onl. +move=> /andP[] _; rewrite /left_limit /open_limit=> /andP[] ge lemin. +apply/andP; split. + apply/andP; split. + by apply: le_trans ge; move: onl=> /andP[]. + apply: (le_trans lemin). + by rewrite ge_min lexx. +apply/andP; split. + apply: le_trans ge; move: onh=> /andP[]. + rewrite (eqP (allP sxl (head dummy_pt (left_pts c))_)) //. + by apply: head_in_not_nil. +by rewrite le_min in lemin; move: lemin=>/andP[]. +Qed. + +End proof_environment. + + +End working_environment. diff --git a/theories/cells_alg.v b/theories/cells_alg.v new file mode 100644 index 0000000..d6dbd89 --- /dev/null +++ b/theories/cells_alg.v @@ -0,0 +1,7448 @@ +From mathcomp Require Import all_ssreflect all_algebra. +Require Export Field. +Require Import generic_trajectories. +Require Import math_comp_complements points_and_edges events cells. +Require Import opening_cells. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Require Import NArithRing. +Import Order.TTheory GRing.Theory Num.Theory Num.ExtraDef Num. + +Open Scope ring_scope. + +Section working_environment. + +Variable R : realFieldType. + +Notation pt := (pt R). +Notation p_x := (p_x R). +Notation p_y := (p_y R). +Notation Bpt := (Bpt R). +Notation edge := (edge R). +Notation event' := (event R edge). +Notation outgoing := (outgoing R edge). +Notation point := (point R edge). + +Notation cell := (cell R edge). + +Notation dummy_pt := (dummy_pt R 1). +Notation dummy_edge := (dummy_edge R 1 edge (@unsafe_Bedge R)). +Notation dummy_cell := (dummy_cell R 1 edge (@unsafe_Bedge _)). +Notation dummy_event := (dummy_event R 1 edge). + +Definition open_cells_decomposition_contact := + open_cells_decomposition_contact R eq_op le +%R (fun x y => x - y) *%R 1 + edge (@left_pt R) (@right_pt R). + +Definition open_cells_decomposition_rec := + open_cells_decomposition_rec R eq_op le +%R (fun x y => x - y) *%R 1 + edge (@unsafe_Bedge R) (@left_pt R) (@right_pt R). + +Definition open_cells_decomposition := + open_cells_decomposition R eq_op le +%R (fun x y => x - y) *%R 1 + edge (@unsafe_Bedge R) (@left_pt R) (@right_pt R). + +Notation scan_state := (scan_state R edge). +Notation sc_open1 := (sc_open1 R edge). +Notation lst_open := (lst_open R edge). +Notation sc_open2 := (sc_open2 R edge). +Notation sc_closed := (sc_closed R edge). +Notation lst_closed := (lst_closed R edge). + + +Definition update_closed_cell := + update_closed_cell R 1 edge. + +Definition set_left_pts := + set_left_pts R. + +Notation low := (low R edge). +Notation high := (high R edge). +Notation left_pts := (left_pts R edge). +Notation right_pts := (right_pts R edge). +Notation Bcell := (Bcell R edge). + +(* TODO : these should probably be in cell.v *) +Lemma high_set_left_pts (c : cell) l : high (set_left_pts c l) = high c. +Proof. by case: c. Qed. + +Lemma low_set_left_pts (c : cell) l : low (set_left_pts c l) = low c. +Proof. by case: c. Qed. + +Definition set_pts := set_pts R edge. + +(* This function is to be called only when the event is in the middle + of the last opening cell. The point e needs to be added to the left + points of one of the newly created open cells, but the one that receives + the first segment of the last opening cells should keep its existing + left points.*) +Definition update_open_cell := + update_open_cell R eq_op le +%R (fun x y => x - y) *%R (fun x y => x / y) 1 + edge (@unsafe_Bedge R) (@left_pt R) (@right_pt R). + +Definition update_open_cell_top := + update_open_cell_top R eq_op le +%R (fun x y => x - y) *%R (fun x y => x / y) 1 + edge (@unsafe_Bedge R) (@left_pt R) (@right_pt R). + +Notation Bscan := (Bscan _ _). + +Definition simple_step := + simple_step R eq_op le +%R (fun x y => x - y) *%R (fun x y => x / y) + 1 edge (@unsafe_Bedge R) (@left_pt R) (@right_pt R). + +Definition step := + step R eq_op le +%R (fun x y => x - y) *%R (fun x y => x / y) + 1 edge (@unsafe_Bedge R) (@left_pt R) (@right_pt R). + +Definition scan events st : seq cell * seq cell := + let final_state := foldl step st events in + (sc_open1 final_state ++ lst_open final_state :: sc_open2 final_state, + lst_closed final_state :: sc_closed final_state). + +Definition start_open_cell := + start_open_cell R eq_op le +%R (fun x y => x - y) + *%R (fun x y => x / y) edge (@left_pt R) (@right_pt R). + +(* +Definition start (events : seq event) (bottom : edge) (top : edge) : + seq cell * seq cell := + match events with + | nil => ([:: start_open_cell bottom top], nil) + | ev0 :: events => + let (newcells, lastopen) := + opening_cells_aux (point ev0) (sort (@edge_below _) (outgoing ev0)) + bottom top in + scan events (Bscan newcells lastopen nil nil + (close_cell (point ev0) (start_open_cell bottom top)) + top (p_x (point ev0))) + end. + +*) + +Lemma cell_edges_sub_high bottom top (s : seq cell) : + cells_bottom_top bottom top s -> + adjacent_cells s -> cell_edges s =i bottom::[seq high c | c <- s]. +Proof. +case: s bottom => [ | c0 s] /= bottom; first by []. +rewrite /cells_bottom_top /cells_low_e_top=> /= /andP[] /eqP lc0 A lowhigh. +rewrite /cell_edges=> g; rewrite mem_cat. +have main : [seq high c | c <- c0 :: s] = + rcons [seq low c | c <- s] (high (last c0 s)). + elim: s c0 lowhigh {lc0 A} => [ | c1 s Ih] c0 lowhigh; first by []. + rewrite /=. + move: lowhigh=> /= /andP[/eqP -> lowhigh]; congr (_ :: _). + by apply: Ih. +rewrite main mem_rcons inE orbC map_cons inE -!orbA. +rewrite !(orbCA _ (g == low _)) orbb. +rewrite inE lc0; congr (_ || _). +by rewrite -map_cons main mem_rcons inE. +Qed. + +Lemma not_bottom_or_top bottom top (ev : event') : + inside_box bottom top (point ev) -> + out_left_event ev -> + {in outgoing ev, forall g, g \notin [:: bottom; top]}. +Proof. +move=> inbox oute g gin; apply/negP=> abs. +have lgq : left_pt g = point ev by apply/eqP/oute. +move: inbox=> /andP[]; rewrite -lgq; move: abs; rewrite !inE=> /orP[] /eqP ->. + by rewrite left_pt_below. +by rewrite (negbTE (left_pt_above _)) !andbF. +Qed. + +Section proof_environment. +Variables bottom top : edge. + +Notation extra_bot := (extra_bot bottom). +Notation close_alive_edges := (close_alive_edges bottom top). +Notation cells_bottom_top := (cells_bottom_top bottom top). +Notation inside_box := (inside_box bottom top). +Notation open_cell_side_limit_ok := (@open_cell_side_limit_ok R). +Notation seq_low_high_shift := (@seq_low_high_shift R). +Notation cover_left_of := (@cover_left_of _ bottom top). + +Section open_cells_decomposition. + +Lemma open_cells_decomposition_contact_none open_cells p : + open_cells_decomposition_contact open_cells p = None -> + open_cells != [::] -> ~~contains_point p (head dummy_cell open_cells). +Proof. +rewrite /contains_point. +case: open_cells => [// | /= c0 q]. +by case : ifP=> ? //; + case: (open_cells_decomposition_contact q p)=> // [] [] []. +Qed. + +Lemma open_cells_decomposition_contact_main_properties open_cells p cc c' lc: + open_cells_decomposition_contact open_cells p = Some (cc, lc, c') -> + cc ++ c' :: lc = open_cells /\ + contains_point p c' /\ + {in cc, forall c, contains_point p c} /\ + (lc != [::] -> ~~ contains_point p (head c' lc)). +Proof. +elim: open_cells cc c' lc => [ // | c q Ih] cc c' lc. +rewrite /=; case: ifP => [ctpcc | nctpcc] //. +case occ_eq : (open_cells_decomposition_contact _ _) + (@open_cells_decomposition_contact_none q p) + => [[[cc1 lc1] c1] | ] nonecase [] <- <- <-; last first. + split;[ by [] | split; [by [] | split; [by [] | ] ]]. + by case: (q) nonecase => [// | c2 q2] ; apply. +have [eqls [ctc1 [allct nctlc1]]] := Ih _ _ _ occ_eq. +split; first by rewrite /=; congr (_ :: _). +split; first by []. +split; last by []. +by move=> w; rewrite inE => /orP[/eqP -> // | ]; apply: allct. +Qed. + +Lemma decomposition_main_properties open_cells p fc cc lcc lc le he: + open_cells_decomposition open_cells p = (fc, cc, lcc, lc, le, he) -> + (exists2 w, w \in open_cells & contains_point' p w) -> + open_cells = fc ++ cc ++ lcc :: lc /\ + contains_point p lcc /\ + {in cc, forall c, contains_point p c} /\ + {in fc, forall c, ~~contains_point p c} /\ + (lc != [::] -> ~~ contains_point p (head lcc lc)) /\ + he = high lcc /\ + le = low (head lcc cc) /\ + le \in cell_edges open_cells /\ + he \in cell_edges open_cells. +Proof. +rewrite /open_cells_decomposition/generic_trajectories.open_cells_decomposition. +elim : open_cells fc cc lcc lc le he => [ | c q Ih] fc cc lcc lc le he. + by rewrite /= => _ [] w. +rewrite /=; case: ifP=> ctc. + rewrite -[generic_trajectories.open_cells_decomposition_contact _ _ _ _ _ + _ _ _ _ _ _ _]/(open_cells_decomposition_contact q p). + case ocdc_eq : (open_cells_decomposition_contact q p) => [[[cc0 lc0] c0]|]. + move=> [] <- <- <- <- <- <- _. + have [qeq [ctc0 [allct nct]] ]:= + open_cells_decomposition_contact_main_properties ocdc_eq. + split; first by rewrite /= qeq. + split; first by []. + split; first by move=> c1 /orP[/eqP -> | ] //; apply: allct. + repeat (split; first by []). + by rewrite -qeq !mem_cat !map_f ?orbT // !(mem_cat, inE) eqxx ?orbT. + move=> [] <- <- <- <- <- <- _. + repeat (split; first by []). + split. + by move: (open_cells_decomposition_contact_none ocdc_eq); case: (q). + split; first by []. + split; first by []. + by rewrite !mem_cat !map_f ?orbT // inE eqxx. +rewrite -[generic_trajectories.open_cells_decomposition_rec _ _ _ _ _ + _ _ _ _ _ _ _ _]/(open_cells_decomposition_rec q p). +case ocdr_eq : (open_cells_decomposition_rec q p) => [[[fc1 cc1] lcc1] lc1]. +move=> [] <- <- <- <- <- <- [] w win ctw. +have ex2 :exists2 w, w \in q & contains_point' p w. + exists w; last by []. + move: win ctw; rewrite inE => /orP[/eqP -> | //]. + by move=> /contains_point'W; rewrite /contains_point ctc. +have := Ih fc1 cc1 lcc1 lc1 (low (head lcc1 cc1)) (high lcc1). +rewrite /open_cells_decomposition_rec in ocdr_eq. +rewrite ocdr_eq => /(_ erefl ex2). +move=> [qeq [ctplcc1 [allct [allnct [nctlc [leeq heq]]]]]]. +split; first by rewrite /= qeq. +split; first by []. +split; first by []. +split. + move=> c0; rewrite inE=> /orP[/eqP -> // | c0in]; last first. + by rewrite ?allnct. + by rewrite /contains_point ctc. +repeat (split; first by []). +by rewrite qeq !mem_cat !map_f ?orbT //; case:(cc1) => [| a b] /=; subset_tac. +Qed. + +Lemma decomposition_connect_properties open_cells p + first_cells contact last_contact last_cells low_f high_f: +s_right_form open_cells -> +seq_valid open_cells p -> +adjacent_cells open_cells -> +cells_bottom_top open_cells -> +between_edges bottom top p -> +open_cells_decomposition open_cells p = + (first_cells, contact, last_contact, last_cells, low_f, high_f) -> +[/\ p >>> low_f, p <<< high_f, valid_edge low_f p, valid_edge high_f p & +forall c, (c \in first_cells) || (c \in last_cells) -> ~ contains_point p c]. +Proof. +move=> rfo sval adj cbtom inbox_p oe. +have [w win ctw'] := exists_cell cbtom adj inbox_p. +have [ocd [ctpl [allct [allnct [nctlc [-> [-> _]]]]]]]:= + decomposition_main_properties oe (exists_cell cbtom adj inbox_p). +have [A B C D E] := + connect_properties cbtom adj rfo sval inbox_p ocd allnct allct ctpl nctlc. +by split => // c cin; apply/negP/E. +Qed. + +Lemma decomposition_not_end open_cells e : +forall first_cells contact last_contact last_cells low_f high_f, +s_right_form open_cells -> +seq_valid open_cells (point e) -> +adjacent_cells open_cells -> +cells_bottom_top open_cells -> +between_edges bottom top (point e) -> +open_cells_decomposition open_cells (point e) = + (first_cells, contact, last_contact, last_cells, low_f, high_f) -> +forall c, (c \in first_cells) || (c \in last_cells) -> + ( ~ event_close_edge (low c) e) /\ ( ~ event_close_edge (high c) e). +Proof. +move=> fc cc lcc lc low_f high_f rfo sval adj cbtom inbox_p oe c cold. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq leq]]]]]]:= + decomposition_main_properties oe (exists_cell cbtom adj inbox_p). +by apply: (fclc_not_end_aux cbtom adj _ sval inbox_p ocd _ lcc_ctn flcnct). +Qed. + +Lemma open_cells_decomposition_point_on open p fc cc lcc lc le he c: + cells_bottom_top open -> + adjacent_cells open -> + between_edges bottom top p -> + seq_valid open p -> + open_cells_decomposition open p = (fc, cc, lcc, lc, le, he) -> + c \in cc -> p === high c. +Proof. + +move=> cbtom adj inbox_p sval oe ccc. +have [ocd [lcc_ctn [allctn _]]]:= decomposition_main_properties oe + (exists_cell cbtom adj inbox_p). +by have := in_cc_on_high adj sval ocd allctn lcc_ctn ccc. +Qed. + +Lemma last_first_cells_high open p fc cc lcc lc le he : + cells_bottom_top open -> + adjacent_cells open -> + between_edges bottom top p -> + open_cells_decomposition open p = (fc, cc, lcc, lc, le, he) -> + last bottom [seq high i | i <- fc] = le. +Proof. +move=> cbtom adj inbox_p oe. +have exi := exists_cell cbtom adj inbox_p. +have [ocd [_ [_ [_ [_ [heq [leq _]]]]]]] := + decomposition_main_properties oe exi. +suff -> : last bottom [seq high i | i <- fc] = low (head lcc cc). + by rewrite leq. +move: cbtom=> /andP[] /andP[] _ /eqP + _. +move : adj; rewrite ocd. + elim/last_ind: {-1}(fc) (erefl fc) => [//= | fc' c1 _]. + by case: (cc) => [ | c2 cc']. +rewrite -cats1 -catA=> fceq /adjacent_catW /= [] _ + _. +rewrite cats1 map_rcons last_rcons. +by case: (cc) => [ | c2 cc'] /andP[] + _; rewrite /adj_rel /= => /eqP. +Qed. + +Lemma head_last_cells_low open p fc cc lcc lc le he : + cells_bottom_top open -> + adjacent_cells open -> + between_edges bottom top p -> + open_cells_decomposition open p = (fc, cc, lcc, lc, le, he) -> + head top [seq low i | i <- lc] = he. +Proof. +move=> cbtom adj inbox_p oe. +have exi := exists_cell cbtom adj inbox_p. +have [ocd [_ [_ [_ [_ [-> _]]]]]] := + decomposition_main_properties oe exi. +move: cbtom=> /andP[] _ /eqP. +move: adj; rewrite ocd => /adjacent_catW [] _ /adjacent_catW [] _ /=. + rewrite !last_cat /=. +case : (lc) => [ | c2 lc'] //=. +by move=> /andP[] /eqP ->. +Qed. + +(* Temporary trial, but this lemma might be better placed in + points_and_edges. *) +Lemma decomposition_above_high_fc p open fc cc lcc lc le he c1: + open_cells_decomposition open p = (fc, cc, lcc, lc, le, he) -> + cells_bottom_top open -> + adjacent_cells open -> + between_edges bottom top p -> + s_right_form open -> + seq_valid open p -> + c1 \in fc -> p >>> high c1. +Proof. +move=> oe cbtom adj inbox_e rfo sval c1in. +have exi := exists_cell cbtom adj inbox_e. +have [ocd [_ [_ [_ [_ [heq leq]]]]]] := decomposition_main_properties oe exi. +have [pal puh vl vp _]:= + decomposition_connect_properties rfo sval adj cbtom inbox_e oe. +rewrite under_pvert_y; last first. + apply: (seq_valid_high sval). + by rewrite map_f //; rewrite ocd; subset_tac. +rewrite -ltNge. +have : pvert_y p le < p_y p. + by move: pal; rewrite under_pvert_y // -ltNge. +apply: le_lt_trans. +move: c1in. +have [fceq |[fc' [lfc fceq]]]: fc = nil \/ exists fc' lfc, fc = rcons fc' lfc. + by elim/last_ind : (fc) => [ | fc' lfc _];[left | right; exists fc', lfc]. + by rewrite fceq. +have := last_first_cells_high cbtom adj inbox_e oe. +rewrite fceq map_rcons last_rcons => <-. +rewrite mem_rcons inE => /orP[/eqP c1lfc | c1o]; first by rewrite c1lfc. +have [a [b pab]] := mem_seq_split c1o. +move: fceq; rewrite pab -cats1 -catA /= => fceq. +(* requirement for path_edge_below_pvert_y *) +have req1 : all (valid_edge (R := _) ^~ p) + [seq high i | i <- c1 :: b ++ [:: lfc]]. + apply/allP; apply: (sub_in1 _ (seq_valid_high sval)); apply: sub_map. + by rewrite ocd fceq; subset_tac. +have req2 : path (@edge_below R) (high c1) [seq high i | i <- b ++ [:: lfc]]. + have := seq_edge_below' adj rfo. + rewrite ocd (_ : fc = rcons a c1 ++ rcons b lfc); last first. + by move: fceq; rewrite -!cats1 !catA /= -!catA /=. + rewrite -!catA [X in path _ _ X]map_cat cat_path=> /andP[] _. + rewrite !map_rcons last_rcons map_cat cat_path => /andP[] + _. + by rewrite -cats1. +have : path (<=%R) (pvert_y p (high c1)) + [seq pvert_y p (high i) | i <- b ++ [:: lfc]]. + by have := path_edge_below_pvert_y req1 req2; rewrite -map_comp. +rewrite le_path_sortedE => /andP[] /allP + _. +move=> /(_ (pvert_y p (high lfc))); apply. +by rewrite (map_f (fun c => pvert_y p (high c))) //; subset_tac. +Qed. + +Lemma decomposition_under_low_lc p open fc cc lcc lc le he c1: + open_cells_decomposition open p = (fc, cc, lcc, lc, le, he) -> + cells_bottom_top open -> + adjacent_cells open -> + between_edges bottom top p -> + s_right_form open -> + seq_valid open p -> + c1 \in lc -> p <<< low c1. +Proof. +move=> oe cbtom adj inbox_e rfo sval c1in. +have exi := exists_cell cbtom adj inbox_e. +have [ocd _] := decomposition_main_properties oe exi. +rewrite strict_under_pvert_y; last first. + by apply/(seq_valid_low sval)/map_f; rewrite ocd; subset_tac. +have [pal puh vl vp _]:= + decomposition_connect_properties rfo sval adj cbtom inbox_e oe. +have puhe : p_y p < pvert_y p he. + by move: puh; rewrite strict_under_pvert_y. +apply: (lt_le_trans puhe). +move: c1in; case lceq : lc => [ // | flc lc'] c1in. +have := head_last_cells_low cbtom adj inbox_e oe. +rewrite lceq /= => <-. +move: c1in; rewrite inE => /orP[/eqP c1flc | c1o]; first by rewrite c1flc. +have [a [b Pab]] := mem_seq_split c1o. +(* requirement for path_edge_below_pvert_y *) +have req1 : all (@valid_edge R ^~ p) + [seq low i | i <- flc :: a ++ c1 :: b]. + apply/allP; apply: (sub_in1 _ (seq_valid_low sval)); apply: sub_map. + by rewrite ocd lceq Pab; subset_tac. +have req2 : path (@edge_below R) (low flc) [seq low i | i <- a ++ c1 :: b]. + have := seq_edge_below' adj rfo. + have [on0 headq] : open != [::] /\ low (head dummy_cell open) = bottom. + by move: cbtom=> /andP[] /andP[] + /eqP + _. + have headq' : head dummy_edge [seq low i | i <- open] = bottom. + by move: on0 headq; case: (open)=> [ // | ? ?] /=. + rewrite headq' => pathoh. + have : path (@edge_below R) bottom (bottom :: [seq high i | i <- open]). + by rewrite /= edge_below_refl. + have := seq_low_high_shift on0 adj; rewrite headq => <-. + rewrite -cats1 cat_path => /andP[] + _. + rewrite ocd lceq Pab. + by rewrite 2!map_cat 2!cat_path /= => /andP[] _ /andP[] _ /andP[] _ /andP[]. +have : path (<=%R) (pvert_y p (low flc)) + [seq pvert_y p (low i) | i <- a ++ c1 :: b]. + by have := path_edge_below_pvert_y req1 req2; rewrite -map_comp. +rewrite le_path_sortedE => /andP[] /allP + _. +move=> /(_ (pvert_y p (low c1))); apply. +by rewrite (map_f (fun c => pvert_y p (low c))); subset_tac. +Qed. + +End open_cells_decomposition. + +Lemma open_cells_decomposition_cat f l p : + adjacent_cells (f ++ l) -> + s_right_form (f ++ l) -> + seq_valid (f ++ l) p -> + (exists2 c, c \in l & contains_point' p c) -> + p >>> low (head dummy_cell l) -> + let '(fc', cc, lcc, lc, le, he) := + open_cells_decomposition l p in + open_cells_decomposition (f ++ l) p = + (f ++ fc', cc, lcc, lc, le, he). +Proof. +move=> + + + exi pal. +elim: f => [ | c0 f Ih]. + move=> adj rfo sval. + by case: (open_cells_decomposition l p) => [[[[[fc cc] lcc] lc] le] he]. +rewrite /= => adj /andP[] lbh0 rfo /andP[] /andP[] vlc0 vhc0 sval. +case ocal_eq : (open_cells_decomposition l p) => + [[[[[fc' cc'] lcc'] lc'] le'] he']. +case oca_eq : (open_cells_decomposition _ _) => + [[[[[fc1 cc1] lcc1] lc1] le1] he1]. +have exi0 : exists2 c, c \in c0 :: f ++ l & contains_point' p c. + by case: exi => c cin A; exists c=> //; subset_tac. +have := decomposition_main_properties oca_eq exi0 => + -[ocd [lcc_ctn [allct [allnct [flnct [heq [leq [lein hein]]]]]]]]. +have := decomposition_main_properties ocal_eq exi => + -[ocd' [lcc_ctn' [allct' [allnct' [flnct' [heq' [leq' [lein' hein']]]]]]]]. +have svalf : seq_valid f p. + by apply/allP=> x xin; apply: (allP sval); subset_tac. +have rfof : s_right_form f. + by apply/allP=> x xin; apply: (allP rfo); subset_tac. +have adjf : adjacent_cells f. + by move: adj; rewrite cat_path=> /andP[] /path_sorted. +have hfq : high (last c0 f) = low (head dummy_cell l). + case: (l) adj exi => [ | c1 l']; first by move => _ []. + by rewrite cat_path /==> /andP[] _ /andP[] /eqP. +move: oca_eq; rewrite /open_cells_decomposition/generic_trajectories.open_cells_decomposition /=. +case: ifP=> [c0ctn | c0nctn]. + move: c0ctn; rewrite /generic_trajectories.contains_point -[X in _ && X]negbK. + have [/eqP f0 | fn0] := boolP (f == nil). + by move: hfq; rewrite f0 /= => ->; rewrite pal andbF. + have := above_all_cells svalf adjf rfof. + have -> : high (last dummy_cell f) = high (last c0 f). + by case: (f) fn0. + rewrite hfq pal=> /(_ isT) [] palf _. + have -> : high c0 = low (head dummy_cell f). + by move: adj fn0; case: (f) => [// | ? ?] /= /andP[] /eqP. + by rewrite palf andbF. +move: ocal_eq; rewrite /open_cells_decomposition/generic_trajectories.open_cells_decomposition. +rewrite -/(open_cells_decomposition_rec _ _). +case ocal_eq: (open_cells_decomposition_rec _ _) => + [[[fc2 cc2] lcc2] lc2] [] <- <- <- <- <- <-. +have adj' : adjacent_cells (f ++ l). + by move: adj=> /path_sorted. +have := Ih adj' rfo sval; rewrite /open_cells_decomposition. +rewrite /generic_trajectories.open_cells_decomposition. +rewrite /open_cells_decomposition_rec in ocal_eq. rewrite ocal_eq. +rewrite -/(open_cells_decomposition_rec _ _). +case: (open_cells_decomposition_rec (f ++ l) p) => [[[fc4 cc4] lcc4] lc4]. +by move=> -[] -> -> -> -> _ _ [] <- <- <- <- <- <-. +Qed. + +Lemma open_cells_decomposition_cat' f l p : + adjacent_cells (f ++ l) -> + s_right_form (f ++ l) -> + seq_valid (f ++ l) p -> + (exists2 c, c \in (f ++ l) & contains_point' p c) -> + f != nil -> + p >>> high (last dummy_cell f) -> + let '(fc', cc, lcc, lc, le, he) := + open_cells_decomposition l p in + open_cells_decomposition (f ++ l) p = + (f ++ fc', cc, lcc, lc, le, he). +Proof. +move=> adj rfo sval [w win wctn] fnnil paf. +have adjf : adjacent_cells f by move: adj=> /adjacent_catW[]. +have rfof : s_right_form f. + by apply/allP=> x xin; apply: (allP rfo); subset_tac. +have svalf : seq_valid f p. + by apply/allP=> x xin; apply: (allP sval); subset_tac. +have winl : w \in l. + have [_ abaf] := above_all_cells svalf adjf rfof paf. + have wnf : w \notin f. + apply/negP=> abs. + by move: wctn; rewrite /contains_point' -[X in _ && X]negbK abaf ?andbF //. + by move: win; rewrite mem_cat (negbTE wnf). +have exi' : exists2 c, c \in l & contains_point' p c by exists w. +have hfq : high (last dummy_cell f) = low (head dummy_cell l). + move: adj fnnil. + case:(f) => [ // | c0 f']; rewrite /= cat_path=> /andP[] _ + _. + by move: winl; case: (l) => [ // | c1 l'] _ /= /andP[] /eqP. +by apply: open_cells_decomposition_cat; rewrite // -hfq. +Qed. + +Lemma open_cells_decomposition_single f l c p : + adjacent_cells (f ++ c :: l) -> + s_right_form (f ++ c :: l) -> + seq_valid (f ++ c :: l) p -> + p >>> low c -> + p <<< high c -> + open_cells_decomposition (f ++ c :: l) p = + (f, nil, c, l, low c, high c). +Proof. +move=> adj srf sv pal puh. +have exi : exists2 c', c' \in (c :: l) & contains_point' p c'. + by exists c;[ rewrite inE eqxx // | rewrite /contains_point' pal underW]. +have := open_cells_decomposition_cat adj srf sv exi pal. +case ocl : (open_cells_decomposition (c :: l) p) => + [[[[[fc cc] lcc] lc] le] he]. +move: ocl; rewrite /open_cells_decomposition /=. +rewrite /generic_trajectories.open_cells_decomposition /=. +rewrite -/(contains_point _ _). +have -> : contains_point p c. + by rewrite contains_pointE underWC // underW. +case lq : l => [ | c1 l'] /=. + by move=> [] <- <- <- <- <- <-; rewrite cats0. +rewrite -/(contains_point _ _). +suff -> : contains_point p c1 = false. + by move=> [] <- <- <- <- <- <-; rewrite cats0. +move: adj=> /adjacent_catW[] _; rewrite lq /= => /andP[] /eqP lc1q _. +by rewrite contains_pointE -lc1q puh. +Qed. + +Section step. + + +Variable e : event'. +Variable fop : seq cell. +Variable lsto : cell. +Variable lop : seq cell. +Variable cls : seq cell. +Variable lstc : cell. +Variable lsthe : edge. +Variable lstx : R. +Variable future_events : seq event'. +Variable p : pt. + +Let open := (fop ++ lsto :: lop). + +(* lsto is only guaranteed to be the highest of the last created cells. *) +(* It might be the case that the next event is in the left side of this *) +(* cell *) +#[clearbody] +Let lstoin : lsto \in open. +Proof. by rewrite /open; subset_tac. Defined. + + +Hypothesis inbox_all_edges : + all (fun g => (g \in [:: bottom; top]) || + (inside_box (left_pt g) && inside_box (right_pt g))) + (cell_edges open). +Hypothesis inbox_all_events : + all inside_box [seq point x | x <- (e :: future_events)]. + +#[clearbody] +Let inbox_e : inside_box (point e). +Proof. by have /andP[] := inbox_all_events. Defined. + +#[clearbody] +Let inbox_es : all inside_box [seq point x | x <- future_events]. +Proof. by have /andP[] := inbox_all_events. Defined. + +Hypothesis oute : out_left_event e. +Hypothesis rfo : s_right_form open. +Hypothesis cbtom : cells_bottom_top open. +Hypothesis adj : adjacent_cells open. +Hypothesis sval : seq_valid open (point e). +Hypothesis cle : close_edges_from_events (e :: future_events). +Hypothesis clae : close_alive_edges open (e :: future_events). +Hypothesis lstheq : lsthe = high lsto. +Hypothesis lstheqc : lsthe = high lstc. +Hypothesis lstxq : lstx = left_limit lsto. +Hypothesis abovelstle : + p_x (point e) = lstx -> (point e) >>> low lsto. +Hypothesis elexp : lexePt (point e) p. +Hypothesis plexfut : {in future_events, forall e', lexePt p (point e')}. +Hypothesis inbox_p : inside_box p. +Hypothesis noc : {in all_edges open (e :: future_events) &, no_crossing R}. +Hypothesis sort_evs : path (@lexPtEv _) e future_events. +Hypothesis pwo : pairwise (@edge_below _) (bottom :: [seq high c | c <- open]). +Hypothesis btom_left_corners : + {in open, forall c, lexPt (bottom_left_corner c) (point e)}. +Hypothesis open_side_limit : all open_cell_side_limit_ok open. +Hypothesis close_side_limit : all (@closed_cell_side_limit_ok _) + (rcons cls lstc). +Hypothesis lex_left_limit : + all (fun x => lexPt x (point e)) (behead (left_pts lsto)). +Hypothesis disjoint_open_closed : + {in open & rcons cls lstc, disjoint_open_closed_cells R}. +Hypothesis disjoint_closed : {in rcons cls lstc &, disjoint_closed_cells R}. +Hypothesis closed_right_limit : + {in rcons cls lstc, forall c, right_limit c <= p_x (point e)}. +Hypothesis uniq_closed : uniq (rcons cls lstc). +Hypothesis non_empty_closed : + {in rcons cls lstc, forall c, exists p, inside_closed' p c}. +Hypothesis non_empty_right : (1 < size (right_pts lstc))%N. +Hypothesis uniq_out : uniq (outgoing e). +Hypothesis high_inj : {in open &, injective high}. +Hypothesis btm_left : bottom_left_cells_lex open (point e). +Hypothesis uniq_open : uniq open. +Hypothesis open_non_inner : + {in open, forall c, non_inner (high c) (point e)}. +Hypothesis lex_open_edges : + {in [seq high c | c <- open], forall g, lexPt (left_pt g) (point e) && + lexePt (point e) (right_pt g)}. +Hypothesis left_limit_has_right_limit : + {in open, forall c p, inside_box p -> left_limit c = p_x p -> + contains_point' p c -> has (inside_closed' p) (rcons cls lstc)}. +Hypothesis cover_left_of_e : cover_left_of (point e) open (rcons cls lstc). + +(* Thanks to the disoc lemma, we only need to prove that the high edges + of all open cells satisfy the pairwise property for edge_below to + obtain disjointness of cells. *) + +Lemma disoc_i i j s : (i < j < size s)%N -> + adjacent_cells s -> + pairwise (@edge_below _) [seq high c | c <- s] -> + all open_cell_side_limit_ok s -> + o_disjoint_e (nth dummy_cell s i) (nth dummy_cell s j). +Proof. +move=> + adjs pws open_side_limit_s. +move=> /andP[] iltj jlts. +have ilts : (i < size s)%N by apply: ltn_trans jlts. +set x := nth dummy_cell s i. +set y := nth dummy_cell s j. +have iin : x \in s by apply: mem_nth. +have jin : y \in s by apply: mem_nth. +have xok : open_cell_side_limit_ok x by apply: (allP open_side_limit_s). +have yok : open_cell_side_limit_ok y by apply: (allP open_side_limit_s). +right=> q; apply/negP=> /andP[]. +move=> /andP[] /[dup] inx /(inside_open_cell_valid xok) /andP[] _ vhx _. +move=> /andP[] /[dup] iny /(inside_open_cell_valid yok) /andP[] vly _. +move=> /andP[] qay _. +move: inx=> /andP[] /andP[] _ quhx _. +case/negP:qay. +move: iltj; rewrite leq_eqVlt=> /orP[/eqP/esym jq | ]. + move: adjs. + rewrite -(cat_take_drop j.+1 s)=> /adjacent_catW[] + _. + rewrite (take_nth dummy_cell jlts) -/y jq (take_nth dummy_cell ilts) -/x. + rewrite -2!cats1 -catA /= =>/adjacent_catW[] _ /=. + by rewrite andbT=> /eqP <-. +move=> i1ltj. +set j' := j.-1. +have jj : j = j'.+1 by rewrite (ltn_predK i1ltj). +have j'lts : (j' < size s)%N. + by apply: ltn_trans jlts; rewrite jj. +have iltj' : (i < j')%N by rewrite -ltnS -jj. +move: adjs. +rewrite -(cat_take_drop j.+1 s)=> /adjacent_catW[] + _. +rewrite (take_nth dummy_cell jlts) -/y jj (take_nth dummy_cell j'lts). +rewrite -2!cats1 -catA /= =>/adjacent_catW[] _ /= /andP[] /eqP lyq _. +apply: (order_edges_viz_point' vhx) => //. +rewrite -lyq. +move: pws => /(pairwiseP dummy_edge) /(_ i j') /=; rewrite size_map 2!inE. +move=> /(_ ilts j'lts iltj'). +by rewrite -[dummy_edge]/(high dummy_cell) !(nth_map dummy_cell). +Qed. + +Lemma disoc s: + adjacent_cells s -> + pairwise (@edge_below _) [seq high c | c <- s] -> + all open_cell_side_limit_ok s -> + {in s &, disjoint_open_cells R}. +Proof. +move=> adjs pws sok. +move=> x y xin yin. +set i := find (pred1 x) s. +set j := find (pred1 y) s. +case : (leqP i j) => [ | jlti]; last first. + have ilts : (i < size s)%N by rewrite -has_find has_pred1. + have jint : (j < i < size s)%N by rewrite jlti ilts. + move: xin; rewrite -has_pred1=> /(nth_find dummy_cell) => /eqP <-. + move: yin; rewrite -has_pred1=> /(nth_find dummy_cell) => /eqP <-. + by apply/o_disjoint_eC/disoc_i. +rewrite leq_eqVlt=> /orP[/eqP ij | iltj]. + move: xin; rewrite -has_pred1=> /(nth_find dummy_cell) /= /eqP. + rewrite -/i ij /j. + move: yin; rewrite -has_pred1=> /(nth_find dummy_cell) /= /eqP -> ->. + by left. +have jlto : (j < size s)%N by rewrite -has_find has_pred1. +have jint : (i < j < size s)%N by rewrite iltj jlto. +move: xin; rewrite -has_pred1=> /(nth_find dummy_cell) => /eqP <-. +move: yin; rewrite -has_pred1=> /(nth_find dummy_cell) => /eqP <-. +by apply/disoc_i. +Qed. + +#[clearbody] +Let bet_e : between_edges bottom top (point e). +Proof. by apply inside_box_between. Defined. + +#[clearbody] +Let exi : exists2 c, c \in open & contains_point' (point e) c. +Proof. by apply: (exists_cell cbtom adj bet_e). Defined. + +Lemma close_cell_ok c : + contains_point (point e) c -> + valid_edge (low c) (point e) -> valid_edge (high c) (point e) -> + open_cell_side_limit_ok c -> + closed_cell_side_limit_ok (close_cell (point e) c). +Proof. +move=> ctp vl vh. +rewrite /open_cell_side_limit_ok/closed_cell_side_limit_ok. +rewrite /close_cell /=; have /exists_point_valid [p1 /[dup] vip1 ->] := vl. +have /exists_point_valid [p2 /[dup] vip2 -> /=] := vh. +move=> /andP[] -> /andP[]-> /andP[]-> /andP[] -> -> /=. +have [o1 /esym/eqP x1]:=intersection_on_edge vip1. +have [o2 /eqP x2]:=intersection_on_edge vip2. +rewrite -?(eq_sym (point e)). +(* TODO : this line performs a lot of complicated things, but they mostly + failed at porting time. *) +case:ifP (o1) (o2) =>[/eqP q1 |enp1];case:ifP=>[/eqP q2 |enp2]; + rewrite ?q1 ?q2; + rewrite -?q1 -?q2 /= ?eqxx ?x2 ?x1 /= => -> -> //=; rewrite ?andbT. +- move: x1 x2 ctp=> /eqP/esym x1 /eqP x2 /andP[] el _. + have := (above_edge_strict_higher_y x1 (negbT enp2) el). + by rewrite /right_limit /= x1 eqxx /=; apply. +- move: x1 x2 ctp=> /eqP/esym x1 /eqP x2 /andP[] _ eh. + have := (under_edge_strict_lower_y x2 (negbT enp1) eh o2). + rewrite /right_limit /= x2 eqxx /=; apply. +move: x1 x2 ctp=> /eqP/esym x1 /eqP x2 /andP[] el eh. +rewrite (above_edge_strict_higher_y x1 _ el) //; last first. + exact: negbT. +rewrite (under_edge_strict_lower_y x2 (negbT enp1) eh) //. +by rewrite !andbT /right_limit /= -x1 -x2 eqxx. +Qed. + +Lemma closing_cells_side_limit' cc : + s_right_form cc -> + seq_valid cc (point e) -> + adjacent_cells cc -> + all open_cell_side_limit_ok cc -> + all (contains_point (point e)) cc -> + point e >>> low (head dummy_cell cc) -> + point e <<< high (last dummy_cell cc) -> + all (@closed_cell_side_limit_ok _) (closing_cells (point e) cc). +Proof. +move=> rfc valc adjc oks ctps abovelow belowhigh. +rewrite /closing_cells. +rewrite all_map. +apply/allP=> //= c cin. +have vlc: valid_edge (low c) (point e) by have:= (allP valc c cin) => /andP[]. +have vhc : valid_edge (high c) (point e) + by have := (allP valc c cin) => /andP[]. +apply: close_cell_ok=> //. + by apply: (allP ctps). +by apply: (allP oks). +Qed. + +Lemma close'_subset_contact q c : + valid_cell c (point e) -> + closed_cell_side_limit_ok (close_cell (point e) c) -> + inside_closed' q (close_cell (point e) c) -> inside_open' q c. +Proof. +move=>[] vl vh. +move=>/closed_right_imp_open. +rewrite inside_open'E // inside_closed'E /close_cell. +have [p1 vip1] := exists_point_valid vl. +have [p2 vip2] := exists_point_valid vh. +rewrite vip1 vip2 /= => cok /andP[] -> /andP[] -> /andP[] -> rlim /=. +by apply: (le_trans rlim cok). +Qed. + +Lemma close_cell_right_limit c : + valid_cell c (point e) -> + right_limit (close_cell (point e) c) = p_x (point e). +Proof. +move=> [vl vh]. +rewrite /close_cell; rewrite !pvertE // /right_limit /=. +by case: ifP=> cnd1 //; case: ifP=> cnd2. +Qed. + +Definition state_open_seq (s : scan_state) := + sc_open1 s ++ lst_open s :: sc_open2 s. + +Definition inv1_seq (s : seq cell) := + close_alive_edges s future_events /\ + (future_events = [::] \/ + seq_valid s (point (head dummy_event future_events))) /\ + adjacent_cells s /\ cells_bottom_top s /\ s_right_form s. + +Definition invariant1 (s : scan_state) := + inv1_seq (state_open_seq s). + +(* Let val_between g (h : valid_edge g (point e)) := + valid_between_events elexp plexfut h inbox_p. *) + +#[clearbody] +Let subo : {subset outgoing e <= all_edges open (e :: future_events)}. +Proof. by rewrite /all_edges; subset_tac. Defined. + +#[clearbody] +Let subo' : {subset sort (@edge_below _) (outgoing e) + <= all_edges open (e :: future_events)}. +Proof. +by move=> x; rewrite mem_sort=> xo; apply: subo. +Defined. + +#[clearbody] +Let oute' : {in sort (@edge_below _) (outgoing e), + forall g, left_pt g == (point e)}. +Proof. by move=> x; rewrite mem_sort; apply: oute. Defined. + +(* This was a temporary movement section for objects + transferred to the opening_cells section, but now it seems + opening_cells_pairwise has to stay in this part of the world. *) + +Lemma opening_cells_pairwise le he : + point e >>> le -> + point e <<< he -> + le \in all_edges open (e :: future_events) -> + he \in all_edges open (e :: future_events) -> + valid_edge le (point e) -> + valid_edge he (point e) -> + pairwise (@edge_below _) + [seq high x | x <- (opening_cells (point e) (outgoing e) le he)]. +Proof. +move=> pal puh lein hein vle vhe. +apply: opening_cells_pairwise'=> //. +have sub : {subset [:: le, he & outgoing e] <= + all_edges open (e :: future_events)}. + move=> g1; rewrite !inE=> /orP[/eqP -> | /orP[/eqP -> | gin]] //. + by rewrite mem_cat events_to_edges_cons !mem_cat gin !orbT. +by move=> g1 g2 /sub g1in /sub g2in; apply: noc. +Qed. + +(* end of temporary moving area. *) +Lemma invariant1_default_case : + let '(fc, cc, lcc, lc, le, he) := + open_cells_decomposition open (point e) in + let '(nos, lno) := + opening_cells_aux (point e) + (sort (@edge_below _) (outgoing e)) le he in + inv1_seq ((fc ++ nos) ++ lno :: lc). +Proof. +case oe : (open_cells_decomposition open (point e)) => + [[[[[fc cc] lcc] lc] le] he]. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vle vhe ncont] := + decomposition_connect_properties rfo sval adj cbtom bet_e oe. +case oca_eq:(opening_cells_aux _ _ _ _) => [nos nlsto]. +rewrite /invariant1 /state_open_seq /=. +have dec_not_end := + decomposition_not_end rfo sval adj cbtom bet_e oe. +have close_fc : close_alive_edges fc future_events. + suff/head_not_end : close_alive_edges fc (e :: future_events). + by apply=> c0 cin; apply: dec_not_end; rewrite cin. + by apply/allP=> c0 cin; apply: (allP clae); rewrite ocd; subset_tac. +have close_lc : close_alive_edges lc future_events. + suff/head_not_end : close_alive_edges lc (e :: future_events). + by apply=> c0 cin; apply: dec_not_end; rewrite cin orbT. + by apply/allP=> c0 cin; apply: (allP clae); rewrite ocd; subset_tac. +have endle : end_edge_ext bottom top le future_events. + suff : end_edge_ext bottom top le (e :: future_events). + rewrite /end_edge_ext; move=> /orP[-> // | ] /= /orP[ | ->]; last first. + by rewrite orbT. + by move: pal=> /[swap] /eqP <-; rewrite right_pt_below. + have := (proj1 (andP (allP clae (head lcc cc) _))); rewrite leq; apply. + by rewrite ocd; subset_tac. +have endhe : end_edge_ext bottom top he future_events. + suff : end_edge_ext bottom top he (e :: future_events). + rewrite /end_edge_ext; move=> /orP[-> // | ] /= /orP[ | ->]; last first. + by rewrite orbT. + move: puh=> /[swap] /eqP <-; rewrite strict_nonAunder; last first. + by apply: valid_edge_right. + by rewrite right_on_edge. + have := (proj2 (andP (allP clae lcc _))); rewrite ?heq; apply. + by rewrite ocd; subset_tac. +move: cle => /= /andP[] cloe _. +have clan := opening_cells_close vle vhe oute endle endhe cloe. +have main := (insert_opening_closeness close_fc clan close_lc). +split. + by move: main; rewrite /opening_cells oca_eq -cats1 -!catA. +have subfc : {subset fc <= open} by rewrite ocd; subset_tac. +have sublc : {subset lc <= open} by rewrite ocd; subset_tac. +(* TODO : redo this as it is overkill for what follows. *) +have svaln : + forall q, inside_box q -> lexePt (point e) q -> + {in future_events, forall e', lexePt q (point e')} -> + seq_valid ((fc ++ nos) ++ nlsto :: lc) q. + move=> q inbox_q elexq qlexfut. + apply/allP=> x; rewrite !(mem_cat, inE) -orbA => /orP[xf | ]. + have /andP [vlx vhx] := allP sval x (subfc _ xf). + have := (allP main x); rewrite mem_cat xf => /(_ isT) /andP claex. + by rewrite (valid_between_events elexq qlexfut vlx inbox_q) + ?(valid_between_events elexq qlexfut vhx inbox_q); case: claex. + rewrite orbA=> /orP[ | xl]; last first. + have /andP [vlx vhx] := allP sval x (sublc _ xl). + move: (elexq);rewrite lexePt_eqVlt => /orP[/eqP <- | elexp']. + by rewrite vlx vhx. + have := (allP main x). + rewrite 2!mem_cat xl !orbT => /(_ isT) /andP claex. + by rewrite (valid_between_events elexq qlexfut vlx inbox_q) + ?(valid_between_events elexq qlexfut vhx inbox_q); case: claex. + move=> xin; have xin' : x \in opening_cells (point e) (outgoing e) le he. + by rewrite /opening_cells oca_eq mem_rcons inE orbC. + have [vlx vhx] := andP (allP (opening_valid oute vle vhe) _ xin'). + have [eelx eehx] := andP (allP clan _ xin'). + by rewrite (valid_between_events elexq qlexfut vlx inbox_q) + ?(valid_between_events elexq qlexfut vhx inbox_q). +split. + case futq : future_events => [ | ev2 fut']; first by left. + right; rewrite /=. + apply: svaln. + by apply: (@allP pt _ _ inbox_es); rewrite map_f // futq inE eqxx. + apply: lexPtW. + by move: sort_evs; rewrite futq /= => /andP[]. + move=> e'; rewrite futq inE => /orP[/eqP -> | ]. + by apply: lexePt_refl. + move=> e'in; apply/lexPtW. + move: sort_evs; rewrite futq /= => /andP[] _. + rewrite path_sortedE; last by move=> x y z; apply: lexPt_trans. + by move=> /andP[] /allP /(_ e' e'in). +have [adjnew lownew] := adjacent_opening_aux vle vhe oute' oca_eq. +have := opening_cells_aux_high_last vle vhe oute'; rewrite oca_eq heq /=. +move=> hnlsto. +split. + suff : adjacent_cells ((fc ++ nos) ++ nlsto :: lc) by []. + rewrite -catA. + have oldnnil : rcons cc lcc != nil. + by apply/eqP/rcons_neq0. + rewrite -cat_rcons; apply: (replacing_seq_adjacent oldnnil). + - by apply/eqP/rcons_neq0. + - by rewrite lownew; move: leq; case: (cc) => [ | ? ?]. + - by rewrite !last_rcons. + - by move: adj; rewrite ocd cat_rcons. + by apply: adjnew. +have nn0 : rcons nos nlsto != nil by apply/eqP/rcons_neq0. +have on0 : rcons cc lcc != nil by apply/eqP/rcons_neq0. +move: cbtom; rewrite ocd -cat_rcons => cbtom'. +have hds: low (head dummy_cell (rcons cc lcc)) = + low (head dummy_cell (rcons nos nlsto)). + by rewrite head_rcons -leq -lownew head_rcons. +have tls : high (last dummy_cell (rcons cc lcc)) = + high (last dummy_cell (rcons nos nlsto)). + by rewrite !last_rcons. +split. + move: cbtom'; + rewrite (replacing_seq_cells_bottom_top _ _ _ _ on0 nn0) //. + by rewrite -catA cat_rcons. +rewrite -catA -cat_rcons. +have lein' : le \in all_edges open (e :: future_events). + by rewrite /all_edges; subset_tac. +have hein' : he \in all_edges open (e :: future_events). + by rewrite /all_edges; subset_tac. +have lebhe : le <| he. + by apply: (edge_below_from_point_above (noc _ _) vle vhe (underWC _)). +have noc2 : {in [:: le, he & outgoing e] &, no_crossing R}. + by apply: (sub_in2 _ noc); rewrite /all_edges; subset_tac. +have subso : {subset sort (@edge_below _) (outgoing e) + <= all_edges open (e :: future_events)}. + by move=> x; rewrite mem_sort; apply: subo. +apply/allP=> x; rewrite 2!mem_cat orbCA => /orP[xin | xold]; last first. + by apply: (allP rfo); rewrite ocd; move: xold => /orP[] ?; subset_tac. +have srt : path (@edge_below _) le (sort (@edge_below _) (outgoing e)). + by have := sorted_outgoing vle vhe pal puh oute noc2. +have := (opening_cells_aux_right_form (underWC pal) puh vle vhe + lein' hein' lebhe oute' noc subso srt oca_eq). +by move=> /allP /(_ x xin). +Qed. + +#[clearbody] +Let exi' : point e >>> lsthe -> + exists2 c, c \in lop & contains_point' (point e) c. +Proof. +rewrite lstheq; move=> pa. +suff abf : {in fop, forall c, point e >>> high c}. +have [wc wcin wcct] := exi; exists wc => //. + move: wcin; rewrite /open !(mem_cat, inE) => /orP[wf | /orP[/eqP wl | //]]. + by move: wcct; rewrite /contains_point' (negbTE (abf _ wf)) andbF. + by move: wcct; rewrite /contains_point' wl (negbTE pa) andbF. +have vfop1 : seq_valid (rcons fop lsto) (point e). + apply/allP=> x; rewrite mem_rcons=> xin; apply: (allP sval). + by move: x xin; rewrite /open; change {subset lsto::fop <= open}; subset_tac. +have vfop : {in rcons fop lsto, forall c, valid_edge (high c) (point e)}. + move=> c cin. + have cin' : high c \in [seq high i | i <- open]. + by apply: map_f; rewrite /open -cat_rcons; subset_tac. + by apply: (seq_valid_high sval cin'). +have rfop : s_right_form (rcons fop lsto). + by apply: all_sub rfo; rewrite /open -cat_rcons; subset_tac. +have afop : adjacent_cells (rcons fop lsto). + by move: adj; rewrite /open -cat_rcons => /adjacent_catW []. +have vh : valid_edge (low (head lsto fop)) (point e). + by move: sval; rewrite /open; case: (fop) => [ | ? ?] /= /andP[] /andP[]. +suff [] : point e >>> low (head lsto fop) /\ + {in fop, forall c, point e >>> high c} by []. +have := above_all_cells vfop1 afop rfop; rewrite last_rcons=> /(_ pa). +have hq : head dummy_cell (rcons fop lsto) = head lsto fop. + by case: (fop) => [ | ? ?]. +rewrite hq => -[-> others]; split=> // x xin. +by apply: others; rewrite mem_rcons inE xin orbT. +Defined. + +Lemma inv1_seq_set_pts s1 s2 c1 lpts1 lpts2 : + inv1_seq (s1 ++ set_pts c1 lpts1 lpts2 :: s2) <-> + inv1_seq (s1 ++ c1 :: s2). +Proof. +rewrite /inv1_seq. +have -> : close_alive_edges (s1 ++ set_pts c1 lpts1 lpts2 :: s2) + future_events = + close_alive_edges (s1 ++ c1 :: s2) future_events. + by rewrite /close_alive_edges !all_cat /=. +have -> : adjacent_cells (s1 ++ set_pts c1 lpts1 lpts2 :: s2) = + adjacent_cells (s1 ++ c1 :: s2). + elim/last_ind : s1 => [ | [ | c0 s1] c0' _]; case: s2 => [ | c2 s2] //=; + by rewrite /adjacent_cells ?cat_rcons ?cat_path //. +have -> : cells_bottom_top (s1 ++ set_pts c1 lpts1 lpts2 :: s2) = + cells_bottom_top (s1 ++ c1 :: s2). + rewrite /cells_bottom_top /cells_low_e_top. + by case: s1 => [ | c0 s1]; elim/last_ind: s2 => [ | s2 c2 _]; + rewrite /= -?cat_rcons ?(last_rcons, cats0, last_cat). +have -> : s_right_form (s1 ++ set_pts c1 lpts1 lpts2 :: s2) = + s_right_form (s1 ++ c1 :: s2). + by rewrite /s_right_form !all_cat /=. +split; move=> [-> [B [-> [-> -> ]]]]; split=> //; split=> //. + case: B; first by left. + by rewrite /seq_valid !all_cat /=; right. +case: B; first by left. +by rewrite /seq_valid !all_cat /=; right. +Qed. + +Lemma inv1_seq_set_left_pts s1 s2 c1 lpts : + inv1_seq (s1 ++ set_left_pts c1 lpts :: s2) <-> + inv1_seq (s1 ++ c1 :: s2). +Proof. exact (inv1_seq_set_pts s1 s2 c1 lpts (right_pts c1)). Qed. + +#[clearbody] +Let vlo : valid_edge (low lsto) (point e). +Proof. by apply: (proj1 (andP (allP sval lsto lstoin))). Defined. + +#[clearbody] +Let vho : valid_edge (high lsto) (point e). +Proof. by apply: (proj2 (andP (allP sval lsto lstoin))). Defined. + +Lemma last_step_situation fc' cc lcc lc le he: + open_cells_decomposition (lsto :: lop) (point e) = + (fc', cc, lcc, lc, le, he) -> + p_x (point e) = lstx -> + ~~ (point e <<< lsthe) -> + point e <<= lsthe -> + fc' = [::] /\ le = low lsto /\ exists cc', cc = lsto :: cc'. +Proof. +move=> oe pxhere eabove ebelow. +have lsto_ctn : contains_point' (point e) lsto. + by rewrite /contains_point' -lstheq ebelow abovelstle. +have exi2 : exists2 c, c \in (lsto :: lop) & contains_point' (point e) c. + by exists lsto; rewrite // inE eqxx. +have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] + := decomposition_main_properties oe exi2. +have fc'0 : fc' = [::]. + case fc'q : fc' => [// | fc'i fc2]. + move: ocd; rewrite fc'q /= => - [] lstoisfc'i _. + move: (all_nct lsto). + by rewrite (contains_point'W lsto_ctn) fc'q lstoisfc'i inE eqxx =>/(_ isT). +split; first by []. +case ccq: cc => [ | cc0 cc']. + move: ocd; rewrite fc'0 ccq /= => -[] lstoq. + move: heq; rewrite -lstoq. + have := open_cells_decomposition_cat adj rfo sval exi2 (abovelstle pxhere). + rewrite oe => oe'. + have [ocd' [lcc_ctn' [all_ct' [all_nct' [flcnct' [heq' [leq' [_ _]]]]]]]] + := decomposition_main_properties oe exi2. + have [pal puh vle vhe]:= + decomposition_connect_properties rfo sval adj cbtom bet_e oe'. + by move: puh; rewrite heq' -lstoq -lstheq (negbTE eabove). +have [ fopq | [fop' [lfop fopq]]] : + fop = nil \/ exists fop' lfop, fop = rcons fop' lfop. + elim/last_ind: (fop) => [| fop' lfop]; first by left. + by right; exists fop', lfop. + move: ocd; rewrite -cat_rcons fc'0 /= => lstohead. + split. + suff : lsto = head lcc cc by move=> ->. + by rewrite -[LHS]/(head lsto (lsto :: lop)) lstohead; case: (cc). + by exists cc'; move: lstohead; rewrite ccq /= => -[] ->. +move: adj; rewrite /open ocd fopq fc'0 cat_rcons /=. +move=> /adjacent_catW[] _ it. +move: (ocd); rewrite fc'0 /=; move: it=> /[swap] <- /andP[] /eqP <- _. +split. + apply/esym; rewrite leq. + move: adj; rewrite /open ocd fc'0 /= fopq cat_rcons=>/adjacent_catW[] _. + by rewrite ccq /= => /andP[] /eqP ->. +by exists cc'; move: ocd; rewrite fc'0 ccq /= => -[] ->. +Qed. + +#[clearbody] +Let loin : low lsto \in all_edges open (e :: future_events). +Proof. by rewrite 2!mem_cat map_f. Defined. + +#[clearbody] +Let hoin : high lsto \in all_edges open (e :: future_events). +Proof. by rewrite 2!mem_cat map_f // orbT. Defined. + +Arguments pt_eqb : simpl never. + +Lemma step_keeps_invariant1 : + invariant1 (step (Bscan fop lsto lop cls lstc lsthe lstx) e). +Proof. +case step_eq : (step _ _) => [fop' lsto' lop' cls' lstc' lsthe' lstx']. +rewrite /state_open_seq /=; move: step_eq. +rewrite /step/generic_trajectories.step -/open. +(* have val_bet := valid_between_events elexp plexfut _ inbox_p. *) +case: ifP=> [pxaway | /negbFE/eqP/[dup] pxhere /abovelstle palstol]. + move: invariant1_default_case. + rewrite -/(open_cells_decomposition _ _). + case oe: (open_cells_decomposition _ _) => [[[[[fc cc ] lcc] lc] le] he]. + rewrite /generic_trajectories.simple_step. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno] def_case. + rewrite /inv1_seq /= in def_case. + move=> [] <- <- <- _ _ _ _. + by apply: def_case. +have infop : {subset fop <= open} by rewrite /open; subset_tac. +have sval1 : seq_valid fop (point e). + by apply/allP=> x xin; apply: (allP sval); apply: infop. +have rfo1 : s_right_form fop. + by apply/allP=> x xin; apply: (allP rfo); apply: infop. +have adj1 : adjacent_cells fop. + by move: adj; rewrite /open => /adjacent_catW[]. +have allnct1 : {in fop, forall c, ~contains_point (point e) c}. + case fop_eq : fop => [// | c1 fop1]. + have := above_all_cells sval1 adj1 rfo1. + have hfopq : high (last dummy_cell fop) = low lsto. + move: adj. + by rewrite /open fop_eq /= cat_path => /andP[] _ /= /andP[] /eqP. + move: palstol; rewrite hfopq=> -> /(_ isT) [] _ M. + by rewrite -fop_eq=> x xin; rewrite contains_pointE (negbTE (M x xin)) andbF. +have inlop : {subset lop <= open} by rewrite /open; subset_tac. +have lopclae : close_alive_edges lop (e :: future_events). + by apply/allP=> x xin; apply: (allP clae x); apply inlop. +have fop_note x : x \in fop -> + ~ event_close_edge (low x) e /\ ~ event_close_edge (high x) e. + move=> xin; apply: contrapositive_close_imp_cont. + - by apply: (allP rfo); rewrite /open; subset_tac. + - by apply/andP; apply: (allP sval); rewrite /open; subset_tac. + by apply: allnct1. +have fopclae : close_alive_edges fop (e :: future_events). + by apply/allP=> x xin; apply: (allP clae); rewrite /open; subset_tac. +move: (cle) => /= /andP[] cloe _. +case: ifP=> [eabove | ebelow]. + rewrite -/(open_cells_decomposition _ _). + case oe: (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. + rewrite /generic_trajectories.simple_step. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + have eabove' : point e >>> low (head dummy_cell lop). + have llopq : low (head dummy_cell lop) = lsthe. + apply: esym; rewrite lstheq. + move: (exi' eabove)=> [w + _]. + move: adj=> /adjacent_catW[] _. + by case: (lop) => [ // | ? ?] /andP[] /eqP. + by rewrite llopq. + have oe' : + open_cells_decomposition open (point e) = + (rcons fop lsto ++ fc', cc, lcc, lc, le, he). + move: adj rfo sval; rewrite /open -cat_rcons=> adj' rfo' sval'. + move: (open_cells_decomposition_cat adj' rfo' sval' (exi' eabove)). + by rewrite oe; apply. + move=> [] <- <- <- _ _ _ _. + have := invariant1_default_case. + by rewrite oe' oca_eq /= cat_rcons. +have /andP [vllsto vhlsto] : valid_edge (low lsto) (point e) && + valid_edge (high lsto) (point e). + by move: sval=> /allP/(_ lsto); rewrite /open; apply; subset_tac. +case: ifP => [ebelow_st {ebelow} | eonlsthe]. + rewrite -/(update_open_cell lsto e). + case uoceq : (update_open_cell lsto e) => [ nos lno] <-. + rewrite /invariant1 /= /state_open_seq /= -catA -cat_rcons. + move: uoceq; rewrite /update_open_cell/generic_trajectories.update_open_cell. + case ogq : (outgoing e) => [ | fog ogs] /=. + move=> -[] <- <- /=; rewrite inv1_seq_set_left_pts. + have := invariant1_default_case. + rewrite open_cells_decomposition_single=> //; last by rewrite -lstheq. + rewrite ogq /=. + do 2 rewrite -/(vertical_intersection_point _ _). + rewrite pvertE // pvertE //=; rewrite cats0. + rewrite -[pt_eqb _ _ (point e) _]/((point e) == _:> pt). + rewrite -[pt_eqb _ _ _ (point e)]/(_ == (point e):> pt). + have /negbTE -> : + (Bpt (p_x (point e)) (pvert_y (point e) (high lsto))) + != point e :> pt. + rewrite pt_eqE /= eqxx /=. + move: ebelow_st; rewrite -/(_ <<< _). + rewrite strict_under_pvert_y lstheq // lt_neqAle eq_sym. + by move=> /andP[]. + have /negbTE -> : + point e != Bpt (p_x (point e)) (pvert_y (point e) (low lsto)) :> pt. + rewrite pt_eqE /= eqxx /=. + by move: palstol; rewrite under_pvert_y // le_eqVlt negb_or=> /andP[]. + set w := [:: _ ; _; _]. + by rewrite (inv1_seq_set_pts fop lop lsto w nil). + have := invariant1_default_case. + rewrite open_cells_decomposition_single=> //; last by rewrite -lstheq. + rewrite -/(opening_cells_aux _ _ _ _). + rewrite ogq; case oca_eq: opening_cells_aux => [[| no0 nos'] lno']. + have ognn : (outgoing e) != [::] by rewrite ogq. + have := opening_cells_aux_absurd_case vlo vho ognn oute. + by rewrite ogq oca_eq. + by move => + [] <- <- /=; rewrite inv1_seq_set_left_pts cat_rcons -!catA /=. +have lsto_ctn : contains_point'(point e) lsto. + rewrite /contains_point'. + by rewrite -lstheq /point_under_edge (negbFE ebelow) abovelstle. +have exi2 : exists2 c, c \in (lsto :: lop) & contains_point' (point e) c. + by exists lsto; rewrite // inE eqxx. +case oe : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. +have := open_cells_decomposition_cat adj rfo sval exi2 palstol. +rewrite oe => oe'. +have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe' exi. +have [ocd' _] := decomposition_main_properties oe exi2. +have [fc'0 [lelsto [cc' ccq]]] : fc' = [::] /\ le = low lsto /\ + exists cc', cc = lsto :: cc'. + by have := last_step_situation oe pxhere (negbT eonlsthe) (negbFE ebelow). +rewrite /generic_trajectories.update_open_cell_top. +rewrite -/(open_cells_decomposition _ _). +rewrite oe. +case o_eq : (outgoing e) => [ | g l]; rewrite -?o_eq; last first. + rewrite -!/(open_cells_decomposition _ _). + have := invariant1_default_case; rewrite oe'. + rewrite -lelsto. + rewrite -!/(opening_cells_aux _ _ _ _). + case: (opening_cells_aux _ _ _ _) => [[ | fno nos] lno]. + move=> + <-; rewrite /invariant1 /state_open_seq /=. + by rewrite !cats0 -!catA. + move=> + <-; rewrite /invariant1 /state_open_seq /=. + rewrite -!catA /= => it. + by rewrite (catA fop) inv1_seq_set_left_pts -catA. +move=> [] <- <- <- _ _ _ _ /=. +have subf : {subset (fop ++ fc') <= open} by rewrite /open ocd; subset_tac. +have adjf : adjacent_cells (fop ++ fc'). + by move: adj; rewrite /open ocd=> /adjacent_catW[]. +have claef : close_alive_edges (fop ++ fc') (e :: future_events). + by apply/allP=> x xin; apply: (allP clae); apply: subf. +have rfof : s_right_form (fop ++ fc'). + by apply/allP=> x xin; apply: (allP rfo); apply: subf. +have svalf : seq_valid (fop ++ fc') (point e). + by apply/allP=> x xin; apply: (allP sval); apply: subf. +have subl : {subset (lsto :: lop) <= open}. + by rewrite /open; subset_tac. +have adjl : adjacent_cells (lsto :: lop). + by move: adj=> /adjacent_catW[]. +have rfol : s_right_form (lsto :: lop). + by apply/allP=> x xin; apply: (allP rfo); apply: subl. +have svall : seq_valid (lsto :: lop) (point e). + by apply/allP=> x xin; apply: (allP sval); apply: subl. +have cbtom' : cells.cells_bottom_top (low lsto) top (lsto :: lop). + move: cbtom; rewrite /open /cells.cells_bottom_top /cells_low_e_top eqxx //=. + by move=> /andP[] _; rewrite last_cat /=. +have [pal puh vl vh not_ct] := + decomposition_connect_properties rfo sval adj cbtom bet_e oe'. +have claef' : close_alive_edges (fop ++ fc') future_events. + elim/last_ind: {-1}(fop ++ fc') (erefl (fop ++ fc')) => [// | fc2 c2 _] f_eq. + have hc2q : high c2 = low (head lcc cc). + move: adj; rewrite /open ocd catA f_eq -cats1 -!catA=> /adjacent_catW[] _. + by rewrite ccq /= => /andP[] /eqP. + have palst : point e >>> high (last dummy_cell (fop ++ fc')). + by rewrite f_eq last_rcons hc2q -leq. + have [above_l above_h] := above_all_cells svalf adjf rfof palst. + have {}allabove_l : {in fop ++ fc', forall c, point e >>> low c}. + move=> c /mem_seq_split [s1 [s2 s_q]]. + elim/last_ind: {-1} (s1) (erefl s1) => [ | s1' c1 _] s1q. + by move: above_l; rewrite s_q s1q /=. + have : point e >>> high c1. + by rewrite above_h // s_q s1q cat_rcons; subset_tac. + have /eqP -> // : high c1 == low c. + move: adjf; rewrite s_q s1q -cats1 -catA /= => /adjacent_catW[] _. + by rewrite /= => /andP[]. + have f_not_end : forall c, c \in fop ++ fc' -> + ~ event_close_edge (low c) e /\ ~ event_close_edge (high c) e. + move=> c cin; apply: contrapositive_close_imp_cont. + - by apply: (allP rfof). + - by apply/andP; apply: (allP svalf). + by apply/negP; rewrite contains_pointE (negbTE (above_h _ cin)) andbF. + apply/allP=> x; rewrite -f_eq => xin. + by apply: (allP (head_not_end claef f_not_end)). +have clael : close_alive_edges lc (e :: future_events). + by apply/allP=> x xin; apply: (allP clae); rewrite /open ocd; subset_tac. +have clael' : close_alive_edges lc future_events. + case lc_eq : (lc) => [ // | c2 lc2]; rewrite -lc_eq. + have [puhlcc adj2] : point e <<< low (head dummy_cell lc) /\ + adjacent_cells lc. + move: adj; rewrite /open ocd lc_eq. + move=> /adjacent_catW[] _ /adjacent_catW[] _ /=. + by move=> /andP[] /eqP <- ->; rewrite -heq. + have sub2 : {subset lc <= open} by rewrite /open ocd; subset_tac. + have sval2 : seq_valid lc (point e). + by apply/allP=> x xin; apply: (allP sval); apply: sub2. + have rfo2 : s_right_form lc. + by apply/allP=> x xin; apply: (allP rfo); apply: sub2. + have below_h : {in lc, forall c, point e <<< high c}. + exact: (below_all_cells sval2 adj2 rfo2 puhlcc). + have below_l : {in lc, forall c, point e <<< low c}. + move=> c /mem_seq_split [s1 [s2 s_q]]. + elim/last_ind: {2}(s1) (erefl s1) => [ | s1' c1 _] s1_q. + by move: puhlcc; rewrite s_q s1_q /=. + move: adj2; rewrite s_q s1_q -cats1 -catA=> /adjacent_catW [] _ /=. + move=> /andP[]/eqP <- _; apply: below_h. + rewrite s_q s1_q cat_rcons; subset_tac. + have l_not_end : forall c, c \in lc -> + ~ event_close_edge (low c) e /\ ~ event_close_edge (high c) e. + move=> c cin; apply: contrapositive_close_imp_cont. + - by apply: (allP rfo2). + - by apply/andP; apply: (allP sval2). + by apply/negP; rewrite contains_pointE negb_and negbK (below_l _ cin). + apply/allP=> x xin. + by apply: (allP (head_not_end clael l_not_end)). +rewrite cats0 /invariant1 /state_open_seq /=; set open' := (X in inv1_seq X). +have clae_part : close_alive_edges open' future_events. + rewrite /close_alive_edges all_cat [all _ (fop ++ fc')]claef' /=. + rewrite [all _ lc]clael' andbT. + have le_end : end_edge_ext bottom top le future_events. + elim/last_ind: {-1} (fop ++ fc') (erefl (fop ++ fc')) => [ | fs c1 _] f_eq. + move: f_eq; case fop_eq: (fop) => [ | //]. + move: cbtom; rewrite /open fop_eq /= => /andP[] /andP[] _ /= /eqP + _. + by rewrite /end_edge_ext lelsto !inE => -> _; rewrite eqxx. + have <- : high c1 = le. + rewrite fc'0 cats0 in f_eq. + move: adj; rewrite /open f_eq -cats1 -catA=>/adjacent_catW[] _ /=. + by rewrite lelsto; move=> /andP[] /eqP. + apply: (proj2 (andP (allP claef' c1 _))). + by rewrite f_eq mem_rcons inE eqxx. + have he_end : end_edge_ext bottom top he future_events. + case lc_eq : lc => [ | c1 lc']. + have hetop : he = top. + move: cbtom=> /andP[] /andP[] _ _. + by rewrite /open ocd lc_eq !last_cat -heq /= => /eqP. + by rewrite /end_edge_ext hetop !inE eqxx ?orbT. + have hlccq : high lcc = low c1. + move: adj; rewrite /open ocd lc_eq. + by move=> /adjacent_catW[] _ /adjacent_catW[] _ /andP[] /eqP. + have c1in : c1 \in lc by rewrite lc_eq inE eqxx. + by have := (allP clael' _ c1in) => /andP[] + _; rewrite -hlccq -heq. + by rewrite -lelsto le_end he_end. +split=> //. +have vhe : valid_edge he (point e). + by have []:= decomposition_connect_properties rfo sval adj cbtom bet_e oe'. +split. + case futq : future_events => [ | e2 fut]; first by left. + have elexe2 : lexePt (point e) (point e2). + by apply/lexPtW; move: sort_evs; rewrite futq /= => /andP[]. + rewrite /seq_valid all_cat /= all_cat andbCA. + have e2lexfut : {in future_events, forall e, lexePtEv e2 e}. + move=> e'; rewrite futq inE=> /orP[/eqP ->|]; first by apply: lexePt_refl. + move=> e'in; apply/lexPtW; move: sort_evs; rewrite futq=> /= /andP[] _. + rewrite path_sortedE; last by move=> x y z; apply: lexPt_trans. + by move=> /andP[] /allP /(_ e') + _; apply. + have inbox_e2 : inside_box (point e2). + by apply: (@allP pt _ _ inbox_es); rewrite futq /= inE eqxx. + right. + apply/andP; split; last first. + rewrite -!all_cat fc'0 cats0; apply/allP=> x xin. + have /andP[vlx vhx] : + valid_edge (low x) (point e) && valid_edge (high x) (point e). + apply: (allP sval); rewrite /open ocd. + by move: xin; rewrite mem_cat=> /orP[] ?; subset_tac. + have /andP[eelx eehx] : + end_edge_ext bottom top (low x) future_events && + end_edge_ext bottom top (high x) future_events. + apply: (allP clae_part). + by rewrite /open'; move: xin; rewrite mem_cat=>/orP[] ?; subset_tac. + by rewrite !(valid_between_events elexe2 e2lexfut _ inbox_e2). + have eelo : end_edge_ext bottom top (low lsto) future_events. + have : end_edge_ext bottom top (low lsto) (e :: future_events). + by apply: (proj1 (andP (allP clae lsto _))). + rewrite /end_edge_ext /= => /orP[-> // | /orP[abs | ->]]; last first. + by rewrite !orbT. + by move: palstol; rewrite -(eqP abs) right_pt_below. + have eehe : end_edge_ext bottom top he future_events. + have : end_edge_ext bottom top (high lcc) (e :: future_events). + apply: (proj2 (andP (allP clae lcc _))). + by rewrite /open ocd; subset_tac. + rewrite /end_edge_ext heq /= => /orP[-> // | /orP[abs | ->]]; last first. + by rewrite orbT. + by move: puh; rewrite heq -(eqP abs) -[_ <<< _]negbK right_pt_above. + by rewrite !(valid_between_events elexe2 e2lexfut _ inbox_e2). +split. + case feq : fop => [ | c0 f]. + rewrite /open' feq fc'0 /=. + move: adj; rewrite /open ocd => /adjacent_catW[] _ /adjacent_catW[] _ /=. + by case: (lc)=> [ // | c2 lc'] /=; rewrite heq. + rewrite /open' -adjacent_cut /=; last by rewrite feq. + apply/andP; split. + apply/andP; split; last by move: adj; rewrite /open ocd=> /adjacent_catW. + rewrite fc'0 cats0; move: adj; rewrite /open feq /= cat_path /=. + by move=> /andP[] _ /andP[]. + move: adj; rewrite /open ocd=> /adjacent_catW[] _ /adjacent_catW[] _ /=. + by case: (lc) => [// | c2 l'] /=; rewrite heq. +have on0 : rcons cc lcc != nil by apply/eqP/rcons_neq0. +rewrite /open'. +set nc := Bcell _ _ _ _. +have nn0 : [:: nc] != nil by []. +split. + rewrite -(replacing_seq_cells_bottom_top _ _ _ _ on0 nn0). + - by rewrite cat_rcons -ocd. + - rewrite /nc /= head_rcons. + by rewrite -leq. + by rewrite /nc/= last_rcons. +rewrite /s_right_form all_cat /=; apply/andP; split. + by apply/allP=> x xin; apply: (allP rfo); rewrite /open ocd; subset_tac. +apply/andP; split; last first. + by apply/allP=> x xin; apply: (allP rfo); rewrite /open ocd; subset_tac. +have noclstohe : below_alt he (low lsto). + by apply: noc; rewrite /all_edges; subset_tac. +have := edge_below_from_point_under noclstohe vhe vlo (underW puh) palstol. +by []. +Qed. + +Lemma pairwise_subst {T : Type} [leT : rel T] (os ns s1 s2 : seq T) : + pairwise leT (s1 ++ os ++ s2) -> + pairwise leT ns -> + allrel leT s1 ns -> + allrel leT ns s2 -> + pairwise leT (s1 ++ ns ++ s2). +Proof. +rewrite !pairwise_cat !allrel_catr => /andP[] /andP[] _ -> /andP[] ->. +by move=>/andP[] _ /andP[] _ -> -> -> ->. +Qed. + +Lemma pairwise_subst1 {T : eqType} [leT : rel T] (oc nc : T)(s1 s2 : seq T) : + leT nc =1 leT oc -> leT^~ nc =1 leT^~ oc -> + pairwise leT (s1 ++ oc :: s2) = pairwise leT (s1 ++ nc :: s2). +Proof. +move=> l r. +by rewrite !(pairwise_cat, pairwise_cons, allrel_consr) (eq_all l) (eq_all r). +Qed. + +Lemma new_edges_above_first_old fc cc lcc lc le: + open = fc ++ cc ++ lcc :: lc -> + all (fun x => valid_edge x(point e)) + [seq high x | x <- fc ++ cc ++ lcc :: lc] -> + pairwise (@edge_below _) [seq high x | x <- fc ++ cc ++ lcc :: lc] -> + all ((@edge_below _)^~ le) [seq high x | x <- fc] -> + point e >>> le -> + point e <<< high lcc -> + valid_edge le (point e) -> + allrel (@edge_below _) + [seq high c | c <- fc] + [seq high c | c <- + opening_cells (point e) (outgoing e) le (high lcc)]. +Proof. +move=> ocd. +rewrite !map_cat !all_cat => /andP[] vfc /andP[] _ /= /andP[] vhe _. +move=> + fcbl pal puh vle. +rewrite !pairwise_cat=> /andP[] fcbcc /andP[] _ /andP[] /=. +rewrite allrel_consr=> /andP[] pw' _ /andP[] pw _. +rewrite /opening_cells. +case oca_eq : opening_cells_aux => [s c]. +have := opening_cells_aux_high vle vhe oute'; rewrite oca_eq /= => highsq. +have := opening_cells_aux_high_last vle vhe oute'; rewrite oca_eq /= => highcq. +rewrite -cats1 map_cat allrel_catr allrel_consr /=. +have -> : all ((@edge_below _)^~ (high c)) [seq high x | x <- fc]. + rewrite highcq; move: fcbcc; rewrite allrel_catr allrel_consr. + by move=> /andP[] _ /andP[]. +rewrite allrel0r. +have -> //: allrel (@edge_below _) [seq high x | x <- fc][seq high y | y <- s]. +rewrite highsq. +apply/allrelP=> x y xin yin. +have vx : valid_edge x (point e) by apply: (allP vfc). +have vy : valid_edge y (point e). + by apply: valid_edge_extremities; rewrite oute'. +have puy : point e <<= y. + by rewrite -(eqP (oute' yin)); apply: left_pt_below. +have xble : x <| le by apply: (allP fcbl). +have pax : point e >>> x. + apply/negP=> pux; case/negP: pal. + by apply: (order_edges_viz_point' vx vle xble pux). +have nocyx : below_alt y x. + apply: noc; rewrite ocd /all_edges/events_to_edges; last first. + by rewrite !(cell_edges_cat, mem_cat) ?xin ?orbT //. + rewrite /= mem_cat [X in (_ || X)]mem_cat. + by rewrite mem_sort in yin; rewrite yin !orbT. +by have := edge_below_from_point_under nocyx vy vx puy pax. +Qed. + +Lemma new_edges_below_last_old fc cc lcc lc le: + open = fc ++ cc ++ lcc :: lc -> + all (fun x => valid_edge x(point e)) + [seq high x | x <- fc ++ cc ++ lcc :: lc] -> + pairwise (@edge_below _) [seq high x | x <- fc ++ cc ++ lcc :: lc] -> + point e >>= le -> + point e <<< high lcc -> + valid_edge le (point e) -> + allrel (@edge_below _) + [seq high c | c <- + opening_cells (point e) (outgoing e) le (high lcc)] + [seq high c | c <- lc]. +Proof. +move=> ocd. +rewrite !map_cat !all_cat => /andP[] _ /andP[] _ /= /andP[] vhe vlc. +move=> + pal puh vle. +rewrite !pairwise_cat=> /andP[] _ /andP[] _ /andP[] _ /andP[] _. +rewrite /= => /andP[] heblc _. +rewrite /opening_cells. +case oca_eq : opening_cells_aux => [s c]. +have := opening_cells_aux_high vle vhe oute'; rewrite oca_eq /= => highsq. +have := opening_cells_aux_high_last vle vhe oute'; rewrite oca_eq /= => highcq. +rewrite -cats1 allrel_mapl allrel_catl /= allrel_consl allrel0l ?andbT. +rewrite highcq heblc andbT. +rewrite -allrel_mapl highsq; apply/allrelP=> x y /[dup] xin xin' yin. +rewrite mem_sort in xin'. +have vx: valid_edge x (point e) by apply valid_edge_extremities; rewrite oute'. +have vy: valid_edge y (point e) by apply: (allP vlc). +have highlccley : high lcc <| y by apply: (allP heblc). +have puy : point e <<< y. + by have := order_edges_strict_viz_point' vhe vy highlccley puh. +have pax : point e >>= x. + rewrite -(eqP (oute' xin)); apply left_pt_above. +have nocxy : below_alt x y. + apply: noc; rewrite /all_edges/events_to_edges/= ocd !mem_cat ?xin' ?orbT //. + by rewrite !map_cat /= !mem_cat !inE yin !orbT. +by have := edge_below_from_point_above nocxy vx vy pax puy. +Qed. + +Lemma step_keeps_pw_default : + let '(fc, cc, lcc, lc, le, he) := + open_cells_decomposition open (point e) in + let '(nos, lno) := + opening_cells_aux (point e) + (sort (@edge_below _) (outgoing e)) le he in + pairwise (@edge_below _) + (bottom :: [seq high x | x <- fc ++ nos ++ lno :: lc]). +Proof. +case oe: (open_cells_decomposition open (point e)) => + [[[[[fc cc] lcc] lc] le] he]. +have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] + := decomposition_main_properties oe exi. +have [pal puh vle vhe allnct] := + decomposition_connect_properties rfo sval adj cbtom bet_e oe. +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +have oc_eq : opening_cells (point e) (outgoing e) le he = rcons nos lno. + by rewrite /opening_cells oca_eq. +rewrite /=; apply/andP; split. + rewrite map_cat all_cat; apply/andP; split. + by move: pwo; rewrite ocd /= map_cat all_cat=> /andP[] /andP[] ->. + rewrite -cat_rcons map_cat all_cat; apply/andP; split; last first. + move: pwo; rewrite ocd /= !map_cat !all_cat /=. + by move=> /andP[] + _; do 3 move=> /andP[] _. + rewrite map_rcons all_rcons. + have := opening_cells_aux_high_last vle vhe oute'; rewrite oca_eq /= => ->. + have -> /= : bottom <| he. + have lcco : lcc \in open by rewrite ocd !mem_cat inE eqxx !orbT. + rewrite heq. + move: pwo=> /= /andP[] /allP /(_ (high lcc)) + _; rewrite map_f //. + by apply. + have := opening_cells_aux_high vle vhe oute'; rewrite oca_eq /= => ->. + apply/allP=> g; rewrite mem_sort=> gin. + have lgq : left_pt g = point e by apply/eqP/oute. + have vlg : valid_edge bottom (left_pt g). + by rewrite lgq; apply: (inside_box_valid_bottom inbox_e). +(* TODO : this should be made a top level lemma *) + have /no_crossingE : below_alt g bottom. + apply: noc. + by rewrite mem_cat /events_to_edges /= !mem_cat gin !orbT. + rewrite 2!mem_cat -orbA; apply/orP; left. + move: cbtom=> /andP[]; case: (open) => [ // | o1 op'] /= /eqP -> _. + by rewrite inE eqxx. + move=> /(_ vlg) [] _; apply. + by move: inbox_e=> /andP[] /andP[] + _ _; rewrite lgq. +rewrite -cat_rcons. +rewrite pairwise_map. +move: pwo; rewrite pairwise_cons ocd -cat_rcons pairwise_map=> /andP[] _ pwo'. +have vhocd : all ((@valid_edge _)^~ (point e)) + [seq high x | x <- fc ++ cc ++ lcc :: lc]. + by rewrite -ocd; apply/allP; apply: seq_valid_high. +move: (pwo'); rewrite cat_rcons -pairwise_map=> pwo2. +have puh' : point e <<< high lcc by rewrite -heq. +apply: (pairwise_subst pwo'); rewrite -?pairwise_map. +- rewrite -oc_eq. + have lein' : le \in all_edges open (e :: future_events). + by rewrite mem_cat lein. + have hein' : he \in all_edges open (e :: future_events). + by rewrite mem_cat hein. + by apply: opening_cells_pairwise. +- have : allrel (@edge_below _) [seq high x | x <- fc] + [seq high x | x <- rcons nos lno]. + have fcle : all ((@edge_below _)^~ le) [seq high x | x <- fc]. + apply/allP=> x /mapP[xc xcin xq]. + elim/last_ind : {-1} (fc) (erefl fc) => [ | fc' lfc _] fcq. + by move: xcin; rewrite fcq. + have := last_first_cells_high cbtom adj bet_e oe => <-. + rewrite fcq map_rcons last_rcons xq. + move: xcin; rewrite fcq mem_rcons inE=> /orP[/eqP -> | xcin ]. + by apply: edge_below_refl. + move: pwo'; rewrite pairwise_cat fcq pairwise_rcons=> /andP[] _ /andP[]. + by move=> /andP[] + _ _ => /allP /(_ xc xcin) /=. + have := new_edges_above_first_old ocd vhocd pwo2 fcle pal puh' vle. + by rewrite -oc_eq heq. + by rewrite allrel_mapr allrel_mapl. +have : allrel (@edge_below _) [seq high x | x <- rcons nos lno] + [seq high x | x <- lc]. + have := new_edges_below_last_old ocd vhocd pwo2 (underWC pal) puh' vle. + by rewrite -heq oc_eq. +by rewrite allrel_mapl allrel_mapr. +Qed. + +#[clearbody] +Let open_edge_valid x : + x \in cell_edges open -> valid_edge x (point e). +Proof. +by rewrite /cell_edges mem_cat => /orP[] /mapP [c /(allP sval) /andP[]+ + ->]. +Defined. + +Lemma step_keeps_pw : + pairwise (@edge_below _) + (bottom :: + [seq high x | x <- state_open_seq (step (Bscan fop lsto lop cls lstc + lsthe lstx) e)]). +Proof. +rewrite /step/=/generic_trajectories.simple_step. +case: ifP=> [pxaway | /negbFE/eqP/[dup] pxhere/abovelstle palstol]. + rewrite -/(open_cells_decomposition _ _). + case oe : (open_cells_decomposition (fop ++ lsto :: lop) (point e))=> + [[[[[fc cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + move: step_keeps_pw_default; rewrite /open. + by rewrite oe oca_eq /state_open_seq /= catA. +case: ifP=> [eabove | ebelow]. + rewrite -/(open_cells_decomposition _ _). + case oe: (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + have eabove' : point e >>> low (head dummy_cell lop). + have llopq : low (head dummy_cell lop) = lsthe. + apply: esym; rewrite lstheq. + move: (exi' eabove)=> [w + _]. + move: adj=> /adjacent_catW[] _. + by case: (lop) => [ // | ? ?] /andP[] /eqP. + by rewrite llopq. + have oe' : + open_cells_decomposition open (point e) = + (rcons fop lsto ++ fc', cc, lcc, lc, le, he). + move: adj rfo sval; rewrite /open -cat_rcons=> adj' rfo' sval'. + move: (open_cells_decomposition_cat adj' rfo' sval' (exi' eabove)). + by rewrite oe; apply. + have := step_keeps_pw_default; rewrite oe' oca_eq. + rewrite [state_open_seq _] + (_ : _ = (rcons fop lsto ++ fc') ++ nos ++ lno :: lc); last first. + by rewrite /state_open_seq /= cat_rcons !catA. + by apply. +case: ifP => [ebelow_st {ebelow} | eonlsthe]. + rewrite /state_open_seq /=. + rewrite /generic_trajectories.update_open_cell. + case oq : (outgoing e) => [ | fog ogs] /=. + rewrite cats0 map_cat /=; apply/andP; split. + move: pwo; rewrite pairwise_cons /open => /andP[] + _. + by rewrite map_cat. + move: pwo; rewrite pairwise_cons /open=> /andP[] _. + by rewrite map_cat /=. + have ocd : open_cells_decomposition open (point e) = + (fop, [::], lsto, lop, low lsto, high lsto). + by rewrite open_cells_decomposition_single; rewrite // -lstheq. + have same_left cg lpts : (fun c' => (edge_below (high cg) (high c'))) =1 + (fun c' => (edge_below (high (set_left_pts cg lpts))(high c'))). + by move=> c'; rewrite /set_left_pts /=. + have same_right cg lpts : (fun c' => edge_below (high c') (high cg)) =1 + (fun c' => edge_below (high c') (high (set_left_pts cg lpts))). + by move=> c'; rewrite /set_left_pts /=. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [[ | f s] c] /=. + rewrite cats0 -cat_rcons. + have:= step_keeps_pw_default. + rewrite ocd oq oca_eq /= cat_rcons !pairwise_map => pw. + have onn : outgoing e != [::] by rewrite oq. + have := opening_cells_aux_absurd_case vlo vho onn oute. + by rewrite oq oca_eq. + have := step_keeps_pw_default. + rewrite ocd oq oca_eq /= !pairwise_map => pw. + rewrite -catA /=. + apply/andP; split. + by move: pw=> /andP[] + _; rewrite !map_cat !all_cat /=. + have := @pairwise_subst1 _ + (fun c1 c2 => edge_below (high c1) (high c2)) f + (set_left_pts f [:: point e & behead (left_pts lsto)] +) fop (s ++ c :: lop) + (same_left f (point e :: behead (left_pts lsto))) + (same_right f (point e :: behead (left_pts lsto))) => <-. + by move: pw=> /andP[] _. +(* Now the point is on lsthe *) +(* Next12 lines duplicated from the end of step_keeps_invariant1 *) +have lsto_ctn : contains_point'(point e) lsto. + rewrite /contains_point'. + by rewrite -lstheq /point_under_edge (negbFE ebelow) abovelstle. +have exi2 : exists2 c, c \in (lsto :: lop) & contains_point' (point e) c. + by exists lsto; rewrite // inE eqxx. +case oe : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. +have := open_cells_decomposition_cat adj rfo sval exi2 palstol. + rewrite oe => oe'. +have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe' exi. +have [ocd' _] := decomposition_main_properties oe exi2. +have [fc'0 [lelsto [cc' ccq]]] : fc' = [::] /\ le = low lsto /\ + exists cc', cc = lsto :: cc'. + by have := last_step_situation oe pxhere (negbT eonlsthe) (negbFE ebelow). +rewrite /generic_trajectories.update_open_cell_top. +case o_eq : (outgoing e) => [ | g l]; rewrite -?o_eq; last first. +(* If there are outgoing edges, this cell is treated as in the default case. *) + have := step_keeps_pw_default. + rewrite -/(open_cells_decomposition _ _) oe' -lelsto. + rewrite oe. + rewrite -/(opening_cells_aux _ _ _ _). + case: (opening_cells_aux _ _ _ _) => [nos lno]. + case nosq : nos => [ | fno nos'] /=. + by rewrite /state_open_seq /= !cats0. + rewrite /state_open_seq /= catA -(catA (_ ++ _)) /= map_cat /= => it. + by rewrite map_cat /=. +rewrite -/(open_cells_decomposition _ _) oe /=. +have := step_keeps_pw_default; rewrite oe' -lelsto o_eq /=. +have vle : valid_edge le (point e) by apply: open_edge_valid. +have vhe : valid_edge he (point e) by apply: open_edge_valid. +do 2 rewrite -/(vertical_intersection_point _ _). +by rewrite pvertE // pvertE // !map_cat /= cats0. +Qed. + +Lemma update_open_cell_side_limit_ok new_op new_lsto: + update_open_cell lsto e = (new_op, new_lsto) -> + p_x (point e) = left_limit lsto -> + point e <<< high lsto -> + point e >>> low lsto -> + all open_cell_side_limit_ok (rcons new_op new_lsto). +Proof. +rewrite /update_open_cell/generic_trajectories.update_open_cell. +move=> + pxq puh pal /=. +have := (allP open_side_limit lsto lstoin). +rewrite /open_cell_side_limit_ok /= => /andP[] lptsno /andP[] alllpts. +move=> /andP[] slpts /andP[] athigh atlow. +case lptsq : (left_pts lsto) lptsno => [ // | p1 [ | p2 lpts']] _ /=. + rewrite lptsq /= in athigh atlow. + (* contradiction with puh pal *) + have pxe1 : p_x (point e) = p_x p1 by rewrite pxq /left_limit lptsq. + have := strict_under_edge_lower_y pxe1 athigh; rewrite puh=> /esym. + have := under_edge_lower_y pxe1 atlow; rewrite (negbTE pal)=>/esym. + move/negbT; rewrite -ltNge=> /lt_trans /[apply]. + by rewrite lt_irreflexive. +have pxe2 : p_x (point e) = p_x p2. + rewrite (eqP (allP alllpts p2 _)); last by rewrite lptsq !inE eqxx orbT. + exact pxq. +have p2lte : p_y p2 < p_y (point e). + have := lex_left_limit; rewrite lptsq /= => /andP[] + _. + by rewrite /lexPt pxe2 lt_irreflexive eqxx. +case ogq : (outgoing e) => [ | fog ogs]. + move=> [] <- <-; rewrite /= andbT /open_cell_side_limit_ok /=. + have pxel : p_x (point e) = p_x (last p2 lpts'). + by rewrite pxq /left_limit lptsq. + move: (alllpts); rewrite /left_limit. + rewrite lptsq /= => /andP[] -> /andP[] /[dup]/eqP p2x -> ->. + rewrite lptsq /= in athigh. + have pxe1 : p_x (point e) = p_x p1. + by have := alllpts; rewrite lptsq /= => /andP[] /eqP ->. + have := strict_under_edge_lower_y pxe1 athigh; rewrite puh=> /esym ye1. + move: (pxel) => /eqP ->; rewrite ye1. + move: slpts; rewrite lptsq /= => /andP[] _ ->. + by rewrite athigh; move: atlow; rewrite lptsq /= => ->; rewrite p2lte !andbT. +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq: (opening_cells_aux _ _ _ _) => [[ | fno nos] lno]. + have onn : outgoing e != [::] by rewrite ogq. + have := opening_cells_aux_absurd_case vlo vho onn oute. + by rewrite ogq oca_eq. +move=> -[] <- <- /=. +have ognn : outgoing e != [::] by rewrite ogq. +have := opening_cells_last_left_pts vlo vho oute ognn puh; rewrite /=. +rewrite ogq oca_eq /= => llnoq /=. +move: (alllpts); rewrite /left_limit. +rewrite lptsq /= => /andP[] _ /andP[] -> ->. +move: pxq; rewrite /left_limit lptsq /= => ->; rewrite eqxx /=. +rewrite p2lte /=. +have := allP open_side_limit lsto lstoin => /andP[] _ /andP[] _. +rewrite lptsq /= => /andP[] /andP[] _ -> /andP[] _ llo. +have := opening_cells_seq_edge_shift _ vlo vho oca_eq. +rewrite -ogq => /(_ oute') /= -[] <- _; rewrite llo andbT. +have := opening_cells_aux_high vlo vho oute'; rewrite ogq oca_eq /= => highout. +apply/andP; split. + have /oute'/eqP <- : high fno \in sort (@edge_below _) (outgoing e). + by rewrite ogq -highout inE eqxx. + by apply left_on_edge. +have := opening_cells_aux_side_limit vlo vho (underWC pal) puh oute'. +rewrite ogq oca_eq => /(_ _ _ erefl) allok. +by apply/allP=> x xin; apply: (allP allok x); rewrite /= inE xin orbT. +Qed. + +Lemma size_left_lsto : + p_x (point e) = lstx -> + point e >>> low lsto -> + point e <<= high lsto -> + (1 < size (left_pts lsto))%N. +Proof. +move=> pxhere pal puh. +have lstok : open_cell_side_limit_ok lsto by apply: (allP open_side_limit). +case lptsq : (left_pts lsto) => [ | p1 [ | p2 lpts]] //. + by move: lstok; rewrite /open_cell_side_limit_ok lptsq. +have /andP[p1onh p1onl] : (p1 === high lsto) && (p1 === low lsto). + by move: lstok; rewrite /open_cell_side_limit_ok /left_limit lptsq /= eqxx /=. +have samex : p_x (point e) = p_x p1. + by have := pxhere; rewrite lstxq /left_limit lptsq /=. +suff : p_y (point e) < p_y (point e) by rewrite lt_irreflexive. +have := same_pvert_y vho samex. +rewrite (on_pvert p1onh). +have := under_pvert_y vho; move: (puh)=> /[swap] -> /[swap] ->. +move=> /le_lt_trans; apply. +have := under_pvert_y vlo; move: (pal) => /[swap] ->. +rewrite (same_pvert_y vlo samex). +by rewrite -ltNge (on_pvert p1onl). +Qed. + +Lemma step_keeps_open_side_limit_default : + let '(fc, cc, lcc, lc, le, he) := + open_cells_decomposition open (point e) in + let '(nos, lno) := opening_cells_aux (point e) + (sort (@edge_below _) (outgoing e)) le he in + all open_cell_side_limit_ok ((fc ++ nos) ++ lno :: lc). +Proof. +case oe: (open_cells_decomposition open (point e)) => + [[[[[fc cc] lcc] lc] le] he]. +have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] + := decomposition_main_properties oe exi. +have [pal puh vle vhe allnct] := + decomposition_connect_properties rfo sval adj cbtom bet_e oe. +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +have oc_eq : opening_cells (point e) (outgoing e) le he = rcons nos lno. + by rewrite /opening_cells oca_eq. +have := opening_cells_side_limit vle vhe (underWC pal) puh oute. +rewrite /opening_cells oca_eq => oknew. +rewrite -catA -cat_rcons !all_cat andbCA; apply/andP; split; first by []. +have := open_side_limit; rewrite ocd -cat_rcons all_cat=> /andP[] -> /=. +by rewrite all_cat /= => /andP[]. +Qed. + +Lemma step_keeps_open_side_limit : + all open_cell_side_limit_ok + (state_open_seq (step (Bscan fop lsto lop cls lstc lsthe lstx) e)). +Proof. +rewrite /step/=/generic_trajectories.simple_step. +case: ifP=> [pxaway | /negbFE/eqP/[dup] pxhere/abovelstle palstol]. + rewrite -/(open_cells_decomposition _ _). + case oe : (open_cells_decomposition (fop ++ lsto :: lop) (point e))=> + [[[[[fc cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + by move: step_keeps_open_side_limit_default; rewrite /open oe oca_eq. +case: ifP=> [eabove | ebelow]. + rewrite -/(open_cells_decomposition _ _). + case oe: (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + have eabove' : point e >>> low (head dummy_cell lop). + have llopq : low (head dummy_cell lop) = lsthe. + apply: esym; rewrite lstheq. + move: (exi' eabove)=> [w + _]. + move: adj=> /adjacent_catW[] _. + by case: (lop) => [ // | ? ?] /andP[] /eqP. + by rewrite llopq. + have oe' : + open_cells_decomposition open (point e) = + (rcons fop lsto ++ fc', cc, lcc, lc, le, he). + move: adj rfo sval; rewrite /open -cat_rcons=> adj' rfo' sval'. + move: (open_cells_decomposition_cat adj' rfo' sval' (exi' eabove)). + by rewrite oe; apply. + move: step_keeps_open_side_limit_default; rewrite /open oe' oca_eq. + by rewrite /state_open_seq /= cat_rcons. +case: ifP => [ebelow_st {ebelow} | eonlsthe]. + rewrite /state_open_seq /=. + rewrite -/(update_open_cell _ _). + case uoc_eq : (update_open_cell lsto e) => [nos lno] /=. + have pxhere' : p_x (point e) = left_limit lsto by rewrite pxhere. + have puh : point e <<< high lsto by rewrite -lstheq. + have nosok := update_open_cell_side_limit_ok uoc_eq pxhere' puh palstol. + rewrite -catA -cat_rcons !all_cat nosok /= -all_cat. + by apply: (all_sub _ open_side_limit); rewrite /open; subset_tac. +move/negbFE:ebelow => ebelow. +move/negbT: eonlsthe=> eonlsthe. +rewrite -/(open_cells_decomposition _ _). +case oe : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. +have exi2 : exists2 c, c \in lsto :: lop & contains_point' (point e) c. + by exists lsto; [subset_tac | rewrite /contains_point' palstol -lstheq]. +have := open_cells_decomposition_cat adj rfo sval exi2 palstol. +have [fc'0 [lelsto _]] := + last_step_situation oe pxhere eonlsthe ebelow. +rewrite oe fc'0 lelsto cats0=> oe'. +rewrite /generic_trajectories.update_open_cell_top. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe' exi. +have lstok : open_cell_side_limit_ok lsto by apply: (allP open_side_limit). +have slpts : (1 < size (left_pts lsto))%N. + by apply: size_left_lsto=> //; rewrite -lstheq. +have [pal puh vle vhe ncont] := + decomposition_connect_properties rfo sval adj cbtom bet_e oe'. +case ogq : (outgoing e) => [ | fog ogs]; rewrite -?ogq; last first. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [[ | fno nos] lno]. + have ognn : outgoing e != [::] by rewrite ogq. + have := opening_cells_aux_absurd_case vlo vhe ognn oute. + by rewrite oca_eq. + have := step_keeps_open_side_limit_default; rewrite /open oe' oca_eq. + rewrite /state_open_seq -!catA /= !all_cat /= !all_cat=> /andP[] ->. + move=> /andP[] _ -> /=; rewrite andbT. + rewrite /open_cell_side_limit_ok /set_left_pts /=. + move: lstok=> /andP[]. + rewrite pxhere lstxq /left_limit. + case lptsq: (left_pts lsto) slpts=> [// | p1 [ // | p2 ps]] _ _ /=. + move=> /andP[] /andP[] _ /[dup] /andP[] x2q _ ->. + move=> /andP[] /andP[] + -> /andP[] _. + have := opening_cells_seq_edge_shift oute' vlo vhe oca_eq. + rewrite eqxx /= => -[] <- _. + move=> _ ->. + have := lex_left_limit; rewrite lptsq /= => /andP[] + _. + rewrite /lexPt lt_neqAle pxhere lstxq /left_limit lptsq /= x2q /= => ->. + have /oute/eqP <- : high fno \in outgoing e. + have := opening_cells_aux_high vlo vhe oute'; rewrite oca_eq /=. + by rewrite -(mem_sort (@edge_below _))=> <-; rewrite inE eqxx. + by rewrite !andbT /=; apply: left_on_edge. +(* Finished the case where there are some elements in outgoing e *) +rewrite /state_open_seq/= !cats0. +rewrite all_cat /=. +move: (open_side_limit); rewrite /open ocd !all_cat /=. +move=> /andP[] -> /andP[] _ /andP[] _ ->; rewrite /= ?andbT. +case lptsq : (left_pts lsto) slpts => [ | p1 [ | p2 lpts]] // _. +rewrite /open_cell_side_limit_ok /=. +have pxe : p_x (point e) = p_x (last p2 lpts). + by rewrite pxhere lstxq /left_limit lptsq /=. +rewrite pxe eqxx /=. +move: (lstok); rewrite /open_cell_side_limit_ok /left_limit lptsq /=. +move=> /andP[] /andP[] /[dup] /eqP p1x -> /andP[] -> ->. +move=> /andP[] /andP[] -> -> /andP[] p1on ->. +rewrite /= !andbT. +have p1e : p1 = (point e). + have samex : p_x (point e) = p_x p1. + by have := pxhere; rewrite lstxq /left_limit lptsq /= p1x. + have samey : p_y (point e) = p_y p1. + have eonlsthe' : point e === high lsto. + by apply: under_above_on=> //; rewrite -lstheq // ?underW. + exact: (on_edge_same_point eonlsthe' p1on samex). + by apply/esym/(@eqP pt); rewrite pt_eqE samex samey !eqxx. +rewrite p1e /generic_trajectories.pvert_y subrr -strict_under_pvert_y //. +by rewrite puh -pxe pvert_on. +Qed. + +Lemma disjoint_open : {in open &, disjoint_open_cells R}. +Proof. +by apply: disoc=> //; have := pwo; rewrite /= => /andP[]. +Qed. + +Lemma step_keeps_open_disjoint : + {in state_open_seq (step (Bscan fop lsto lop cls lstc lsthe lstx) e) &, + disjoint_open_cells R}. +Proof. +have := step_keeps_invariant1; rewrite /invariant1/inv1_seq. +set s' := (state_open_seq _) => -[clae' [sval' [adj' [cbtom' srf']]]]. +have := step_keeps_pw; rewrite -/s' => /= /andP[] _ pw'. +have := step_keeps_open_side_limit; rewrite -/s'=> ok'. +apply: disoc=>//. +Qed. + +Section arbitrary_closed. + +Variable old_closed : seq cell. + +Hypothesis disjoint_open_old_closed : + {in open & old_closed, disjoint_open_closed_cells R}. + +Hypothesis disjoint_old_closed : {in old_closed &, disjoint_closed_cells R}. +Hypothesis old_closed_right_limit : + {in old_closed, forall c, right_limit c <= p_x (point e)}. + +Lemma step_keeps_disjoint_default : + let '(fc, cc, lcc, lc, le, he) := + open_cells_decomposition open (point e) in + let '(nos, lno) := + opening_cells_aux (point e) + (sort (@edge_below _) (outgoing e)) le he in + let closed := closing_cells (point e) cc in + let last_closed := close_cell (point e) lcc in + let closed_cells := old_closed ++ rcons closed last_closed in + {in closed_cells &, disjoint_closed_cells R} /\ + {in fc ++ nos ++ lno :: lc & closed_cells, + disjoint_open_closed_cells R}. +Proof. +case oe : (open_cells_decomposition open (point e)) => + [[[[[fc cc] lcc] lc] le] he]. + have [ocd [lcc_ctn [all_ct [all_nct [flcnct + [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vle vhe ncont] + := connect_properties cbtom adj rfo sval bet_e ocd all_nct all_ct + lcc_ctn flcnct. +have allcont : all (contains_point (point e)) (rcons cc lcc). + by rewrite -cats1 all_cat /= lcc_ctn !andbT; apply/allP. +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +move=> closed last_closed closed_cells. +have svalcc : seq_valid (rcons cc lcc) (point e). + apply/allP=> c cin; apply: (allP sval); rewrite ocd !mem_cat. + move: cin; rewrite mem_rcons inE. + by move=> /orP[/eqP |] ->; rewrite ?inE ?eqxx ?orbT //. +have adjcc : adjacent_cells (rcons cc lcc). + by move: adj; rewrite ocd -cat_rcons =>/adjacent_catW[] _ /adjacent_catW[]. +have rfocc : s_right_form (rcons cc lcc). + apply/allP=> c cin; apply: (allP rfo); rewrite ocd !mem_cat. + move: cin; rewrite mem_rcons inE. + by move=> /orP[/eqP |] ->; rewrite ?inE ?eqxx ?orbT //. +have closed_map : closing_cells (point e) (rcons cc lcc) = + rcons [seq close_cell (point e) c | c <- cc] + (close_cell (point e) lcc). + by rewrite /closing_cells map_rcons. +have ccok : all open_cell_side_limit_ok (rcons cc lcc). + apply/allP=> c cin; apply: (allP open_side_limit); rewrite ocd !mem_cat. + move: cin; rewrite mem_rcons inE. + by move=> /orP[/eqP |] ->; rewrite ?inE ?eqxx ?orbT //. +have := closing_cells_side_limit' rfocc svalcc adjcc ccok allcont. +rewrite head_rcons pal last_rcons puh=> /(_ isT isT). +rewrite [X in all _ X]closed_map=> /allP cl_sok. +have oldcl_newcl : + {in old_closed & closing_cells (point e) (rcons cc lcc), + disjoint_closed_cells R}. + move=> c1 c2 c1in; rewrite closed_map -map_rcons=> /mapP[c2' c2'in c2eq]. + have c2'open : c2' \in open. + by rewrite ocd -cat_rcons !mem_cat c2'in !orbT. + have vc2 : valid_cell c2' (point e) by apply/andP/(allP sval). + right; rewrite /c_disjoint=> q; apply/negP=> /andP[inc1 inc2]. + rewrite c2eq in inc2. + case/negP:(disjoint_open_old_closed c2'open c1in q). + rewrite inc1 andbT. + apply:(close'_subset_contact vc2 _ inc2). + by move: (cl_sok c2); rewrite c2eq; apply; rewrite -map_rcons; apply: map_f. +split. + move=> c1 c2; rewrite !mem_cat. + move=> /orP[c1old | c1new] /orP[c2old | c2new]. + by apply: disjoint_old_closed. + by apply: oldcl_newcl; rewrite // closed_map. + apply: c_disjoint_eC; apply: oldcl_newcl; first by []. + by rewrite closed_map. + rewrite -map_rcons in c1new c2new. + move: c1new c2new => /mapP[c1' c1'in c1eq] /mapP[c2' c2'in c2eq]. + have c1'open : c1' \in open by rewrite ocd -cat_rcons !mem_cat c1'in orbT. + have c2'open : c2' \in open by rewrite ocd -cat_rcons !mem_cat c2'in orbT. + have vc1 : valid_cell c1' (point e) by apply/andP/(allP sval). + have vc2 : valid_cell c2' (point e) by apply/andP/(allP sval). + have [/eqP c1c2 | c1nc2] := boolP(c1' == c2'). + by left; rewrite c1eq c2eq c1c2. + right=> q; apply/negP=> /andP[inc1 inc2]. + case: (disjoint_open c1'open c2'open)=> [/eqP | /(_ q)]. + by rewrite (negbTE c1nc2). + move=> /negP[]. + rewrite c1eq in inc1; rewrite c2eq in inc2. + rewrite (close'_subset_contact vc1 _ inc1); last first. + by apply: cl_sok; rewrite -map_rcons; apply: map_f. + rewrite (close'_subset_contact vc2 _ inc2) //. + by apply: cl_sok; rewrite -map_rcons; apply: map_f. +rewrite -leq in vle; rewrite -heq in vhe. +move=> c1 c2; rewrite -cat_rcons 2!mem_cat orbCA=> /orP[c1newo |c1old] c2in. + have rlc2 : right_limit c2 <= p_x (point e). + move: c2in; rewrite /closed_cells mem_cat. + move=> /orP[/old_closed_right_limit // |]. + rewrite -map_rcons=> /mapP[c2' c2'in ->]. + by rewrite close_cell_right_limit //; apply/andP/(allP svalcc). + move=> q; rewrite inside_open'E inside_closed'E; apply/negP. + move=> /andP[] /andP[] _ /andP[] _ /andP[] + _ + /andP[] _ /andP[] _ /andP[] _ +. + have := opening_cells_left oute vle vhe. + rewrite /opening_cells oca_eq=> /(_ _ c1newo) => -> peq qrlc2. + by move: rlc2; rewrite leNgt=>/negP[]; apply: (lt_le_trans peq). +have c1open : c1 \in open by rewrite ocd -cat_rcons !mem_cat orbCA c1old orbT. +move: c2in; rewrite /closed_cells mem_cat=>/orP[c2old |]. + by apply: disjoint_open_old_closed. +rewrite -map_rcons=> /mapP[c2' c2'in c2eq] q; apply/negP=> /andP[] inc1 inc2. +have c2'open : c2' \in open by rewrite ocd -cat_rcons !mem_cat c2'in !orbT. +have [c1eqc2 | disjc1c2] := disjoint_open c1open c2'open. + case (negP (ncont _ c1old)). + rewrite c1eqc2. + by move: c2'in; rewrite mem_rcons inE=> /orP[/eqP -> | /all_ct]. +move: (disjc1c2 q); rewrite inc1 //=. +have vc2 : valid_cell c2' (point e) by apply/andP/(allP sval). +rewrite c2eq in inc2. +rewrite (close'_subset_contact vc2 _ inc2) //. +by apply: cl_sok; rewrite -map_rcons; apply: map_f. +Qed. + +End arbitrary_closed. + +Lemma bottom_edge_below : {in cell_edges open, forall g, bottom <| g}. +Proof. +move: pwo=> /= /andP[] /allP pwo' _ g. +rewrite (cell_edges_sub_high cbtom adj) inE=> /orP[/eqP -> | /pwo' //]. +by apply: edge_below_refl. +Qed. + +Definition state_closed_seq (s : scan_state) := + rcons (sc_closed s) (lst_closed s). + +Lemma adjacent_update_open_cell new_op new_lsto: + update_open_cell lsto e = (new_op, new_lsto) -> + low lsto = low (head dummy_cell (rcons new_op new_lsto)) /\ + high lsto = high (last dummy_cell (rcons new_op new_lsto)) /\ + adjacent_cells (rcons new_op new_lsto). +Proof. +rewrite /update_open_cell/generic_trajectories.update_open_cell. +case o_eq : (outgoing e) => [ | g os]. + by move=> [] <- <- /=. +rewrite -o_eq. +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq : (opening_cells_aux _ _ _ _) => [[ // | fno nos] lno] [] <- <-. + have onn : outgoing e != [::] by rewrite o_eq. + by have := opening_cells_aux_absurd_case vlo vho onn oute; rewrite oca_eq. +rewrite /= last_rcons. +have [/= A ->] := adjacent_opening_aux vlo vho oute' oca_eq. +split;[ | split]=> //=. + have := opening_cells_aux_high_last vlo vho oute'. + by rewrite oca_eq /=. +by move: A; case : (nos). +Qed. + +Lemma low_all_edges c evs: c \in open -> low c \in all_edges open evs. +Proof. by move=> cin; rewrite !mem_cat map_f ?orbT. Qed. + +Lemma high_all_edges c evs: c \in open -> high c \in all_edges open evs. +Proof. by move=> cin; rewrite !mem_cat map_f ?orbT. Qed. + +Lemma update_open_cell_right_form new_op new_lsto: + update_open_cell lsto e = (new_op, new_lsto) -> + point e <<< high lsto -> + point e >>> low lsto -> + s_right_form (rcons new_op new_lsto). +Proof. +move=> + puho palo. +have noco : below_alt (low lsto) (high lsto). + apply: noc; first by apply: low_all_edges; rewrite /open; subset_tac. + by apply: high_all_edges; rewrite /open; subset_tac. +have rflsto : low lsto <| high lsto. + by apply: (edge_below_from_point_above noco vlo vho (underWC _)). +rewrite /update_open_cell/generic_trajectories.update_open_cell. +have srt : path (@edge_below _) (low lsto) (sort (@edge_below _) (outgoing e)). + apply: (sorted_outgoing vlo vho palo puho oute). + apply: sub_in2 noc=> x; rewrite 2!inE => /orP[/eqP ->|/orP[/eqP ->|]] //. + by apply: subo. +case ogeq : (outgoing e) => [ | g os]. + move=> [] <- <- /=; rewrite andbT. + by apply: (edge_below_from_point_above noco vlo vho (underWC _)). +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq : (opening_cells_aux _ _ _ _) => [[ | fno nos] lno]. + move=> [] <- <- /=; rewrite andbT. + rewrite -ogeq /= in oca_eq. + have /= := opening_cells_aux_right_form (underWC palo) + puho vlo vho loin hoin rflsto oute' noc subo' srt oca_eq. + by rewrite andbT. +move=> [] <- <- /=. +rewrite -ogeq /= in oca_eq. +by have /= := opening_cells_aux_right_form (underWC palo) +puho vlo vho loin hoin rflsto oute' noc subo' srt oca_eq. +Qed. + +Lemma update_open_cell_end_edge new_op new_lsto : + end_edge_ext bottom top (low lsto) future_events -> + end_edge_ext bottom top (high lsto) future_events -> + valid_edge (low lsto) (point e) -> + valid_edge (high lsto) (point e) -> + update_open_cell lsto e = (new_op, new_lsto) -> + {in rcons new_op new_lsto, forall x, + end_edge_ext bottom top (low x) future_events && + end_edge_ext bottom top (high x) future_events}. +Proof. +move=> endl endh vl vh. +rewrite /update_open_cell/generic_trajectories.update_open_cell. +case ogeq : (outgoing e) => [ | fog ogs]. + move=> [] <- <- /= x; rewrite inE=> /eqP -> /=. + by rewrite endl endh. +move: cle; rewrite /= => /andP[] cloe _. +have cllsto := opening_cells_close vl vh oute endl endh cloe => {cloe}. +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq : (opening_cells_aux _ _ _ _) => [[ | fno nos] lno]. + have onn : outgoing e != [::] by rewrite ogeq. + have := opening_cells_aux_absurd_case vlo vho onn oute. + by rewrite ogeq oca_eq. +move=> -[] <- <- /= x; rewrite inE=> /orP[/eqP -> | xin]. + by rewrite /=; apply: (allP cllsto); rewrite /opening_cells ogeq oca_eq /=; + subset_tac. +by apply: (allP cllsto); rewrite /opening_cells ogeq oca_eq /= inE xin orbT. +Qed. + +Lemma update_open_cell_end_edge' c nos lno : + valid_edge (low c) (point e) -> + valid_edge (high c) (point e) -> + update_open_cell c e = (nos, lno) -> + close_alive_edges (rcons nos lno) future_events = + close_alive_edges (opening_cells (point e) (outgoing e) + (low c) (high c)) future_events. +Proof. +move=> vlc vhc; rewrite /update_open_cell/generic_trajectories.update_open_cell. +case ogeq : (outgoing e) => [ | fog ogs]. + move=> -[] <- <- /=. + rewrite /opening_cells /=. + rewrite -/(vertical_intersection_point _ _) /= pvertE //. + by rewrite -/(vertical_intersection_point _ _) pvertE. +rewrite /opening_cells /=. +have onn : outgoing e != [::] by rewrite ogeq. +have := opening_cells_aux_absurd_case vlc vhc onn oute; rewrite ogeq. +rewrite -/(opening_cells_aux _ _ _ _). +by case oca_eq : (opening_cells_aux _ _ _ _) => [[ | ? ?] ?] + [] <- <- /=. +Qed. + +(* Lemma update_open_cell_valid c nos lno : + valid_edge (low c) (point e) -> + valid_edge (high c) (point e) -> + update_open_cell c e = (nos, lno) -> + seq_valid (rcons nos lno) p = + seq_valid (opening_cells (point e) (outgoing e) (low c) (high c)) p. +Proof. +move=> vlc vhc; rewrite /update_open_cell/generic_trajectories.update_open_cell. +case ogeq : (outgoing e) => [ | fog ogs]. + move=> -[] <- <- /=. + rewrite /opening_cells /= -/(vertical_intersection_point _ _) pvertE //. + by rewrite -/(vertical_intersection_point _ _) pvertE. +rewrite /opening_cells /=. +have onn : outgoing e != [::] by rewrite ogeq. +have := opening_cells_aux_absurd_case vlc vhc onn oute; rewrite ogeq. +rewrite -/(opening_cells_aux _ _ _ _). +by case oca_eq : (opening_cells_aux _ _ _ _) => [[ | ? ?] ?] + [] <- <- /=. +Qed. +*) +Lemma lex_left_pts_inf' : + let '(fc, _, _, lc, le, he) := + open_cells_decomposition open (point e) in + let '(nos, lno) := + opening_cells_aux (point e) (sort (@edge_below _) (outgoing e)) le he in + {in fc ++ nos ++ lno :: lc, + forall c, lexePt (bottom_left_corner c) (point e)}. +Proof. +case oe : (open_cells_decomposition _ _) => [[[[[fc cc] lcc] lc] le] he]. +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +have [ocd [_ [_ [_ [_ [leq [heq [lein hein]]]]]]]]:= + decomposition_main_properties oe exi. +have [pal puh vle vhe A']:= decomposition_connect_properties rfo sval adj cbtom + bet_e oe. +have sublehe : {subset rcons (le :: sort (@edge_below _) (outgoing e)) he <= + all_edges open (e :: future_events)}. + move=> x; rewrite mem_rcons inE => /orP[/eqP -> | ]. + by rewrite /all_edges; subset_tac. + rewrite inE=> /orP[/eqP -> | ]. + by rewrite /all_edges; subset_tac. + by apply: subo'. +have noc2: + {in rcons (le :: sort (@edge_below _) (outgoing e)) he &, no_crossing R}. + by move=> x y xin yin; apply: noc; apply: sublehe. +move=> x; rewrite !(mem_cat, inE) => /orP[xfc | ]. + by apply: lexPtW; apply: btom_left_corners; rewrite ocd; subset_tac. +rewrite orbA=> /orP[xin | xlc]; last first. + apply: lexPtW. + apply: btom_left_corners; rewrite ocd; subset_tac. +have noclh : below_alt le he. + by apply: noc2; rewrite ?(mem_rcons, inE) eqxx ?orbT. +have lebhe : le <| he. + apply: (edge_below_from_point_above noclh vle vhe (underWC pal) puh). +have := opening_cells_last_lexePt oute (underWC pal) puh vle vhe noc2 lebhe. +rewrite /opening_cells oca_eq; apply. +by rewrite mem_rcons inE orbC. +Qed. + +Lemma step_keeps_btom_left_corners_default q : + lexPt (point e) q -> + let '(fc, _, _, lc, le, he) := + open_cells_decomposition open (point e) in + let '(nos, lno) := + opening_cells_aux (point e) (sort (@edge_below _) (outgoing e)) le he in + {in fc ++ nos ++ lno :: lc, forall c, lexPt (bottom_left_corner c) q}. +Proof. +move=> lexq. +case oe : (open_cells_decomposition _ _) => [[[[[fc cc] lcc] lc] le] he]. +case oca_eq: (opening_cells_aux _ _ _ _) => [nos lno]. +have := lex_left_pts_inf'; rewrite oe oca_eq => main. +by move=> x xin; apply: lexePt_lexPt_trans lexq; apply: main. +Qed. + +Lemma leftmost_points_max : + open_cell_side_limit_ok (start_open_cell bottom top) -> + left_limit (start_open_cell bottom top) = + max (p_x (left_pt bottom)) (p_x (left_pt top)). +Proof. +rewrite /start_open_cell/generic_trajectories.start_open_cell /leftmost_points => /andP[] /=. +rewrite R_ltb_lt. +case: ltrP => cmpl. + rewrite -/(vertical_intersection_point _ _). + case peq: (vertical_intersection_point (left_pt top) bottom) => [p' | //]. + move=> _ /andP[] samex _ /=. + move: peq. + rewrite /vertical_intersection_point/generic_trajectories.vertical_intersection_point. + by case: ifP=> // ve [] <-. +rewrite -/(vertical_intersection_point _ _). +case peq: (vertical_intersection_point (left_pt bottom) top)=> [p' | //] _. +by case: ifP=> [/eqP A | B]; move=> /andP[]. +Qed. + +Lemma trial1 c1 c2 : + below_alt (high c1) (low c2) -> + open_cell_side_limit_ok c1 -> + open_cell_side_limit_ok c2 -> + valid_edge (high c1) (point e) -> + valid_edge (low c2) (point e) -> + pvert_y (point e) (high c1) < pvert_y (point e) (low c2) -> + o_disjoint c1 c2. +Proof. +move=> noc12 ok1 ok2 vhc1 vlc2 cmpc1c2 q; apply/andP=>-[]. +move=> /andP[]inc1 _ /andP[] inc2 /andP[] str2 _. +have /andP[_ vhc1q] := inside_open_cell_valid ok1 inc1. +have /andP[vlc2q _] := inside_open_cell_valid ok2 inc2. +move: (inc1)=> /andP[] /andP[] _ qh1 _. +have := transport_above_edge noc12 vhc1 vlc2 vhc1q vlc2q cmpc1c2 str2. +rewrite /point_under_edge. +by rewrite qh1. +Qed. + +Lemma trial2 c1 c2 : + high c1 <| low c2 -> + open_cell_side_limit_ok c1 -> + open_cell_side_limit_ok c2 -> + valid_edge (high c1) (point e) -> + valid_edge (low c2) (point e) -> + o_disjoint c1 c2. +Proof. +move=> c1bc2 ok1 ok2 v1 v2 q; apply/negP=> /andP[]. +move=>/andP[] /andP[] /andP[] _ qbh1 /andP[] _ inx /andP[] _ stricterx. +have inx' : left_limit c1 < p_x q <= open_limit c1. + by rewrite stricterx inx. +move: inx' {inx stricterx} => /(valid_high_limits ok1) vqhc1. +move=>/andP[] /andP[] _ /andP[] _ inx /andP[] qalc2 stricterx. +have inx' : left_limit c2 < p_x q <= open_limit c2. + by rewrite stricterx inx. +move: inx' {inx stricterx} => /(valid_low_limits ok2) vqlc2. +rewrite (under_pvert_y vqlc2) -ltNge in qalc2. +rewrite -/(point_under_edge _ _) in qbh1. +rewrite (under_pvert_y vqhc1) in qbh1. +have /pvert_y_edge_below : pvert_y q (low c2) < pvert_y q (high c1). + by apply: (lt_le_trans qalc2 qbh1). +by move=> /(_ vqlc2 vqhc1) /negP; apply. +Qed. + +Lemma lexPt_left_pt_strict_under_edge_to_p_x (pt : pt) g: + valid_edge g pt -> lexPt (left_pt g) pt -> pt <<< g -> + p_x (left_pt g) < p_x pt. +Proof. +move=> vg. +rewrite /lexPt eq_sym=> /orP[ | /andP[] /eqP samex]; first by []. +have := same_pvert_y vg samex. +rewrite (on_pvert (left_on_edge g))=> <-. +rewrite ltNge le_eqVlt negb_or andbC. +by move=> /[swap]; rewrite strict_under_pvert_y // => ->. +Qed. + +Lemma pvert_y_right_pt (g : edge) : pvert_y (right_pt g) g = p_y (right_pt g). +Proof. apply/on_pvert/right_on_edge. Qed. + +Lemma inside_box_sorted_le : + sorted <=%R [seq pvert_y (point e) (high c) | c <- extra_bot :: open]. +Proof. +have adj' : adjacent_cells (extra_bot :: open). + rewrite /=; move: cbtom=> /andP[] /andP[]; case: (open) adj => // o1 os + _. + by move=> /= -> /eqP ->; rewrite eqxx. +apply adjacent_right_form_sorted_le_y => //=. + rewrite andbb; apply/andP; split=> //. + by apply: (inside_box_valid_bottom_top inbox_e)=> //; rewrite inE eqxx. +by rewrite edge_below_refl. +Qed. + +Lemma head_cat [T : eqType] (s1 s2 : seq T) (a : T): + s1 != nil -> head a (s1 ++ s2) = head a s1. +Proof. by case : s1 => [ | b s1]. Qed. + +(* This is not used, just now. *) +Lemma left_limit_closing_cells (cc : seq cell) (p1 : pt) : + adjacent_cells cc -> seq_valid cc p1 -> + p1 >>> low (head_cell cc) -> p1 <<< high (last_cell cc) -> + all (contains_point p1) cc -> + [seq left_limit i | i <- closing_cells p1 cc] = [seq left_limit i | i <- cc]. +Proof. +move=> adjcc svalcc pale puhe allcont. +rewrite /closing_cells. +rewrite -map_comp; rewrite -eq_in_map /close_cell => -[] ls rs lo hi cin /=. +move: (allP svalcc _ cin) => /= /andP[] vloc vhic. +by rewrite (pvertE vloc) (pvertE vhic). +Qed. + +Definition set_right_pts (c : cell) (l : seq pt) := + Bcell (left_pts c) l (low c) (high c). + +Lemma inside_closed_set_right_pts (c : cell) l q: + last dummy_pt (right_pts c) = last dummy_pt l -> + inside_closed' q c = inside_closed' q (set_right_pts c l). +Proof. +rewrite /inside_closed' /set_right_pts /inside_closed_cell /contains_point /=. +by rewrite /right_limit /= => ->. +Qed. + +Lemma update_closed_cell_keeps_right_limit c pt : + (1 < size (right_pts c))%N -> + closed_cell_side_limit_ok c -> + right_limit (update_closed_cell c pt) = + right_limit c. +Proof. +move=> non_empty. +do 5 move=> /andP[_]; move=> /andP[ptsn0 /andP[/allP allx _]]. +rewrite /update_closed_cell /right_limit /=. +move: non_empty. +by case: (right_pts c) => [ | hr [ | r2 rpts]]. +Qed. + +Lemma inside_closed'_update q1 q: + inside_closed' q lstc = inside_closed' q (update_closed_cell lstc q1). +Proof. +have samer : last dummy_pt (right_pts lstc) = + last dummy_pt (head dummy_pt (right_pts lstc) :: q1 :: + (behead (right_pts lstc))). + move: non_empty_right. + by case : (right_pts lstc) => [ // | hr [ // | r2 rpts]]. +rewrite /update_closed_cell. +have := inside_closed_set_right_pts q samer. +rewrite /set_right_pts /=. +by rewrite /set_right_pts /= => <- //. +Qed. + +Definition update_pts_head (l : seq pt) (p : pt) := + p :: behead l. + +Definition update_pts_single (l : seq pt) (p : pt) := + head dummy_pt l :: p :: behead l. + +Lemma update_open_cell_outgoing_empty c (lo : seq cell * cell) : + valid_edge (low c) (point e) -> + valid_edge (high c) (point e) -> + open_cell_side_limit_ok c -> + p_x (point e) = left_limit c -> + (1 < size (left_pts c))%N -> + point e >>> low c -> + point e <<< high c -> +outgoing e = [::] -> + update_open_cell c e = + ([::], set_left_pts + c (update_pts_single (left_pts c) (point e))). +Proof. +intros vl vh okc xq lptsgt pal puh ogq. +by rewrite /update_open_cell/generic_trajectories.update_open_cell ogq. +Qed. + +Lemma update_open_cell_tail c (lo : seq cell * cell) : + valid_edge (low c) (point e) -> + valid_edge (high c) (point e) -> + open_cell_side_limit_ok c -> + p_x (point e) = left_limit c -> + (1 < size (left_pts c))%N -> + point e >>> low c -> + point e <<< high c -> + outgoing e != [::] -> + behead (rcons (update_open_cell c e).1 + (update_open_cell c e).2) = + behead (opening_cells (point e) (outgoing e) (low c) (high c)). +Proof. +move=> vl vh cok at_x lgt1 pal puh on0. +rewrite /update_open_cell/generic_trajectories.update_open_cell. +case ogq : (outgoing e) => [ | fog ogs]; first by rewrite ogq in on0. +case oca_eq : generic_trajectories.opening_cells_aux => [nos lno]. +have son0 : (fog :: ogs) != [::] by []. +have oute2 : {in fog :: ogs, + forall g, left_pt g == point e}. + by rewrite -ogq. +have := opening_cells_aux_absurd_case vl vh son0 oute2. +rewrite /opening_cells_aux oca_eq /=. +case nosq : nos => [ | fno nos']; first by []. +move=> _ /=. +by rewrite /opening_cells/opening_cells_aux oca_eq nosq. +Qed. + +Lemma update_open_cellE1 c c1 : + valid_edge (low c) (point e) -> + valid_edge (high c) (point e) -> + open_cell_side_limit_ok c -> + p_x (point e) = left_limit c -> + (1 < size (left_pts c))%N -> + point e >>> low c -> + point e <<< high c -> + c1 \in (update_open_cell c e).1 -> + exists2 c', c' \in (opening_cells_aux (point e) + (sort (@edge_below _) (outgoing e)) (low c) + (high c)).1 & + c1 = c' \/ + exists2 l, last dummy_pt l = last dummy_pt (left_pts c') & + c1 = set_left_pts c' l. +Proof. +move=> vle vhe cok xcond sl pal puh. +rewrite /update_open_cell/generic_trajectories.update_open_cell. +case ogq : (outgoing e) => [ | fog ogs] //=. +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq : (opening_cells_aux _ _ _ _) => [ [// | fno nos] lno] /=. +rewrite inE => /orP[/eqP -> | ]. + exists fno; first by rewrite inE eqxx. + right; exists (point e :: behead (left_pts c)). + case lptsq : (left_pts c) sl => [ // | p1 [ // | p2 lpts]] _ /=. + move: cok; rewrite /open_cell_side_limit_ok=> /andP[] _ /andP[] allx. + move=> /andP[] _ /andP[] _; rewrite lptsq /=. + have oute2 : {in (fog :: ogs), + forall g, left_pt g == point e}. + by rewrite -ogq; exact oute. + have oute3 : {in sort (@edge_below _) (fog :: ogs), + forall g, left_pt g == point e}. + by move=> g; rewrite mem_sort; apply: oute2. + have := opening_cells_side_limit vle vhe (underWC pal) puh oute2. + rewrite /opening_cells oca_eq=> /allP /(_ fno). + rewrite inE eqxx=> /(_ isT)=> /andP[] _ /andP[] _ /andP[] _ /andP[] _. + have := opening_cells_first_left_pts (high c) vle _ pal. + rewrite ogq oca_eq => /(_ isT) /= -> /=. + have [_ /= ] := adjacent_opening_aux vle vhe oute3 oca_eq => ->. + rewrite /=. + move=> /on_edge_same_point /[apply] /=. + rewrite xcond /left_limit lptsq /= => /(_ erefl) ->. + by apply/(@eqP pt); rewrite pt_eqE /= !eqxx. + by []. +move=> c1in; exists c1; first by rewrite inE c1in orbT. +by left. +Qed. + +Lemma update_open_cellE2 c : + valid_edge (low c) (point e) -> + valid_edge (high c) (point e) -> + open_cell_side_limit_ok c -> + p_x (point e) = left_limit c -> + (1 < size (left_pts c))%N -> + point e >>> low c -> + point e <<< high c -> + (update_open_cell c e).2 = + (opening_cells_aux (point e) (sort (@edge_below _) (outgoing e)) (low c) + (high c)).2 \/ + (update_open_cell c e).2 = + (set_left_pts c (head dummy_pt + (left_pts c) :: point e :: behead (left_pts c))). +Proof. +move=> vle vhe cok xcond sl pal puh. +rewrite /update_open_cell/generic_trajectories.update_open_cell. +case ogq : (outgoing e)=> [ | fog ogs]; first by right. +left; rewrite -ogq. +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq : (opening_cells_aux _ _ _ _) => [ [ | fno nos] lno] //=. +have ognn : outgoing e != [::] by rewrite ogq. +have := opening_cells_aux_absurd_case vle vhe ognn oute. +by rewrite oca_eq. +Qed. + +Lemma inside_open'_set_pts (c : cell) l1 l2 q : + last dummy_pt l1 = last dummy_pt (left_pts c) -> + inside_open' q c = inside_open' q (set_pts c l1 l2). +Proof. +move=> same_lim. +rewrite /inside_open' /inside_open_cell /contains_point /left_limit /=. +by rewrite same_lim. +Qed. + +Lemma oc_disjoint_set_left_pts c1 c2 l : + last dummy_pt l = last dummy_pt (left_pts c1) -> + oc_disjoint c1 c2 -> + oc_disjoint (set_left_pts c1 l) c2. +Proof. +move=> eql ref q. +rewrite -inside_open'_set_pts; last by apply/esym. +exact: (ref q). +Qed. + +Let step_keeps_disjoint_default' := + step_keeps_disjoint_default disjoint_open_closed disjoint_closed + closed_right_limit. + +Lemma appE {T : Type} (l1 l2 : seq T) : app l1 l2 = cat l1 l2. +Proof. by elim: l1 => [ | a l1 /= ->]. Qed. + +Lemma step_keeps_disjoint : + let s' := step (Bscan fop lsto lop cls lstc lsthe lstx) e in + {in state_closed_seq s' &, disjoint_closed_cells R} /\ + {in state_open_seq s' & state_closed_seq s', + disjoint_open_closed_cells R}. +Proof. +rewrite /step/=/generic_trajectories.simple_step. +case: ifP=> [pxaway |/negbFE/eqP /[dup] pxhere /abovelstle palstol]. + rewrite -/(open_cells_decomposition _ _). + case oe : (open_cells_decomposition open (point e)) => + [[[[[fc cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + rewrite /state_closed_seq /state_open_seq /=. + rewrite -[X in rcons X _]cat_rcons rcons_cat /=. + have := step_keeps_disjoint_default'; rewrite oe oca_eq /=. + move=> [] A B; split;[apply: A | ]. + by rewrite -catA; apply: B. +case: ifP=> [eabove | ebelow]. +rewrite -/(open_cells_decomposition _ _). +case oe : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + have eabove' : point e >>> low (head dummy_cell lop). + have llopq : low (head dummy_cell lop) = lsthe. + apply: esym; rewrite lstheq. + move: (exi' eabove)=> [w + _]. + move: adj=> /adjacent_catW[] _. + by case: (lop) => [ // | ? ?] /andP[] /eqP. + by rewrite llopq. + have oe' : + open_cells_decomposition open (point e) = + (rcons fop lsto ++ fc', cc, lcc, lc, le, he). + move: adj rfo sval; rewrite /open -cat_rcons=> adj' rfo' sval'. + move: (open_cells_decomposition_cat adj' rfo' sval' (exi' eabove)). + by rewrite oe; apply. + have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe' exi. + have [pal puh vle vhe _]:= + decomposition_connect_properties rfo sval adj cbtom bet_e oe'. + rewrite /state_open_seq /state_closed_seq /= rcons_cat. + rewrite !appE. + rewrite -(cat_rcons lsto) -catA -(cat_rcons lno). + have := step_keeps_disjoint_default'. + by rewrite oe' oca_eq /= -(cat_rcons lno) -(cat_rcons lstc). +case: ifP => [ebelow_st {ebelow} | eonlsthe]. + rewrite -/(open_cells_decomposition _ _). + have oe : open_cells_decomposition open (point e) = + (fop, [::], lsto, lop, low lsto, high lsto). + by rewrite open_cells_decomposition_single=> //; rewrite -lstheq. + have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. + rewrite /state_open_seq /state_closed_seq /=. + rewrite -/(update_open_cell _ _). + case uoc_eq : (update_open_cell lsto e) => [nos lno] /=. + split. + have lstcn : lstc \notin cls. + by move: uniq_closed; rewrite rcons_uniq=> /andP[]. + have lstcin : lstc \in rcons cls lstc by rewrite mem_rcons inE eqxx. + have in' c : c \in cls -> c \in rcons cls lstc. + by move=> cin; rewrite mem_rcons inE cin orbT. + have main c1 q: + c_disjoint c1 lstc -> + c_disjoint c1 (update_closed_cell lstc q). + by move=> /[swap] q1 /(_ q1); rewrite -inside_closed'_update. + move=> c1 c2; rewrite !mem_rcons !inE !(orbC _ (_ \in cls)). + move=>/orP[c1in | /eqP ->] /orP[c2in | /eqP ->]; last by left. + by apply: disjoint_closed; rewrite mem_rcons inE ?c1in ?c2in orbT. + right; apply: main; case: (disjoint_closed (in' _ c1in) lstcin)=> //. + by move: lstcn=> /[swap] <-; rewrite c1in. + apply: c_disjoint_eC; right; apply: main. + case: (disjoint_closed (in' _ c2in) lstcin)=> //. + by move: lstcn=> /[swap] <-; rewrite c2in. + have main c : + oc_disjoint c lstc -> + oc_disjoint c (update_closed_cell lstc (point e)). + by rewrite /oc_disjoint=> /[swap] q /(_ q); rewrite -inside_closed'_update. + have := step_keeps_disjoint_default'. + have lstok : open_cell_side_limit_ok lsto. + by apply: (allP open_side_limit); rewrite /open mem_cat /= inE eqxx orbT. + have pxo : p_x (point e) = left_limit lsto by rewrite -lstxq. + have slpts : (1 < size (left_pts lsto))%N. + by apply: size_left_lsto=> //; rewrite -lstheq; apply: underW. + have puh : point e <<< high lsto by rewrite -lstheq. + have := update_open_cellE1 vlo vho lstok pxo slpts palstol puh. + rewrite uoc_eq /=. + have := update_open_cellE2 vlo vho lstok pxo slpts palstol puh. + rewrite uoc_eq /=. + rewrite oe. + case oca_eq : (opening_cells_aux _ _ _ _) => [nos' lno'] /= helper2 helper1. + move=> [] _ helper3. + move=> c1 c2 c1in; rewrite mem_rcons inE => /orP[/eqP -> | ]. + apply: main. + move: c1in; rewrite -!catA /= mem_cat=> /orP[c1f |]. + apply: disjoint_open_closed; last by rewrite mem_rcons inE eqxx. + by rewrite /open mem_cat c1f. + rewrite mem_cat=> /orP[]. + move=>/helper1 [c1' c1'in]=>- [-> | ]. + by apply: helper3; rewrite !mem_cat ?mem_rcons ?c1'in ?inE ?eqxx ?orbT. + move=>[l lq ->] q. + suff -> : inside_open' q (set_left_pts c1' l) = inside_open' q c1'. + by apply: (helper3 c1' lstc _ _ q); + rewrite !mem_cat ?mem_rcons ?c1'in ?inE ?eqxx ?orbT. + by apply/esym/inside_open'_set_pts/esym. + rewrite inE=> /orP[/eqP -> | ]. + case: helper2=> [ -> | -> ]. + by apply: helper3; rewrite !mem_cat ?mem_rcons !inE !eqxx ?orbT. + set W := (set_left_pts _ _). + move=> q. + suff -> : inside_open' q W = inside_open' q lsto. + by apply: disjoint_open_closed; + rewrite ?mem_rcons ?mem_cat /= ?inE ?eqxx ?orbT. + apply/esym/inside_open'_set_pts. + have := size_left_lsto pxhere palstol (underW puh). + by case : (left_pts lsto) => [ | p1 [ | p2 lpts]]. + move=> c1f. + by apply: disjoint_open_closed; + rewrite ?mem_cat ?mem_rcons ?inE ?c1f ?eqxx ?orbT. + move=> c2in. + move: c1in; rewrite -catA !mem_cat /= => /orP[c1f |]. + by apply: disjoint_open_closed; + rewrite ?mem_cat ?mem_rcons ?inE ?c1f ?eqxx ?c2in ?orbT. + move=> /orP[/helper1 [c1' c1no'] |]. + move=> [-> | [l lq -> q] ]. + by apply: helper3; rewrite !(mem_rcons, mem_cat, inE) ?c1no' ?c2in ?orbT. + suff -> : inside_open' q (set_left_pts c1' l) = inside_open' q c1'. + by apply: helper3; + rewrite !(mem_cat, inE, mem_rcons) ?c1'in ?c2in ?c1no' ?orbT. + by apply/esym/inside_open'_set_pts/esym. + rewrite inE=> /orP[/eqP -> | ]. + move: helper2=> [-> | ->]. + by apply: helper3; rewrite !(mem_cat, mem_rcons, inE) ?eqxx ?c2in ?orbT. + set W := (set_left_pts _ _). + move=> q. + suff -> : inside_open' q W = inside_open' q lsto. + by apply: disjoint_open_closed; + rewrite ?mem_rcons ?mem_cat /= ?inE ?eqxx ?c2in ?orbT. + apply/esym/inside_open'_set_pts. + have := size_left_lsto pxhere palstol (underW puh). + by case : (left_pts lsto) => [ | p1 [ | p2 lpts]]. + move=> c1f. + by apply: disjoint_open_closed; + rewrite ?mem_cat ?mem_rcons ?inE ?c1f ?c2in ?orbT. +rewrite /generic_trajectories.update_open_cell_top. +move : ebelow eonlsthe; rewrite lstheq=> /negbFE ebelow /negP/negP eonlsthe. +have ponlsthe : point e === lsthe. + by rewrite lstheq; apply: under_above_on. +have exi2 : exists2 c, c \in (lsto :: lop) & + contains_point' (point e) c. + exists lsto; first by rewrite inE eqxx. + by rewrite /contains_point' palstol /point_under_edge ebelow. +case ogq : (outgoing e) => [ | fog og]; last first. + rewrite -/(open_cells_decomposition _ _). + case oe : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. + have := open_cells_decomposition_cat adj rfo sval exi2 palstol. + rewrite oe=> oe'. + have lelow : le = low lsto. + move: oe; rewrite /open_cells_decomposition/generic_trajectories.open_cells_decomposition /=. + rewrite -/(contains_point _ _). + have -> : contains_point (point e) lsto. + by rewrite contains_pointE /point_under_edge ebelow underWC. + rewrite -/(open_cells_decomposition_contact _ _). + case : (open_cells_decomposition_contact _ _) => [[[a b] c] |] /=; + by move=> [] _ _ _ _ ->. + have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi2. + have [pal puh vle vhe _]:= + decomposition_connect_properties rfo sval adj cbtom bet_e oe'. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [[ | fno nos] lno]. + have ognn : outgoing e != nil by rewrite ogq. + have:= opening_cells_aux_absurd_case vlo vhe ognn oute. + by rewrite ogq oca_eq /=. + rewrite /state_open_seq /state_closed_seq /=. + have := step_keeps_disjoint_default'; rewrite oe' ogq lelow oca_eq /=. + move=> [] clsdisj ocdisj. + split. + move=> x y xin yin; apply: clsdisj. + move: xin; rewrite !(mem_rcons, inE, mem_cat). + move=>/orP[-> | /orP[ | /orP[ ->| ->]]]; rewrite ?orbT //. + by case: (cc) => /= [// | ? ?]; rewrite !inE /= => ->; rewrite ?orbT. + move: yin; rewrite !(mem_rcons, inE, mem_cat). + move=>/orP[-> | /orP[ | /orP[ ->| ->]]]; rewrite ?orbT //. + by case: (cc) => /= [// | ? ?]; rewrite !inE /= => ->; rewrite ?orbT. + move=> x y. + rewrite !mem_cat !inE -!orbA !(orbCA _ (_ == set_left_pts _ _)). + move=>/orP[]; last first. + move=> xin yin; apply: ocdisj. + rewrite !(mem_cat, inE). + by move: xin=> /orP[-> | /orP[-> | ->]]; rewrite ?orbT //. + move: yin; rewrite !(mem_rcons, mem_cat, inE). + move=>/orP[-> | /orP[ | /orP[-> | ->] ]]; rewrite ?orbT //. + by case: (cc) => /= [// | ? ?]; rewrite !inE /= => ->; rewrite ?orbT. + move=> /eqP -> yin. + apply: oc_disjoint_set_left_pts; last first. + apply: ocdisj;[subset_tac | ]. + move: yin; rewrite !(mem_cat, inE, mem_rcons). + move=> /orP[-> | /orP[ | /orP[-> | ->]]]; rewrite ?orbT //. + by case: (cc) => /= [// | ? ?]; rewrite !inE /= => ->; rewrite ?orbT. + have ognn : outgoing e != nil by rewrite ogq. + have slsto := size_left_lsto pxhere palstol ebelow. + have:= opening_cells_first_left_pts he vlo ognn palstol. + rewrite ogq oca_eq /= => -> /=. + move: slsto; case lptsq : (left_pts lsto) => [// | fp [// | sp lpts]] _ /=. + have : open_cell_side_limit_ok lsto. + by apply: (allP open_side_limit); rewrite /open mem_cat inE eqxx orbT. + move=> /andP[] _ /andP[] A /andP[] _ /andP[] _ onlow. + rewrite pxhere lstxq /left_limit lptsq /=. + apply/(@eqP pt); rewrite pt_eqE /= eqxx /= eq_sym; apply/eqP. + have -> : pvert_y (point e) (low lsto) = pvert_y (last sp lpts) (low lsto). + apply: same_pvert_y=> //. + by rewrite pxhere lstxq /left_limit lptsq. + by apply: on_pvert; move: onlow; rewrite lptsq. +rewrite -/(open_cells_decomposition _ _). +case oe : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. +have := open_cells_decomposition_cat adj rfo sval exi2 palstol. +rewrite oe /= => oe'. +rewrite /state_closed_seq /state_open_seq /=. +have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe' exi. +have [pal puh vle vhe _]:= + decomposition_connect_properties rfo sval adj cbtom bet_e oe'. +set nlsto := (X in (_ ++ X :: lc)). +have lelow : le = low lsto. + move: oe; rewrite /open_cells_decomposition/generic_trajectories.open_cells_decomposition /=. + rewrite -/(contains_point _ _). + have -> : contains_point (point e) lsto. + by rewrite contains_pointE /point_under_edge ebelow underWC. + rewrite -/(open_cells_decomposition_contact _ _). + case : (open_cells_decomposition_contact _ _) => [[[a b] c] |] /=; + by move=> [] _ _ _ _ ->. +have := step_keeps_disjoint_default'; rewrite oe' ogq lelow /=. +rewrite -/(vertical_intersection_point _ _). +rewrite pvertE // -/(vertical_intersection_point _ _) pvertE //=. +have: Bpt (p_x (point e)) (pvert_y (point e) he) == point e :>pt = false. + apply/negP=> abs. + move: puh; rewrite strict_under_pvert_y // -[X in p_y X](eqP abs) /=. + by rewrite lt_irreflexive. +have: point e == Bpt (p_x (point e)) (pvert_y (point e) (low lsto)) :> pt + = false. + apply/negP=> abs. + move: pal; rewrite under_pvert_y // lelow [X in p_y X](eqP abs) /=. + by rewrite le_eqVlt eqxx. +do 2 rewrite -[pt_eqb _ _ _ _]/(_ == _ :> pt). +move=> -> -> [] clcnd clopcnd. +split. + move=> x y xin yin; apply: clcnd. + move: xin; rewrite !(mem_rcons, mem_cat, inE) orbCA=> /orP[]; last first. + by move=> /orP[->| /orP[] ->]; rewrite ?orbT. + by case: (cc) => //= a l; rewrite inE=> ->; rewrite ?orbT. + move: yin; rewrite !(mem_rcons, mem_cat, inE) orbCA=> /orP[]; last first. + by move=> /orP[->| /orP[] ->]; rewrite ?orbT. + by case: (cc) => //= a l; rewrite inE=> ->; rewrite ?orbT. +rewrite cats0. +move=> x y xin yin. +have yin' : y \in cls ++ lstc :: rcons (closing_cells (point e) cc) + (close_cell (point e) lcc). + move: yin; rewrite !(mem_rcons, mem_cat, inE) orbCA=> /orP[]; last first. + by move=> /orP[-> | /orP[] ->]; rewrite ?orbT. + by case: (cc) => //= ? ?; rewrite inE=> ->; rewrite ?orbT. +move: xin; rewrite !(mem_cat, mem_rcons, inE)=> /orP[xin | ]. + apply: clopcnd; first by rewrite !(mem_cat, mem_rcons, inE) xin. + by rewrite cat_rcons. +move=>/orP[/eqP -> | xin]; last first. + apply: clopcnd. + by rewrite !(mem_cat, mem_rcons, inE) xin !orbT. + by rewrite cat_rcons. +move=> q. +move: clopcnd; set w := (X in _ ++ X :: _). +have nlstoq : nlsto = set_pts w + (Bpt (p_x (point e)) (pvert_y (point e) he) :: left_pts lsto) + (right_pts lsto). + by rewrite /nlsto /generic_trajectories.pvert_y subrr. +move=> clopcnd. +rewrite nlstoq -inside_open'_set_pts. + apply: clopcnd. + by rewrite !(mem_cat, mem_rcons, inE) eqxx ?orbT. + by rewrite cat_rcons. +rewrite /w /=. +have /andP[] := allP open_side_limit lsto lstoin. +case plstq : (left_pts lsto) => [ // | a l] _ /= /andP[] A /andP[] _ /andP[] _. +move: lstxq; rewrite /left_limit plstq /= => sx one. +apply/(@eqP pt); rewrite pt_eqE /= pxhere sx eqxx /=. +rewrite -(on_pvert one). +apply/eqP; apply: same_pvert_y; first by case/andP: one. +by rewrite pxhere sx. +Qed. + +Lemma opening_cells_subset' p' (le he : edge) (s sup : seq edge) : + le \in sup -> he \in sup -> {subset s <= sup} -> + valid_edge le p' -> valid_edge he p' -> + {in s, forall g, left_pt g == p'} -> + {subset cell_edges (opening_cells p' s le he) <= sup}. +Proof. +move=> lein hein ssub vl vh outp' /= g. +have ocs := opening_cells_subset vl vh outp'. +rewrite mem_cat=> /orP[] /mapP [/= c /[swap] + /ocs +] => <-. + by move=> /andP[] + _; rewrite inE=> /orP[/eqP -> // | ]; apply: ssub. +by move=> /andP[] _; rewrite inE=> /orP[/eqP -> // | ]; apply: ssub. +Qed. + +Lemma step_keeps_injective_high_default : + let '(fc, cc, lcc, lc, le, he) := + open_cells_decomposition open (point e) in + let '(nos, lno) := + opening_cells_aux (point e) + (sort (@edge_below _) (outgoing e)) le he in + {in fc ++ nos ++ lno :: lc &, injective high}. +Proof. + case oe : open_cells_decomposition => [[[[[fc cc] lcc] lc] le] he]. + have [ocd [lcc_ctn [all_ct [all_nct [flcnct + [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vle vhe ncont] + := connect_properties cbtom adj rfo sval bet_e ocd all_nct all_ct + lcc_ctn flcnct. +have dupcase c1 c2 : (c1 \in fc) || (c1 \in lc) -> + c2 \in opening_cells (point e) (outgoing e) le he -> + high c1 = high c2 -> c1 = c2. + move=> c1in; rewrite leq heq => c2in hc1c2. + have v1 : valid_edge (high c1) (point e). + move: sval=>/allP/(_ c1); rewrite ocd -cat_rcons !mem_cat orbCA c1in orbT. + by move=> /(_ isT) /andP[]. + have v2 : valid_edge (high c2) (point e). + have /andP[ _ ] := opening_cells_subset vle vhe oute c2in. + rewrite inE=> /orP[/eqP -> // | ]. + by have := opening_valid oute vle vhe => /allP /(_ _ c2in) /andP[]. + have : point e <<< high c1 \/ point e >>> high c1. + move: c1in=> /orP[] c1in. + right. + by have := decomposition_above_high_fc oe cbtom adj bet_e rfo sval c1in. + left. + have [s1 [s2 lcq]] := mem_seq_split c1in. + case s2q : s2 => [ | c1' s2']. + move: inbox_e=> /andP[] /andP[] _ + _. + suff -> : high c1 = top by []. + move: cbtom=> /andP[] _ /eqP; rewrite ocd lcq s2q /=. + by rewrite !(last_cat, last_cons) /=. + have c1'in : c1' \in lc by rewrite lcq s2q mem_cat !inE eqxx !orbT. + have := decomposition_under_low_lc oe cbtom adj bet_e rfo sval c1'in. + suff -> : high c1 = low c1' by []. + move: adj; rewrite /adjacent_cells ocd=> /sorted_catW /andP[] _. + move=> /sorted_catW /andP[] _; rewrite lcq s2q. + by rewrite /= -cat_rcons cat_path last_rcons /= => /andP[] _ /andP[] /eqP. + have /andP[lows ] := opening_cells_subset vle vhe oute c2in. + rewrite inE => /orP[/eqP hc1he | ]; last first. + rewrite hc1c2 => /oute/eqP <-. + move=> [ | ]. + rewrite strict_nonAunder; last first. + by apply valid_edge_extremities; rewrite eqxx ?orbT. + by rewrite left_on_edge. + rewrite under_onVstrict ?left_on_edge //. + by apply valid_edge_extremities; rewrite eqxx ?orbT. + have c1hec : c1 = lcc. + apply: high_inj. + by rewrite ocd -cat_rcons!mem_cat orbCA c1in orbT. + by rewrite ocd !(mem_cat, inE) eqxx !orbT. + by rewrite hc1c2. + have := ncont _ c1in. + by rewrite c1hec lcc_ctn. +have henout : he \notin outgoing e. + apply/negP=> /oute /eqP abs. + have := + bottom_left_lex_to_high cbtom adj rfo open_side_limit inbox_e btm_left. + move=> /(_ lcc); rewrite ocd !(mem_cat, inE) eqxx !orbT => /(_ isT). + by rewrite -heq abs lexPt_irrefl. +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +move=> c1 c2; rewrite -cat_rcons !mem_cat orbCA=> /orP[] c1in; last first. + rewrite orbCA=> /orP[] c2in; last first. + by apply: high_inj; + rewrite ocd -cat_rcons !mem_cat orbCA ?c1in ?c2in ?orbT. + by apply: (dupcase _ c2 c1in); rewrite /opening_cells oca_eq. +rewrite orbCA=> /orP[] c2in; last first. + move/esym=> tmp; apply/esym; move: tmp. + by apply: (dupcase _ c1 c2in); rewrite /opening_cells oca_eq. +have : uniq (rcons (sort (@edge_below _) (outgoing e)) he). + by rewrite rcons_uniq mem_sort henout sort_uniq. +rewrite heq -(opening_cells_high vle vhe oute) => /uniq_map_injective; apply. +all: rewrite /opening_cells -heq -leq oca_eq; by []. +Qed. + +(* TODO : propose for inclusion in math-comp *) +Lemma uniq_index (T : eqType) (x : T) l1 l2 : + uniq (l1 ++ x :: l2) -> index x (l1 ++ x :: l2) = size l1. +Proof. +elim: l1 => [/= | a l1 Ih]; first by rewrite eqxx. +rewrite /= => /andP[]. +case: ifP => [/eqP -> | _ _ /Ih -> //]. +by rewrite mem_cat inE eqxx orbT. +Qed. + +Lemma index_map_in (T1 T2 : eqType) (f : T1 -> T2) (s : seq T1) : + {in s &, injective f} -> + {in s, forall x, index (f x) [seq f i | i <- s] = index x s}. +Proof. +elim: s => [ // | a s Ih] inj x xin /=. +case: ifP => [/eqP/inj| fanfx]. + rewrite inE eqxx; move=> /(_ isT xin) => ->. + by rewrite eqxx. +case: ifP=> [/eqP ax | xna ]; first by rewrite ax eqxx in fanfx. +congr (_.+1). +apply: Ih=> //. + by move=> x1 x2 x1in x2in; apply: inj; rewrite !inE ?x1in ?x2in ?orbT. +by move: xin; rewrite inE eq_sym xna. +Qed. + +Lemma update_cells_injective_high l1 l2 l2' l3: + uniq (l1 ++ l2 ++ l3) -> + [seq high c | c <- l2] = [seq high c | c <- l2'] -> + {in l1 ++ l2 ++ l3 &, injective high} -> + {in l1 ++ l2' ++ l3 &, injective high}. +Proof. +move=> u2 eqh inj0 x1 x2; rewrite !mem_cat orbCA=> x1in. +rewrite orbCA=> x2in hx1x2. +move: x1in=> /orP[x1l2' | x1in]; last first. + move: x2in=> /orP[x2l2' | x2in]; last first. + by move: hx1x2; apply: inj0; rewrite !mem_cat orbCA ?x1in ?x2in ?orbT. + move: u2; rewrite uniq_catCA cat_uniq=> /andP[] _ /andP[] /negP abs _. + have : high x2 \in [seq high c | c <- l2]. + by rewrite eqh; apply: map_f. + move=> /mapP[x20 x20in hx20]. + rewrite -hx1x2 in hx20. + have x1x20: x1 = x20. + by apply: inj0; rewrite // ?mem_cat orbCA ?x20in ?x1in ?orbT. + case: abs; apply/hasP; exists x20=> //. + by rewrite -x1x20 mem_cat. +move: x2in=> /orP[x2l2'| x2in]; last first. + move: u2; rewrite uniq_catCA cat_uniq=> /andP[] _ /andP[] /negP abs _. + have : high x1 \in [seq high c | c <- l2]. + by rewrite eqh; apply: map_f. + move=> /mapP[x10 x10in hx10]. + rewrite hx1x2 in hx10. + have x2x10: x2 = x10. + by apply: inj0; rewrite // !mem_cat orbCA ?x10in ?x2in ?orbT. + case: abs; apply/hasP; exists x10=> //. + by rewrite -x2x10 mem_cat. +remember (index x1 l2') as j1 eqn:j1def. +remember (index x2 l2') as j2 eqn:j2def. +have inj2 : {in l2 &, injective high}. + by move=> u1 {}u2 uin1 uin2; apply: inj0; rewrite !mem_cat ?uin1 ?uin2 orbT. +have ul2 : uniq l2. + by move: u2; rewrite !cat_uniq=> /andP[] _ /andP[] _ /andP[]. +have uh : uniq [seq high c | c <- l2]. + by rewrite (map_inj_in_uniq inj2). +have := nth_index dummy_cell x1l2'; rewrite -j1def => j1q. +have := nth_index dummy_cell x2l2'; rewrite -j2def => j2q. +have j1lt : (j1 < size l2')%N by rewrite j1def index_mem. +have j2lt : (j2 < size l2')%N by rewrite j2def index_mem. +have : nth (high dummy_cell) [seq high c | c <- l2'] j1 = high x1. + by rewrite (nth_map dummy_cell) // j1q. +have : nth (high dummy_cell) [seq high c | c <- l2'] j2 = high x1. + by rewrite hx1x2 (nth_map dummy_cell) // j2q. +move=> <-; rewrite -eqh. +move: uh=> /uniqP => /(_ dummy_edge); rewrite [X in size X]eqh size_map. +move=> /(_ j1 j2); rewrite !inE => /(_ j1lt j2lt) /[apply]. +by rewrite -j1q -j2q => ->. +Qed. + +Lemma step_keeps_uniq_default fc cc lcc lc le he nos lno: + open_cells_decomposition open (point e) = (fc, cc, lcc, lc, le, he) -> + opening_cells_aux (point e) + (sort (@edge_below _) (outgoing e)) le he = (nos, lno) -> + uniq (fc ++ nos ++ lno :: lc). +Proof. +move=> oe oca_eq. +have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vle vhe old_nctn]:= + decomposition_connect_properties rfo sval adj cbtom bet_e oe. +have := opening_cells_contains_point vle vhe pal puh oute. +rewrite /opening_cells oca_eq => /(_ _ erefl)=> new_ctn. +have uo : uniq (sort (@edge_below _) (outgoing e)) by rewrite sort_uniq. +have heno : he \notin (sort (@edge_below _) (outgoing e)). + apply/negP=> /oute'/eqP; move: puh=> /[swap] <-. + by rewrite (negbTE (left_pt_above he)). +have uniqnew := opening_cells_aux_uniq uo heno oute' vle vhe oca_eq. +rewrite -cat_rcons uniq_catCA cat_uniq uniqnew. +move: uniq_open; rewrite ocd -cat_rcons uniq_catCA cat_uniq=> /andP[] _. +move=>/andP[] _ ->; rewrite andbT /= -all_predC /=. +apply/allP=> x /=; rewrite mem_cat=> /old_nctn nctn. +by apply/negP=> /new_ctn/nctn. +Qed. + +Lemma step_keeps_injective_high : + let s' := step (Bscan fop lsto lop cls lstc lsthe lstx) e in + {in state_open_seq s' &, injective high}. +Proof. +rewrite /step/=/generic_trajectories.simple_step. +case: ifP=> [pxaway |/negbFE/eqP /[dup] pxhere /abovelstle palstol]. + rewrite -/(open_cells_decomposition _ _). + case oe : (open_cells_decomposition open (point e)) => + [[[[[fc cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + rewrite /state_closed_seq /state_open_seq /=. + have := step_keeps_injective_high_default; rewrite oe oca_eq /=. + by rewrite catA. +case: ifP=> [eabove | ebelow]. +rewrite -/(open_cells_decomposition _ _). +case oe : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + have eabove' : point e >>> low (head dummy_cell lop). + have llopq : low (head dummy_cell lop) = lsthe. + apply: esym; rewrite lstheq. + move: (exi' eabove)=> [w + _]. + move: adj=> /adjacent_catW[] _. + by case: (lop) => [ // | ? ?] /andP[] /eqP. + by rewrite llopq. + have oe' : + open_cells_decomposition open (point e) = + (rcons fop lsto ++ fc', cc, lcc, lc, le, he). + move: adj rfo sval; rewrite /open -cat_rcons=> adj' rfo' sval'. + move: (open_cells_decomposition_cat adj' rfo' sval' (exi' eabove)). + by rewrite oe; apply. + have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe' exi. + have [pal puh vle vhe _]:= + decomposition_connect_properties rfo sval adj cbtom bet_e oe'. + rewrite /state_open_seq. + rewrite appE. + rewrite -(cat_rcons lsto) -catA -(cat_rcons lno). + have := step_keeps_injective_high_default. + by rewrite oe' oca_eq /= !catA -cat_rcons. +case: ifP => [ebelow_st {ebelow} | eonlsthe]. + have oe : open_cells_decomposition open (point e) = + (fop, [::], lsto, lop, low lsto, high lsto). + by rewrite open_cells_decomposition_single=> //; rewrite -lstheq. + have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. + rewrite /state_open_seq /=. + rewrite -/(update_open_cell _ _). + case uoc_eq : (update_open_cell _ _) => [nos lno] /=. + rewrite -catA -cat_rcons. + move: uoc_eq; rewrite /update_open_cell/generic_trajectories.update_open_cell. + case ogq : (outgoing e) => [ | fog ogs]. + move=> [] <- <-; rewrite [rcons _ _]/=. + have uniqlsto : uniq (fop ++ [:: lsto] ++ lop). + by move: uniq_open; rewrite /open. + set w := (X in fop ++ X ++ lop). + have samehigh: [seq high c | c <- [:: lsto]] = [seq high c | c <- w] by []. + by apply: (update_cells_injective_high uniqlsto samehigh). + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [[ | fno nos'] lno']. + have ogn : outgoing e != [::] by rewrite ogq. + have := opening_cells_aux_absurd_case vlo vho ogn oute. + by rewrite ogq oca_eq. + move=> [] <- <-. + have := step_keeps_injective_high_default. + rewrite oe ogq oca_eq -cat_rcons. + apply: update_cells_injective_high. + have := step_keeps_uniq_default oe; rewrite ogq=> /(_ _ _ oca_eq). + by rewrite cat_rcons catA. + by rewrite !map_rcons. +case oe': open_cells_decomposition => [[[[[fc' cc'] lcc'] lc'] le'] he']. +have lsto_ctn : contains_point' (point e) lsto. + rewrite /contains_point' palstol -lstheq. + by move: ebelow=> /negbT; rewrite negbK. +have exi2 : exists2 c, c \in lsto :: lop & contains_point' (point e) c. + by exists lsto; [rewrite inE eqxx | ]. +have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe' exi2. +rewrite /update_open_cell_top/generic_trajectories.update_open_cell_top. +rewrite -/(open_cells_decomposition _ _) oe'. +case ogq : (outgoing e) => [ | fog ogs] /=. + rewrite /state_open_seq /= cats0 -cat1s. + have : {in fop ++ fc' ++ [:: lcc'] ++ lc' &, injective high}. + have subtmp : {subset fop ++ fc' ++ lcc' :: lc' <= open}. + move=> x; rewrite /open ocd !(mem_cat, inE). + repeat (move=> /orP[ -> | ]; rewrite ?orbT //). + by move=> ->; rewrite ?orbT. + by move=> x y xin yin; apply: high_inj; apply: subtmp. + rewrite catA. + apply: update_cells_injective_high. + rewrite cat_uniq; move: uniq_open; rewrite /open ocd catA. + rewrite [X in is_true X -> _]cat_uniq=> /andP[] -> /= /andP[]. + rewrite has_cat negb_or => /andP[] _ /= => ->. + by rewrite [X in is_true X -> _]cat_uniq => /andP[] _ /andP[] _. + by rewrite /= heq. +have := open_cells_decomposition_cat adj rfo sval exi2 palstol. +rewrite oe' => oe. +have [pal puh vle vhe _]:= + decomposition_connect_properties rfo sval adj cbtom bet_e oe. +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq : (opening_cells_aux _ _ _ _) => [ [ | fno nos] lno]. + have ogn : fog :: ogs != nil by []. + have := opening_cells_aux_absurd_case vlo vhe ogn. + by rewrite -[X in {in X, _}]ogq oca_eq => /(_ oute). +rewrite /state_open_seq /= !catA -(catA (_ ++ _)) -cat_rcons. +have := step_keeps_injective_high_default. +rewrite oe ogq. +have le'q : le' = low lsto. + have := last_step_situation oe' pxhere. + rewrite -/(point_strictly_under_edge _ _) in eonlsthe. + rewrite eonlsthe=> /(_ isT). + move: ebelow=> /negbT. + rewrite -/(point_under_edge _ _). + by rewrite negbK=> -> /(_ isT)[] + []. +rewrite le'q oca_eq -cat_rcons. +apply: update_cells_injective_high=> //. +have := step_keeps_uniq_default oe; rewrite ogq le'q=> /(_ _ _ oca_eq). +by rewrite cat_rcons !catA. +Qed. + +(* TODO : understand why closing_cells_to_the_left seems to use too many + hypotheses, once out of the section. *) +Lemma closing_cells_to_the_left fc cc lcc lc le he : + open_cells_decomposition open (point e) = (fc, cc, lcc, lc, le, he) -> + {in closing_cells (point e) cc, forall c, right_limit c <= p_x (point e)} /\ + right_limit (close_cell (point e) lcc) <= p_x (point e). +Proof. +move=> oe. +have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vle vhe _]:= + decomposition_connect_properties rfo sval adj cbtom bet_e oe. +split; last first. + have vlolcc : valid_edge (low lcc) (point e). + apply: (proj1 (andP (allP sval lcc _))). + by rewrite ocd !(mem_cat, inE) eqxx ?orbT. + rewrite /close_cell (pvertE vlolcc). + rewrite -heq (pvertE vhe) /right_limit /=. + by case: ifP; case: ifP. +move=> c /mapP[c' c'in ->]. +have c'in2 : c' \in open by rewrite ocd !mem_cat c'in ?orbT. +have /andP[vlc vhc] := allP sval c' c'in2. +rewrite /close_cell (pvertE vlc) (pvertE vhc) /=. +by case: ifP; case: ifP. +Qed. + +Lemma step_keeps_closed_to_the_left : + let s' := step (Bscan fop lsto lop cls lstc lsthe lstx) e in + {in state_closed_seq s', forall c, right_limit c <= p_x (point e)}. +Proof. +rewrite /step/=/generic_trajectories.simple_step. +case: ifP => [pxaway | /negbFE/eqP/[dup] pxhere /abovelstle palstol]. + rewrite -/(open_cells_decomposition _ _). + case oe : (open_cells_decomposition _ _) => [[[[[fc cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + rewrite /state_closed_seq /=. + have [ccP lccP] := closing_cells_to_the_left oe. + move=> x; rewrite mem_rcons inE => /orP[/eqP -> // | ]. + by rewrite appE -cat_rcons mem_cat => /orP[/closed_right_limit | /ccP]. +case: ifP=> [eabove | ebelow]. + rewrite -/(open_cells_decomposition _ _). + case oe' : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + have eabove' : point e >>> low (head dummy_cell lop). + have llopq : low (head dummy_cell lop) = lsthe. + apply: esym; rewrite lstheq. + move: (exi' eabove)=> [w + _]. + move: adj=> /adjacent_catW[] _. + by case: (lop) => [ // | ? ?] /andP[] /eqP. + by rewrite llopq. + move: adj rfo sval; rewrite /open -cat_rcons => adj' rfo' sval'. + have := open_cells_decomposition_cat adj' rfo' sval' (exi' eabove) eabove'. + rewrite oe' cat_rcons => oe. + have [ccP lccP] := closing_cells_to_the_left oe. + rewrite /state_closed_seq /=. + move=> x; rewrite mem_rcons inE => /orP[/eqP -> // | ]. + by rewrite appE -cat_rcons mem_cat => /orP[ /closed_right_limit | /ccP]. +case: ifP => [ebelow_st {ebelow} | eonlsthe]. + rewrite -/(update_open_cell _ _). + case uoc_eq : (update_open_cell _ _) => [nos lno]. + rewrite /state_closed_seq /=. + move=> x; rewrite mem_rcons inE => /orP[/eqP -> | ]. + rewrite update_closed_cell_keeps_right_limit //; last first. + by apply: (allP close_side_limit); rewrite mem_rcons inE eqxx. + by apply: closed_right_limit; rewrite mem_rcons inE eqxx. + move=> xin. + suff /closed_right_limit : x \in rcons cls lstc by []. + by rewrite mem_rcons inE xin orbT. +rewrite -/(open_cells_decomposition _ _). +case oe' : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. +rewrite -/(update_open_cell_top lsto _ e). +case uoct_eq : (update_open_cell_top lsto _ _) => [nos lno]. +have exi2 : exists2 c, c \in (lsto :: lop) & + contains_point' (point e) c. + exists lsto; first by rewrite inE eqxx. + by rewrite /contains_point' palstol -lstheq /point_under_edge (negbFE ebelow). +have := open_cells_decomposition_cat adj rfo sval exi2 palstol. +rewrite -/(open_cells_decomposition _ _). +rewrite oe' => oe. +rewrite /state_closed_seq /=. +have [ccP lccP] := closing_cells_to_the_left oe. +move=> x; rewrite mem_rcons inE => /orP[/eqP ->|]; first by []. +rewrite mem_cat=> /orP[xin | ]. + have /ccP // : x \in closing_cells (point e) cc. + by move/mapP: xin=> [] x' x'in ->; apply/map_f/mem_behead. +by rewrite -mem_rcons; apply: closed_right_limit. +Qed. + +Lemma contains_right (c : cell) : + c \in open -> right_pt (high c) = point e -> contains_point (point e) c. +Proof. +move=> cino rq. +have /andP[vlc vhc] := allP sval c cino. +apply/andP; split; last first. + rewrite -/(point_under_edge _ _). + by rewrite under_onVstrict // -rq right_on_edge. +apply/negP=> abs. +have bl := allP rfo c cino. +have := order_edges_strict_viz_point vlc vhc bl abs. +by rewrite (strict_nonAunder vhc) -rq right_on_edge. +Qed. + +Lemma inbox_lexePt_right_bt g pt: + inside_box pt -> + g \in [:: bottom; top] -> lexePt pt (right_pt g). +Proof. +rewrite !inE /inside_box /lexePt. +by move=> /andP[] _ /andP[] /andP[] _ lb /andP[] _ lt /orP[] /eqP ->; + rewrite ?lt ?lb. +Qed. + +Lemma inside_box_lexPt_bottom pt : + inside_box pt -> lexPt (left_pt bottom) pt && lexPt pt (right_pt bottom). +Proof. +by move=> /andP[] _ /andP[] /andP[] lp pr _; rewrite /lexPt lp pr. +Qed. + +Lemma inside_box_lexPt_top pt : + inside_box pt -> lexPt (left_pt top) pt && lexPt pt (right_pt top). +Proof. +by move=> /andP[] _ /andP[] _ /andP[] lp pr; rewrite /lexPt lp pr. +Qed. + +Lemma step_keeps_lex_edge_default : + let '(fc, cc, lcc, lc, le, he) := + open_cells_decomposition open (point e) in + let '(nos, lno) := opening_cells_aux (point e) + (sort (@edge_below _) (outgoing e)) le he in + forall e', inside_box (point e') -> lexPtEv e e' -> + (forall e2, e2 \in future_events -> lexePtEv e' e2) -> + {in [seq high c | c <- fc ++ nos ++ lno :: lc], forall g, + lexPt (left_pt g) (point e') && lexePt (point e') (right_pt g)}. +Proof. +case oe : (open_cells_decomposition _ _) => + [[[[[fc cc] lcc] lc] le] he]. +case oca_eq:(opening_cells_aux _ _ _ _) => [nos nlsto]. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vl vp nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. +move=> e' inbox_e' ee' e'fut g. +rewrite !map_cat !mem_cat. +have old: (g \in [seq high c | c <- fc]) || (g \in [seq high c | c <- lc]) -> + lexPt (left_pt g) (point e') && lexePt (point e') (right_pt g). + move=> gin; apply/andP; split. + have /lexPt_trans : lexPt (left_pt g) (point e). + have /lex_open_edges /andP[] // : g \in [seq high c | c <- open]. + rewrite ocd !map_cat !mem_cat map_cons inE. + by move: gin => /orP[ | ] ->; rewrite ?orbT. + by apply. + have /mapP [c cin gq] : g \in [seq high c | c <- fc ++ lc]. + by rewrite map_cat mem_cat. + have cino : c \in open. + by move: cin; rewrite ocd !mem_cat /= inE=> /orP[] ->; rewrite ?orbT. + move : (allP clae _ cino)=> /andP[] _; rewrite /end_edge. + move=> /orP[ /(inbox_lexePt_right_bt inbox_e') | ]; first by rewrite gq. + rewrite -gq; move=> /hasP [e2 e2in /eqP /[dup] e2P ->]. + apply: e'fut. + move: e2in; rewrite inE => /orP[/eqP e2e | ]; last by []. + move: (cin); rewrite mem_cat => /nc []. + by apply: contains_right; rewrite // -e2e -gq. +move=> /orP[oldf |]; first by apply: old; rewrite oldf. +rewrite /= inE orbA=> /orP[| oldl]; last by apply: old; rewrite oldl orbT. +move=> /orP[go | ghe]. + have := opening_cells_aux_high vl vp oute'; rewrite oca_eq /=. + move: go=> /[swap] -> /[dup] go /oute' /eqP /[dup] ge ->. + rewrite mem_sort in go. + apply/andP; split; first by exact ee'. + have := cle; rewrite /= /close_out_from_event /end_edge => /andP[] + _. + move=> /allP /(_ g go). + by move=> /hasP[e3 e3in /eqP ->]; apply: e'fut. +have := opening_cells_aux_high_last vl vp oute'; rewrite oca_eq /= -(eqP ghe). +move=> {}ghe. +have lcco : lcc \in open by rewrite ocd !mem_cat inE eqxx !orbT. +have /lex_open_edges : g \in [seq high c | c <- open]. + by apply/mapP; exists lcc; rewrite // ghe. +move=> /andP[] left_e e_right. +rewrite (lexPt_trans left_e ee') /=. +have := (allP clae lcc lcco) => /andP[] _; rewrite /end_edge. +move=> /orP[]. + rewrite !inE -heq -ghe => /orP[] /eqP ->; move: inbox_e'. + by move=> /inside_box_lexPt_bottom /andP[] _ /lexPtW. + by move=> /inside_box_lexPt_top /andP[] _ /lexPtW. +move=> /hasP [e2 + /eqP ge2]. +rewrite inE=> /orP[ /eqP abs | ]. + suff /onAbove : point e === he by rewrite puh. + by rewrite -abs -ge2 heq right_on_edge. +by move=> /e'fut; rewrite /lexePtEv -ge2 -heq ghe. +Qed. + +Lemma step_keeps_lex_edge : + let s' := step (Bscan fop lsto lop cls lstc lsthe lstx) e in + forall e', inside_box (point e') -> lexPtEv e e' -> + (forall e2, e2 \in future_events -> lexePtEv e' e2) -> + {in [seq high c | c <- state_open_seq s'], forall g, + lexPt (left_pt g) (point e') && lexePt (point e') (right_pt g)}. +Proof. +rewrite /step/=/generic_trajectories.simple_step. +case: ifP => [pxaway | /negbFE/eqP/[dup] pxhere /abovelstle palstol]. + rewrite -/(open_cells_decomposition _ _). + case oe : (open_cells_decomposition _ _) => [[[[[fc cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + rewrite /state_open_seq /state_closed_seq /=. + move=> e' in_e' ee' e'fut. + by have := step_keeps_lex_edge_default; rewrite oe oca_eq catA; apply. +case: ifP=> [eabove | ebelow]. + rewrite -/(open_cells_decomposition _ _). + case oe' : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + have eabove' : point e >>> low (head dummy_cell lop). + have llopq : low (head dummy_cell lop) = lsthe. + apply: esym; rewrite lstheq. + move: (exi' eabove)=> [w + _]. + move: adj=> /adjacent_catW[] _. + by case: (lop) => [ // | ? ?] /andP[] /eqP. + by rewrite llopq. + move: adj rfo sval; rewrite /open -cat_rcons => adj' rfo' sval'. + have := open_cells_decomposition_cat adj' rfo' sval' (exi' eabove) eabove'. + rewrite oe' cat_rcons => oe. + rewrite /state_open_seq /state_closed_seq /=. + have := step_keeps_lex_edge_default; rewrite oe oca_eq. + move=> main e' in_e' ee' e'fut g /mapP[c cin gq]. + apply: (main e' in_e' ee' e'fut); apply/mapP; exists c; last by []. + by move: cin; rewrite !(mem_rcons, mem_cat, inE) !orbA (orbC _ (c == lsto)). +have ebelow' : point e <<= lsthe by exact (negbFE ebelow). +case: ifP => [ebelow_st | enolsthe]. + rewrite /state_open_seq /update_open_cell/generic_trajectories.update_open_cell /=. + have belowo : point e <<< high lsto by rewrite -lstheq. + have := open_cells_decomposition_single adj rfo sval palstol belowo. + move=> oe. + have [ocd [lcc_ctn [_ [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. + have [pal puh vl vp nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. + case ogq: (outgoing e) => [ | fog ogs] /=. + move=> e' in_e' ee' e'fut; rewrite cats0=> g /mapP [c + gq]. + rewrite mem_cat inE orbCA gq=> /orP[/eqP /[dup] cq -> /= | ]. + rewrite (fun h => lexPt_trans h ee')/=; last first. + apply: (proj1 (andP (lex_open_edges (map_f _ _)))). + by rewrite mem_cat inE eqxx orbT. + have /andP[_ /orP[|] ] := (allP clae lsto lstoin). + by move=>/(inbox_lexePt_right_bt in_e'). + move=> /hasP [e2]. + rewrite inE => /orP[/eqP -> | /e'fut +] /eqP rq. + move: (strict_nonAunder vho); rewrite -lstheq /point_strictly_under_edge ebelow_st=>/esym. + move: gq; rewrite cq high_set_left_pts=> gq. + by rewrite lstheq -rq right_on_edge. + by rewrite /lexePtEv -rq. + move=> cold; apply/andP. + have cino : c \in open. + by rewrite mem_cat inE; move: cold=> /orP[] ->; rewrite ?orbT . + split. + apply: lexPt_trans ee'. + by have /andP[] := lex_open_edges (map_f _ cino). + have /andP[_] := (allP clae _ cino). + move=> /orP[]. + by move=> /(inbox_lexePt_right_bt in_e'). + move=> /hasP[e2 + /eqP e2P]; rewrite inE => /orP[/eqP e2e | ]. + rewrite e2e in e2P. + by move: (nc _ cold)=> []; apply: contains_right. + by move=> /e'fut; rewrite /lexePtEv -e2P. + rewrite -ogq. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [[ | fno nos] lno]. + have ogn : outgoing e != [::] by rewrite ogq. + have := opening_cells_aux_absurd_case vlo vho ogn oute. + by rewrite oca_eq. + rewrite /= => e' in_e' ee' e'fut g /mapP[c cin gq]. + have := step_keeps_lex_edge_default. + rewrite oe oca_eq=> /(_ e' in_e' ee' e'fut) main. + move: cin; rewrite -!catA /= mem_cat => /orP[cin | ]. + by apply: main; apply/mapP; exists c; rewrite // mem_cat cin. + rewrite inE=> /orP[/eqP cq | ]. + rewrite gq cq high_set_left_pts; apply: main. + by apply/mapP; exists fno; rewrite // !(mem_cat, inE) eqxx ?orbT. + move=> cin; apply: main. + by apply/mapP; exists c; rewrite //= mem_cat inE cin !orbT. +move=> e' in_e' ee' e'fut. +rewrite -/(open_cells_decomposition _ _). +case oe' : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. +rewrite -/(update_open_cell_top _ _ _). +case uoctq: update_open_cell_top => [nos lno]. +rewrite /state_open_seq /= -!catA. +move=> g /mapP [c cin gq]; rewrite gq {gq}. +have exi2 : exists2 c, c \in lsto :: lop & contains_point' (point e) c. + exists lsto; first by rewrite inE eqxx. + by rewrite /contains_point' palstol -lstheq ebelow'. +have := open_cells_decomposition_cat adj rfo sval exi2 palstol. +rewrite oe'=> oe. +have [ocd [lcc_ctn [_ [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vl vp nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. +have := step_keeps_lex_edge_default; rewrite oe => main. +move: uoctq; rewrite /update_open_cell_top/generic_trajectories.update_open_cell_top. +have := last_step_situation oe' pxhere (negbT enolsthe) ebelow'. +move=> [] fc'0 [] leo [cc' ccq]. +case ogq : (outgoing e) => [ | fog ogs]; last first. + rewrite -ogq. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [ [ | fno nos'] lno']. + have ogn : outgoing e != [::] by rewrite ogq. + have := opening_cells_aux_absurd_case vlo vp ogn oute. + by rewrite oca_eq. + move=> -[] nosq lnoq. + move: main; rewrite leo oca_eq => /(_ _ in_e' ee' e'fut) main. + move: cin; rewrite mem_cat=> /orP[cin | ]. + by apply: main; apply/mapP; exists c; rewrite // !mem_cat cin. + rewrite fc'0 /= mem_cat inE orbA=> /orP[|cin]; last first. + by apply: main; apply/mapP; exists c; rewrite // !(mem_cat, inE) cin !orbT. + move=> /orP[ | /eqP clno]; last first. + apply: main; apply/mapP; exists c; rewrite // lnoq !(mem_cat, inE) clno. + by rewrite eqxx !orbT. + rewrite -nosq inE=> /orP[ | cin]; last first. + by apply: main; apply/mapP; exists c; rewrite // !(mem_cat, inE) cin !orbT. + move=> /eqP ->; rewrite high_set_left_pts. + by apply: main; apply/mapP; exists fno; rewrite // !mem_cat inE eqxx !orbT. +move=> [] nosq lnoq. +have oca_eq : opening_cells_aux (point e) (sort (@edge_below _) (outgoing e)) + le he = + ([::], (Bcell (@no_dup_seq pt + [:: (Bpt (p_x (point e)) (pvert_y (point e) he)); + (point e); + (Bpt (p_x (point e)) (pvert_y (point e) le))]) [::] le he)). + rewrite ogq -[sort _ _]/[::]. + rewrite /opening_cells_aux/generic_trajectories.opening_cells_aux. + by rewrite -/(vertical_intersection_point _ _) (pvertE vl) + -/(vertical_intersection_point _ _) (pvertE vp). +move: main; rewrite oca_eq => /(_ _ in_e' ee' e'fut)=> main. +move: cin; rewrite mem_cat=> /orP[cin |]. + by apply: main; apply/mapP; exists c; rewrite // !mem_cat cin. +rewrite fc'0 -nosq /= inE=> /orP[/eqP clno | cin]; last first. + by apply: main; apply/mapP; exists c; rewrite // !(mem_cat, inE) cin !orbT. +apply: main. +rewrite map_cat /=. +suff ->: high c = he by rewrite !(mem_cat, inE) eqxx !orbT. +by rewrite clno -lnoq /=. +Qed. + +Lemma opening_cells_aux_cover_outgoing le he nos lno: + valid_edge le (point e) -> + opening_cells_aux (point e) (sort (@edge_below _) (outgoing e)) le he = + (nos, lno) -> + {in (outgoing e), forall g, + exists c, c \in nos /\ high c = g /\ left_limit c = p_x (left_pt g)}. +Proof. +move=> + + g go. +have go' : g \in sort (@edge_below _) (outgoing e) by rewrite mem_sort. +elim: (sort _ _) go' oute' le nos lno {go} => [ // | g' og Ih]. +rewrite inE=> /orP[/eqP -> | gin]; move=> + le nos lno vle. + have /[swap] /[apply] /eqP lpg' : g' \in g' :: og by rewrite inE eqxx. + rewrite /=. + rewrite -/(opening_cells_aux _ _ _ _). + case: (opening_cells_aux _ _ _ _) => s nc. + rewrite -/(vertical_intersection_point _ _) (pvertE vle). + set it := Bcell _ _ _ _; move=> [] sq ncq; exists it. + rewrite -sq inE eqxx; split=> //; split=> //. + rewrite /left_limit /=. + rewrite -[pt_eqb _ _ _ _]/(_ == _ :> pt). + by case: ifP => [/eqP -> /=| /= ]; rewrite lpg'. +move=> outg'. +have outg : {in og, forall g, left_pt g == point e}. + by move=> x xin; apply: outg'; rewrite inE xin orbT. +rewrite /=. +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq : (opening_cells_aux _ _ _ _) => [s nc]. +rewrite -/(vertical_intersection_point _ _) (pvertE vle) => - [sq ncq]. +have vg : valid_edge g' (point e). + rewrite -(eqP (outg' g' _)); last by rewrite inE eqxx. + by apply: valid_edge_left. +have [it [P1 P2]]:= Ih gin outg g' s nc vg oca_eq. + exists it; split; last by []. +by rewrite -sq inE P1 orbT. +Qed. + +Lemma step_keeps_edge_covering_default gen_closed fc cc lcc lc le he nos lno: + open_cells_decomposition open (point e) = (fc, cc, lcc, lc, le, he) -> + opening_cells_aux (point e) (sort (@edge_below _) (outgoing e)) le he = + (nos, lno) -> + forall g, + edge_covered g open gen_closed \/ g \in outgoing e -> + edge_covered g (fc ++ nos ++ lno :: lc) + (gen_closed ++ rcons (closing_cells (point e) cc) + (close_cell (point e) lcc)). +Proof. +move=> oe oca_eq. +have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vle vhe old_nctn]:= + decomposition_connect_properties rfo sval adj cbtom bet_e oe. +move=> g [go | gn]; last first. + have [c [cin [highc cleft]]]:= + opening_cells_aux_cover_outgoing vle oca_eq gn. + left; exists c, [::]; split=> /=; first by []. + split; first by move=> c'; rewrite inE=> /eqP ->. + split; first by []. + split; last by []. + by rewrite !mem_cat cin !orbT. +case: go => [[opc [pcc [pccsub opcP]]] | + [ pcc [pccn0 [pccsub pccP]]]]; last first. + right; exists pcc. + split;[exact pccn0 | split; [ | exact pccP]]. + by move=> g1 /pccsub; rewrite mem_cat=> ->. +move: opcP => [highc [cnc [opco pccl]]]. +have [ghe | gnhe] := eqVneq g he. + have vllcc : valid_edge (low lcc) (point e). + apply: (seq_valid_low sval); rewrite ocd !map_cat !mem_cat /= inE. + by rewrite eqxx ?orbT. + have lccq : lcc = opc. + apply: high_inj=> //; first by rewrite ocd !(mem_cat, inE) eqxx !orbT. + by rewrite (highc opc) ?ghe; last rewrite mem_rcons inE eqxx. + left; exists lno, (rcons pcc (close_cell (point e) lcc)). + split. + move=> c; rewrite mem_rcons inE=> /orP[/eqP -> | /pccsub]. + by rewrite !(mem_rcons, mem_cat, inE) eqxx ?orbT. + by rewrite mem_cat=> ->. + split. + move=> c; rewrite !(mem_rcons, inE). + move=> /orP[/eqP |/orP[/eqP | inpcc]]; last 1 first. + by apply: highc; rewrite !(mem_rcons, mem_cat, inE, inpcc, orbT). + rewrite /close_cell. + move=> ->; rewrite ghe. + have := higher_edge_new_cells oute vle vhe. + by rewrite /opening_cells oca_eq => /(_ _ erefl); rewrite last_rcons. + rewrite /close_cell=> ->. + by rewrite -heq (pvertE vhe) (pvertE vllcc) /= ghe. + split. + elim/last_ind : {-1} pcc (erefl pcc) => [pcceq | pcc1 lpcc _ pcceq]. + rewrite /= andbT. + rewrite close_cell_right_limit; last first. + by rewrite /valid_cell vllcc -heq vhe. + have /(_ lno) -> // := opening_cells_left oute vle vhe. + by rewrite /opening_cells oca_eq mem_rcons inE eqxx. + rewrite connect_limits_rcons; last by apply/eqP/rcons_neq0. + apply/andP; split; last first. + rewrite last_rcons right_limit_close_cell //. + have /(_ lno) -> // := opening_cells_left oute vle vhe. + by rewrite /opening_cells oca_eq mem_rcons inE eqxx. + by rewrite -heq. + rewrite connect_limits_rcons; last by apply/eqP/rcons_neq0. + move: cnc. + rewrite pcceq connect_limits_rcons; last by apply/eqP/rcons_neq0. + move=> /andP[] -> /eqP ->. + by rewrite left_limit_close_cell lccq eqxx. + split; first by rewrite !(mem_cat, inE, eqxx, orbT). + move: pccl; rewrite lccq; case: (pcc)=> /=; last by []. + by rewrite left_limit_close_cell. +rewrite -cat_rcons. +move: opco; rewrite ocd -cat_rcons !mem_cat orbCA => /orP[]; last first. + move=> opc_pres. + left; exists opc, pcc. + split; first by apply: subset_catrl. + split; first by []. + split; first by []. + split; last by []. + by rewrite !mem_cat orbCA opc_pres orbT. +move=> opcc. +right. +have [_ highopc leftopc] := close_cell_preserve_3sides (point e) opc. +exists (rcons pcc (close_cell (point e) opc)). +split. + by apply/eqP/rcons_neq0. +split. + move=> c; rewrite mem_rcons inE=> /orP[/eqP -> | ]. + rewrite mem_cat/closing_cells; apply/orP; right. + by rewrite -map_rcons; apply/mapP; exists opc. + by move=> /pccsub cin; rewrite mem_cat cin. +split. + move=> c; rewrite mem_rcons inE => /orP[/eqP -> | inpcc]; last first. + by apply highc; rewrite mem_rcons inE inpcc orbT. + by rewrite highopc; apply highc; rewrite mem_rcons inE eqxx. +split. + have [/eqP -> | pccn0] := boolP (pcc == [::]). + by []. + move: cnc; rewrite !connect_limits_rcons // => /andP[] -> /eqP -> /=. + by rewrite /left_limit leftopc. +split. + move: pccl; case pccq: pcc => [ | pcc0 pcc'] //=. + by rewrite /left_limit leftopc. +have opco : opc \in open. + by rewrite ocd -cat_rcons !mem_cat opcc orbT. +rewrite /last_cell last_rcons right_limit_close_cell; last first. + by apply/(seq_valid_high sval)/map_f. + by apply/(seq_valid_low sval)/map_f. +have hopc : high opc = g by apply: highc; rewrite mem_rcons inE eqxx. +have {}opcc : opc \in cc. + move: opcc; rewrite mem_rcons inE=> /orP[] // /eqP abs. + by case/eqP: gnhe; rewrite -hopc abs. +have e_on : point e === high opc. + by apply: (open_cells_decomposition_point_on cbtom adj bet_e sval oe opcc). +have [ abs | -> ] := open_non_inner opco e_on; last by rewrite hopc. +have := bottom_left_lex_to_high cbtom adj rfo open_side_limit. +move=> /(_ _ inbox_e btm_left _ opco). +by rewrite abs lexPt_irrefl. +Qed. + +Lemma edge_covered_set_left_pts g l1 c l2 l3 lpts : + left_limit c = p_x (last dummy_pt lpts) -> + edge_covered g (l1 ++ c :: l2) l3 -> + edge_covered g (l1 ++ (set_left_pts c lpts) :: l2) l3. +Proof. +move=> left_cond [active | [pcc pccP]]; last by right; exists pcc; exact pccP. +move: active => [opc [pcc [pccP1 [pccP2 [pccP3 [pccP4 pccP5]]]]]]. +have [copc | cnopc] := eqVneq c opc. + left; exists (set_left_pts c lpts), pcc. + split; first by []. + split. + move=> x; rewrite mem_rcons inE=> /orP[ /eqP -> | xin]; last first. + by apply: pccP2; rewrite mem_rcons inE xin orbT. + rewrite /set_left_pts /=. + by apply: pccP2; rewrite mem_rcons inE copc eqxx. + split. + have [-> | pccn0] := eqVneq pcc [::]; first by []. + move: pccP3; rewrite !connect_limits_rcons // => /andP[] -> /eqP -> /=. + rewrite /set_left_pts /=. + by rewrite -copc left_cond /left_limit. + split; first by rewrite mem_cat inE eqxx orbT. + move: pccP5; have [-> /= | pccn0] := eqVneq pcc [::]. + by rewrite -copc left_cond. + by move: pccn0; case: (pcc). +left; exists opc, pcc. +split; first by []. +split; first by []. +split; first by []. +split; last by []. +move: pccP4. +rewrite !mem_cat !inE=> /orP[ -> | /orP [ | -> ]]; rewrite ?orbT //. +by move: cnopc=> /[swap]; rewrite eq_sym=> ->. +Qed. + +Lemma update_closed_cell_keep_left_limit c pt : + left_limit (update_closed_cell c pt) = left_limit c. +Proof. by move: c => [? ? ? ?]. Qed. + +Lemma connect_limits_seq_subst (l : seq cell) c c' : + left_limit c = left_limit c' -> right_limit c = right_limit c' -> + connect_limits l -> connect_limits (seq_subst l c c'). +Proof. +move=> ll rr; elim: l => [ | a [ | b l] Ih] /=; first by []. + by case: ifP. +move=> /[dup] conn /andP[ab conn']. +have conn0 : path (fun c1 c2 => right_limit c1 == left_limit c2) a (b :: l). + by exact: conn. +have /Ih : sorted (fun c1 c2 => right_limit c1 == left_limit c2) (b :: l). + by apply: (path_sorted conn0). +case: ifP=> [/eqP ac | anc]. + rewrite /=; case: ifP => [/eqP bc | bnc]. + by rewrite /= -rr -ll -ac (eqP ab) ac -bc eqxx. + by rewrite /= -rr -ac ab. +rewrite /=; case: ifP=> [/eqP bc | bnc]. + by rewrite /= -ll -bc ab. +by rewrite /= ab. +Qed. + +Lemma edge_covered_update_closed_cell g l1 l2 c pt : + (1 < size (right_pts c))%N -> + closed_cell_side_limit_ok c -> + edge_covered g l1 (rcons l2 c) -> + edge_covered g l1 (rcons l2 (update_closed_cell c pt)). +Proof. +move=> szpts cok ecg. +have lq : left_limit (update_closed_cell c pt) = left_limit c. + by case: (c). +have rq : right_limit (update_closed_cell c pt) = right_limit c. + rewrite update_closed_cell_keeps_right_limit //. +case: ecg => [[oc [pcc [ocP1 [hP [cP [ocin conn]]]]]] | ]. + left; exists oc, (seq_subst pcc c (update_closed_cell c pt)). + split. + elim: (pcc) ocP1 => [ // | a l Ih]. + move=> subh x; rewrite /=. + have /Ih {} Ih : {subset l <= rcons l2 c}. + by move=> y yin; have /subh : y \in a:: l by rewrite inE yin orbT. + case: ifP => [ac | anc]; rewrite !(inE, mem_rcons). + by move=> /orP[-> // | /Ih]; rewrite mem_rcons inE. + move=> /orP[xa | ]. + have /subh : x \in a :: l by rewrite inE xa. + by rewrite mem_rcons inE (eqP xa) anc /= orbC => ->. + by move/Ih; rewrite mem_rcons inE. + split. + move=> x; rewrite mem_rcons inE => /orP[xoc | ]. + by apply: hP; rewrite mem_rcons inE xoc. + have : {in pcc, forall c, high c = g}. + by move=> y yin; apply: hP; rewrite mem_rcons inE yin orbT. + elim: (pcc) => [ // | a l Ih] {}hP. + have /Ih {}Ih : {in l, forall c, high c = g}. + by move=> y yin; apply: hP; rewrite inE yin orbT. + rewrite /=; case: ifP=> [ac | anc]. + rewrite inE=> /orP[/eqP -> | ]; last by []. + have: high c = g by apply: hP; rewrite inE eq_sym ac. + by case: (c). + rewrite inE=> /orP[/eqP -> | ]; last by []. + by apply: hP; rewrite inE eqxx. + split. + elim/last_ind: (pcc) cP => [// | pcc' lpcc _]. + rewrite connect_limits_rcons; last by apply/eqP/rcons_neq0. + move=> /andP[] cP cc. + rewrite connect_limits_rcons; last first. + by case: (pcc')=> /= [ | ? ?]; case: ifP. + apply/andP; split; last first. + rewrite -cats1 seq_subst_cat /=. + move: cc; rewrite last_rcons=> /eqP <-. + case: ifP; rewrite cats1 last_rcons; last by []. + by rewrite rq => /eqP ->. + by apply: connect_limits_seq_subst. + split; first by []. + case: (pcc) conn => [ | fpcc pcc']/=; first by []. + by case: ifP=> [ /eqP -> | ]. +move=> [pcc [P0 [P1 [P2 [P3 [P4 P5]]]]]]. +right. +exists (seq_subst pcc c (update_closed_cell c pt)). +split. + by rewrite seq_subst_eq0. +split. + elim : (pcc) P1 => [ | a l Ih] P1; first by []. + have ain : a \in rcons l2 c by apply: P1; rewrite inE eqxx. + have /Ih {} Ih : {subset l <= rcons l2 c}. + by move=> y yin; apply: P1; rewrite inE yin orbT. + rewrite /=; case: ifP=> [ ac | anc]. + move=> g'; rewrite !inE => /orP[/eqP -> | /Ih]; last by []. + by rewrite mem_rcons inE eqxx. + move=> g'; rewrite !inE=> /orP[/eqP -> | ]. + by move: ain; rewrite !mem_rcons !inE anc /= orbC => ->. + by apply: Ih. +split. + elim: (pcc) P2 => [ | a l Ih] P2; first by []. + have /Ih {} Ih : {in l, forall c, high c = g}. + by move=> x xin; apply: P2; rewrite inE xin orbT. + rewrite /=; case: ifP => [ac | anc]. + move=> c'; rewrite inE => /orP[/eqP -> | ]. + move: (P2 c); rewrite inE eq_sym ac => /(_ isT). + by case: (c). + by apply: Ih. + move=> c'; rewrite inE => /orP[/eqP -> | ]. + by apply: P2; rewrite inE eqxx. + by apply: Ih. +split; first by apply: connect_limits_seq_subst. +split. + move: P4; case: (pcc)=> [ | a l]; first by []. + rewrite /=; case: ifP=> [/eqP ac | anc] /=; last by []. + by rewrite lq ac. +move: P5; elim/last_ind : (pcc) => [ | l b _]; first by []. +rewrite -cats1 seq_subst_cat /=; case: ifP=> [/eqP bc | bnc]. + by rewrite /last_cell !last_cat /= rq bc. +by rewrite /last_cell !last_cat /=. +Qed. + +Lemma lsthe_at_left : point e <<= lsthe -> + p_x (left_pt lsthe) < p_x (point e). +Proof. +move=> puh. +have /lex_open_edges/andP[+ _] : lsthe \in [seq high c | c <- open]. + by apply/mapP; exists lsto. +rewrite /lexPt=> /orP[ | /andP[] /eqP samex lty]; first by []. +have vhe : valid_edge lsthe (point e). + move: (allP sval lsto); rewrite /open mem_cat inE eqxx !orbT. + by move=> /(_ isT)=> /andP[]; rewrite lstheq. +move: puh; rewrite under_pvert_y //. +move: (samex)=> /esym samex'. +rewrite (same_pvert_y vhe samex'). +by rewrite (on_pvert (left_on_edge _)) leNgt lty. +Qed. + +Lemma step_keeps_edge_covering: + let s' := step (Bscan fop lsto lop cls lstc lsthe lstx) e in + forall g, edge_covered g open (rcons cls lstc) \/ g \in outgoing e -> + edge_covered g (state_open_seq s') (state_closed_seq s'). +Proof. +rewrite /step/=/generic_trajectories.simple_step. +case: ifP => [pxaway | /negbFE/eqP/[dup] pxhere /abovelstle palstol]. + rewrite -/(open_cells_decomposition _ _). + case oe : (open_cells_decomposition _ _) => [[[[[fc cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + rewrite /state_open_seq /state_closed_seq /=. + move=> g gin. + have := step_keeps_edge_covering_default oe oca_eq gin. + by rewrite -!cats1 -?catA /=. +case: ifP=> [eabove | ebelow]. + rewrite -/(open_cells_decomposition _ _). + case oe' : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + have eabove' : point e >>> low (head dummy_cell lop). + have llopq : low (head dummy_cell lop) = lsthe. + apply: esym; rewrite lstheq. + move: (exi' eabove)=> [w + _]. + move: adj=> /adjacent_catW[] _. + by case: (lop) => [ // | ? ?] /andP[] /eqP. + by rewrite llopq. + move: adj rfo sval; rewrite /open -cat_rcons => adj' rfo' sval'. + have := open_cells_decomposition_cat adj' rfo' sval' (exi' eabove) eabove'. + rewrite oe' cat_rcons => oe. + rewrite /state_open_seq /state_closed_seq /=. + move=> g gin. + have := step_keeps_edge_covering_default oe oca_eq gin. + by rewrite !cat_rcons -!cats1 -?catA /=. +have [p1 [p2 [pts ptsq]]]: exists p1 p2 pts, left_pts lsto = p1 :: p2 :: pts. + have ebelow' : point e <<= high lsto. + by move/negbFE :ebelow; rewrite lstheq. + have := size_left_lsto pxhere palstol ebelow'. + case: (left_pts lsto) => [// | pt1 [ // | pt2 pts]] _. + by exists pt1, pt2, pts. +case: ifP => [ebelow_st {ebelow} | eonlsthe]. + rewrite /update_open_cell/generic_trajectories.update_open_cell. + case ogq : (outgoing e) => [ /= | fog ogs]. + move=> g [ ecg | //]. + rewrite /state_open_seq /= cats0 /state_closed_seq /=. + apply: edge_covered_set_left_pts. + by rewrite /left_limit ptsq. + apply: edge_covered_update_closed_cell=> //. + by apply: (allP close_side_limit); rewrite mem_rcons inE eqxx. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [[ | fno nos] lno] /=. + have outn0 : fog :: ogs != nil by []. + have oute2 : {in fog :: ogs, forall g, left_pt g == point e}. + by rewrite -ogq. + have := opening_cells_aux_absurd_case vlo vho outn0 oute2. + by rewrite oca_eq. + move=> g [ecg | gnew]; last first. + left. + have :=opening_cells_aux_cover_outgoing vlo. + move=> /(_ (high lsto) (fno :: nos) lno); rewrite ogq=> /(_ oca_eq). + move=> /(_ g gnew) [gc [P1 [P2 P3]]]. + exists (if gc == fno then + set_left_pts fno (point e :: behead (left_pts lsto)) + else gc), [::]. + split; first by []. + split. + move=> x; rewrite /= inE => /eqP ->. + case: ifP => [/eqP <- | ]; last by []. + by case: (gc) P2. + split; first by []. + split. + rewrite /state_open_seq /=. + move: P1; case: ifP => [/eqP -> _ | ]. + by rewrite !mem_cat inE eqxx orbT. + by rewrite inE=> -> /=; rewrite !mem_cat inE=> ->; rewrite ?orbT. + rewrite /head_cell /=; case: ifP=> [/eqP <- | ]; last by []. + move: lstxq; rewrite /left_limit. + rewrite ptsq /left_limit /= => <-. + by rewrite (eqP (@oute g _)) ?pxhere // ogq. + move: ecg=> [[oc [pcc [P1 [P2 [P3 [P4 P5]]]]]] | ]. + move: P4; rewrite mem_cat inE orbCA=> /orP[/eqP oclsto | inold]. + rewrite /state_open_seq /state_closed_seq /=. + rewrite /= -catA /=. + apply: edge_covered_set_left_pts. + rewrite (opening_cells_left oute vlo vho). + by rewrite pxhere lstxq /left_limit ptsq. + by rewrite /opening_cells ogq oca_eq mem_rcons !inE eqxx !orbT. + apply: edge_covered_update_closed_cell=> //. + by apply: (allP close_side_limit); rewrite mem_rcons inE eqxx. + left; exists lno, pcc. + split; first by []. + split. + move=> x; rewrite mem_rcons inE=> /orP[/eqP -> | xin]; last first. + by apply P2; rewrite mem_rcons inE xin orbT. + have := opening_cells_aux_high_last vlo vho oute'. + rewrite ogq oca_eq /= -oclsto=> ->; apply: P2. + by rewrite mem_rcons inE eqxx. + have left_lno : left_limit lno = lstx. + have := opening_cells_left oute vlo vho. + rewrite -pxhere /opening_cells ogq oca_eq; apply. + by rewrite mem_rcons inE eqxx. + split. + elim/last_ind: {-1} pcc (erefl pcc) => [ | pcc' pcl _] pccq; + first by []. + rewrite connect_limits_rcons; last by apply/eqP/rcons_neq0. + move: P3; rewrite pccq connect_limits_rcons; last first. + by apply/eqP/rcons_neq0. + move=> /andP[] -> /eqP ->. + by rewrite oclsto -lstxq left_lno eqxx. + split; first by rewrite !(mem_cat, inE) eqxx !orbT. + move: P5; case: (pcc) => //=. + by rewrite left_lno oclsto lstxq. + rewrite /state_closed_seq /state_open_seq /=. + rewrite -!catA /=. + have left_fno : left_limit fno = lstx. + have := opening_cells_left oute vlo vho. + rewrite -pxhere /opening_cells ogq oca_eq; apply. + by rewrite mem_rcons !inE eqxx !orbT. + apply: edge_covered_set_left_pts. + by rewrite left_fno lstxq /left_limit ptsq. + apply: edge_covered_update_closed_cell=> //. + by apply: (allP close_side_limit); rewrite mem_rcons inE eqxx. + left; exists oc, pcc; repeat (split; first by []); split; last by []. + by rewrite !(mem_cat, inE); move: inold=> /orP[] ->; rewrite ?orbT. + move=> [pcc [P1 [P2 [P3 [P4 P5]]]]]. + rewrite /state_open_seq /state_closed_seq /=. + apply: edge_covered_update_closed_cell => //. + by apply: (allP close_side_limit); rewrite mem_rcons inE eqxx. + by right; exists pcc; repeat (split; first by []); done. +rewrite -/(open_cells_decomposition _ _). +case oe' : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. +have exi2 : exists2 c, c \in (lsto :: lop) & contains_point' (point e) c. + have : contains_point' (point e) lsto. + by rewrite /contains_point' palstol -lstheq /point_under_edge (negbFE ebelow). + by exists lsto;[rewrite inE eqxx | ]. +have := open_cells_decomposition_cat adj rfo sval exi2. +rewrite /= oe' => /(_ palstol)=> oe. +have [ocd [lcc_ctn [all_ct [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vle vhe old_nctn]:= + decomposition_connect_properties rfo sval adj cbtom bet_e oe. +rewrite -/(update_open_cell_top _ _ _). +case uoct_eq: (update_open_cell_top lsto he e) => [nos lno]. +rewrite /state_closed_seq /state_open_seq /= -!catA /=. +move=> g [ | ]; last first. + case ogq : (outgoing e) => [// | fog ogs]; rewrite -ogq => go. + move: uoct_eq; rewrite /update_open_cell_top/generic_trajectories.update_open_cell_top ogq. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [[ | fno nos'] lno']. + have ogn : fog :: ogs != [::] by []. + have := opening_cells_aux_absurd_case vlo vhe ogn. + by rewrite -[X in {in X, _}]ogq oca_eq=> /(_ oute). + rewrite -ogq in oca_eq. + move=> [] <- <-. + have [oc [P1 [P2 P3]]] := opening_cells_aux_cover_outgoing vlo oca_eq go. + left; exists (if oc == fno then + set_left_pts fno (point e :: behead (left_pts lsto)) + else oc), [::]. + split;[by [] | split;[ | split; [by [] | ]]]. + case: ifP => [/eqP ocfno | ocnfno]; last first. + by move=> x; rewrite mem_rcons !inE=> /orP[/eqP -> | ]. + move=> x; rewrite inE -ocfno=> /eqP ->. + by case: (oc) P2. + split. + case: ifP => [/eqP ocfno | ocnfno]. + by rewrite !(mem_cat, inE) eqxx !orbT. + by move: P1; rewrite inE ocnfno /= !(mem_cat, inE)=> ->; rewrite !orbT. + rewrite /=; case: ifP => [ocfno | ocnfno]; last by []. + move: lstxq; rewrite /left_limit ptsq -pxhere /= => <-. + by apply/f_equal/esym/(@eqP pt)/oute. +move=> [ | [pcc [P0 [P1 [P2 [P3 [P4 P5]]]]]]]; last first. + move: uoct_eq; rewrite /update_open_cell_top/generic_trajectories.update_open_cell_top. + case ogq : (outgoing e) => [ | fog ogs]. + move=> [] <- <- /=. + right; exists pcc; split; [by [] | split; last by []]. + move=> x /P1; rewrite !(mem_rcons, inE, mem_cat). + by move=> /orP[] ->; rewrite ?orbT. + rewrite -ogq. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => + [[ | fno nos'] lno']. + have ogn : outgoing e != [::] by rewrite ogq. + have := opening_cells_aux_absurd_case vlo vhe ogn oute. + by rewrite oca_eq. + move=> [] <- <-. + right; exists pcc. + split; first by []. + split; last by []. + move=> x /P1. + by rewrite !(mem_cat, mem_rcons, inE)=> /orP[] ->; rewrite ?orbT. +move=> [oc [pcc [P1 [P2 [P3 [P4 P5]]]]]]. +move: P4; rewrite /open ocd. +move=> ocin. +have olds : [|| oc \in fop, oc \in fc' | (oc \in lc)] -> + edge_covered g (fop ++ fc' ++ nos ++ lno :: lc) + (rcons (closing_cells (point e) (behead cc) ++ lstc :: cls) + (close_cell (point e) lcc)). + move=> ocin'; left; exists oc, pcc. + split. + move=> x /P1; rewrite !(mem_rcons, mem_cat, inE). + by move=> /orP[] ->; rewrite ?orbT. + do 2 (split; first by []). + split; last by []. + rewrite !(mem_cat, inE). + by move: ocin'=> /orP[-> | /orP[] -> ]; rewrite ?orbT. +move: ocin; rewrite -!catA !(mem_cat, inE) => /orP[ocin |]. + by apply: olds; rewrite ocin ?orbT. +move=> /orP[ocin |]; first by apply: olds; rewrite ocin ?orbT. +rewrite orbA=> /orP[ | ocin];last by apply: olds; rewrite ocin ?orbT. +have ealsthe : point e >>= lsthe by rewrite /point_strictly_under_edge eonlsthe. +have ebelow' : point e <<= lsthe by rewrite /point_under_edge (negbFE ebelow). +have := last_step_situation oe' pxhere ealsthe ebelow'. +move=> [-> /= [leo [cc' ccq]] ]. +have ll := lsthe_at_left ebelow'. +rewrite ccq inE -orbA => /orP[/eqP oclsto | ]. + have gq : g = lsthe. + by rewrite lstheq -oclsto P2 // mem_rcons inE eqxx. + have [pcc1 [pcc' pccq]] : exists pcc1 pcc', pcc = pcc1 :: pcc'. + case pccq : pcc => [ | pcc1 pcc']; last by exists pcc1, pcc'. + move: P5; rewrite pccq /= oclsto -lstxq -pxhere => abs. + by rewrite abs gq lt_irreflexive in ll. + right; exists pcc. + split. + by rewrite pccq. + split. + move=> x /P1; rewrite !(mem_rcons, mem_cat, inE). + by move=> /orP[] -> ; rewrite ?orbT. + split. + by move=> x xin; apply: P2; rewrite mem_rcons inE xin orbT. + split. + move: P3; rewrite connect_limits_rcons; last by rewrite pccq. + by move=> /andP[]. + split; first by move: P5; rewrite pccq. + move: P3; rewrite connect_limits_rcons; last by rewrite pccq. + move=> /andP[] _ /eqP ->. + have eon : point e === high lsto. + rewrite -lstheq. + by apply: under_above_on; first rewrite lstheq. + move: (open_non_inner lstoin eon)=> []; last first. + rewrite -lstheq gq oclsto => <-. + by rewrite -lstxq pxhere. + by move: ll=> /[swap] ->; rewrite -lstheq lt_irreflexive. + move=> /orP[ | oclcc]; last first. + have hlnoq : high lno = high lcc. + move: uoct_eq; rewrite /update_open_cell_top/generic_trajectories.update_open_cell_top. + case ogq: (outgoing e) => [| fog ogs]; first by move=> [] _ <- /=. + rewrite -ogq. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [[ | fno nos'] lno']. + have := opening_cells_aux_high_last vle vhe oute'; rewrite leo oca_eq /=. + by move=> /[swap] - [] _ <- => ->. + have := opening_cells_aux_high_last vle vhe oute'; rewrite leo oca_eq /=. + by move=> /[swap] - [] _ <- => ->. + have llno : left_limit lno = p_x (point e). + move: uoct_eq; rewrite /update_open_cell_top/generic_trajectories.update_open_cell_top. + case ogq: (outgoing e) => [| fog ogs]. + have:= size_left_lsto pxhere palstol. + rewrite -lstheq => /(_ ebelow'). + move: lstxq; rewrite /left_limit pxhere => -> + [] _ <- /=. + by case: (left_pts lsto). + rewrite -ogq. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq: opening_cells_aux => [ [ | fno nos'] lno'] [] _ <-; + have := opening_cells_left oute vlo vhe; + rewrite /opening_cells oca_eq=> /(_ lno'); + by rewrite mem_rcons inE eqxx=> /(_ isT). + have vlcc : valid_cell lcc (point e). + by apply/andP/(allP sval); rewrite /open ocd !(mem_cat, inE) eqxx ?orbT. + left; exists lno, (rcons pcc (close_cell (point e) lcc)). + split. + move=> c; rewrite !(mem_rcons, mem_cat, inE)=> /orP[-> |]; first by []. + by move=> /P1; rewrite mem_rcons inE => ->; rewrite !orbT. + split. + move=> c; rewrite mem_rcons inE => /orP[/eqP -> |]. + by rewrite hlnoq; apply: P2; rewrite (eqP oclcc) mem_rcons inE eqxx. + rewrite mem_rcons inE => /orP[/eqP -> | ]. + have [_ -> _] := close_cell_preserve_3sides (point e) lcc. + by rewrite -(eqP oclcc); apply: P2; rewrite mem_rcons inE eqxx. + by move=> cin; apply: P2; rewrite mem_rcons inE cin orbT. + split. + rewrite connect_limits_rcons; last by apply/eqP/rcons_neq0. + rewrite last_rcons close_cell_right_limit // llno eqxx andbT. + case pccq : pcc => [ | pcc1 pcc']; first by []. + rewrite connect_limits_rcons //. + move: P3; rewrite pccq connect_limits_rcons // => /andP[] -> /=. + move=> /eqP ->; rewrite /left_limit (eqP oclcc). + by have [_ _ ->] := close_cell_preserve_3sides (point e) lcc. + split; first by rewrite !mem_cat inE eqxx !orbT. + rewrite /head_cell !head_rcons. + move: P5; rewrite (eqP oclcc) => <-. + case: (pcc) => [ /= | ? ?]; last by []. + by rewrite left_limit_close_cell. +move=> ocin. +have ocin' : oc \in cc by rewrite ccq inE ocin orbT. +have right_pt_e : right_pt (high oc) = point e. + have := open_cells_decomposition_point_on cbtom adj bet_e sval oe ocin'. + have ocop : oc \in open by rewrite /open ocd !mem_cat ocin' ?orbT. + have := open_non_inner ocop; rewrite /non_inner => /[apply]. + move=> [ abs |->]; last by []. + have : high oc \in [seq high c | c <- open] by apply: map_f. + by move=> /lex_open_edges; rewrite abs lexPt_irrefl. +right; exists (rcons pcc (close_cell (point e) oc)). +split. + by apply/eqP/rcons_neq0. +split. + have clocin : close_cell (point e) oc \in closing_cells (point e) cc'. + by apply: map_f. + move=> c; rewrite !(mem_rcons, mem_cat, inE)=> /orP[ /eqP -> | /P1]. + by rewrite clocin ?orbT. + by rewrite mem_rcons inE=> ->; rewrite !orbT. +split. + move=> c; rewrite mem_rcons inE => /orP[/eqP -> | ]. + have [_ -> _] := close_cell_preserve_3sides (point e) oc. + by apply: P2; rewrite mem_rcons inE eqxx. + by move=> cin; apply: P2; rewrite mem_rcons inE cin orbT. +split. + case pccq : pcc => [ | pcc1 pcc']; first by []. + rewrite connect_limits_rcons /left_limit; last by []. + have [_ _ ->] := close_cell_preserve_3sides (point e) oc. + by move: P3; rewrite pccq connect_limits_rcons. +split. + case pccq : pcc => [ | pcc1 pcc'] /=. + move: P5; rewrite pccq /= /left_limit. + by have [_ _ ->] := close_cell_preserve_3sides (point e) oc. + by move: P5; rewrite pccq. +rewrite /last_cell last_rcons close_cell_right_limit; last first. + by apply/andP/(allP sval); rewrite /open ocd !mem_cat ocin' !orbT. +rewrite P2 in right_pt_e; last by rewrite mem_rcons inE eqxx. +by rewrite right_pt_e. +Qed. + +Lemma step_keeps_subset_default: + let '(fc, cc, lcc, lc, le, he) := + open_cells_decomposition open (point e) in + let '(nos, lno) := opening_cells_aux (point e) + (sort (@edge_below _) (outgoing e)) le he in + {subset [seq high c | c <- fc ++ nos ++ lno :: lc] + <= [seq high c | c <- open] ++ outgoing e}. +Proof. +case oe : (open_cells_decomposition _ _) => + [[[[[fc cc] lcc] lc] le] he]. +case oca_eq:(opening_cells_aux _ _ _ _) => [nos lno]. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vl vp nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. +move=> g; rewrite ocd -2!cat_rcons !map_cat /= !(mem_cat, inE). +rewrite orbCA=> /orP[ | gold]; last first. + by apply/orP; left; rewrite orbCA gold orbT. +suff -> : [seq high c | c <- rcons nos lno] =i rcons (outgoing e) he. + by rewrite map_rcons !mem_rcons !inE heq=> /orP[-> | ->]; rewrite !orbT. +have := opening_cells_aux_high vl vp oute'; rewrite oca_eq /=. +rewrite map_rcons=> -> g'; rewrite !mem_rcons !inE mem_sort; congr (_ || _). +by have := opening_cells_aux_high_last vl vp oute'; rewrite oca_eq /= => ->. +Qed. + +Lemma step_keeps_subset : + let s' := step (Bscan fop lsto lop cls lstc lsthe lstx) e in + {subset [seq high c | c <- state_open_seq s'] <= + [seq high c | c <- open] ++ outgoing e}. +Proof. +rewrite /step/=/generic_trajectories.simple_step. +case: ifP => [pxaway | /negbFE/eqP/[dup] pxhere /abovelstle palstol]. + rewrite -/(open_cells_decomposition _ _). + case oe : (open_cells_decomposition _ _) => [[[[[fc cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +rewrite /state_open_seq /= -catA. + by have := step_keeps_subset_default; rewrite oe oca_eq. +case: ifP=> [eabove | ebelow]. + rewrite -/(open_cells_decomposition _ _). + case oe' : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. + have eabove' : point e >>> low (head dummy_cell lop). + have llopq : low (head dummy_cell lop) = lsthe. + apply: esym; rewrite lstheq. + move: (exi' eabove)=> [w + _]. + move: adj=> /adjacent_catW[] _. + by case: (lop) => [ // | ? ?] /andP[] /eqP. + by rewrite llopq. + move: adj rfo sval; rewrite /open -cat_rcons => adj' rfo' sval'. + have := open_cells_decomposition_cat adj' rfo' sval' (exi' eabove) eabove'. + rewrite oe' cat_rcons => oe. + rewrite /state_open_seq /= -!catA /=. + have := step_keeps_subset_default. + by rewrite oe oca_eq; rewrite cat_rcons -!catA. +have ebelow' : point e <<= lsthe by exact (negbFE ebelow). +case: ifP => [ebelow_st | enolsthe]. + have belowo : point e <<< high lsto by rewrite -lstheq. + have := open_cells_decomposition_single adj rfo sval palstol belowo. + move=> oe. + have [ocd [lcc_ctn [_ [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. + have [pal puh vl vp nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. + rewrite /update_open_cell/generic_trajectories.update_open_cell /state_open_seq. + case ogq: (outgoing e) => [ | fog ogs] /=. + have := step_keeps_subset_default; rewrite oe ogq /=. + rewrite !cats0. + do 2 rewrite -/(vertical_intersection_point _ _). + by rewrite (pvertE vl) (pvertE vp) /= !map_cat /=. + have := step_keeps_subset_default; rewrite oe ogq /=. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [ [ | fno nos'] lno'] /=. + have := opening_cells_aux_absurd_case vl vp => /(_ (fog :: ogs) isT). + by rewrite -ogq => /(_ oute); rewrite ogq oca_eq. + move=> main g gin; apply: main; move: gin. + by repeat (rewrite !map_cat /=); rewrite -!catA. +rewrite -/(open_cells_decomposition _ _). +case oe' : (open_cells_decomposition _ _) => [[[[[fc' cc] lcc] lc] le] he]. +rewrite -/(update_open_cell_top _ _ _). +case uoctq: update_open_cell_top => [nos lno]. +rewrite /state_open_seq /= -!catA. +move=> g /mapP [c cin gq]; rewrite gq {gq}. +have exi2 : exists2 c, c \in lsto :: lop & contains_point' (point e) c. + exists lsto; first by rewrite inE eqxx. + by rewrite /contains_point' palstol -lstheq ebelow'. +have := open_cells_decomposition_cat adj rfo sval exi2 palstol. +rewrite oe'=> oe. +have [ocd [lcc_ctn [_ [all_nct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vl vp nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. +have := last_step_situation oe' pxhere (negbT enolsthe) ebelow'. +move=> [fc'0 [leo [cc' ccq]]]. +case ogq : (outgoing e) => [ | fog ogs]; last first. + move: uoctq; rewrite /update_open_cell_top/generic_trajectories.update_open_cell_top. + rewrite -/(opening_cells_aux _ _ _ _). + case oca_eq : (opening_cells_aux _ _ _ _) => [ [ | fno nos'] lno']. + have ogn : outgoing e != [::] by rewrite ogq. + have := opening_cells_aux_absurd_case vlo vp ogn oute. + by rewrite oca_eq. + rewrite ogq. + have := step_keeps_subset_default; rewrite oe. + rewrite leo oca_eq fc'0 cats0 /= -ogq. + move=> main [] nosq lnoq; apply: main. + move: cin; rewrite mem_cat map_cat=> /orP[cin |cin]. + by rewrite mem_cat map_f. + rewrite 2!mem_cat inE fc'0 /= -nosq inE -orbA in cin. + rewrite mem_cat /=; apply/orP; right. + move: cin=> /orP[/eqP -> | cin]. + by rewrite high_set_left_pts inE eqxx. + rewrite inE; apply/orP; right. + by apply/map_f; rewrite mem_cat inE lnoq. +move: uoctq; rewrite /update_open_cell_top/generic_trajectories.update_open_cell_top ogq => -[] nosq lnoq. +move: cin; rewrite /open ocd fc'0 -nosq !cats0 /= mem_cat. +rewrite map_cat inE mem_cat. +move=> /orP[cin | cin]. + by rewrite map_f. +apply/orP; right. +rewrite map_cat mem_cat; apply/orP; right. +move: cin=> /orP[/eqP -> | cin]. + by rewrite -lnoq /= heq inE eqxx. +by rewrite /= inE map_f ?orbT. +Qed. + +(* Keeping as a record that this statement should be proved. However, + since this statement is not used yet, we do not start a proof. *) +Definition TODO_step_keeps_left_pts_inf := + let s' := step (Bscan fop lsto lop cls lstc lsthe lstx) e in + {in state_open_seq s', forall c, lexPt (bottom_left_corner c) (point e)}. + +Lemma step_keeps_left_limit_has_right_limit_default : + let '(fc, cc, lcc, lc, le, he) := + open_cells_decomposition open (point e) in + let '(nos, lno) := opening_cells_aux (point e) + (sort (@edge_below _) (outgoing e)) le he in + {in fc ++ nos ++ lno :: lc, + forall c p, inside_box p -> left_limit c = p_x p -> + contains_point' p c -> + has (inside_closed' p) + (cls ++ lstc :: rcons (closing_cells (point e) cc) + (close_cell (point e) lcc))}. +Proof. +case oe : (open_cells_decomposition _ _) => + [[[[[fc cc] lcc] lc] le] he]. +case oca_eq:(opening_cells_aux _ _ _ _) => [nos lno]. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vl vp nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. +remember (fc ++ nos ++ lno :: lc) as open' eqn:openeq. +remember (cls ++ lstc :: rcons (closing_cells (point e) cc) + (close_cell (point e) lcc)) as closed' eqn:closeeq. +have := invariant1_default_case. + rewrite oe oca_eq => - [] clae' [] sval' [] adj' []cbtom' rfo'. +move=> c cin pt' inboxp lbnd pin. +move: cin; rewrite openeq -cat_rcons !mem_cat orbCA orbC=> /orP[cold | cnew]. + rewrite closeeq -cat_rcons has_cat; apply/orP; left. + apply: (left_limit_has_right_limit _ inboxp lbnd pin). + by rewrite ocd -cat_rcons !mem_cat orbCA cold orbT. +have lcco : lcc \in open. + by rewrite ocd !(mem_cat, inE) eqxx !orbT. +have ppe : p_x pt' = p_x (point e). + have := (opening_cells_left oute vl vp); rewrite /opening_cells oca_eq. + by rewrite -lbnd; apply. +have adjcc : adjacent_cells cc. + by move: adj; rewrite ocd=> /adjacent_catW[] _ /adjacent_catW[]. +have valcc : seq_valid cc (point e). + by apply/allP=> x xin; apply: (allP sval); rewrite ocd !mem_cat xin ?orbT. +have lonew : low (head dummy_cell + (opening_cells (point e) (outgoing e) le he)) = le. + have := adjacent_opening_aux vl vp oute'; rewrite /opening_cells oca_eq. + by move=> /(_ _ _ erefl) []. +have lonew' : head dummy_edge + [seq low c | c <- opening_cells (point e) (outgoing e) le he] = le. + move: (opening_cells_not_nil (outgoing e) le he) lonew. + by set w := opening_cells _ _ _ _; case: w=> [ | a tl]. +have highnew : [seq high i | i <- opening_cells (point e)(outgoing e) le he]= + rcons (sort (@edge_below _) (outgoing e)) he. + by rewrite (opening_cells_high vl vp). +have allval : all (fun g => valid_edge g pt') + (head dummy_edge [seq low i | i <- opening_cells (point e) + (outgoing e) le he] :: + [seq high i | i <- opening_cells (point e) (outgoing e) le he]). + apply/allP=> x; rewrite inE=> xin. + suff : valid_edge x (point e) by rewrite /valid_edge/generic_trajectories.valid_edge ppe. + move: xin=> /orP[/eqP xin | xin]; first by rewrite xin lonew'. + rewrite (opening_cells_high vl vp) // ?mem_rcons inE mem_sort in xin. + case/orP: xin=> [/eqP -> // | xin ]. + apply: valid_edge_extremities; apply/orP; left. + by apply: oute. +set lec := head lcc cc. +have [cc' ccq] : exists cc', rcons cc lcc = lec :: cc'. + rewrite /lec; case: (cc) => [ | a b]; first by exists [::]. + by exists (rcons b lcc). +have lecc : lec \in rcons cc lcc by rewrite ccq inE eqxx. +have lecin : lec \in open. + by rewrite ocd -cat_rcons !mem_cat lecc ?orbT. +have vhlece : valid_edge (high lec) (point e). + by have := seq_valid_high sval (map_f high lecin). +have vhlecp : valid_edge (high lec) pt'. + by move: vhlece; rewrite /valid_edge/generic_trajectories.valid_edge ppe. +move: adj'; rewrite -catA -cat_rcons => + /adjacent_catW[] _ /adjacent_catW[] adjo _. +have adjo' : adjacent_cells (opening_cells (point e) (outgoing e) le he). + by rewrite /opening_cells oca_eq. +have [yle | yabove] := lerP (p_y pt') (p_y (point e)). + have pale : pt' >>> le. + have /mem_seq_split [s1 [s2 s1s2q]] := cnew. + case s1q : s1 => [ | c0 s1']. + move: lonew; rewrite /opening_cells oca_eq s1s2q s1q /= => <-. + by move: pin=> /andP[]. + have lco : low c \in outgoing e. + have := seq_low_high_shift + (opening_cells_not_nil (outgoing e) le he (point e)) + adjo'. + rewrite /opening_cells oca_eq /= s1s2q s1q /= => - []. + rewrite -[RHS]/[seq high i | i <- (c0 :: s1') ++ c :: s2] -s1q -s1s2q. + move: (opening_cells_high vl vp oute); rewrite /opening_cells oca_eq. + move=> ->=> /rcons_inj [] lows _. + have : low c \in [seq low i | i <- s1' ++ c :: s2]. + by apply: map_f; rewrite mem_cat inE eqxx orbT. + by rewrite lows mem_sort. + have vlce : valid_edge (low c) (point e). + by apply: valid_edge_extremities; rewrite (oute lco). + move: pin => /andP[] + _; rewrite under_pvert_y; last first. + by move: vlce; rewrite /valid_edge/generic_trajectories.valid_edge ppe. + rewrite -(same_pvert_y vlce)//. + by rewrite on_pvert ?yle // -(eqP (oute lco)) // left_on_edge. + have plec : contains_point' pt' lec. + rewrite /contains_point' -leq pale. + rewrite under_pvert_y //. + apply: (le_trans yle). + rewrite -(same_pvert_y vhlece)//. + rewrite -under_pvert_y //. + case ccq': cc => [ | cc0 ccs]. + by move: ccq; rewrite ccq' /= => -[] <- _; rewrite -heq; apply/underW. + suff/allct/andP[] : lec \in cc by []. + by move: ccq; rewrite ccq' /= => -[] -> _; rewrite inE eqxx. + have [/eqP lbnd' | safe] := boolP(left_limit lec == p_x pt'). + rewrite closeeq has_cat. + have := (left_limit_has_right_limit lecin inboxp lbnd' plec). + move=> /hasP[x]; rewrite mem_rcons inE => /orP[] xin xP. + by apply/orP; right; apply/hasP; exists x=> //; rewrite inE xin. + by apply/orP; left; apply/hasP; exists x. + have lbnd2 : left_limit lec < p_x pt'. + rewrite lt_neqAle safe /=. + rewrite ppe; apply/lexePt_xW/lexPtW. + by apply: (btm_left lecin). + rewrite closeeq has_cat; apply/orP; right. + apply/hasP; exists (close_cell (point e) lec). + rewrite inE; apply/orP; right; rewrite /closing_cells -map_rcons. + by apply:map_f; rewrite ccq inE eqxx. + have vlec : valid_cell lec (point e). + by apply/andP/(allP sval). + rewrite inside_closed'E /left_limit. + have [-> -> ->]:= close_cell_preserve_3sides (point e) lec. + move: plec=> /andP[] -> ->. + by rewrite (close_cell_right_limit) // lbnd2 ppe lexx. +have plcc : contains_point' pt' lcc. + have puhe : pt' <<= he. + have /mem_seq_split [s1 [s2 s1s2q]] := cnew. + elim /last_ind: {2} (s2) (erefl s2) => [ | s2' c2 _] s2q. + move: highnew; rewrite /opening_cells oca_eq s1s2q s2q cats1 map_rcons. + move=>/rcons_inj[] _ <-. + by move: pin => /andP[]. + have hco : high c \in outgoing e. + have := opening_cells_high vl vp oute. + rewrite /opening_cells oca_eq s1s2q s2q. + rewrite (_ : [seq high i | i <- s1 ++ c :: rcons s2' c2] = + rcons [seq high i | i <- s1 ++ c :: s2'] (high c2)); last first. + by rewrite !map_cat /= map_rcons -!cats1 /= -!catA /=. + move=> /rcons_inj[] his _. + have : high c \in [seq high i | i <- s1 ++ c :: s2']. + by apply: map_f; rewrite mem_cat inE eqxx orbT. + by rewrite his mem_sort. + have vhce : valid_edge (high c) (point e). + by apply: valid_edge_extremities; rewrite (oute hco). + move: (pin) => /andP[] _; rewrite under_pvert_y; last first. + by move: vhce; rewrite /valid_edge/generic_trajectories.valid_edge ppe. + rewrite -(same_pvert_y vhce)// on_pvert; last first. + by rewrite -(eqP (oute hco)) // left_on_edge. + move=> ple. + have ppe': p_y pt' = p_y (point e). + by apply: le_anti; rewrite ple (ltW yabove). + have/eqP -> : pt' == point e :> pt by rewrite pt_eqE ppe ppe' !eqxx. + by apply/underW. + rewrite /contains_point'; rewrite -heq puhe andbT. + have vllcce : valid_edge (low lcc) (point e). + by apply: (seq_valid_low sval); apply/map_f. + have vllccp : valid_edge (low lcc) pt'. + by move: vllcce; rewrite /valid_edge/generic_trajectories.valid_edge ppe. + rewrite under_pvert_y // -?ltNge. + apply: le_lt_trans yabove. + rewrite -(same_pvert_y vllcce)// leNgt -strict_under_pvert_y //. + by have /andP[] := lcc_ctn. +have [/eqP lbnd' | safe] := boolP(left_limit lcc == p_x pt'). + rewrite closeeq has_cat /= orbA. + have := left_limit_has_right_limit lcco inboxp lbnd' plcc. + move/hasP=> [x]; rewrite mem_rcons inE=> /orP[/eqP -> ->| xin xP]. + by rewrite orbT. + by apply/orP; left; apply/orP; left; apply/hasP; exists x. +have lbnd2 : left_limit lcc < p_x pt'. + rewrite lt_neqAle safe /=. + rewrite ppe; apply/lexePt_xW/lexPtW. + by apply: (btom_left_corners lcco). +rewrite closeeq has_cat; apply/orP; right. +apply/hasP; exists (close_cell (point e) lcc). + by rewrite inE mem_rcons inE eqxx ?orbT. +have vlcc : valid_cell lcc (point e). + by apply/andP/(allP sval). +rewrite inside_closed'E /left_limit. +have [-> -> ->]:= close_cell_preserve_3sides (point e) lcc. +move: plcc=> /andP[] -> ->. +by rewrite (close_cell_right_limit) // lbnd2 ppe lexx. +Qed. + +(* This statement is the normal lifting of the previous statement from + the default case to the complete step function. However, this proof + is not used for now, so we make it a definition just to keep in records what + should be the lemma statement. *) +Definition TODO_step_keeps_cover_left_border := + let s' := step (Bscan fop lsto lop cls lstc lsthe lstx) e in + {in state_open_seq s', forall c p, inside_box p -> left_limit c = p_x p -> + contains_point' p c -> + has (inside_closed' p) (state_closed_seq s')}. +(* +Proof. +have [ + [+ [+ []]]] := step_keeps_invariant1. +set open0 := state_open_seq _ => + + + + + step_res c cin pt. +have := step_keeps_left_pts_inf. +have noc' : {in cell_edges open ++ outgoing e &, no_crossing R}. + by move=> g1 g2 g1in g2in; apply: noc; rewrite /= !mem_cat orbA + -2!mem_cat ?g1in ?g2in. +*) + +(* The following statement is not necessary for a safety statement, since a + vertical cell decomposition that returns an empty list of cells would indeed + return only cells whose interior is safe. *) + +Lemma step_keeps_cover_default : + let '(fc, cc, lcc, lc, le, he) := + open_cells_decomposition open (point e) in + let '(nos, lno) := opening_cells_aux (point e) + (sort (@edge_below _) (outgoing e)) le he in + cover_left_of p (fc ++ nos ++ lno :: lc) + (cls ++ lstc :: rcons (closing_cells (point e) cc) + (close_cell (point e) lcc)). +Proof. +case oe : (open_cells_decomposition _ _) => + [[[[[fc cc] lcc] lc] le] he]. +case oca_eq:(opening_cells_aux _ _ _ _) => [nos lno]. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have oc_eq : opening_cells (point e) (outgoing e) le he = rcons nos lno. + by rewrite /opening_cells oca_eq. +have [pal puh vl vp nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. +remember (fc ++ nos ++ lno :: lc) as open' eqn:openeq. +remember (cls ++ lstc :: rcons (closing_cells (point e) cc) + (close_cell (point e) lcc)) as closed' eqn:closeeq. +have := invariant1_default_case. +rewrite oe oca_eq => - [] clae' [] sval' [] adj' []cbtom' rfo'. +have := step_keeps_left_limit_has_right_limit_default. +have := step_keeps_btom_left_corners_default. +rewrite oe oca_eq -openeq. +move=> btm_left' left_border_in'. +move=> q inbox_q limrq. +have [qright | qleft] := boolP(lexPt (point e) q). + rewrite /inside_box in inbox_q. + move: (inbox_q) => /andP[] bet_q _. + have [c cin ctn]:= exists_cell cbtom' adj' bet_q. + move: cin. + + have subpq1 : subpred (lexePt p) (lexePt q). + by move=> x px; apply/(lexePt_trans limrq). + have limr : all (lexePt p) [seq point x | x <- future_events]. + by apply/allP=> x /mapP [ev evc ->]; apply: plexfut. + have limrq1 := sub_all subpq1 limr. + rewrite -catA -cat_rcons !mem_cat orbCA -mem_cat=> /orP[] cin; last first. + have [inc | ninc] := boolP(inside_open' q c). + apply/orP; left; rewrite openeq -cat_rcons !has_cat orbCA -has_cat. + by apply/orP; right; apply/hasP; exists c. + have cin0 : c \in open. + by rewrite ocd -cat_rcons !mem_cat orbCA -mem_cat cin ?orbT. + have cin1 : c \in open'. + by rewrite openeq -cat_rcons !mem_cat orbCA -mem_cat cin orbT. + apply/orP; right. + rewrite closeeq -cat_rcons has_cat; apply/orP; left. + move: ninc; rewrite inside_open'E; rewrite lt_neqAle. + move: (ctn)=> /andP[] -> -> /=. + have -> : left_limit c <= p_x q. + have : p_x (point e) <= p_x q by apply/lexePt_xW/lexPtW. + apply: le_trans. + rewrite /left_limit -[X in X <= _]/(p_x (bottom_left_corner c)). + by apply/lexePt_xW/lexPtW; apply: btm_left. + have -> : p_x q <= open_limit c. + rewrite /open_limit le_min. + have extg : + forall g, g \in [:: bottom; top] -> p_x q <= p_x (right_pt g). + move: inbox_q=> /andP[] _ /andP[] /andP[] _ /ltW + /andP[] _ /ltW. + by move=> A B g; rewrite !inE=> /orP[] /eqP ->. + have intg g : has (event_close_edge g) future_events -> + p_x q <= p_x (right_pt g). + move=>/hasP[] ev' ev'in /eqP ->. + by apply/lexePt_xW/(lexePt_trans limrq)/(allP limr)/map_f. + move: clae'; rewrite -catA -openeq=> /allP /(_ _ cin1) /andP[]. + by move=> /orP[/extg | /intg] -> /orP[/extg | /intg] ->. + rewrite !andbT negbK => /eqP atll. + by apply: (left_limit_has_right_limit _ inbox_q atll ctn). + + have limrq' : forall e, e \in future_events -> lexePt q (point e). + by move/(sub_all subpq1): (limr); rewrite all_map=>/allP. + have [vertp | rightofp] : left_limit c = p_x q \/ left_limit c < p_x q. + have cin' : c \in opening_cells (point e) (outgoing e) le he. + by rewrite oc_eq. + rewrite (opening_cells_left oute vl vp cin'). + move: qright=> /lexPtW/lexePt_xW; rewrite le_eqVlt=> /orP[/eqP -> | ->]. + by left. + by right. + rewrite closeeq (left_border_in' _ _ _ _ vertp ctn) ?orbT //. + by rewrite openeq -cat_rcons !mem_cat cin ?orbT. + apply/orP; left; rewrite openeq -cat_rcons; rewrite !has_cat. + apply/orP; right; apply/orP; left. + apply/hasP; exists c=> //. + rewrite inside_open'E rightofp /open_limit le_min. + have [/andP[_ ->] /andP[_ ->]] : valid_cell c q. + have := opening_valid oute vl vp=> /allP; rewrite oc_eq=> /(_ c cin). + move=> /andP[] vlce vhce. + have := (allP clae' c); rewrite -catA -cat_rcons !mem_cat cin orbT. + move=> /(_ isT). + move=> /andP[] end_edge_lc end_edge_hc. + have := + valid_between_events (lexPtW qright) limrq' vlce inbox_q end_edge_lc. + have := + valid_between_events (lexPtW qright) limrq' vhce inbox_q end_edge_hc. + move=> vhcq vlcq. + by split. + by move: ctn=> /andP[] -> ->. +have qe : p_x q <= p_x (point e). + by apply: lexePt_xW; rewrite lexePtNgt. +have inclosing : forall c, c \in cc -> inside_open' q c -> + (forall c, c \in cc -> valid_edge (low c) (point e) && + (valid_edge (high c) (point e))) -> + exists2 c', c' \in closing_cells (point e) cc & inside_closed' q c'. + move=> c cin ins allval. + exists (close_cell (point e) c). + by apply: map_f. + move: ins; rewrite inside_open'E andbA=>/andP[] ctn /andP[liml _] /=. + move: ctn=>/andP [qlc qhc]. + rewrite /contains_point/close_cell /=. + have [p1 vip1] := exists_point_valid (proj1 (andP (allval _ cin))). + have [p2 vip2] := exists_point_valid (proj2 (andP (allval _ cin))). + have [onl x1] := intersection_on_edge vip1. + have [onh x2] := intersection_on_edge vip2. + by rewrite inside_closed'E vip1 vip2 qlc qhc; case: ifP=> [p1e | p1ne]; + case: ifP=> [p2e | p2ne]; rewrite liml /right_limit /= -?x2 -?x1. +(* TODO : inclosing and inclosel could probably be instances of a single + statement. maybe replacing cc with rcons cc lcc in the statement of + inclosing. *) +have inclosel : inside_open' q lcc -> + inside_closed' q (close_cell (point e) lcc). + rewrite inside_open'E andbA=> /andP[] /andP[qlc qhc] /andP[liml _] /=. + have lccin : lcc \in open by rewrite ocd !mem_cat inE eqxx ?orbT. + have [p1 vip1] := exists_point_valid (proj1 (andP (allP sval _ lccin))). + have [p2 vip2] := exists_point_valid (proj2 (andP (allP sval _ lccin))). + have [onl x1] := intersection_on_edge vip1. + have [onh x2] := intersection_on_edge vip2. + by rewrite inside_closed'E /close_cell vip1 vip2 qlc qhc /=; + case: ifP=> [p1e | p1ne]; case: ifP=> [p2e | p2ne]; + rewrite liml /right_limit /= -?x2 -?x1. +move: qleft; rewrite -lexePtNgt lexePt_eqVlt. +have svalcc : + forall c : cell, + c \in cc -> valid_edge (low c) (point e) && valid_edge (high c) (point e). + by move=> x xin; apply: (allP sval); rewrite ocd !mem_cat xin orbT. +move=> /orP[/eqP qe' | qlte ]. + rewrite qe'. + apply/orP; right; apply/hasP. + set opc := head lcc cc. + have opcin' : opc \in open. + rewrite ocd -cat_rcons !mem_cat orbCA; apply/orP; left. + by rewrite /opc; case: (cc)=> [ | ? ?]; rewrite /= inE eqxx. + have adjcc : adjacent_cells cc. + by move: adj; rewrite ocd => /adjacent_catW[] _ /adjacent_catW[]. + have opc_ctn' : contains_point' (point e) opc. + rewrite /contains_point' -leq pal /=. + case ccq : cc => [ | c1 cc']; rewrite /opc ccq /=. + by rewrite -heq; apply underW. + by have /allct/andP[] : c1 \in cc by rewrite ccq inE eqxx. + have [leftb | ] := + boolP(p_x (last dummy_pt (left_pts opc)) < p_x (point e)); last first. + move=> nleftb. + have := btom_left_corners opcin';rewrite /bottom_left_corner. + rewrite /lexPt (negbTE nleftb) /= => /andP[/eqP sx yl]. + have /hasP[x xin xP] := + left_limit_has_right_limit opcin' inbox_e sx opc_ctn'. + exists x=> //. + by rewrite closeeq -cat_rcons mem_cat xin. + have : inside_open' (point e) opc. + have elt: all (lexePt (point e)) [seq point e0 | e0 <- e :: future_events]. + rewrite /=; rewrite lexePt_eqVlt eqxx /=. + move: sort_evs; rewrite path_sortedE; last exact: lexPtEv_trans. + move=> /andP[cmpE _]; apply/allP=> x /mapP[ev evin ->]. + by apply/lexPtW/(allP cmpE). + by apply: (contains_to_inside_open' sval clae inbox_e leftb). + move: (opc_ctn'). + rewrite -qe'=> einopc einop'. + case ccq : cc => [ | cc1 cc'] /=. + exists (close_cell (point e) lcc). + by rewrite closeeq !(mem_cat, inE, mem_rcons) eqxx ?orbT. + by apply: inclosel; move: einop'; rewrite /opc ccq. + have opcincc : opc \in cc by rewrite /opc ccq /= inE eqxx. + have [it itin itP]:= inclosing opc opcincc einop' svalcc. + exists it; last by []. + by rewrite closeeq mem_cat inE mem_rcons inE itin ?orbT. +have /orP[| already_closed]:= + cover_left_of_e inbox_q (lexPtW qlte); last first. + by rewrite closeeq -cat_rcons has_cat already_closed orbT. +rewrite openeq ocd -2!cat_rcons 2!has_cat orbCA. +move=> /orP[/hasP[opc opcin qinopc] | keptopen]. + move: opcin; rewrite mem_rcons inE=> /orP[opclcc | opcin]; last first. + have [it it1 it2] := inclosing _ opcin qinopc svalcc. + apply/orP; right; apply/hasP. + by exists it=> //; rewrite closeeq !(inE, mem_cat, mem_rcons) it1 ?orbT. + apply/orP; right; apply/hasP; exists (close_cell (point e) lcc). + by rewrite closeeq !(mem_cat, inE, mem_rcons) eqxx ?orbT. + by apply: inclosel; rewrite -(eqP opclcc). +apply/orP; left; apply/hasP. +move: keptopen; rewrite -has_cat=>/hasP[it + it2]. +by rewrite mem_cat=> infclc; exists it; rewrite // !mem_cat orbCA infclc orbT. +Qed. + +Lemma step_keeps_right_limit_closed_default : + let '(fc, cc, lcc, lc, le, he) := + open_cells_decomposition open (point e) in + let '(nos, lno) := opening_cells_aux (point e) + (sort (@edge_below _) (outgoing e)) le he in + {in rcons(cls ++ + lstc :: closing_cells (point e) cc) (close_cell (point e) lcc) & + future_events, forall c e, right_limit c <= p_x (point e)}. +Proof. +case oe : (open_cells_decomposition _ _) => + [[[[[fc cc] lcc] lc] le] he]. +case oca_eq:(opening_cells_aux _ _ _ _) => [nos lno]. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +move=> c ev; rewrite mem_rcons=> cin evin. +suff rl_ev' : right_limit c <= p_x (point e). + apply: (le_trans rl_ev'). + move: sort_evs; rewrite /= path_sortedE; last by apply: lexPtEv_trans. + move=> /andP[] /allP /(_ ev evin) /orP[/ltW // | /andP[] /eqP -> _] _. + by apply: le_refl. +have := sval; rewrite ocd /seq_valid !all_cat=> /andP[] _ /andP[] svalcc /=. +move=> /andP[] /andP[] vllcc vhlcc _. +move: cin; rewrite inE => /orP[/eqP -> | ]. + by have := right_limit_close_cell vllcc vhlcc=> ->; apply: le_refl. +rewrite mem_cat=> /orP[cold | ]. + by apply: closed_right_limit; rewrite mem_rcons inE cold orbT. +rewrite inE=> /orP[cold | ]. + by apply: closed_right_limit; rewrite mem_rcons inE cold. +move=> /mapP [c' c'in ->]. +have /andP[vlc' vhc'] := allP svalcc c' c'in. +by rewrite (right_limit_close_cell vlc' vhc') le_refl. +Qed. + +(* TODO : move to other file *) +Lemma close_cell_in (p' : pt) c : + valid_cell c p' -> + p' \in (right_pts (close_cell p' c): seq pt). +Proof. +move=> [] vl vh. +rewrite /close_cell; rewrite (pvertE vl) (pvertE vh) /=. +by case: ifP=> [/eqP <- | ]; + case: ifP=> [/eqP <- // | _ ]; rewrite !inE eqxx ?orbT. +Qed. + +Lemma last_closing_side_char pp fc cc lcc lc le he : + open_cells_decomposition open (point e) = (fc, cc, lcc, lc, le, he) -> + cc != [::] -> + in_safe_side_right pp (close_cell (point e) lcc) = + [&& p_x pp == p_x (point e), p_y (point e) < p_y pp & pp <<< he]. +Proof. +move=> oe ccn0. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vle vhe nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. +have lccin : lcc \in open by rewrite ocd !(mem_cat, inE) eqxx !orbT. +have /andP [vlcc vhcc] : valid_edge (low lcc) (point e) && + valid_edge (high lcc) (point e) by apply: (allP sval). +have := right_limit_close_cell vlcc vhcc. +rewrite /in_safe_side_right. +move=> ->. +have [/eqP samex /= | ] := boolP (p_x pp == p_x (point e)); last by []. +have [-> -> _] := close_cell_preserve_3sides (point e) lcc. +rewrite -heq. +have eonllcc : (point e) === low lcc. + have := open_cells_decomposition_point_on cbtom adj + (inside_box_between inbox_e) sval oe. + elim /last_ind: {-1} (cc) (erefl cc) ccn0 => [ | cc' cc2 _] ccq // _. + have : cc2 \in rcons cc' cc2 by rewrite mem_rcons mem_head. + move=> + /(_ cc2) =>/[swap] /[apply]. + move: adj; rewrite ocd ccq cat_rcons; do 2 move =>/adjacent_catW[] _. + by move=> /= /andP[] /eqP ->. +have vppl : valid_edge (low lcc) pp by rewrite (same_x_valid _ samex). +have vpphe : valid_edge he pp by rewrite (same_x_valid _ samex). +rewrite (under_pvert_y vppl) (same_pvert_y vppl samex) -ltNge. +rewrite (on_pvert eonllcc). +rewrite (andbC _ (pp <<< he)). +have [ppuh | ] := boolP (pp <<< he); last by []. +have [ppae | ] := boolP (p_y (point e) < p_y pp); last by []. +rewrite /right_pts/close_cell (pvertE vlcc) (pvertE vhcc) /=. +rewrite !pt_eqE !eqxx /=. +rewrite (on_pvert eonllcc) eqxx. +rewrite -heq; move: (puh). +rewrite (strict_under_pvert_y vhe) lt_neqAle eq_sym=>/andP[]/negbTE -> _. +have ppuhy : (p_y pp == pvert_y (point e) he) = false. + apply/negbTE; move: (ppuh). + rewrite (strict_under_pvert_y vpphe) lt_neqAle=> /andP[] + _. + by rewrite (same_pvert_y vpphe samex). +rewrite !(@in_cons pt). +rewrite !pt_eqE ppuhy andbF orbF. +move: ppae; rewrite lt_neqAle eq_sym=>/andP[] /negbTE -> _. +by rewrite andbF. +Qed. + +Lemma first_closing_side_char pp fc cc1 cc lcc lc le he : + open_cells_decomposition open (point e) = (fc, cc1 :: cc, lcc, lc, le, he) -> + in_safe_side_right pp (close_cell (point e) cc1) = + [&& p_x pp == p_x (point e), p_y pp < p_y (point e) & pp >>> le]. +Proof. +move=> oe. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [/= leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vle vhe nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. +have cc1in : cc1 \in open by rewrite ocd !(mem_cat, inE) eqxx !orbT. +have /andP [vlcc1 vhcc1] : valid_edge (low cc1) (point e) && + valid_edge (high cc1) (point e) by apply: (allP sval). +have := right_limit_close_cell vlcc1 vhcc1. +rewrite /in_safe_side_right. +move=> ->. +have [/eqP samex /= | ] := boolP (p_x pp == p_x (point e)); last by []. +have [-> -> _] := close_cell_preserve_3sides (point e) cc1. +rewrite -leq. +have eonhcc1 : (point e) === high cc1. + have := open_cells_decomposition_point_on cbtom adj + (inside_box_between inbox_e) sval oe. + by move=> /(_ cc1 (mem_head _ _)). +have vpph : valid_edge (high cc1) pp by rewrite (same_x_valid _ samex). +have vpple : valid_edge le pp by rewrite (same_x_valid _ samex). +rewrite (strict_under_pvert_y vpph) (same_pvert_y vpph samex). +rewrite (on_pvert eonhcc1). +have [ppue /= | ] := boolP (p_y pp < p_y (point e)); last by []. +have [ppal/= | ] := boolP (pp >>> le); last by []. +rewrite /right_pts/close_cell (pvertE vlcc1) (pvertE vhcc1) /=. +rewrite !pt_eqE !eqxx /=. +rewrite (on_pvert eonhcc1) eqxx. +rewrite -leq; move: (pal). +rewrite (under_pvert_y vle) -ltNge lt_neqAle eq_sym => /andP[] /negbTE -> _. +have ppaly : (p_y pp == pvert_y (point e) le) = false. + apply/negbTE; move: (ppal). + rewrite (under_pvert_y vpple) -ltNge lt_neqAle eq_sym=> /andP[] + _. + by rewrite (same_pvert_y vpple samex). +rewrite !(@in_cons pt) !pt_eqE ppaly andbF. +move: ppue; rewrite lt_neqAle eq_sym=>/andP[] /negbTE -> _. +by rewrite andbF. +Qed. + +Lemma middle_closing_side_char pp fc cc1 cc lcc lc le he : + open_cells_decomposition open (point e) = (fc, cc1 :: cc, lcc, lc, le, he) -> + ~~ has (in_safe_side_right pp) [seq close_cell (point e) c | c <- cc]. +Proof. +move=> oe. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vle vhe nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. +rewrite -all_predC; apply/allP=> c /mapP [c' cin cq] /=. +have /andP[vlc' vhc']: valid_edge (low c') (point e) && + valid_edge (high c') (point e). + by apply: (allP sval); rewrite ocd !(mem_cat, inE) cin !orbT. +have := right_limit_close_cell vlc' vhc'. +have allon := open_cells_decomposition_point_on cbtom adj + (inside_box_between inbox_e) sval oe. +have /allon eonh : c' \in cc1 :: cc by rewrite inE cin orbT. +have eonl : point e === low c'. + have [s1 [s2 ccq]] := mem_seq_split cin. + have := adj; rewrite ocd ccq /= => /adjacent_catW[] _ /=. + rewrite /= cat_path=> /andP[] + _. + rewrite cat_path=> /andP[] _ /= /andP[] /eqP <- _. + by apply: allon; rewrite ccq -cat_cons mem_cat mem_last. +rewrite /in_safe_side_right cq=> ->. +have [-> -> _] := close_cell_preserve_3sides (point e) c'. +have [/eqP samex /= | ] := boolP (p_x pp == p_x (point e)); last by []. +have vpph : valid_edge (high c') pp by rewrite (same_x_valid _ samex). +have vppl : valid_edge (low c') pp by rewrite (same_x_valid _ samex). +rewrite (strict_under_pvert_y vpph) (same_pvert_y vpph samex). +rewrite (on_pvert eonh). +rewrite (under_pvert_y vppl) (same_pvert_y vppl samex). +rewrite (on_pvert eonl). +by case : ltP; rewrite // le_eqVlt=> ->; rewrite orbT andbF. +Qed. + +Lemma mem_no_dup_seq {A: eqType} (s : seq A) : no_dup_seq s =i s. +Proof. +elim: s => [ | a [ | b s] Ih]; first by []. + by []. +rewrite -[no_dup_seq _]/(if a == b then no_dup_seq (b :: s) else + a :: no_dup_seq (b :: s)). +have [ab | anb] := (eqVneq a b). + by move=> c; rewrite Ih !inE ab; case: (c == b). +by move=> c; rewrite 2!inE Ih. +Qed. + +Lemma single_closing_side_char fc lcc lc le he pp : + open_cells_decomposition open (point e) = (fc, [::], lcc, lc, le, he) -> + in_safe_side_right pp (close_cell (point e) lcc) = + ([&& p_x pp == p_x (point e), pp >>> le & p_y pp < p_y (point e)] || + [&& p_x pp == p_x (point e), pp <<< he & p_y (point e) < p_y pp]). +Proof. +move=> oe. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [/= leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vle vhe nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. +have /andP[vllcc vhlcc] : valid_edge (low lcc) (point e) && + valid_edge (high lcc) (point e). + by apply: (allP sval); rewrite ocd /= !(mem_cat, inE) eqxx !orbT. +have [ppe | ppne] := eqVneq (pp : pt) (point e). + rewrite ppe !lt_irreflexive !andbF. + apply /negbTE. + have einr := close_cell_in (conj vllcc vhlcc). + by rewrite /in_safe_side_right einr !andbF. +have := right_limit_close_cell vllcc vhlcc. +rewrite /in_safe_side_right. +move=> ->. +have [/eqP samex /= | ] := boolP (p_x pp == p_x (point e)); last by []. +have [-> -> _] := close_cell_preserve_3sides (point e) lcc. +rewrite -heq -leq. +have puhy : p_y (point e) < pvert_y (point e) he. + by rewrite -(strict_under_pvert_y vhe). +have paly : pvert_y (point e) le < p_y (point e). + by rewrite ltNge -(under_pvert_y vle). +rewrite /close_cell/right_pts -leq -heq (pvertE vle) (pvertE vhe). +rewrite (@mem_no_dup_seq pt) !(@in_cons pt) (negbTE ppne) /=. +have [vpple vpphe] : valid_edge le pp /\ valid_edge he pp. + by rewrite !(same_x_valid _ samex). +have [pu | ] := ltrP (p_y pp) (p_y (point e)). + rewrite !pt_eqE /= andbT samex /=. + rewrite ltNge le_eqVlt pu orbT andbF orbF. + have ppuhe : pp <<< he. + rewrite strict_under_pvert_y // (same_pvert_y _ samex) //. + apply: (lt_trans pu). + by rewrite -strict_under_pvert_y. + rewrite (andbCA _ (pp >>> le)). + have [ppale /= | ] := boolP (pp >>> le); last by []. + have ppaly : (p_y pp == pvert_y (point e) le) = false. + apply/negbTE; move: (ppale). + rewrite (under_pvert_y vpple) -ltNge lt_neqAle eq_sym=> /andP[] + _. + by rewrite (same_pvert_y vpple samex). + have ppuhy : (p_y pp == pvert_y (point e) he) = false. + apply/negbTE; move: (ppuhe). + rewrite (strict_under_pvert_y vpphe) lt_neqAle=> /andP[] + _. + by rewrite (same_pvert_y vpphe samex). + by rewrite ppaly ppuhy ppuhe !eqxx. +rewrite le_eqVlt => /orP[samey | /[dup] pa ->]. + by case/negP: ppne; rewrite pt_eqE samex eq_sym samey !eqxx. +rewrite andbF andbT /=. +have [ppuhe /= | ] := boolP (pp <<< he); last by []. + +rewrite !pt_eqE /= samex /=. +have ppale : pp >>> le. + rewrite under_pvert_y // (same_pvert_y _ samex) // -ltNge. + apply: (lt_trans _ pa). + by rewrite ltNge -under_pvert_y. +have ppaly : (p_y pp == pvert_y (point e) le) = false. + apply/negbTE; move: (ppale). + rewrite (under_pvert_y vpple) -ltNge lt_neqAle eq_sym=> /andP[] + _. + by rewrite (same_pvert_y vpple samex). +have ppuhy : (p_y pp == pvert_y (point e) he) = false. + apply/negbTE; move: (ppuhe). + rewrite (strict_under_pvert_y vpphe) lt_neqAle=> /andP[] + _. + by rewrite (same_pvert_y vpphe samex). +by rewrite ppale ppuhy ppaly !eqxx. +Qed. + +Lemma sides_equiv fc cc lcc lc le he: + open_cells_decomposition open (point e) = (fc, cc, lcc, lc, le, he) -> + forall p, has (in_safe_side_right p) + (rcons (closing_cells (point e) cc) + (close_cell (point e) lcc)) == + has (in_safe_side_left p) + (opening_cells (point e) (outgoing e) le he). +Proof. +move=> oe pp. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [pal puh vle vhe nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. +have [ogq | ogq] := eqVneq (outgoing e) [::]. + rewrite (single_opening_cell_side_char pp vle vhe pal puh ogq). + case ccq : cc => [ | cc1 cc']. + move: (oe); rewrite ccq=> oe'. + by rewrite /= (single_closing_side_char pp oe') orbF. + move: (oe); rewrite ccq=> oe'. + rewrite /= has_rcons. + rewrite (first_closing_side_char pp oe'). + rewrite (negbTE (middle_closing_side_char _ oe')) orbF. + rewrite (last_closing_side_char pp oe'); last by []. + by rewrite (andbC (pp >>> le)) (andbC (pp <<< he)). +rewrite /opening_cells; case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +have oeq : opening_cells (point e) (outgoing e) le he = rcons nos lno. + by rewrite /opening_cells oca_eq. +have := opening_cells_aux_absurd_case vle vhe ogq oute; rewrite oca_eq /=. +case nosq : nos => [ | fno nos'] // _. +move: oeq; rewrite nosq=> oeq. +rewrite /=. +rewrite (first_opening_cells_side_char pp ogq vle vhe pal oute oeq). +rewrite [in X in _ == X]has_rcons. +rewrite (last_opening_cells_safe_side_char pp ogq vle vhe puh oute oeq). +rewrite (negbTE (middle_opening_cells_side_char pp ogq vle vhe oute oeq)) orbF. +case ccq : cc => [ | cc1 cc']. + move: (oe); rewrite ccq=> oe'. + rewrite /= (single_closing_side_char pp oe') orbF. + by rewrite (andbC (_ >>> _)) (andbC (_ <<< _)). +move: (oe); rewrite ccq=> oe'. +rewrite /= has_rcons. +rewrite (first_closing_side_char pp oe'). +rewrite (negbTE (middle_closing_side_char _ oe')) orbF. +by rewrite (last_closing_side_char pp oe'); last by []. +Qed. + +End step. + +End proof_environment. + +Notation open_cell_side_limit_ok := + (@open_cell_side_limit_ok R). + +Lemma inside_box_left_ptsP bottom top p : + open_cell_side_limit_ok (start_open_cell bottom top) -> + inside_box bottom top p -> left_limit (start_open_cell bottom top) < p_x p. +Proof. +move=> sok /andP[] _ /andP[] /andP[] valb _ /andP[] valt _. +rewrite leftmost_points_max //. +by case : (lerP (p_x (left_pt bottom)) (p_x (left_pt top))). +Qed. + +Lemma cell_edges_start bottom top : + cell_edges [::(start_open_cell bottom top)] = [:: bottom; top]. +Proof. by []. Qed. + +Record common_invariant bottom top edge_set s + (events : seq event') := + { inv1 : inv1_seq bottom top events (state_open_seq s); + lstx_eq : lst_x _ _ s = left_limit (lst_open s); + high_lsto_eq : high (lst_open s) = lst_high _ _ s; + edges_sub : {subset all_edges (state_open_seq s) events <= + bottom :: top :: edge_set}; + closed_events : close_edges_from_events events; + out_events : {in events, forall e, out_left_event e}; + inbox_events : all (inside_box bottom top) + [seq point x | x <- events]; + lex_events : sorted (@lexPtEv _) events; + sides_ok : all open_cell_side_limit_ok (state_open_seq s); +}. + +Record common_general_position_invariant bottom top edge_set s + (events : seq event') := + { gcomm : common_invariant bottom top edge_set s events; + general_pos : + all (fun ev => lst_x _ _ s < p_x (point ev)) events && + sorted (fun e1 e2 => p_x (point e1) < p_x (point e2)) events; +}. + +Record common_non_gp_invariant bottom top edge_set s (events : seq event') := + { ngcomm : common_invariant bottom top edge_set s events; + lst_side_lex : + (1 < size (left_pts (lst_open s)))%N && + path (@lexPt _) (nth dummy_pt (left_pts (lst_open s)) 1) + [seq point e | e <- events]}. + +(* This lemma only provides a partial correctness statement in the case + where the events are never aligned vertically. This condition is + expressed by the very first hypothesis. TODO: it relies on the assumption + that the first open cell is well formed. This basically means that the + two edges have a vertical overlap. This statement should be probably + be made clearer in a different way. + + TODO: one should probably also prove that the final sequence of open + cells, here named "open", should be reduced to only one element. *) +Record disjoint_general_position_invariant (bottom top : edge) + (edge_set : seq edge) + (s : scan_state) (events : seq event') := + { op_cl_dis : + {in state_open_seq s & state_closed_seq s, + disjoint_open_closed_cells R}; + cl_dis : {in state_closed_seq s &, disjoint_closed_cells R}; + common_inv_dis : common_general_position_invariant bottom top + edge_set s events; + pairwise_open : pairwise (@edge_below _) + (bottom :: [seq high c | c <- state_open_seq s]); + closed_at_left : + {in state_closed_seq s & events, + forall c e, right_limit c <= p_x (point e)}; + }. + +Definition dummy_state := + Bscan [::] dummy_cell [::] [::] dummy_cell dummy_edge 0. + +Definition initial_state bottom top (events : seq event') := + match events with + | [::] => dummy_state + | ev :: future_events => + let (nos, lno) := + opening_cells_aux (point ev) (sort (@edge_below _) (outgoing ev)) + bottom top in + Bscan nos lno [::] [::] + (close_cell (point ev) (start_open_cell bottom top)) + top (p_x (point ev)) + end. + +Lemma initial_intermediate bottom top s events : +(* sorted (fun e1 e2=> p_x (point e1) < p_x (point e2)) events -> *) + bottom <| top -> + (* TODO: rephrase this statement in a statement that easier to understand. *) + open_cell_side_limit_ok (start_open_cell bottom top) -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + all (inside_box bottom top) [seq point e | e <- events] -> + sorted (@lexPtEv _) events -> + {subset flatten [seq outgoing e | e <- events] <= s} -> + {in events, forall ev, out_left_event ev} -> + close_edges_from_events events -> + events != [::] -> + let op0 := (* close_cell (point (head (dummy_event _) events)) *) + (start_open_cell bottom top) in + all open_cell_side_limit_ok [:: op0] /\ + cells_bottom_top bottom top [:: op0] /\ + adjacent_cells [:: op0] /\ + seq_valid [:: op0] (point (head dummy_event events)) /\ + s_right_form [:: op0] /\ + all (inside_box bottom top) [seq point e | e <- behead events] /\ + close_edges_from_events (behead events) /\ + {in behead events, forall e, out_left_event e} /\ + close_alive_edges bottom top [:: op0] events /\ + valid_edge bottom (point (head dummy_event events)) /\ + valid_edge top (point (head dummy_event events)) /\ + open_cells_decomposition ([::] ++ [:: op0]) + (point (head dummy_event events)) = + ([::], [::], op0, [::], low op0, high op0) /\ + {in bottom :: top :: s &, no_crossing R} /\ + {in all_edges [:: op0] events &, no_crossing R} /\ + pairwise (@edge_below _) (bottom :: [seq high c | c <- [:: op0]]) /\ + sorted (@lexPtEv _) (behead events). +Proof. +move=> boxwf startok nocs' evin lexev evsub out_evs cle. +have nocs : {in bottom :: top :: s &, no_crossing R}. + by apply: inter_at_ext_no_crossing. +case evsq : events => [ | ev future_events]; [by [] | move=> _ /=]. +set op0 := (start_open_cell bottom top). +have op0sok : all open_cell_side_limit_ok ([::] ++ [::op0]). + by rewrite /= /op0 startok. +have cbtom0 : cells_bottom_top bottom top [:: op0]. + by rewrite /op0 /cells_bottom_top/cells_low_e_top/= !eqxx. +have adj0: adjacent_cells [:: op0] by []. +have sval0 : seq_valid [:: op0] (point ev). + move: evin; rewrite evsq /= => /andP[] /andP[] _ /andP[] ebot etop _. + have betW : forall a b c : R, a < b < c -> a <= b <= c. + by move=> a b c /andP[] h1 h2; rewrite !ltW. + by rewrite /= /valid_edge/generic_trajectories.valid_edge /= !betW. +have rf0: s_right_form [:: op0] by rewrite /= boxwf. +have inbox0 : all (inside_box bottom top) [seq point e | e <- future_events]. + by move: evin; rewrite evsq map_cons /= => /andP[]. +have cle0 : close_edges_from_events future_events. + by move: cle; rewrite evsq /= => /andP[]. +have oute0 : {in future_events, forall e, out_left_event e}. + by move=> e ein; apply: out_evs; rewrite evsq inE ein orbT. +have clae0 : close_alive_edges bottom top [:: op0] (ev :: future_events). + by rewrite /=/end_edge_ext !inE !eqxx !orbT. +have noc0 : {in all_edges [:: op0] (ev :: future_events) &, no_crossing R}. + rewrite /=; move: nocs; apply sub_in2. + move=> x; rewrite -evsq !inE. + move=> /orP[ -> // | /orP[-> // | ]]; rewrite ?orbT //. + by move=> /evsub ->; rewrite !orbT. +have [vb vt] : valid_edge bottom (point ev) /\ valid_edge top (point ev). + have /(allP sval0) : start_open_cell bottom top \in [:: op0]. + by rewrite inE eqxx. + by rewrite /= => /andP[]. +have /andP[/andP[pal puh] _] : inside_box bottom top (point ev). + by apply: (@allP pt _ _ evin); rewrite evsq map_f// inE eqxx. +have : open_cells_decomposition [:: op0] (point ev) = + ([::], [::], op0, [::], bottom, top). + apply: (open_cells_decomposition_single + (isT : adjacent_cells ([::] ++ [:: op0])) rf0 sval0 pal puh). +have pw0 : pairwise (@edge_below _) (bottom :: [seq high c | c <- [::op0]]). + by rewrite /= !andbT /=. +have lexev0 : sorted (@lexPtEv _) future_events. + by move: lexev; rewrite evsq=> /path_sorted. +do 15 (split; first by []). +by []. +Qed. + +Lemma initial_common_invariant bottom top s events: + bottom <| top -> + (* TODO: rephrase this statement in a statement that easier to understand. *) + open_cell_side_limit_ok (start_open_cell bottom top) -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + all (inside_box bottom top) [seq point e | e <- events] -> + sorted (@lexPtEv _) events -> + {subset flatten [seq outgoing e | e <- events] <= s} -> + {in events, forall ev, out_left_event ev} -> + close_edges_from_events events -> + events != [::] -> + common_invariant bottom top s + (initial_state bottom top events) (behead events). +Proof. +move=> boxwf startok nocs' evin lexev evsub out_evs cle evsn0. +have := + initial_intermediate boxwf startok nocs' evin lexev evsub out_evs cle evsn0. +case evsq : events evsn0 => [ | ev future_events]; [by [] | move=> _]. +move=> [op0sok [cbtom0 [adj0 /= + [sval0 [rf0 [inbox0 [cle0 [oute0 [clae0 [vb + [vt [oe [nocs [noc0 [pw0 lexev0]]]]]]]]]]]]]]]. +have evins : ev \in events by rewrite evsq inE eqxx. +set op0 := start_open_cell bottom top. +case oca_eq: (opening_cells_aux _ _ _ _) => [nos lno]. +set w := Bscan _ _ _ _ _ _ _. +have [state1 ] : exists state1, state1 = w by exists w. +rewrite /w => {w} st1q. +set cl0 := lst_closed state1. +set ops0 := [::] ++ [:: op0]. +have evsin0 : all (inside_box bottom top) [seq point ev | ev <- events]. + exact: evin. +have oute : out_left_event ev by apply: out_evs. +have oute' : {in sort (@edge_below _) (outgoing ev), forall g, + left_pt g == point ev}. + by move=> g; rewrite mem_sort; apply: oute. +have edges_sub1 : {subset all_edges (rcons nos lno) + future_events <= [:: bottom, top & s]}. + move=> g; rewrite mem_cat=> /orP[ | gfut ]; last first. + have /evsub {}gfut : g \in events_to_edges events. + by rewrite evsq events_to_edges_cons mem_cat gfut orbT. + by rewrite !inE gfut; rewrite !orbT. + have := opening_cells_subset vb vt oute. + rewrite /opening_cells oca_eq=> main. + rewrite mem_cat=> /orP[] /mapP [c /main + ->] => /andP[]; rewrite !inE. + move=> /orP[-> | +] _; first by rewrite ?orbT. + move=> {}main; apply/orP; right; apply/orP; right. + by apply/evsub/flattenP; exists (outgoing ev); rewrite // map_f. + move=> _ /orP[-> |]; first by rewrite ?orbT. + move=> {}main; apply/orP; right; apply/orP; right. + by apply/evsub/flattenP; exists (outgoing ev); rewrite // map_f. +have pin : inside_box bottom top (point ev). + by apply: (@allP pt _ _ evin); rewrite evsq /= inE eqxx. +have inbox_all_events0 : + all (inside_box bottom top) [seq point x | x <- (ev :: future_events)]. + by move: evin; rewrite evsq. +have evlexfut : path (@lexPtEv _) ev future_events. + by move: lexev; rewrite evsq. +have rf0' : s_right_form ([::] ++ [:: start_open_cell bottom top]) by []. +have cle0' : close_edges_from_events (ev :: future_events) by rewrite -evsq. +have := invariant1_default_case + inbox_all_events0 oute rf0' cbtom0 adj0 sval0 cle0' clae0 noc0 + evlexfut. +rewrite oe oca_eq /=. +move=> /[dup] inv1 -[] clae1 [] sval' [] adj1 [] cbtom1 rf1. +have rl0 : {in [::], forall c : cell, right_limit c <= p_x (point ev)} by []. +have cl0q : cl0 = close_cell (point ev) op0 by rewrite /cl0 st1q. +rewrite -cats1 in edges_sub1 sval'. +have lstx1op : lst_x _ _ state1 = left_limit (lst_open state1). + have := opening_cells_left oute vb vt; rewrite /opening_cells. + by rewrite oca_eq st1q => -> //=; rewrite mem_rcons inE eqxx. +have he1q' : high (lst_open state1) = lst_high _ _ state1. + rewrite st1q /=. + by have := opening_cells_aux_high_last vb vt oute'; rewrite oca_eq. +move: lstx1op he1q'; rewrite st1q=> lstx1op he1q'. +have oks1 : all open_cell_side_limit_ok (nos ++ [:: lno]). + have := pin => /andP[] /andP[] /underWC pal puh _. + have := opening_cells_side_limit vb vt pal puh oute. + by rewrite /opening_cells oca_eq cats1. +by constructor. +Qed. + +Lemma initial_common_general_position_invariant bottom top s events: + sorted (fun e1 e2=> p_x (point e1) < p_x (point e2)) events -> + bottom <| top -> + (* TODO: rephrase this statement in a statement that easier to understand. *) + open_cell_side_limit_ok (start_open_cell bottom top) -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + all (inside_box bottom top) [seq point e | e <- events] -> + sorted (@lexPtEv _) events -> + {subset flatten [seq outgoing e | e <- events] <= s} -> + {in events, forall ev, out_left_event ev} -> + close_edges_from_events events -> + events != [::] -> + common_general_position_invariant bottom top s + (initial_state bottom top events) (behead events). +Proof. +move=> ltev boxwf startok nocs' evin lexev evsub out_evs cle evsn0. +have ici := initial_common_invariant boxwf startok nocs' evin lexev evsub + out_evs cle evsn0. +constructor; first by exact: ici. +case evsq : events => [ | ev1 evs] //. +move: ltev; rewrite evsq /=. +rewrite path_sortedE; last by move=> x y z; apply: lt_trans. +move=> /andP[] + ->; rewrite andbT. +rewrite /initial_state /=. +by case oca_eq: (opening_cells_aux _ _ _ _). +Qed. + +Lemma opening_cells_aux_event le he p gs nos lno : + valid_edge le p -> + valid_edge he p -> + p >>= le -> + p <<< he -> + {in gs, forall g, left_pt g == p} -> + opening_cells_aux p gs le he = (nos, lno) -> + (1 < size (left_pts lno))%N /\ + nth dummy_pt (left_pts lno) 1 = p. +Proof. +move=> vle vhe; elim: gs le vle nos lno=> + [ | g1 gs Ih] le vle nos lno pal puh oute /=. + rewrite -/(vertical_intersection_point p le) (pvertE vle). + rewrite -/(vertical_intersection_point p he) (pvertE vhe). + case: ifP=> [/eqP abs1 | dif1 //]; last first. + case: ifP=> [/eqP abs2 | dif2 //]; last first. + by move=> [] _ <- /=. + by move=> [] _ <- /=; split; [ | rewrite -abs2]. + move=> [] _. + rewrite (strict_under_pvert_y vhe) ltNge in puh. + move: puh => /negP; case. + by rewrite on_pvert // -abs1 pvert_on. +case oca_eq : (opening_cells_aux p gs g1 he) => [no1 lno1]. +rewrite -/(vertical_intersection_point p le) (pvertE vle). +have g1q : left_pt g1 = p. + have g1in : g1 \in g1 :: gs by rewrite inE eqxx. + by rewrite (eqP (oute g1 g1in)). +have vg : valid_edge g1 p. + by rewrite -g1q valid_edge_left. +case: ifP => [/eqP ponl | dif]; last first. + move=> [] A <-. + apply: (Ih g1 vg no1)=> //. + by rewrite -g1q; apply: left_pt_above. + by move=> g gin; apply: oute; rewrite inE gin orbT. +move=> [] _ <-. +apply: (Ih g1 vg no1)=> //. + by rewrite -g1q; apply: left_pt_above. +by move=> g gin; apply: oute; rewrite inE gin orbT. +Qed. + +Lemma sorted_cat_rcons [T : Type] (rel : rel T) s1 e s2 : + sorted rel ((rcons s1 e) ++ s2) = + sorted rel (rcons s1 e) && path rel e s2. +Proof. +elim: s1 => [ | e1 s1 Ih] //. +by rewrite /= cat_path last_rcons. +Qed. + +Lemma initial_common_non_gp_invariant bottom top s events: + bottom <| top -> + (* TODO: rephrase this statement in a statement that easier to understand. *) + open_cell_side_limit_ok (start_open_cell bottom top) -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + all (inside_box bottom top) [seq point e | e <- events] -> + sorted (@lexPtEv _) events -> + {subset flatten [seq outgoing e | e <- events] <= s} -> + {in events, forall ev, out_left_event ev} -> + close_edges_from_events events -> + events != [::] -> + common_non_gp_invariant bottom top s + (initial_state bottom top events) (behead events). +Proof. +move=> boxwf startok nocs' evin lexev evsub out_evs cle evsn0. +have ici := initial_common_invariant boxwf startok nocs' evin lexev evsub + out_evs cle evsn0. +constructor; first by exact: ici. +case evsq : events evsn0 => [ | ev1 evs] //= _. +case oca_eq: (opening_cells_aux _ _ _ _) => [nos lno]. +have oute1 : out_left_event ev1. + by apply: out_evs; rewrite evsq inE eqxx. +have oute1' : {in sort (@edge_below _) (outgoing ev1), forall g, + left_pt g == point ev1}. + by move=> g; rewrite mem_sort; apply: oute1. +have := sides_ok ici. +rewrite /initial_state evsq oca_eq /state_open_seq/= all_cat /= andbT. +move=> /andP[] _; rewrite /open_cell_side_limit_ok. +move=> /andP[] _ /andP[] samex /andP[] srt _. +have ev1in : inside_box bottom top (point ev1). + by apply: (allP evin); rewrite evsq map_f // inE eqxx. +have [vb vt] : valid_edge bottom (point ev1) /\ valid_edge top (point ev1). + by rewrite !(inside_box_valid_bottom_top ev1in) // !inE eqxx ?orbT. +move: (ev1in); rewrite /inside_box=> /andP[] /andP[] /underWC ev1a ev1u _. +have [] := opening_cells_aux_event vb vt ev1a ev1u oute1' oca_eq. +case lptsq : (left_pts lno) => [ | p1 [ | p2 ps]] //= _ p2q. +rewrite p2q path_map. +by move: lexev; rewrite evsq /=. +Qed. + +Lemma initial_disjoint_general_position_invariant + bottom top s events: + sorted (fun e1 e2=> p_x (point e1) < p_x (point e2)) events -> + bottom <| top -> + (* TODO: rephrase this statement in a statement that easier to understand. *) + open_cell_side_limit_ok (start_open_cell bottom top) -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + all (inside_box bottom top) [seq point e | e <- events] -> + sorted (@lexPtEv _) events -> + {subset flatten [seq outgoing e | e <- events] <= s} -> + {in events, forall ev, out_left_event ev} -> + close_edges_from_events events -> + events != [::] -> + disjoint_general_position_invariant bottom top s + (initial_state bottom top events) + (* (head (dummy_event _) events) *) (behead events). +Proof. +move=> ltev boxwf startok nocs' evin lexev evsub out_evs cle evsn0. +have := initial_common_general_position_invariant ltev boxwf startok + nocs' evin lexev evsub out_evs cle evsn0. +have := initial_intermediate boxwf startok nocs' evin lexev evsub + out_evs cle evsn0. +move: evsn0; case evsq : events => [ | ev evs];[by [] | move=> _]. +lazy zeta; rewrite [head _ _]/= [behead _]/=. +move=> -[] op0sok [cbtom0 [adj0 [sval0 [rf0 [inbox0 +[cle0 [oute0 [clae0 [vb [vt [oe [nocs [noc0 [pw0 lexev0]]]]]]]]]]]]]]. +have evins : ev \in events by rewrite evsq inE eqxx. +rewrite /initial_state /state_open_seq/state_closed_seq/= => Cinv. +case oca_eq: (opening_cells_aux _ _ _ _) Cinv => [nos lno] Cinv. +move: (Cinv)=> -[] []; rewrite /state_open_seq/state_closed_seq/=. +move=> inv1 pxe hlno edges_sub1 cle1 oute1 inbox1 lexevs sok1 gen_pos. +set op0 := start_open_cell bottom top. +have op0_cl0_dis : {in [:: op0] & [::], disjoint_open_closed_cells R} by []. +have inbox0' : all (inside_box bottom top) [seq point e | e <- ev :: evs]. + by rewrite -evsq. +have cl0_dis : {in [::] &, disjoint_closed_cells R} by []. +have rl0 : {in [::], forall c : cell, right_limit c <= p_x (point ev)} by []. +have := @step_keeps_disjoint_default bottom top ev [::] + op0 [::] evs inbox0' (out_evs _ evins) rf0 cbtom0 adj0 + sval0 pw0 op0sok [::] op0_cl0_dis cl0_dis rl0. + rewrite oe oca_eq /= => -[] cl_dis1 op_cl_dis1. +have pw1 : pairwise (@edge_below _) + (bottom:: [seq high c | c <- (nos ++ [:: lno ])]). + have rf0' : s_right_form ([::] ++ [:: op0]) by []. + have := step_keeps_pw_default inbox0' (out_evs _ evins) rf0' cbtom0 adj0 + sval0 noc0 pw0. + by rewrite oe oca_eq. +have rl_closed1 : {in [:: close_cell (point ev) op0] & evs, + forall c e, right_limit c <= p_x (point e)}. + have vho : valid_edge (high op0) (point ev) by []. + have vlo : valid_edge (low op0) (point ev) by []. + have := right_limit_close_cell vlo vho=> rlcl0 c e. + rewrite inE=> /eqP ->. + move: lexev; rewrite evsq /= path_sortedE; last by apply: lexPtEv_trans. + move=> /andP[] + _=> /allP /[apply]. + rewrite rlcl0=> /orP[]; first by move/ltW. + by move=> /andP[] /eqP -> _; apply: le_refl. +by constructor. +Qed. + +Lemma simple_step_common_invariant + bottom top s fop lsto lop fc cc lcc lc le he cls lstc ev + lsthe lstx evs : + bottom <| top -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + {in s, forall g, inside_box bottom top (left_pt g) && + inside_box bottom top (right_pt g)} -> + open_cells_decomposition (fop ++ lsto :: lop) (point ev) = + (fc, cc, lcc, lc, le, he) -> + common_invariant bottom top s + (Bscan fop lsto lop cls lstc lsthe lstx) + (ev :: evs) -> + common_invariant bottom top s + (simple_step fc cc lc lcc le he cls lstc ev) + evs. +Proof. +move=> boxwf nocs' inbox_s oe. +move=> []; rewrite /state_open_seq/state_closed_seq/=. +move=> inv lstxq lstheq sub_edges cle out_es /[dup] inbox0. +move=> /andP[] inbox_e inbox_es. +move=> lexev oks. +move: (inv)=> [] clae [] []; first by []. +move=> sval [] adj [] cbtom rfo. +have oute : out_left_event ev. + by apply: out_es; rewrite inE eqxx. +have oute' : {in sort (@edge_below _) (outgoing ev), + forall g, left_pt g == point ev}. + by move=> g; rewrite mem_sort; apply: oute. +have nocs : {in bottom :: top :: s &, no_crossing R}. + by apply: inter_at_ext_no_crossing. +have noco : {in all_edges (fop ++ lsto :: lop) (ev :: evs) &, + no_crossing R}. + by move=> g1 gt2 g1in g2in; apply: nocs; apply: sub_edges. +rewrite /simple_step/generic_trajectories.simple_step. +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +have inv' : inv1_seq bottom top evs ((fc ++ nos) ++ lno :: lc). + have := invariant1_default_case inbox0 oute rfo cbtom adj sval cle clae + noco lexev. + by rewrite oe oca_eq. +have := inv' => -[] clae' [] sval' [] adj' []cbtom' rfo'. +have exi := exists_cell cbtom adj (inside_box_between inbox_e). +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. +have [{}pal {}puh vl vp nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. +have /esym left_last : left_limit lno = p_x (point ev). + apply: (opening_cells_left oute vl vp). + by rewrite /opening_cells oca_eq mem_rcons inE eqxx. +have heqo : high lno = he. + by have := opening_cells_aux_high_last vl vp oute'; rewrite oca_eq. +have sub_edges' : {subset all_edges ((fc ++ nos) ++ lno :: lc) evs <= + [:: bottom, top & s]}. + have := step_keeps_subset_default inbox0 oute rfo cbtom adj sval. + rewrite oe oca_eq !catA /= /all_edges => main g. + rewrite mem_cat=> /orP[ | gin]; last first. + apply: sub_edges; rewrite mem_cat; apply/orP; right. + by rewrite events_to_edges_cons mem_cat gin orbT. + rewrite (cell_edges_sub_high cbtom' adj') inE=> /orP[/eqP -> | /main]. + by rewrite inE eqxx. + rewrite mem_cat=> /orP[] gin; apply: sub_edges; last first. + by rewrite mem_cat events_to_edges_cons orbC mem_cat gin. + by rewrite mem_cat mem_cat gin orbT. +have cle' : close_edges_from_events evs by move: cle=> /andP[]. +have out_es' : {in evs, forall e, out_left_event e}. + by move=> e ein; apply: out_es; rewrite inE ein orbT. +have lexev' : sorted (@lexPtEv _) evs by move: lexev=> /path_sorted. +have oks' : all open_cell_side_limit_ok ((fc ++ nos) ++ lno :: lc). + have := step_keeps_open_side_limit_default inbox0 oute rfo + cbtom adj sval oks; rewrite oe oca_eq. + by []. +by constructor. +Qed. + +Lemma simple_step_common_general_position_invariant + bottom top s fop lsto lop fc cc lcc lc le he cls lstc ev + lsthe lstx evs : + bottom <| top -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + {in s, forall g, inside_box bottom top (left_pt g) && + inside_box bottom top (right_pt g)} -> + open_cells_decomposition (fop ++ lsto :: lop) (point ev) = + (fc, cc, lcc, lc, le, he) -> + common_general_position_invariant bottom top s + (Bscan fop lsto lop cls lstc lsthe lstx) + (ev :: evs) -> + common_general_position_invariant bottom top s + (simple_step fc cc lc lcc le he cls lstc ev) + evs. +Proof. +move=> boxwf nocs' inbox_s oe. +move=> [] comi /andP[] lstxlt ltev'. +have comi' := (simple_step_common_invariant boxwf nocs' inbox_s oe comi). +have ltev1 : all (fun e => + lst_x _ _ (simple_step fc cc lc lcc le he cls lstc ev) < + p_x (point e)) evs && + sorted (fun e1 e2 => p_x (point e1) < p_x (point e2)) evs. + rewrite (lstx_eq comi'). + have oute : out_left_event ev by apply: (out_events comi); rewrite inE eqxx. + have [_ [sval' [adj [cbtom rfo]]]] := inv1 comi. + have /= /andP[inbox_e inbox_es] := inbox_events comi. + have sval : seq_valid + (state_open_seq (Bscan fop lsto lop cls lstc lsthe lstx)) + (point ev). + by case sval'; first done. + have [{}pal {}puh vl vp nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. + have := opening_cells_left oute vl vp. + rewrite /opening_cells/simple_step/generic_trajectories.simple_step. + rewrite -/(opening_cells_aux (point ev) (sort (@edge_below _) (outgoing ev)) + le he). + case oca_eq : opening_cells_aux => [nos lno] /=. + have lnoin : lno \in rcons nos lno by rewrite mem_rcons inE eqxx. + move => /(_ _ lnoin) ->. + move: ltev'; rewrite /= path_sortedE //. + by move=> x y z; apply: lt_trans. +by constructor. +Qed. + +Lemma same_x_point_above_low_lsto bottom top s fop lsto lop cls lstc + ev lsthe lstx evs : + lstx = p_x (point ev) -> + common_non_gp_invariant bottom top s + (Bscan fop lsto lop cls lstc lsthe lstx) (ev :: evs) -> + point ev >>> low lsto. +Proof. +move=> at_lstx comng. +have comi := ngcomm comng. +have lstx_ll : lstx = left_limit lsto. + rewrite -[lstx]/(lst_x _ _ (Bscan fop lsto lop cls lstc lsthe lstx)). + by rewrite (lstx_eq comi). +have := lst_side_lex comng. +set W := (X in size X); rewrite -/W. +have : open_cell_side_limit_ok lsto. + by apply: (allP (sides_ok comi)); rewrite mem_cat inE eqxx orbT. +rewrite /open_cell_side_limit_ok => /andP[] _ /andP[] + /andP[] + /andP[]. +move=> + + _ +. +rewrite -/W. + case wq : W => [ | p1 [ | p2 ps]] //= A /andP[] _ higherps + /andP[] ll _. + move: A => /andP[] _ /andP[] p2x allx. + have lx : p_x (last p2 ps) == left_limit lsto. + case : (ps) allx => [ | p3 pst] // /allP; apply=> /=. + by rewrite mem_last. + have samex : p_x (point ev) = p_x (last p2 ps). + by rewrite -at_lstx lstx_ll (eqP lx). + have cmpy : p_y (last p2 ps) <= p_y p2. + case psq : ps => [ | p3 pst] //. + apply ltW. + rewrite (path_sortedE (rev_trans lt_trans)) psq in higherps. + move: higherps=> /andP[] /allP /(_ (p_y (last p3 pst))) + _. + rewrite map_f; last by rewrite mem_last. + by move=> /(_ isT). + move=> /(under_edge_lower_y samex) ->. + rewrite -ltNge. + apply: (le_lt_trans cmpy). + move: ll; rewrite /lexPt. + by rewrite lt_neqAle samex (eqP p2x) eq_sym lx /=. +Qed. + +Lemma update_open_cell_common_invariant + bottom top s fop lsto lop cls lstc ev + lsthe lstx evs : + bottom <| top -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + {in s, forall g, inside_box bottom top (left_pt g) && + inside_box bottom top (right_pt g)} -> + lstx = p_x (point ev) -> + (point ev) <<< lsthe -> + common_non_gp_invariant bottom top s + (Bscan fop lsto lop cls lstc lsthe lstx) + (ev :: evs) -> + common_invariant bottom top s + (step (Bscan fop lsto lop cls lstc lsthe lstx) ev) + evs. +Proof. +move=> bxwf nocs' inbox_s at_lstx under_lsthe comng. +have comi := ngcomm comng. +rewrite /step/generic_trajectories.step. +rewrite /same_x at_lstx eqxx /=. +rewrite -/(point_under_edge _ _) underW /=; last by []. +rewrite -/(point ev <<< lsthe) under_lsthe. +have oute : out_left_event ev. + by apply: (out_events comi); rewrite inE eqxx. +have oute' : {in sort (@edge_below _) (outgoing ev), + forall g, left_pt g == point ev}. + by move=> g; rewrite mem_sort; apply: oute. +have [clae [sval' [adj [cbtom rfo]]]] := inv1 comi. +have sval : seq_valid (state_open_seq (Bscan fop lsto lop cls lstc lsthe lstx)) + (point ev). + by case: sval'. +have lstx_ll : lstx = left_limit lsto. + rewrite -[lstx]/(lst_x _ _ (Bscan fop lsto lop cls lstc lsthe lstx)). + by rewrite (lstx_eq comi). +have pal : (point ev) >>> low lsto. + by exact: (same_x_point_above_low_lsto at_lstx comng). +have abovelow : p_x (point ev) = lstx -> (point ev) >>> low lsto by []. +have noc : {in all_edges (fop ++ lsto :: lop) (ev :: evs) &, + no_crossing R}. + apply: inter_at_ext_no_crossing. + by apply: (sub_in2 (edges_sub comi) nocs'). +have lstoin : lsto \in (fop ++ lsto :: lop). + by rewrite mem_cat inE eqxx orbT. +have sok : open_cell_side_limit_ok lsto. + by apply: (allP (sides_ok comi)); exact: lstoin. +have xev_llo : p_x (point ev) = left_limit lsto. + by rewrite -at_lstx -(lstx_eq comi). +have puho : point ev <<< high lsto. + move: under_lsthe. + rewrite -[lsthe]/(lst_high _ _ (Bscan fop lsto lop cls lstc lsthe lstx)). + by rewrite -(high_lsto_eq comi). +have [vl vh] := (andP (allP sval lsto lstoin)). +have sll : (1 < size (left_pts lsto))%N. + by apply: (size_left_lsto sval lstx_ll (sides_ok comi) (esym at_lstx) pal + (underW puho)). +have ogsub : {subset (outgoing ev) <= [:: bottom, top & s]}. + move=> g gin; apply: (edges_sub comi); rewrite /all_edges mem_cat. + by apply/orP; right; rewrite events_to_edges_cons mem_cat gin. +constructor. +- have := step_keeps_invariant1 cls lstc (inbox_events comi) oute rfo cbtom adj + sval + (closed_events comi) clae (esym (high_lsto_eq comi)) abovelow noc + (lex_events comi). + rewrite /step /generic_trajectories.step/same_x -at_lstx eqxx /=. + rewrite -/(point_under_edge _ _) underW /=; last by []. + by rewrite -/(point ev <<< lsthe) under_lsthe. +- rewrite -/(update_open_cell lsto ev). + case uoc_eq : update_open_cell => [nos lno] /=. + have [case1 | case2]:= update_open_cellE2 oute vl vh sok xev_llo sll pal puho. + apply/esym. + have := opening_cells_left oute vl vh. + rewrite /opening_cells; move: case1; case: opening_cells_aux=> [nos' lno']. + rewrite uoc_eq /= => <- /(_ lno). + by apply; rewrite mem_rcons inE eqxx. + move: case2; rewrite uoc_eq /= => ->. + by rewrite (add_point_left_limit _ sll). +- rewrite -/(update_open_cell lsto ev). + case uoc_eq : update_open_cell => [nos lno] /=. + have [case1 | case2]:= update_open_cellE2 oute vl vh sok xev_llo sll pal puho. + rewrite uoc_eq /= in case1; rewrite case1. + have := opening_cells_aux_high_last vl vh oute'. + case: opening_cells_aux => [lno' nos'] /= => ->. + by apply: (high_lsto_eq comi). + rewrite uoc_eq /= in case2; rewrite case2. + rewrite high_set_left_pts. + by apply: (high_lsto_eq comi). +have llin : low lsto \in [:: bottom, top & s]. + apply: (edges_sub comi); rewrite /all_edges mem_cat /state_open_seq /=. + by rewrite cell_edges_cat mem_cat cell_edges_cons inE eqxx !orbT. +have hlin : high lsto \in [:: bottom, top & s]. + apply: (edges_sub comi); rewrite /all_edges mem_cat /state_open_seq /=. + by rewrite cell_edges_cat mem_cat cell_edges_cons !inE eqxx !orbT. +- rewrite -/(update_open_cell lsto ev). + case uoc_eq : update_open_cell => [nos lno]. + rewrite /all_edges /state_open_seq /=. + apply: subset_catl; last first. + move=> g gin; apply: (edges_sub comi); rewrite /all_edges. + by rewrite mem_cat orbC events_to_edges_cons mem_cat gin orbT. + move=> g; rewrite cell_edges_cat mem_cat cell_edges_cons 2!inE. + rewrite cell_edges_cat mem_cat -!orbA=> /orP[gin | ] . + apply: (edges_sub comi); rewrite /state_open_seq /= /all_edges mem_cat. + by rewrite cell_edges_cat mem_cat gin. + move=> /orP[gin | ]. + have [c cin gq] : exists2 c, c \in nos & g = high c \/ g = low c. + move: gin; rewrite mem_cat=> /orP[] /mapP[c cin gq]; exists c=> //. + by right. + by left. + have := update_open_cellE1 oute vl vh sok xev_llo sll pal puho. + rewrite uoc_eq /= => /(_ _ cin) [c' c'in Pc]. + have /andP [lc'in hc'in] : (low c' \in [:: bottom, top & s]) && + (high c' \in [:: bottom, top & s]). + have := opening_cells_subset' llin hlin ogsub vl vh oute. + rewrite /opening_cells. + move: c'in; case : opening_cells_aux => [nos' lno'] /= c'in main. + by rewrite !main // mem_cat map_f ?orbT // mem_rcons inE c'in ?orbT. + move: Pc gq=> [-> | [l lv ->]]. + by move=> [] ->. + rewrite high_set_left_pts low_set_left_pts. + by move=> [] ->. +- rewrite orbA=> /orP[ | gin]; last first. + apply: (edges_sub comi); rewrite /all_edges mem_cat /state_open_seq /=. + by rewrite cell_edges_cat mem_cat cell_edges_cons !inE gin !orbT. + have := update_open_cellE2 oute vl vh sok xev_llo sll pal puho. + rewrite uoc_eq /=. + have := opening_cells_subset' llin hlin ogsub vl vh oute. + rewrite /opening_cells. + move: opening_cells_aux => [nos' lno'] /= main. + move=> [] -> /orP gin. + apply: main; rewrite mem_cat; move: gin. + by move=> [] /eqP ->; rewrite map_f ?orbT //; rewrite mem_rcons inE eqxx. + move: gin; rewrite low_set_left_pts high_set_left_pts=> gin. + apply: (edges_sub comi); rewrite /all_edges/state_open_seq /=. + rewrite mem_cat cell_edges_cat mem_cat cell_edges_cons !inE. + by move: gin=> [] ->; rewrite ?orbT. +- by move: (closed_events comi)=> /andP[]. +- by move=> e1 e1in; apply: (out_events comi); rewrite inE e1in orbT. +- by move: (inbox_events comi)=> /andP[]. +- move: (lex_events comi)=> /=. + rewrite path_sortedE; last by apply:lexPtEv_trans. + by move=> /andP[]. +have xev_ll : p_x (point ev) = left_limit lsto. + by rewrite -at_lstx lstx_ll. +case uocq : (generic_trajectories.update_open_cell _ _ _ _ + _ _ _ _ _ _ _ _ lsto ev) => [new_opens last_new_open]. +rewrite /state_open_seq/=. +rewrite -catA -cat_rcons 2!all_cat andbCA. +move: (sides_ok comi). +rewrite !all_cat /= andbCA => /andP[] lstook ->; rewrite andbT. +have sz_lptso := size_left_lsto sval lstx_ll + (sides_ok comi) (esym at_lstx) pal (underW puho) + => /=. +have lxlftpts : all (fun x => lexPt x (point ev)) (behead (left_pts lsto)). + have := lst_side_lex comng => /=. + case lptsq : (left_pts lsto) => [ | p1 [ | p2 ps]] //= /andP[] p2lex _. + rewrite p2lex /=. + apply/allP => px pxin. + apply: (lexPt_trans _ p2lex). + move: (sides_ok comi)=> /allP /(_ _ lstoin) /andP[] _. + rewrite lptsq /= => /andP[] /andP[] _ /andP[] p2ll /allP psll. + move=> /andP[] /andP[] _ + _. + rewrite (path_sortedE (rev_trans (lt_trans)))=> /andP[] /allP cmpy _. + rewrite /lexPt (eqP p2ll) (esym (eqP (psll _ pxin))) eqxx. + by rewrite (cmpy (p_y px)) ?orbT // map_f. +apply: (update_open_cell_side_limit_ok oute sval + (sides_ok comi) lxlftpts uocq xev_ll puho pal). +Qed. + +Lemma update_open_cell_common_non_gp_invariant + bottom top s fop lsto lop cls lstc ev + lsthe lstx evs : + bottom <| top -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + {in s, forall g, inside_box bottom top (left_pt g) && + inside_box bottom top (right_pt g)} -> + lstx = p_x (point ev) -> + (point ev) <<< lsthe -> + common_non_gp_invariant bottom top s + (Bscan fop lsto lop cls lstc lsthe lstx) + (ev :: evs) -> + common_non_gp_invariant bottom top s + (step (Bscan fop lsto lop cls lstc lsthe lstx) ev) + evs. +Proof. +move=> bxwf nocs' inbox_s at_lstx under_lsthe comng. +have comi := ngcomm comng. +constructor. + now apply: update_open_cell_common_invariant. +rewrite /step/generic_trajectories.step. +rewrite /same_x at_lstx eqxx /=. +rewrite -/(point_under_edge _ _) underW /=; last by []. +rewrite -/(point ev <<< lsthe) under_lsthe. +case uocq : (generic_trajectories.update_open_cell _ _ _ _ _ _ + _ _ _ _ _ _ lsto ev) => [nos lno] /=. +have oute : out_left_event ev. + by apply: (out_events comi); rewrite inE eqxx. +have [clae [sval' [adj [cbtom rfo]]]] := inv1 comi. +have sval : seq_valid (state_open_seq (Bscan fop lsto lop cls lstc lsthe lstx)) + (point ev). + by case: sval'. +have lstoin : lsto \in (fop ++ lsto :: lop). + by rewrite mem_cat inE eqxx orbT. +have [vl vh] := (andP (allP sval lsto lstoin)). +have sok : open_cell_side_limit_ok lsto. + by apply: (allP (sides_ok comi)); exact: lstoin. +have xev_llo : p_x (point ev) = left_limit lsto. + by rewrite -at_lstx -(lstx_eq comi). +have puho : point ev <<< high lsto. + move: under_lsthe. + rewrite -[lsthe]/(lst_high _ _ (Bscan fop lsto lop cls lstc lsthe lstx)). + by rewrite -(high_lsto_eq comi). +have pal : (point ev) >>> low lsto. + by exact: (same_x_point_above_low_lsto at_lstx comng). +have lstx_ll : lstx = left_limit lsto. + rewrite -[lstx]/(lst_x _ _ (Bscan fop lsto lop cls lstc lsthe lstx)). + by rewrite (lstx_eq comi). +have sll : (1 < size (left_pts lsto))%N. + by apply: (size_left_lsto sval lstx_ll (sides_ok comi) (esym at_lstx) pal + (underW puho)). +have [case1 | case2]:= update_open_cellE2 oute vl vh sok xev_llo sll pal puho. + rewrite /update_open_cell uocq /= in case1. + rewrite case1. + case oca_eq : (opening_cells_aux _ _ _ _) => [nos1 lno1] /=. + have [sz prf]:= last_opening_cells_left_pts_prefix vl vh puho oute oca_eq. + rewrite sz /=. + set thenth := nth _ _ _. + suff -> : thenth = point ev. + rewrite (@path_map _ _ (@point) (@lexPt R) ev evs). + exact: (lex_events comi). + have := take_nth dummy_pt sz; rewrite prf /thenth. + case lpts1 : (left_pts lno1) sz => [ | a [ | b tl]] //= _. + by move=> [] _ /esym. +rewrite /update_open_cell uocq /= in case2. +rewrite case2 /=. +rewrite (@path_map _ _ (@point) (@lexPt R) ev evs). +exact: (lex_events comi). +Qed. + +Lemma simple_step_disjoint_general_position_invariant + bottom top s fop lsto lop fc cc lcc lc le he cls lstc ev + lsthe lstx evs : + bottom <| top -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + {in s, forall g, inside_box bottom top (left_pt g) && + inside_box bottom top (right_pt g)} -> + open_cells_decomposition (fop ++ lsto :: lop) (point ev) = + (fc, cc, lcc, lc, le, he) -> + disjoint_general_position_invariant bottom top s + (Bscan fop lsto lop cls lstc lsthe lstx) + (ev :: evs) -> + disjoint_general_position_invariant bottom top s + (simple_step fc cc lc lcc le he cls lstc ev) + evs. +Proof. +move=> boxwf nocs' inbox_s oe. +move=> []; rewrite /state_open_seq/state_closed_seq/=. +move=> oc_dis c_dis Cinv pw rl. +have := Cinv=> -[] []; rewrite /state_open_seq/state_closed_seq/=. +move=> inv1 lstxq lstheq sub_edges cle out_es inbox_es lexev oks gen_pos. +have := inv1 => -[] clae [] []; first by []. +move=> sval []adj []cbtom rfo. +rewrite /simple_step/generic_trajectories.simple_step. +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +have Cinv' : common_general_position_invariant bottom top s + (Bscan (fc ++ nos) lno lc + (cls ++ lstc :: closing_cells (point ev) cc) + (close_cell (point ev) lcc) he (p_x (point ev))) evs. + have := simple_step_common_general_position_invariant boxwf nocs' inbox_s oe. + rewrite /simple_step/generic_trajectories.simple_step. + rewrite -/(opening_cells_aux _ _ _ _). + by rewrite oca_eq=> /(_ _ _ lsthe lstx); apply. +have cl_at_left' : {in rcons cls lstc, + forall c, right_limit c <= p_x (point ev)}. + by move=> c cin; apply: rl; rewrite // inE eqxx. +have oute : out_left_event ev by apply: out_es; rewrite inE eqxx. +have := step_keeps_disjoint_default inbox_es oute rfo + cbtom adj sval pw oks oc_dis c_dis cl_at_left'. +rewrite oe oca_eq /= !cat_rcons -!cats1 /= => disjointness. +have op_cl_dis': + {in (fc ++ nos) ++ lno :: lc & rcons (cls ++ lstc :: + closing_cells (point ev) cc) (close_cell (point ev) lcc), + disjoint_open_closed_cells _}. + move=> c1 c2; rewrite -!(cats1, catA)=> c1in c2in. + by apply: (proj2 (disjointness)). +have cl_dis : {in rcons (cls ++ lstc :: closing_cells (point ev) cc) + (close_cell (point ev) lcc) &, disjoint_closed_cells R}. + by rewrite -!(cats1, catA); apply: (proj1 disjointness). +have nocs : {in bottom :: top :: s &, no_crossing R}. + by apply: inter_at_ext_no_crossing. +have noc : {in all_edges (fop ++ lsto :: lop) (ev :: evs) &, + no_crossing R}. + by move=> g1 gt2 g1in g2in; apply: nocs; apply: sub_edges. +have pwo' : pairwise (@edge_below _) + (bottom :: [seq high c | c <- (fc ++ nos) ++ lno :: lc]). +have := step_keeps_pw_default inbox_es oute rfo cbtom adj sval + noc pw. + by rewrite oe oca_eq -catA. +have right_limit_closed' : + {in rcons(cls ++ + lstc :: closing_cells (point ev) cc) (close_cell (point ev) lcc) & + evs, forall c e, right_limit c <= p_x (point e)}. + have:= step_keeps_right_limit_closed_default inbox_es cbtom adj + sval lexev cl_at_left'. + by rewrite oe oca_eq /=. +by constructor. +Qed. + +Definition start := + start R eq_op le +%R (fun x y => x - y) *%R (fun x y => x / y) 1 edge + (@unsafe_Bedge _) (@left_pt _) (@right_pt _). + +Lemma start_eq_initial (bottom top : edge) (ev : event') : + start ev bottom top = initial_state bottom top [:: ev]. +Proof. by []. Qed. + +Definition complete_last_open : edge -> edge -> cell -> cell := + complete_last_open + R eq_op le +%R (fun x y => x - y) *%R (fun x y => x / y) edge + (@left_pt _) (@right_pt _). + +Lemma map_eq [A B : Type] (f : A -> B) l : + List.map f l = [seq f x | x <- l]. +Proof. by []. Qed. + +Definition main_process bottom top evs := + match evs with + | ev :: evs => scan evs (initial_state bottom top (ev :: evs)) + | [::] => ([:: start_open_cell bottom top], [::]) + end. + +Lemma complete_process_eq bottom top ev evs : + complete_process R eq_op le +%R (fun x y => x - y) *%R (fun x y => x / y) 1 edge + (@unsafe_Bedge _) (@left_pt _) (@right_pt _) (ev :: evs) bottom top = + match scan evs (initial_state bottom top (ev :: evs)) with + (a, b) => [seq complete_last_open bottom top c | c <- a] ++ b + end. +Proof. by []. Qed. + + +Lemma complete_disjoint_general_position bottom top s closed open evs : + sorted (fun e1 e2=> p_x (point e1) < p_x (point e2)) evs -> + bottom <| top -> + (* TODO: rephrase this statement in one that is easier to understand. *) + open_cell_side_limit_ok (start_open_cell bottom top) -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + {in s, forall g, inside_box bottom top (left_pt g) && + inside_box bottom top (right_pt g)} -> + all (inside_box bottom top) [seq point e | e <- evs] -> + sorted (@lexPtEv _) evs -> + {subset flatten [seq outgoing e | e <- evs] <= s} -> + {in evs, forall ev, out_left_event ev} -> + close_edges_from_events evs -> + main_process bottom top evs = (open, closed) -> + {in closed &, disjoint_closed_cells R} /\ + {in open & closed, disjoint_open_closed_cells R}. +Proof. +move=> ltev boxwf startok nocs' inbox_s evin lexev evsub out_evs cle. +have nocs : {in bottom :: top :: s &, no_crossing R}. + by apply: inter_at_ext_no_crossing. +rewrite /main_process/scan. +case evsq : evs => [ | ev future_events]. + move=> [] <- <-; split; last by []. + by move=> c1 c2; rewrite in_nil. +have evsn0 : evs != [::] by rewrite evsq. +have := initial_disjoint_general_position_invariant ltev boxwf startok nocs' + evin lexev evsub out_evs cle evsn0. +rewrite /initial_state evsq. +case oca_eq : (opening_cells_aux _ _ _ _) => [nos1 lno1] /=. +elim: (future_events) {oca_eq evsq} (Bscan _ _ _ _ _ _ _)=> [ | ev' fut' Ih]. + move=> state_f /=; case: state_f=> [] f m l cls lstc lsthe lstx. + move=> /[swap] -[] <- <-; case; rewrite /state_open_seq /state_closed_seq /=. + move=> dis_op_cl dis_cl *; split; move=> c1 c2 c1in c2in. + by apply: dis_cl; rewrite // mem_rcons. + by apply: dis_op_cl; rewrite // mem_rcons. +move=> {evs ltev evin lexev evsub out_evs cle evsn0}. +move=> [fop lsto lop cls lstc lsthe lstx]. +case; set ops' := (state_open_seq _); set (cls' := state_closed_seq _). +rewrite /=. +move=> dis_open_closed dis_cl /[dup] Cinv [] [] inv1 lstxq lstheq sub_edges. +move=> /[dup] cle /andP[cl_e_fut' cle'] out_fut'. +move=> /[dup] inbox_all_events' /andP[inbox_e inbox_all_events] lexevs oks. +move=> /andP[] /andP[] lstxlte lstx_fut' ltfut' edges_pairwise cl_at_left. +move: (inv1)=> [] clae [] pre_sval [] adj [] cbtom rfo. +have sval : seq_valid (fop ++ lsto :: lop) (point ev') by case: pre_sval. + +rewrite /=/simple_step; case: ifP=> [_ | ]; last first. + move=> /negbFE; rewrite /same_x eq_sym=> /eqP abs; suff: False by []. + by move : lstxlte; rewrite abs lt_irreflexive. +rewrite -/(open_cells_decomposition _ _). +rewrite /generic_trajectories.simple_step. +case oe : (open_cells_decomposition _ _) => [[[[[fc cc] lcc] lc] le] he]. +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +apply: Ih. +have := + simple_step_disjoint_general_position_invariant boxwf nocs' inbox_s oe. + rewrite /simple_step/generic_trajectories.simple_step. + rewrite -/(opening_cells_aux _ _ _ _). + rewrite oca_eq=> /(_ _ _ lsthe lstx). +by apply. +Qed. + +Record edge_covered_general_position_invariant (bottom top : edge) + (edge_set : seq edge) (processed_set : seq event') + (s : scan_state) (events : seq event') := + { edge_covered_ec : {in processed_set, forall e, + {in outgoing e, forall g, + edge_covered g (state_open_seq s) (state_closed_seq s)}}; + processed_covered : {in processed_set, forall e, + exists2 c, c \in (state_closed_seq s) & + point e \in (right_pts c : seq pt) /\ point e >>> low c} ; + common_inv_ec : common_general_position_invariant bottom top edge_set + s events; + non_in_ec : + {in edge_set & events, forall g e, non_inner g (point e)}; + uniq_ec : {in events, forall e, uniq (outgoing e)}; + inj_high : {in state_open_seq s &, injective high}; + bot_left_cells : + {in state_open_seq s & events, + forall c e, lexPt (bottom_left_corner c) (point e)}; + }. + +Lemma in_cell_edges_has_cell (s : seq cell) (g : edge) : + (g \in cell_edges s) = has (fun c => (g == low c) || (g == high c)) s. +Proof. +by elim: s => [ | c0 s Ih] //=; rewrite cell_edges_cons !inE !orbA Ih. +Qed. + +Lemma bottom_left_start bottom top p : + inside_box bottom top p -> + open_cell_side_limit_ok (start_open_cell bottom top) -> + bottom_left_cells_lex [:: start_open_cell bottom top] p. +Proof. +move=> inbox_p startok c; rewrite inE => /eqP ->. +have := leftmost_points_max startok => llq. +move: (startok); rewrite /open_cell_side_limit_ok=> /andP[] ln0. +move=> /andP[] samex _. +rewrite /bottom_left_corner. +have /eqP := (allP samex (last dummy_pt (left_pts (start_open_cell bottom top))) + (last_in_not_nil _ ln0)). +rewrite llq. +rewrite /lexPt=> ->. +move: inbox_p=> /andP[] _ /andP[] /andP[] + _ /andP[] + _. +case: (lerP (p_x (left_pt bottom)) (p_x (left_pt top))). + by move=> _ _ ->. +by move=> _ ->. +Qed. + +Lemma initial_edge_covering_general_position + bottom top s events: + sorted (fun e1 e2=> p_x (point e1) < p_x (point e2)) events -> + sorted (@lexPtEv _) events -> + bottom <| top -> + close_edges_from_events events -> + (* TODO: rephrase this statement in a statement that easier to understand. *) + open_cell_side_limit_ok (start_open_cell bottom top) -> + {in bottom :: top :: s &, forall g1 g2, inter_at_ext g1 g2} -> + {in s & events, forall g e, non_inner g (point e)} -> + all (inside_box bottom top) [seq point e | e <- events] -> + {subset flatten [seq outgoing e | e <- events] <= s} -> + {in events, forall ev, out_left_event ev} -> + {in events, forall ev, uniq (outgoing ev)} -> + events != [::] -> + edge_covered_general_position_invariant bottom top s + [:: (head dummy_event events)] + (initial_state bottom top events) (behead events). +Proof. +move=> gen_pos lexev wf cle startok nocs' n_inner inbox_es sub_es out_es + uniq_out_es evsn0. +rewrite /initial_state. +have := initial_intermediate wf startok nocs' inbox_es lexev sub_es + out_es cle evsn0. +have := initial_common_general_position_invariant gen_pos wf startok nocs' + inbox_es lexev sub_es out_es cle evsn0. +case evsq : events evsn0 => [ // | e evs] _. +case oca_eq: (opening_cells_aux _ _ _ _) => [nos lno]. +lazy zeta; rewrite [head _ _]/= [behead _]/=. +have oute : out_left_event e by apply: out_es; rewrite evsq inE eqxx. +move=> Cinv [] ok0 []cbtom0 []adj0 []sval0 []rf0 []inbox_es0 []cle1 + []out_es1 []clae0 []vb []vt []oe0 []nocs []noc0 []pw0 lexevs. +have inbox_e : inside_box bottom top (point e). + by apply/(@allP pt _ _ inbox_es)/map_f; rewrite evsq inE eqxx. +have /andP[eab ebt] : (point e >>> bottom) && (point e <<< top). + by move: inbox_e=> /andP[]. +have cle0 : close_edges_from_events (e :: evs) by rewrite -evsq. +move: inbox_es; rewrite evsq=> inbox_es. +move: Cinv; rewrite/initial_state oca_eq/state_open_seq/state_closed_seq/=. +move=> /[dup] Cinv; rewrite /state_open_seq/state_closed_seq /=. +move=> -[] []; rewrite /state_open_seq/state_closed_seq /=. +move=> inv1 px1 lstheq1 sub1 _ _ _ _ oks1 lexpt1. +have [clae1 [pre_sval [adj1 [cbtom1 rf1]]]] := inv1. +set op0 := start_open_cell bottom top. +have inj_high0 : {in [:: start_open_cell bottom top] &, injective high}. + by move=> g1 g2; rewrite !inE=> /eqP -> /eqP ->. +have uniq1 : {in evs, forall e, uniq (outgoing e)}. + by move=> ev evin; apply: uniq_out_es; rewrite evsq inE evin orbT. +have rf0' : s_right_form ([::] ++ [:: op0]) by []. +have btm_left_lex0 : + bottom_left_cells_lex [:: start_open_cell bottom top] (point e). + by apply: bottom_left_start inbox_e startok. +have inj_high1 : {in nos ++ [:: lno] &, injective high}. + have uniq_e : uniq (outgoing e) by apply: uniq_out_es; rewrite evsq inE eqxx. + have := step_keeps_injective_high_default inbox_es oute rf0' cbtom0 + adj0 sval0 ok0 uniq_e inj_high0 btm_left_lex0. + by rewrite oe0 oca_eq. +have n_inner0 : {in [:: start_open_cell bottom top], + forall c, non_inner (high c) (point e)}. + move=> c; rewrite inE /non_inner=> /eqP -> /onAbove. + by move: inbox_e=> /andP[] /andP[] _ ->. +have n_inner1 : {in s & evs, forall g e, non_inner g (point e)}. + by move=> g ev gin evin; apply: n_inner; rewrite // evsq inE evin orbT. +have cov1 : {in [:: e], forall e', + {in outgoing e', forall g, (edge_covered g (nos ++ [:: lno]) + [:: close_cell (point e) op0])}}. + move=> e'; rewrite inE => /eqP -> {e'}. + have := step_keeps_edge_covering_default inbox_es oute rf0' cbtom0 adj0 sval0 + ok0 inj_high0 btm_left_lex0 n_inner0 oe0 oca_eq=> /=. + move=> main g gin. + by apply: (main [::]); right. +have btm_left_lex1 : {in nos ++ [:: lno] & evs, + forall c e0, lexPt (bottom_left_corner c) (point e0)}. + move=> c ev cin evin. + have eev : lexPtEv e ev. + move: lexev; rewrite evsq /= path_sortedE; last by apply: lexPtEv_trans. + by move=> /andP [] /allP + _; apply. + have := step_keeps_btom_left_corners_default inbox_es oute rf0' cbtom0 + adj0 sval0 noc0 btm_left_lex0; rewrite oe0 oca_eq=> /(_ _ eev). + by apply. +rewrite /state_open_seq/state_closed_seq/=. +have cov_p1 : {in [:: e], forall e', + exists2 c, c \in [:: close_cell (point e) op0] & + point e' \in (right_pts c : seq pt)/\ point e' >>> low c}. + move=> e'; rewrite inE => /eqP -> {e'}. + exists (close_cell (point e) op0); first by rewrite mem_head. + split. + by exact: (@close_cell_in _ op0 (conj vb vt)). + by have [-> _ _] := close_cell_preserve_3sides (point e) op0. +by constructor. +Qed. + +Lemma edge_covered_sub (g : edge) op1 op2 cl1 cl2 : + op1 =i op2 -> cl1 =i cl2 -> + edge_covered g op1 cl1 -> edge_covered g op2 cl2. +Proof. +move=> eqop eqcl [[opc [cls [P1 [P2 [P3 [P4 P5]]]]]] | ]. + left; exists opc, cls. + split;[ |split;[by [] | split;[by [] | split;[ | by []]]]] . + by move=> c; rewrite -eqcl; apply: P1. + by rewrite -eqop. +move=> [pcc [P1 [P2 [P3 [P4 [P5 P6]]]]]]. +right; exists pcc; split;[by [] | split;[ | by []]]. +by move=> c; rewrite -eqcl; apply: P2. +Qed. + +Lemma inside_box_non_inner bottom top (p : pt) : + inside_box bottom top p -> non_inner bottom p /\ non_inner top p. +Proof. +move=> /andP[] /andP[] absbot abstop _; split. + move=> /[dup] /andP[] _ vb; move: absbot; rewrite under_onVstrict // negb_or. + by move=> /[swap] ->. +move=> /[dup] /andP[] _ vt; move: abstop; rewrite strict_nonAunder //. +by move=> /[swap] ->. +Qed. + +Lemma simple_step_edge_covered_general_position + bottom top s cov_set fop lsto lop fc cc lcc lc le he cls lstc ev + lsthe lstx evs : + bottom <| top -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + {in s, forall g, inside_box bottom top (left_pt g) && + inside_box bottom top (right_pt g)} -> + open_cells_decomposition (fop ++ lsto :: lop) (point ev) = + (fc, cc, lcc, lc, le, he) -> + edge_covered_general_position_invariant bottom top s + cov_set (Bscan fop lsto lop cls lstc lsthe lstx) + (ev :: evs) -> + edge_covered_general_position_invariant bottom top s + (rcons cov_set ev) (simple_step fc cc lc lcc le he cls lstc ev) + evs. +Proof. +move=> boxwf nocs' inbox_s. +have nocs : {in bottom :: top :: s &, no_crossing R}. + by apply: inter_at_ext_no_crossing. +set st := Bscan _ _ _ _ _ _ _. +move=> oe. +move=> [] covered p_covered /[dup] Cinv [] [] /[dup] inv_s [] clae. +move=> - [] []; first by []. +rewrite /state_open_seq/state_closed_seq /= => sval [] adj [] cbtom rfo. +move=> lstxq lstheq sub_edges cle out_es. +move=> /[dup] inbox0 /andP[] inbox_e inbox_es lexev. +move=> oks /andP[] lstxlt pathlt n_inner uniq_evs inj_high btm_left_lex. +have out_e : out_left_event ev by apply: out_es; rewrite inE eqxx. +have noc : {in all_edges (state_open_seq st) (ev :: evs) &, no_crossing R}. + by move=> g1 g2 g1in g2in; apply: nocs; apply: sub_edges. +(* TODO: this should not be needed, if we had enough theorems about + simple_step. *) +have lstxneq : p_x (point ev) != lstx. + by move: lstxlt; rewrite lt_neqAle eq_sym=> /andP[] /andP[]. +case oca_eq : + (opening_cells_aux (point ev) (sort (@edge_below _) (outgoing ev)) le he) => + [nos lno]. +have Cinv' := + simple_step_common_general_position_invariant boxwf nocs' inbox_s oe Cinv. +have btm_left_lex_e : {in (state_open_seq st), forall c, + lexPt (bottom_left_corner c) (point ev)}. + by move=> c cin; apply: btm_left_lex; rewrite // inE eqxx. +have n_inner2 : {in state_open_seq st, + forall c, non_inner (high c) (point ev)}. + move=> c cin. + have /sub_edges : high c \in all_edges (state_open_seq st) (ev :: evs). + by rewrite 2!mem_cat map_f ?orbT. + have /inside_box_non_inner [nib nit] : inside_box bottom top (point ev). + by move: inbox0 => /andP[]. + rewrite !inE => /orP[/eqP -> | /orP [/eqP -> | hcin ]] //. + by apply: n_inner; rewrite // inE eqxx. +have cov' : {in rcons cov_set ev,forall e', + {in outgoing e', forall g, edge_covered g (state_open_seq + (simple_step fc cc lc lcc le he cls lstc ev)) + (state_closed_seq + (simple_step fc cc lc lcc le he cls lstc ev))}}. + have main:= step_keeps_edge_covering_default + inbox0 out_e rfo cbtom adj sval oks inj_high btm_left_lex_e n_inner2 + oe oca_eq. + have := main (state_closed_seq st) => {}main. + move=> e' e'in g gin. + have /main : edge_covered g (fop ++ lsto :: lop) (state_closed_seq st) \/ + g \in outgoing ev. + move: e'in; rewrite -cats1 mem_cat=> /orP[/covered|]; last first. + by move: gin=> /[swap]; rewrite inE=> /eqP ->; right. + by move=> /(_ _ gin); left. + rewrite /state_open_seq /state_closed_seq /=. + apply: edge_covered_sub. + rewrite /simple_step/generic_trajectories.simple_step. + rewrite -/(opening_cells_aux _ _ _ _). + by rewrite oca_eq /= -catA. + rewrite /simple_step/generic_trajectories.simple_step. + rewrite -/(opening_cells_aux _ _ _ _). + by rewrite oca_eq /= !cat_rcons -!cats1 -!catA. +have n_inner' : {in s & evs, forall g e, non_inner g (point e)}. + by move=> g e gin ein; apply: n_inner; rewrite // inE ein orbT. +have uniq' : {in evs, forall e, uniq (outgoing e)}. + by move=> g gin; apply: uniq_evs; rewrite inE gin orbT. +have uniq_ev : uniq (outgoing ev) by apply: uniq_evs; rewrite inE eqxx. +have inj_high' : + {in state_open_seq (simple_step fc cc lc lcc le he cls lstc ev) &, + injective high}. + have := step_keeps_injective_high_default inbox0 out_e rfo cbtom adj sval + oks uniq_ev inj_high btm_left_lex_e. + rewrite /simple_step/generic_trajectories.simple_step. + rewrite -/(open_cells_decomposition _ _). + rewrite -/(opening_cells_aux _ _ _ _). + by rewrite oe oca_eq /state_open_seq /= -catA. +have btm_left_lex' : + {in state_open_seq (simple_step fc cc lc lcc le he cls lstc ev) & evs, + forall c e, lexPt (bottom_left_corner c) (point e)}. + have := step_keeps_btom_left_corners_default inbox0 out_e rfo cbtom adj + sval noc btm_left_lex_e. + rewrite /simple_step/= /= oe oca_eq /= /state_open_seq /=. + rewrite catA=> main. + move=> c e cin ein; apply: main=> //=. + move: lexev; rewrite path_sortedE; last by apply: lexPtEv_trans. + by move=> /andP[] /allP /(_ e ein). + move: cin; rewrite /generic_trajectories.simple_step. + by rewrite -/(opening_cells_aux _ _ _ _) oca_eq. +have p_cov' : {in rcons cov_set ev, forall e, exists2 c, + c \in state_closed_seq (simple_step fc cc lc lcc le he cls lstc ev) & + point e \in (right_pts c : seq pt) /\ point e >>> low c}. + have exi := exists_cell cbtom adj (inside_box_between inbox_e). + have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe exi. + have [{}pal {}puh vle vhe nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe. + move=> e; rewrite mem_rcons inE=> /orP[]; last first. + move=> /p_covered [] c cin pin. + rewrite /state_closed_seq/simple_step/generic_trajectories.simple_step. + rewrite -/(opening_cells_aux _ _ _ _). + rewrite oca_eq /=. + exists c; last by []. + by rewrite -cats1 /= appE -(cat_rcons lstc) !mem_cat cin. + move=> /eqP -> {e}. + exists (close_cell (point ev) (head lcc cc)). + rewrite /state_closed_seq /simple_step/generic_trajectories.simple_step. + rewrite -/(opening_cells_aux _ _ _ _). + rewrite oca_eq /= -cats1 -catA /=. + rewrite -cat_rcons mem_cat; apply/orP; right. + by case: (cc) => [ | ? ?]; rewrite /= mem_head. + have hdin : head lcc cc \in fop ++ lsto :: lop. + rewrite ocd mem_cat; apply/orP; right. + by case: (cc)=> [ | ? ?]; rewrite /= mem_head. + split. + by apply/close_cell_in/andP/(allP sval). + have [-> _ _] := close_cell_preserve_3sides (point ev) (head lcc cc). + by rewrite -leq. +by constructor. +Qed. + +Lemma start_edge_covered_general_position bottom top s closed open evs : + sorted (fun e1 e2=> p_x (point e1) < p_x (point e2)) evs -> + bottom <| top -> + (* TODO: rephrase this statement in one that is easier to understand. *) + open_cell_side_limit_ok (start_open_cell bottom top) -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + {in s, forall g, inside_box bottom top (left_pt g) && + inside_box bottom top (right_pt g)} -> + all (inside_box bottom top) [seq point e | e <- evs] -> + sorted (@lexPtEv _) evs -> + {subset events_to_edges evs <= s} -> + {in evs, forall ev, out_left_event ev} -> + close_edges_from_events evs -> + {in s & evs, forall g e, non_inner g (point e)} -> + {in evs, forall e, uniq (outgoing e)} -> + main_process bottom top evs = (open, closed) -> + {in events_to_edges evs, forall g, edge_covered g open closed} /\ + {in evs, forall e, exists2 c, c \in closed & + point e \in (right_pts c : seq pt) /\ point e >>> low c}. +Proof. +move=> ltev boxwf startok nocs' inbox_s evin lexev evsub out_evs cle + n_inner uniq_edges. +(* +have nocs : {in bottom :: top :: s &, no_crossing R}. + by apply: inter_at_ext_no_crossing. +*) +rewrite /start. +case evsq : evs => [ | ev future_events]; first by split; move=> r_eq ?. +have evsn0 : evs != [::] by rewrite evsq. +have := initial_edge_covering_general_position ltev lexev boxwf cle + startok nocs' n_inner evin evsub out_evs uniq_edges evsn0. +rewrite /initial_state evsq /=. +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +set istate := Bscan _ _ _ _ _ _ _. +move=> istateP req. +suff main : forall events op cl st cov_set, + edge_covered_general_position_invariant bottom top s cov_set st events -> + scan events st = (op, cl) -> + ({in events_to_edges (cov_set ++ events), forall g, edge_covered g op cl} /\ + {in cov_set ++ events, forall e, exists2 c, c \in cl & + point e \in (right_pts c : seq pt) /\ point e >>> low c}). + by move: req; apply: (main _ _ _ _ [:: ev]). + move=> {req istateP istate oca_eq lno nos evsn0 evsq future_events ev}. + move=> {uniq_edges n_inner out_evs evsub lexev evin startok ltev}. + move=> {cle closed open evs}. + elim=> [ | ev evs Ih] op cl st cov_set. + case: st => fop lsto lop cls lstc lsthe lstx /=. + move=> []; rewrite /state_open_seq/state_closed_seq /= => + p_main. + move=> main _ _ _ _ _ [] <- <-; rewrite cats0; split. + move=> g=> /flatten_mapP[e' /main /[apply]]. + apply: edge_covered_sub; first by []. + by move=> c; rewrite mem_rcons. + move=> e=> /p_main [c2 c2in pin2]; exists c2=> //. + by move: c2in; rewrite mem_rcons. +move=> inv0; rewrite -cat_rcons. +apply: Ih. +case stq : st => [fop lsto lop cls lstc lsthe lstx]. +rewrite /step/generic_trajectories.step. +have /andP[/andP[+ _] _] := general_pos (common_inv_ec inv0). +rewrite lt_neqAle eq_sym => /andP[] lstxneq _. +rewrite stq /= in lstxneq; rewrite lstxneq. +rewrite -/(open_cells_decomposition _ _). +case oe : (open_cells_decomposition _ _) => [[[[[fc cc] lcc] lc] le] he]. +move: (inv0); rewrite stq=> inv1. +by have := simple_step_edge_covered_general_position boxwf nocs' + inbox_s oe inv1. +Qed. + +Record safe_side_general_position_invariant (bottom top : edge) + (edge_set : seq edge) (processed_set : seq event') + (s : scan_state) (events : seq event') := + { disjoint_ss : + disjoint_general_position_invariant bottom top edge_set s events; + covered_ss : + edge_covered_general_position_invariant bottom top edge_set + processed_set s events; + left_proc : {in processed_set & events, forall e1 e2, + p_x (point e1) < p_x (point e2)}; + rf_closed : {in state_closed_seq s, forall c, low c <| high c}; + diff_edges : + {in state_open_seq s ++ state_closed_seq s, forall c, low c != high c}; + sub_closed : + {subset cell_edges (state_closed_seq s) <= bottom :: top :: edge_set}; + (* TODO : move this to the common invariant. *) + left_o_lt : + {in state_open_seq s & events, + forall c e, left_limit c < p_x (point e)}; + left_o_b : + {in state_open_seq s, forall c, left_limit c < + min (p_x (right_pt bottom)) (p_x (right_pt top))}; + closed_lt : + {in state_closed_seq s, forall c, left_limit c < right_limit c}; + closed_ok : + all (@closed_cell_side_limit_ok R) (state_closed_seq s); + (* TODO : move this to the disjoint invariant. *) + cl_at_left_ss : + {in state_closed_seq s & events, + forall c e, right_limit c < p_x (point e)}; + safe_side_closed_edges : + {in events_to_edges processed_set & state_closed_seq s, forall g c p, + in_safe_side_left p c || in_safe_side_right p c -> ~ p === g}; + safe_side_open_edges : + {in events_to_edges processed_set & state_open_seq s, forall g c p, + in_safe_side_left p c -> ~p === g}; + safe_side_closed_points : + {in processed_set & state_closed_seq s, forall e c p, + in_safe_side_left p c || in_safe_side_right p c -> + p != point e :> pt}; + safe_side_open_points : + {in processed_set & state_open_seq s, forall e c p, + in_safe_side_left p c -> + p != point e :> pt}; +}. + +Lemma events_to_edges_rcons evs (e : event') : + events_to_edges (rcons evs e) = events_to_edges evs ++ outgoing e. +Proof. by rewrite /events_to_edges /= map_rcons flatten_rcons. Qed. + +Lemma valid_open_limit (c : cell) p : + valid_edge (low c) p -> valid_edge (high c) p -> p_x p <= open_limit c. +Proof. +move=> /andP[] _ lp /andP[] _ hp; rewrite /open_limit. +by have [A | B] := lerP (p_x (right_pt (low c))) (p_x (right_pt (high c))). +Qed. + +Lemma on_edge_inside_box (bottom top g : edge) p : + inside_box bottom top (left_pt g) -> + inside_box bottom top (right_pt g) -> + p === g -> + inside_box bottom top p. +Proof. +move=> inl inr pon. +rewrite /inside_box. +have -> : p >>> bottom. + have la : left_pt g >>> bottom by move: inl=>/andP[] /andP[]. + have ra : right_pt g >>> bottom by move: inr=>/andP[] /andP[]. + by have := point_on_edge_above_strict pon la ra. +have -> : p <<< top. + have lu : left_pt g <<< top by move: inl=>/andP[] /andP[]. + have ru : right_pt g <<< top by move: inr=>/andP[] /andP[]. + by have := point_on_edge_under_strict pon lu ru. +move: pon => /andP[] _ /andP[] lp pr. +move: inl => /andP[] _ /andP[] /andP[] bl _ /andP[] tl _. +move: inr => /andP[] _ /andP[] /andP[] _ rb /andP[] _ rt. +rewrite (lt_le_trans bl lp) (lt_le_trans tl lp). +by rewrite (le_lt_trans pr rb) (le_lt_trans pr rt). +Qed. + +Lemma inside_box_lt_min_right (p : pt) bottom top : + inside_box bottom top p -> + p_x p < min (p_x (right_pt bottom)) (p_x (right_pt top)). +Proof. +move=> /andP[] _ /andP[] /andP[] _ + /andP[] _. +by case : (ltrP (p_x (right_pt bottom)) (p_x (right_pt top))). +Qed. + +Lemma initial_safe_side_general_position bottom top s events: + sorted (fun e1 e2=> p_x (point e1) < p_x (point e2)) events -> + sorted (@lexPtEv _) events -> + bottom <| top -> + close_edges_from_events events -> + (* TODO: rephrase this statement in a statement that easier to understand. *) + open_cell_side_limit_ok (start_open_cell bottom top) -> + {in bottom :: top :: s &, forall g1 g2, inter_at_ext g1 g2} -> + {in s & events, forall g e, non_inner g (point e)} -> + all (inside_box bottom top) [seq point e | e <- events] -> + {subset flatten [seq outgoing e | e <- events] <= s} -> + {in events, forall ev, out_left_event ev} -> + {in events, forall ev, uniq (outgoing ev)} -> + events != [::] -> + safe_side_general_position_invariant bottom top s + [::(head dummy_event events)] + (initial_state bottom top events) (behead events). +Proof. +move=> gen_pos lexev wf cle startok nocs' n_inner inbox_es sub_es out_es + uniq_out_es evsn0. +have := initial_intermediate wf startok nocs' inbox_es lexev sub_es + out_es cle evsn0. +have := initial_disjoint_general_position_invariant gen_pos wf startok + nocs' inbox_es lexev sub_es out_es cle evsn0. +have := initial_edge_covering_general_position gen_pos lexev wf cle + startok nocs' n_inner inbox_es sub_es out_es uniq_out_es evsn0. +case evsq: events evsn0=> [ | ev evs]; [by [] | move=> evsn0]. +rewrite /initial_state. +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +move=> e_inv d_inv. +move=> []; set op0 := start_open_cell bottom top. +rewrite [head _ _]/= [behead _]/=. +move=> ok0 [] btom0 [] adj0 [] sval0 [] rf0 [] inbox_es0 [] cle0 [] oute0. +move=> [] clae0 [] vb0 [] vt0 [] oe0 [] noc0 [] noc'0 [] pw0 lexevs. +have u0 : uniq (outgoing ev) by apply: uniq_out_es; rewrite evsq mem_head. +have oute : out_left_event ev by apply: out_es; rewrite evsq mem_head. +have inbox_e : inside_box bottom top (point ev). + by have := inbox_es; rewrite evsq => /andP[]. +have /andP [pab put] : (point ev >>> bottom) && (point ev <<< top). + by move: inbox_e=> /andP[]. +have rf_closed1 : {in [:: close_cell (point ev) op0], forall c, + low c <| high c}. + rewrite /close_cell (pvertE vb0) (pvertE vt0) /= => c. + by rewrite inE=> /eqP -> /=. +have dif1 : {in (nos ++ [:: lno]) ++ + [:: close_cell (point ev) op0], forall c, low c != high c}. + move=> c; rewrite mem_cat=> /orP[]. + rewrite cats1. + have := opening_cells_low_diff_high oute u0 vb0 vt0 pab put. + by rewrite /opening_cells oca_eq; apply. + rewrite inE /close_cell (pvertE vb0) (pvertE vt0) => /eqP -> /=. + by apply/negP=> /eqP abs; move: pab; rewrite abs (underW put). +have subc1 : {subset cell_edges [:: close_cell (point ev) op0] <= + bottom :: top :: s}. + move=> c; rewrite !mem_cat !inE=> /orP[] /eqP ->. + have [-> _ _] := close_cell_preserve_3sides (point ev) op0. + by rewrite eqxx. + have [_ -> _] := close_cell_preserve_3sides (point ev) op0. + by rewrite eqxx orbT. +have lte : {in evs, forall e, p_x (point ev) < p_x (point e)}. + move: gen_pos; rewrite evsq /=. + rewrite path_sortedE; last by move=> ? ? ?; apply: lt_trans. + by move=> /andP[] /allP. +have llt: {in nos ++ [:: lno] & evs, forall c e, left_limit c < p_x (point e)}. + move=> c e cin ein. + have lte' : p_x (point ev) < p_x (point e) by apply: lte. + have := opening_cells_left oute vb0 vt0. + by rewrite /opening_cells oca_eq -cats1=> /(_ _ cin) => ->. +have llop0ltev : left_limit op0 < p_x (point ev). + rewrite (leftmost_points_max startok). + have := inbox_e=> /andP[] _ /andP[] /andP[] + _ /andP[] + _. + by case: (lerP (p_x (left_pt bottom)) (p_x (left_pt top))). +have lltr : {in [:: close_cell (point ev) op0], + forall c, left_limit c < right_limit c}. + move=> c; rewrite inE=> /eqP ->. + rewrite (@right_limit_close_cell _ (point ev) op0 vb0 vt0). + by rewrite left_limit_close_cell. +have clok: all (@closed_cell_side_limit_ok _) [:: close_cell (point ev) op0]. + rewrite /= andbT. + by apply: close_cell_ok; rewrite // contains_pointE underWC // underW. +have rllt : {in [:: close_cell (point ev) op0] & evs, + forall c e, right_limit c < p_x (point e)}. + move=> c e; rewrite inE => /eqP -> ein. + by rewrite right_limit_close_cell //; apply: lte. +(* Main points. *) +have safe_cl : {in events_to_edges [:: ev] & [:: close_cell (point ev) op0], + forall g c p, in_safe_side_left p c || in_safe_side_right p c -> + ~ p === g}. + move=> g c gin. + have lgq : left_pt g = point ev. + apply/eqP/oute. + by move: gin; rewrite /events_to_edges /= cats0. + rewrite inE => /eqP -> p /orP[] pin. + move=> /andP[] _ /andP[] + _. + rewrite leNgt=> /negP; apply. + move: pin=> /andP[] /eqP -> _. + by rewrite left_limit_close_cell lgq. + move=> pong. + move: pin=> /andP[] + /andP[] _ /andP[] _ . + rewrite right_limit_close_cell // => /eqP samex. + move/negP;apply. + suff -> : p = point ev by rewrite close_cell_in. + apply/eqP; rewrite pt_eqE samex eqxx/=; apply/eqP. + apply: (on_edge_same_point pong) => //. + by rewrite -lgq left_on_edge. +have safe_op : {in events_to_edges [:: ev] & nos ++ [:: lno], + forall g c p, in_safe_side_left p c -> ~ p === g}. + move=> g c gin cin p pin pong. + move: cin; rewrite cats1=> cin. + have lgq : left_pt g = point ev. + apply/eqP/oute. + by move: gin; rewrite /events_to_edges /= cats0. + have eong : point ev === g by rewrite -lgq left_on_edge. + move: pin=> /andP[] + /andP[] _ /andP[] _. + have := opening_cells_left oute vb0 vt0. + have := opening_cells_in vb0 vt0 oute. + rewrite /opening_cells oca_eq=> /(_ _ cin) evin /(_ _ cin) -> /eqP samex. + move/negP; apply. + suff -> : p = point ev. + by apply: (opening_cells_in vb0 vt0 oute); rewrite /opening_cells oca_eq. + apply/eqP; rewrite pt_eqE samex eqxx/=; apply/eqP. + apply: (on_edge_same_point pong eong samex) => //. +have cl_no_event : {in [:: ev] & [:: close_cell (point ev) op0], + forall e c (p : pt), in_safe_side_left p c || in_safe_side_right p c -> + p != point e}. + move=> e c; rewrite !inE => /eqP -> /eqP -> p /orP[]. + move=> /andP[] xlop0 _. + apply/eqP=> pev. + move: llop0ltev; rewrite -pev (eqP xlop0). + by rewrite left_limit_close_cell lt_irreflexive. + move=> /andP[] _ /andP[] _ /andP[] _ /negP it; apply/eqP=> pev. + case: it; rewrite pev. + by apply: close_cell_in. +have op_no_event : {in [:: ev] & nos ++ [:: lno], + forall e c (p : pt), in_safe_side_left p c -> p != point e}. + move=> e c; rewrite !inE=> /eqP ->; rewrite cats1=> cin p pin. + apply/negP=> /eqP pev. + move: pin=> /andP[] _ /andP[] _ /andP[] _ /negP[] . + have := opening_cells_in vb0 vt0 oute; rewrite /opening_cells oca_eq pev. + by apply. +have lt_p_ev : + {in [:: ev] & evs, forall e1 e2 : event', p_x (point e1) < p_x (point e2)}. + by move=> e1 e2; rewrite inE => /eqP ->; apply: lte. +have ll_o_b : + {in nos ++ [:: lno], forall c, + left_limit c < min (p_x (right_pt bottom)) (p_x (right_pt top))}. + move=> c cin. + have := opening_cells_left oute vb0 vt0; rewrite /opening_cells oca_eq. + rewrite -cats1 => /(_ _ cin) ->. + by apply: inside_box_lt_min_right. +by constructor. +Qed. + +Lemma start_safe_sides bottom top s closed open evs : + sorted (fun e1 e2=> p_x (point e1) < p_x (point e2)) evs -> + bottom <| top -> + (* TODO: rephrase this statement in one that is easier to understand. *) + open_cell_side_limit_ok (start_open_cell bottom top) -> + {in bottom :: top :: s &, forall e1 e2, inter_at_ext e1 e2} -> + {in s, forall g, inside_box bottom top (left_pt g) && + inside_box bottom top (right_pt g)} -> + all (inside_box bottom top) [seq point e | e <- evs] -> + sorted (@lexPtEv _) evs -> + {subset events_to_edges evs <= s} -> + {in evs, forall ev, out_left_event ev} -> + close_edges_from_events evs -> + {in s & evs, forall g e, non_inner g (point e)} -> + {in evs, forall e, uniq (outgoing e)} -> + main_process bottom top evs = (open, closed) -> + {in closed, forall c, + low c <| high c /\ + low c != high c /\ + left_limit c < right_limit c /\ + closed_cell_side_limit_ok c /\ + forall p : pt, + in_safe_side_left p c || in_safe_side_right p c -> + {in events_to_edges evs, forall g, ~ p === g} /\ + {in evs, forall ev, p != point ev}} /\ + {subset (cell_edges closed) <= [:: bottom, top & s]} /\ + all (@closed_cell_side_limit_ok R) closed /\ + size open = 1%N /\ low (head_cell open) = bottom /\ + high (head_cell open) = top /\ + {in open & closed, disjoint_open_closed_cells R} /\ + (evs != [::] -> + left_limit (head_cell open) < min (p_x (right_pt bottom)) + (p_x (right_pt top))). +Proof. +move=> ltev boxwf startok nocs' inbox_s evin lexev evsub out_evs cle + n_inner uniq_edges. +have nocs : {in bottom :: top :: s &, no_crossing R}. + by apply: inter_at_ext_no_crossing. +rewrite /main_process/scan/=. +case evsq : evs => [ | ev future_events]; first by move=> [] <- <-. +have evsn0 : evs != [::] by rewrite evsq. +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +set istate := Bscan _ _ _ _ _ _ _. +have : safe_side_general_position_invariant bottom top s [:: ev] + istate future_events. + have := initial_safe_side_general_position ltev lexev boxwf cle startok + nocs' n_inner evin evsub out_evs uniq_edges evsn0. + by rewrite evsq /= oca_eq. +move=> invss req. +suff main: forall events op cl st processed_set, + safe_side_general_position_invariant bottom top s processed_set st events -> + scan events st = (op, cl) -> + {in cl, forall c, + low c <| high c /\ + low c != high c /\ + left_limit c < right_limit c /\ + closed_cell_side_limit_ok c /\ + forall p : pt, in_safe_side_left p c || in_safe_side_right p c -> + {in events_to_edges (processed_set ++ events), forall g, ~ p === g} /\ + {in processed_set ++ events, forall e', p != point e'}} /\ + {in op, forall (c : cell) (p : pt), in_safe_side_left p c -> + {in events_to_edges (processed_set ++ events), forall g, ~ p === g} /\ + {in processed_set ++ events, forall e', p != point e'}} /\ + {subset (cell_edges cl) <= [:: bottom, top & s]} /\ + all (@closed_cell_side_limit_ok _) cl /\ + size op = 1%N /\ + low (head_cell op) = bottom /\ + high (head_cell op) = top /\ + {in op & cl, disjoint_open_closed_cells R} /\ + (left_limit (head_cell op) < min (p_x (right_pt bottom)) + (p_x (right_pt top))). + have [A [B [C [D [E [F [G [H I]]]]]]]] := main _ _ _ _ _ invss req. + split; last by []. + move=> c cin; move: (A c cin) => [] crf [] difc [] lltr [] clok A'. + do 4 (split; first by []). + by move=> p pside; have := A' _ pside. +elim=> [ | {evsq oca_eq istate invss}ev {req}future_events Ih] op cl st p_set. + case stq : st => [fop lsto lop cls lstc lsthe lstx] []. + move=> d_inv e_inv. + set c_inv := common_inv_dis d_inv. + rewrite /state_open_seq/state_closed_seq/= => old_lt_fut b_e d_e subc + lolt lo_lb rllt clok rl A B C D. + rewrite /= => -[] <- <-; rewrite !cats0. + split. + move=> c cin. + split; first by apply: b_e; rewrite mem_rcons. + split; first by apply: d_e; rewrite mem_cat mem_rcons cin orbT. + split; first by apply: rllt; rewrite mem_rcons. + split; first by apply: (allP clok); rewrite mem_rcons. + move=> p pin; split. + by move=> g gin; apply: (A g c gin); rewrite // mem_rcons. + by move=> e ein; apply: (C e c ein); rewrite // mem_rcons. + split; last first. + split; last first. + split. + rewrite (eq_all_r (_ : lstc :: cls =i rcons cls lstc)) //. + by move=> c; rewrite mem_rcons. + (* TODO : find a place for this as a lemma. *) + have [[] [] + + _ _ _ _ _ _ _ + _] := c_inv; rewrite /state_open_seq/=. + rewrite /state_open_seq/= /close_alive_edges => clae. + move=> [] _ [] adj [] cbtom rfo _. + have htop : {in fop ++ lsto :: lop, forall c, high c = top}. + move=> c cin. + have := allP clae _ cin; rewrite /end_edge_ext ?orbF => /andP[] lP. + rewrite !inE => /orP[] /eqP hcq; rewrite hcq //. + have := d_e c; rewrite mem_cat cin hcq=> /(_ isT). + move: lP; rewrite !inE => /orP[] /eqP lcq; rewrite lcq ?eqxx //. + move: evin; rewrite evsq /= => /andP[] + _. + move=> /[dup]/inside_box_valid_bottom_top vbt. + have vb : valid_edge bottom (point ev) by apply: vbt; rewrite inE eqxx. + have vt : valid_edge top (point ev). + by apply: vbt; rewrite !inE eqxx orbT. + move=> /andP[] /andP[] pab put _ tnb. + have abs : top <| bottom by rewrite -lcq -hcq; apply: (allP rfo). + have := order_edges_strict_viz_point' vt vb abs put. + by move: pab; rewrite under_onVstrict // orbC => /[swap] ->. + have := inj_high e_inv; rewrite /state_open_seq/= => ijh. + have f0 : fop = [::]. + elim/last_ind: (fop) adj ijh htop => [ // | fs f1 _] + ijh htop. + rewrite -cats1 -catA /= => /adjacent_catW[] _ /= /andP[] /eqP f1l _. + move: (d_e lsto); rewrite !mem_cat inE eqxx ?orbT => /(_ isT). + rewrite -f1l (htop f1); last by rewrite !(mem_rcons, mem_cat, inE) eqxx. + by rewrite (htop lsto) ?eqxx // mem_cat inE eqxx ?orbT. + have l0 : lop = [::]. + case lopq: (lop) adj ijh htop => [ // | l1 ls] + ijh htop. + move=> /adjacent_catW[] _ /= /andP[] /eqP hl _. + move: (d_e l1); rewrite lopq !(mem_cat, inE) eqxx ?orbT => /(_ isT). + rewrite -hl (htop l1); last by rewrite !(mem_cat, inE) eqxx !orbT. + by rewrite (htop lsto) ?eqxx // mem_cat inE eqxx ?orbT. + rewrite f0 l0 /=. + move: cbtom; rewrite f0 l0 /= /cells_bottom_top /cells_low_e_top /=. + move=> /andP[] /eqP lq /eqP hq. + do 3 (split; first by []). + split. + move=> c1 c2 c1in c2in; apply: (op_cl_dis d_inv); + by rewrite /state_open_seq/state_closed_seq f0 l0 ?mem_rcons. + by apply: lo_lb; rewrite mem_cat inE eqxx orbT. +(* End of lemma *) + move=> g; rewrite -[lstc :: cls]/([:: lstc] ++ cls) cell_edges_catC cats1. + by apply: subc. + move=> c cin p pin. + split. + by move=> g gin; apply: (B g c gin). + by move=> g gin; apply: (D g c gin). +rewrite /scan/=. +move=> [] d_inv e_inv old_lt_fut rf_cl d_e subc lolt lo_lb rllt clok rl A B C D. +set c_inv := common_inv_dis d_inv. +rewrite /step/generic_trajectories.step/=. +case stq : st => [fop lsto lop cls lstc lsthe lstx]. +have /andP[/andP[+ _] _] := general_pos c_inv. +rewrite lt_neqAle=> /andP[] + _. +rewrite stq eq_sym /= => ->. +rewrite -/(open_cells_decomposition _ _). +case oe : (open_cells_decomposition _ _) => [[[[[fc cc] lcc] lc] le] he]. +rewrite /simple_step/generic_trajectories.simple_step/=. +rewrite -/(opening_cells_aux _ _ _ _). +case oca_eq : (opening_cells_aux _ _ _ _) => [{}nos {}lno]. +rewrite -(cat_rcons ev). +apply: Ih. +have [clae [pre_sval [adj [cbtom rfo]]]] := inv1 (gcomm c_inv). +move: pre_sval=> [| sval]; first by[]. +have inbox_es := inbox_events (gcomm c_inv). +have inbox_e : inside_box bottom top (point ev) by move: inbox_es=>/andP[]. +move: (oe); rewrite (_ : fop ++ lsto :: lop = state_open_seq st); last first. + by rewrite stq. +move=> oe'. +have exi' := exists_cell cbtom adj (inside_box_between inbox_e). +move: (exi'); rewrite stq => exi. +have [ocd [lcc_ctn [allct [allnct [flcnct [heq [leq [lein hein]]]]]]]] := + decomposition_main_properties oe' exi'. +have [{}pal {}puh vl vp nc]:= + decomposition_connect_properties rfo sval adj cbtom + (inside_box_between inbox_e) oe'. +have oute : out_left_event ev. + by apply: (out_events (gcomm c_inv)); rewrite inE eqxx. +have oute' : + {in (sort (@edge_below _) (outgoing ev)), forall g, left_pt g == point ev}. + by move=> g; rewrite mem_sort; apply: oute. +set rstate := Bscan _ _ _ _ _ _ _. +have d_inv': + disjoint_general_position_invariant bottom top s rstate future_events. + move: (d_inv); rewrite stq=> d_inv'. + have := simple_step_disjoint_general_position_invariant boxwf nocs' + inbox_s oe d_inv'. + rewrite /simple_step/generic_trajectories.simple_step/=. + by rewrite -/(opening_cells_aux _ _ _ _) oca_eq. +have e_inv' :edge_covered_general_position_invariant bottom top s + (rcons p_set ev) rstate future_events. + move: e_inv; rewrite stq=> e_inv. + have := simple_step_edge_covered_general_position boxwf nocs' + inbox_s oe e_inv. + rewrite /simple_step/generic_trajectories.simple_step/=. + by rewrite -/(opening_cells_aux _ _ _ _) oca_eq. +(* Proving that low and high edges of every cell are distinct. *) +have low_diff_high' : + {in state_open_seq rstate ++ + state_closed_seq rstate, forall c : cell, low c != high c}. + move=> c; rewrite mem_cat=> /orP[]. + rewrite /state_open_seq /= -catA -cat_rcons !mem_cat orbCA. + move=> /orP[ | cold]; last first. + by apply: d_e; rewrite ocd -cat_rcons !mem_cat orbCA cold orbT. + have uo : uniq (outgoing ev) by apply: (uniq_ec e_inv) (mem_head _ _). + have := opening_cells_low_diff_high oute uo vl vp pal puh. + by rewrite /opening_cells oca_eq; apply. + rewrite /state_closed_seq /= -cats1 -!catA /= -cat_rcons. + rewrite mem_cat => /orP[cold | ]. + by apply: d_e; rewrite mem_cat stq /state_closed_seq/= cold orbT. + rewrite cats1 -map_rcons=> /mapP[c' c'in ->]. + have [-> -> _] := close_cell_preserve_3sides (point ev) c'. + by apply: d_e; rewrite mem_cat ocd -cat_rcons !mem_cat c'in !orbT. +(* Provint that closed cells used edges only from the initial set. *) +have subc' : + {subset cell_edges (state_closed_seq rstate) <= [:: bottom, top & s]}. + move=> g; rewrite /state_closed_seq/= -cats1 -catA /= -cat_rcons. + rewrite cell_edges_cat mem_cat=> /orP[gold | ]. + by apply: subc; rewrite stq. + have subo := edges_sub (gcomm c_inv). + rewrite cats1 -map_rcons mem_cat=> /orP[] /mapP[c'] /mapP[c2 c2in ->] ->. + have [-> _ _] := close_cell_preserve_3sides (point ev) c2. + apply: subo; rewrite !mem_cat; apply/orP; left; apply/orP; left. + by rewrite map_f // ocd -cat_rcons !mem_cat c2in orbT. + have [_ -> _] := close_cell_preserve_3sides (point ev) c2. + apply: subo; rewrite !mem_cat; apply/orP; left; apply/orP; right. + by rewrite map_f // ocd -cat_rcons !mem_cat c2in orbT. +(* Proving that open cells have a left side that is smaller than any + event first coordinate. *) +have loplte : {in state_open_seq rstate & future_events, + forall (c : cell) (e : event'), left_limit c < p_x (point e)}. + move=> c e; rewrite /state_open_seq/= -catA -cat_rcons => cin ein. + move: cin; rewrite !mem_cat orbCA => /orP[ | cold ]; last first. + apply: lolt; first by rewrite ocd -cat_rcons !mem_cat orbCA cold orbT. + by rewrite inE ein orbT. + have := opening_cells_left oute vl vp; rewrite /opening_cells oca_eq=> main. + move=> /main=> ->. + move: (proj2 (andP (general_pos c_inv))). + rewrite /= path_sortedE; last by move=> x y z; apply: lt_trans. + by move=> /andP[] /allP /(_ _ ein). +(* Proving that cells have distinct left and right sides. *) +have lltr : + {in state_closed_seq rstate, forall c : cell, left_limit c < right_limit c}. + rewrite /state_closed_seq/= -cats1 -catA /= -cat_rcons. + move=> c; rewrite mem_cat=> /orP[cold | ]. + by apply: rllt; rewrite stq. + rewrite cats1 -map_rcons=> /mapP [c' c'in ->]. + have [vlc' vhc'] : valid_edge (low c') (point ev) /\ + valid_edge (high c')(point ev). + apply/andP; have := allP sval; rewrite ocd -cat_rcons=> /(_ c'); apply. + by rewrite !mem_cat c'in orbT. + have := right_limit_close_cell vlc' vhc'=> ->. + rewrite left_limit_close_cell lolt //; last by rewrite inE eqxx. + by rewrite ocd -cat_rcons !mem_cat c'in orbT. +(* proving a closed_cell ok invariant. *) +have clok' : all (@closed_cell_side_limit_ok _) (state_closed_seq rstate). + apply/allP; rewrite /state_closed_seq/= -cats1 -catA /= -cat_rcons. + move=> c; rewrite mem_cat=> /orP[cin | cin]. + by apply: (allP clok); rewrite stq. + move: cin; rewrite /closing_cells cats1 -map_rcons=> /mapP[c' c'in ->]. + have ccont : contains_point (point ev) c'. + by move: c'in; rewrite mem_rcons inE => /orP[/eqP -> | /allct]. + have c'in' : c' \in state_open_seq st. + by rewrite ocd -cat_rcons !mem_cat c'in orbT. + have /(allP sval) /= /andP[vlc' vhc'] := c'in'. + have c'ok : open_cell_side_limit_ok c'. + by apply: (allP (sides_ok (gcomm c_inv))). + by apply close_cell_ok. +(* proving a right_limit stronger invariant. *) +have rllte : {in state_closed_seq rstate & future_events, + forall (c : cell) (e : event'), right_limit c < p_x (point e)}. + rewrite /state_closed_seq/=. + move=> c e cin ein. + move: cin; rewrite -cats1 -catA /= -cat_rcons mem_cat=> /orP[cold | cnew]. + by apply: rl; rewrite ?stq // inE ein orbT. + have in_es := inbox_events (gcomm c_inv). + have := closing_cells_to_the_left in_es rfo cbtom adj sval. + rewrite stq=> /(_ _ _ _ _ _ _ oe)=> -[] main1 main2. + have eve : p_x (point ev) < p_x (point e). + have:= general_pos c_inv=> /andP[] _ /=. + rewrite path_sortedE; last by move=> x y z; apply: lt_trans. + by move=> /andP[] /allP /(_ e ein). + apply: le_lt_trans eve. + move: cnew; rewrite mem_cat=> /orP[cin | ]; last first. + by rewrite inE=> /eqP ->. + by apply: (main1 _ cin). + +have safe_side_bound : {in rcons cls lstc, forall c p, + in_safe_side_left p c || in_safe_side_right p c -> + p_x p <= right_limit c}. + move=> c p cin /orP[] /andP[] /eqP -> _; last by rewrite le_refl. + by apply/ltW/rllt; rewrite /state_closed_seq stq. +have not_safe_event : {in rcons (closing_cells (point ev) cc) + (close_cell (point ev) lcc), forall c, + ~~ (in_safe_side_left (point ev) c || in_safe_side_right (point ev) c)}. + move=> c cin; apply/negP. + move: cin; rewrite -map_rcons=> /mapP[c' c'in cq]. + have c'in' : c' \in state_open_seq st. + by rewrite ocd -cat_rcons !mem_cat c'in orbT. + move=> /orP[ /andP[] + _ | /andP[] _ /andP[] _ /andP[] _ ]. + rewrite cq left_limit_close_cell=> /eqP abs. + have := lolt c' _ c'in' (mem_head _ _). + by rewrite abs lt_irreflexive. + by rewrite cq close_cell_in //; apply/andP/(allP sval). +have in_safe_side_left_close_cell : + {in rcons cc lcc, forall c p, in_safe_side_left p (close_cell (point ev) c) = + in_safe_side_left p c}. + move=> c cin p; rewrite /in_safe_side_left. + have [-> -> ->] := close_cell_preserve_3sides (point ev) c. + by rewrite left_limit_close_cell. +(* Now comes the real important property. *) +have cl_safe_edge : + {in events_to_edges (rcons p_set ev) & state_closed_seq rstate, + forall (g : edge) (c : cell) (p : pt), + in_safe_side_left p c || in_safe_side_right p c -> ~ p === g}. + rewrite events_to_edges_rcons /state_closed_seq/=. + move=> g c gin cin p pin. + move: cin; rewrite -cats1 -catA /= -cat_rcons mem_cat=> /orP[cold | cnew]. + move: gin; rewrite mem_cat=> /orP[gold | gnew]. + (* the edge and the cell are old *) + by apply: (A g c); rewrite // stq /state_closed_seq/=. + (* the edge is new, the cell is old, I need to prove the events would + need to be vertically aligned here. *) + have cin' : c \in state_closed_seq st by rewrite stq. + have abs := rl _ _ cin' (mem_head _ _). + move=> /andP[] _ /andP[] + _. + have := out_events (gcomm c_inv) (mem_head _ _) gnew=> /eqP ->. + (* TODO : have the same condition, but for the right side of closed cells. *) + suff prl : p_x p <= right_limit c. + rewrite leNgt=> /negP; apply. + by apply: le_lt_trans abs. + have cold' : c \in state_closed_seq st by rewrite stq. + move: pin => /orP[]; last first. + by rewrite /in_safe_side_right => /andP[] /eqP -> _. + rewrite /in_safe_side_left=> /andP[] /eqP -> _. + by apply/ltW/rllt. + (* now the cells are newly closed. *) + move: cnew pin; rewrite cats1 /closing_cells -map_rcons. + move=> /mapP[c' c'in ->]. + have c'in' : c' \in state_open_seq st. + by rewrite ocd -cat_rcons !mem_cat c'in orbT. + move=> /orP[pin | pin]. + have pin': in_safe_side_left p c'. + by move: pin; rewrite in_safe_side_left_close_cell. + move: pin=> /andP[]; rewrite left_limit_close_cell => pl _. + move: gin; rewrite mem_cat=> /orP[gin | ]. + by apply: B pin'. + move=> /oute /eqP lgq /andP[] _ /andP[]; rewrite lgq leNgt=> /negP[]. + by rewrite (eqP pl); apply: lolt; rewrite // inE eqxx. + have vc' : valid_cell c' (point ev) by apply/andP/(allP sval). + have /eqP samex : p_x p == p_x (point ev). + by move: pin=> /andP[] + _; rewrite close_cell_right_limit. + move: gin; rewrite mem_cat=> /orP[gin | /oute/eqP lgq ]; last first. + have peg : point ev === g by rewrite -lgq left_on_edge. + move=> pong. + have /eqP samey := on_edge_same_point pong peg samex. + have pev : p = point ev by apply/eqP; rewrite pt_eqE samex samey eqxx. + have := not_safe_event (close_cell (point ev) c'). + rewrite -[e in in_safe_side_right e _]pev pin orbT. + by rewrite /closing_cells -map_rcons map_f // => /(_ isT). + move: gin=> /flatten_mapP[e' e'in gin]. + have := edge_covered_ec e_inv e'in gin=> -[]; last first. + move=> [[ | pcc0 pcc] []]; first by []. + move=> _ /= [pccsub [pcchigh [_ [_ rlpcc]]]] /andP[] _ /andP[] _. + rewrite leNgt=> /negP; apply. + rewrite samex -rlpcc; apply:rl; last by rewrite inE eqxx. + by apply/pccsub; rewrite /last_cell /= mem_last. + move=> [] opc [] pcc [] _ [] opch [] _ [] opco _ abs. + have [vlc'p vhc'p] : valid_edge (low c') p /\ valid_edge (high c') p. + by move: vc'; rewrite /valid_cell !(same_x_valid _ samex). + have pinc' : contains_point' p c'. + rewrite /contains_point'. + have [<- <- _] := close_cell_preserve_3sides (point ev) c'. + by have /andP[_ /andP[] /underW -> /andP[] ->] := pin. + have {}opch : high opc = g by apply: opch; rewrite mem_rcons inE eqxx. + have [vplc vphc] : valid_edge (low opc) p /\ valid_edge (high opc) p. + by rewrite !(same_x_valid _ samex); apply/andP/(allP sval). + have rfc : low opc <| high opc by apply: (allP rfo). + have cnt : contains_point p opc. + rewrite contains_pointE; apply/andP; rewrite under_onVstrict; last first. + by have := (allP sval _ opco) => /andP[]. + rewrite opch abs; split; last by []. + apply/negP=> pun. + have := order_edges_strict_viz_point' vplc vphc rfc pun. + by apply/negP/onAbove; rewrite opch. + have pw : pairwise (@edge_below _) [seq high c | c <- state_open_seq st]. + by move: (pairwise_open d_inv)=> /= /andP[]. + have [puhc' palc'] : p <<< high c' /\ p >>> low c'. + apply/andP; move: pin=> /andP[] _ /andP[] + /andP[] + _. + by have [-> -> _] := close_cell_preserve_3sides (point ev) c' => ->. + have : p >>= low opc by move: cnt=> /andP[]. + rewrite strict_nonAunder // negb_and negbK=> /orP[ | stricter]; last first. + have := disoc adj pw (sides_ok (gcomm c_inv)). + move=> /(_ opc c' opco c'in') [ab' | ]. + by move: puhc'; rewrite strict_nonAunder // -ab' opch abs. + move=> /(_ p) + ; move=>/negP. + rewrite inside_open'E stricter valid_open_limit //. + move: cnt; rewrite contains_pointE=> /andP[] _ ->. + rewrite samex lolt //=; last by rewrite inE eqxx. + rewrite inside_open'E (underW puhc') palc' valid_open_limit //. + by rewrite samex lolt // inE eqxx. + move=> ponl. + have vbp : valid_edge bottom p. + by rewrite (same_x_valid _ samex) (inside_box_valid_bottom inbox_e). + have vtp : valid_edge top p. + rewrite (same_x_valid _ samex) /valid_edge/generic_trajectories.valid_edge. + by move: inbox_e=> /andP[] _ /andP[] _ /andP[] /ltW -> /ltW ->. + have bottom_b_c' : bottom <| low c'. + have [-> | ] := eqVneq bottom (low c'); first by apply: edge_below_refl. + have [s1 [s2]] := mem_seq_split c'in'. + elim/last_ind: s1 => [ | s1 op' _] /= => odec. + by move: cbtom => /andP[]; rewrite odec /= => /eqP ->; rewrite eqxx. + have := adj. + rewrite odec cat_rcons=> /adjacent_catW /= [] _ /andP[] /eqP <- _ _. + have := pairwise_open d_inv=> /= /andP[] /allP /(_ (high op')) + _. + apply; apply/mapP; exists op'=> //. + by rewrite // odec !mem_cat mem_rcons inE eqxx. + have pab : p >>> bottom. + apply/negP=> pub. + have:= order_edges_viz_point' vbp vlc'p bottom_b_c' pub. + by move: palc'=> /[swap] => ->. + have ldifh : low opc != high opc by apply: d_e; rewrite mem_cat opco. + have low_opc_s : low opc \in [:: bottom, top & s]. + by apply: (edges_sub (gcomm c_inv)); rewrite !mem_cat map_f. + have high_opc_s : high opc \in [:: bottom, top & s]. + by apply: (edges_sub (gcomm c_inv)); rewrite !mem_cat map_f ?orbT. + have := nocs' (low opc) (high opc) low_opc_s high_opc_s. + move=> [Q | ]; first by rewrite Q eqxx in ldifh. + have ponh : p === high opc by rewrite opch. + have opcok : open_cell_side_limit_ok opc. + by apply: (allP (sides_ok (gcomm c_inv))). + move=> /(_ _ ponl ponh); rewrite !inE=> /orP[/eqP pleft | /eqP]. + have : left_limit opc < p_x p. + by rewrite samex; apply: lolt; rewrite // inE eqxx. + have := left_limit_max opcok. + have [_ | ] := lerP (p_x (left_pt (high opc)))(p_x (left_pt (low opc))). + by move=> /le_lt_trans /[apply]; rewrite pleft lt_irreflexive. + move=> /lt_le_trans /[apply]=> /lt_trans /[apply]. + by rewrite pleft lt_irreflexive. +(* Here p is vertically aligned with p_x, but it must be an event, + because it is the end of an edge. *) + move=> prl. + have put : p <<< top. + apply: (order_edges_strict_viz_point' vhc'p vtp _ puhc'). + move: cbtom=> /andP[] _. + have := pw. + have [s1 [s2 s1q]] := mem_seq_split c'in'. + rewrite s1q last_cat /= map_cat pairwise_cat /=. + move=> /andP[] _ /andP[] _ /andP[] allabovec' _ /eqP highlast. + case s2q : s2 => [ | c2 s3]. + by rewrite -highlast s2q edge_below_refl. + have /(allP allabovec') : (high (last c' s2)) \in [seq high c | c <- s2]. + by rewrite map_f // s2q /= mem_last. + by rewrite highlast. + have := (allP clae _ opco)=> /andP[] + _ => /orP[]. + rewrite !inE => /orP[] /eqP=> ab'. + by move: pab; rewrite under_onVstrict // -ab' ponl. + by move: put; rewrite strict_nonAunder // -ab' ponl. + move=> /hasP[e2 + /eqP pe2]; rewrite inE=> /orP[/eqP e2ev | e2in]. + (* if e' cannot be ev, because p cannot be ev because of pin *) + have := pin=> /andP[]. + by rewrite prl pe2 e2ev close_cell_in // ?andbF. +(* if e' is in future_events, then e' and p cannot have the same p_x, + because e' and ev don't, but p and e' are at the same point *) + have /andP[_ /=]:= general_pos c_inv. + rewrite path_sortedE; last by move=> ? ? ?; apply: lt_trans. + move=> /andP[] /allP /(_ e2 e2in). + by rewrite -pe2 -prl samex ltxx. +have op_safe_edge : + {in events_to_edges (rcons p_set ev) & state_open_seq rstate, + forall g c p, in_safe_side_left p c -> ~ p === g}. +(* We should re-use the proof that was just done. *) + move=> g c gin; rewrite /rstate/state_open_seq/=. + rewrite -catA -cat_rcons !mem_cat orbCA=> /orP[cnew | cold]; last first. + have cin : c \in state_open_seq st. + by rewrite ocd -cat_rcons !mem_cat orbCA cold orbT. + move: gin; rewrite events_to_edges_rcons mem_cat=> /orP[gold | gnew]. + by apply: (B _ _ gold cin). + move=> p pin /andP[] _ /andP[] pong _. + have := lolt _ _ cin (mem_head _ _). + move: (pin)=> /andP[] /eqP <- _. + rewrite ltNge=> /negP; apply. + by move: pong; rewrite (eqP (oute _ gnew)). + move=> p pin. + have : has (in_safe_side_left p) + (opening_cells (point ev) (outgoing ev) le he). + by apply/hasP; exists c; rewrite // /opening_cells oca_eq. + have := sides_equiv inbox_es oute rfo cbtom adj sval; rewrite stq /=. + move=> /(_ _ _ _ _ _ _ oe p) /eqP <- => /hasP[] c' c'in pin'. + have := cl_safe_edge _ c' gin; apply. + by rewrite /rstate /state_closed_seq/= rcons_cat /= mem_cat inE c'in ?orbT. + by rewrite pin' orbT. +have cl_safe_event : + {in rcons p_set ev & state_closed_seq rstate, forall e c (p : pt), + in_safe_side_left p c || in_safe_side_right p c -> p != point e}. + move=> e c; rewrite mem_rcons inE=> /orP[/eqP -> | ein]. + move=> cin p pin; apply/negP=> /eqP pev. + move: cin. + rewrite /rstate/state_closed_seq/= -cats1 -catA /= -cat_rcons mem_cat. + move=> /orP[]; last by rewrite cats1=> /not_safe_event; rewrite -pev pin. + move=> cin; have cin' : c \in state_closed_seq st by rewrite stq. + move: (cin)=> /safe_side_bound/(_ _ pin); rewrite pev leNgt=> /negP; apply. + by apply: (rl _ _ cin' (mem_head _ _)). + rewrite /rstate/state_closed_seq/= -cats1 -catA /= -cat_rcons mem_cat. + move=> /orP[cin | ]. + have cin' : c \in state_closed_seq st by rewrite stq. + by apply: (C _ _ ein cin'). + rewrite cats1 -map_rcons=> /mapP[c' c'in /[dup] cq ->]. + have c'in' : c' \in state_open_seq st. + by rewrite ocd -cat_rcons !mem_cat c'in orbT. + move=> p /orP[] pin. + apply: (D e c' ein c'in'). + by move: pin; rewrite in_safe_side_left_close_cell. + have /andP[vlc' vhc'] : valid_edge (low c') (point ev) && + valid_edge (high c') (point ev). + by apply: (allP sval). + move: (pin) => /andP[] + _. + rewrite right_limit_close_cell // => /eqP pxq. + apply/eqP=> abs. + have := old_lt_fut _ _ ein (mem_head _ _). + by rewrite -abs pxq lt_irreflexive. +have op_safe_event : +{in rcons p_set ev & state_open_seq rstate, + forall (e : event') (c : cell) (p : pt), + in_safe_side_left p c -> p != point e}. + move=> e c ein; rewrite /rstate/state_open_seq/=. + rewrite -catA -cat_rcons !mem_cat orbCA=> /orP[cnew | cold]; last first. + have cin : c \in state_open_seq st. + by rewrite ocd -cat_rcons !mem_cat orbCA cold orbT. + move: ein; rewrite mem_rcons inE=> /orP[/eqP -> | eold]; last first. + by apply: (D _ _ eold cin). + (* use lolt *) + have := lolt _ _ cin (mem_head _ _)=> llt p /andP[] /eqP pll _. + apply/eqP=> pev. + by move: llt; rewrite -pll pev lt_irreflexive. + move=> p pin. + have : has (in_safe_side_left p) + (opening_cells (point ev) (outgoing ev) le he). + by apply/hasP; exists c; rewrite // /opening_cells oca_eq. + have := sides_equiv inbox_es oute rfo cbtom adj sval; rewrite stq /=. + move=> /(_ _ _ _ _ _ _ oe p) /eqP <- => /hasP[] c' c'in pin'. + have := cl_safe_event _ c' ein; apply. + by rewrite /rstate /state_closed_seq/= rcons_cat /= mem_cat inE c'in ?orbT. + by rewrite pin' orbT. +have old_lt_fut' : + {in rcons p_set ev & future_events, + forall e1 e2, p_x (point e1) < p_x (point e2)}. + move=> e1 e2; rewrite mem_rcons inE=>/orP[/eqP -> | e1old] e2fut; last first. + by apply: old_lt_fut; rewrite // inE e2fut orbT. + have := general_pos c_inv=> /andP[] _ /=. + rewrite path_sortedE; last by move=> ? ? ?; apply: lt_trans. + by move=> /andP[] /allP + _; apply. +have rf_closed1 : {in state_closed_seq rstate, forall c, low c <| high c}. + move=> c; rewrite /rstate/state_closed_seq/=. + rewrite appE -cat_rcons -cats1 -catA. + rewrite mem_cat=> /orP[cin | ]. + by apply: rf_cl; rewrite /state_closed_seq stq/=. + rewrite cats1 -map_rcons=> /mapP[c' c'in ->]. + have [-> -> _] := close_cell_preserve_3sides (point ev) c'. + have [[] + _ _ _ _ _ _ _ _ _] := c_inv. + move=> [] _ [] _ [] _ [] _ /allP; apply. + by rewrite ocd -cat_rcons !mem_cat c'in orbT. +have lo_lb' : {in state_open_seq rstate, forall c, + left_limit c < min (p_x (right_pt bottom)) (p_x (right_pt top))}. + move=>c; rewrite /state_open_seq/= -catA -cat_rcons !mem_cat orbCA. + move=> /orP[cnew | cold]; last first. + by apply: lo_lb; rewrite ocd -cat_rcons !mem_cat orbCA cold orbT. + have := opening_cells_left oute vl vp ; rewrite /opening_cells oca_eq. + move=> /(_ _ cnew) ->. + by apply: inside_box_lt_min_right. +by constructor. +Qed. + +(* + +Lemma start_cover (bottom top : edge) (s : seq edge) closed open : + bottom <| top -> + open_cell_side_limit_ok (start_open_cell bottom top) -> + {in bottom :: top :: s &, no_crossing R} -> + all (inside_box bottom top) [seq left_pt x | x <- s] -> + all (inside_box bottom top) [seq right_pt x | x <- s] -> + start (edges_to_events s) bottom top = (closed, open) -> + forall p, inside_box bottom top p -> + has (inside_closed' p) closed || has (inside_open' p) open. +Proof. +move=> boxwf boxwf2 nocs leftin rightin; rewrite /start. +set evs := edges_to_events s. +have/perm_mem := edges_to_events_no_loss s. + rewrite -/evs/events_to_edges/= => stoevs. +set op0 := [:: Bcell (leftmost_points bottom top) [::] bottom top]. +set cl0 := (X in scan _ _ X). +have : sorted (@lexPt R) [seq point x | x <- evs]. + by apply: sorted_edges_to_events. +have : cells_bottom_top bottom top op0. + by rewrite /op0/cells_bottom_top/cells_low_e_top/= !eqxx. +have : adjacent_cells op0 by []. +have : s_right_form op0 by rewrite /= boxwf. +have : close_alive_edges bottom top op0 evs. + by rewrite /=/end_edge !inE !eqxx !orbT. +have : {in cell_edges op0 ++ flatten [seq outgoing i | i <- evs] &, + no_crossing R}. + rewrite /=; move: nocs; apply sub_in2. + move=> x; rewrite !inE => /orP[ -> // | /orP[-> // | ]]; rewrite ?orbT //. + by rewrite -stoevs => ->; rewrite ?orbT. +have : {in evs, forall ev, out_left_event ev}. + by apply: out_left_edges_to_events. +have : close_edges_from_events bottom top evs. + by apply: edges_to_events_wf. +have evsin0 : all (inside_box bottom top) + [seq point ev | ev <- evs]. + apply/allP. + have : {subset [seq right_pt g | g <- s] <= inside_box bottom top}. + by apply/allP: rightin. + have : {subset [seq left_pt g | g <- s] <= inside_box bottom top}. + by apply/allP: leftin. + by apply: edges_to_events_subset. +have btm_left0 : {in [seq point e | e <- evs], + forall e, bottom_left_cells_lex op0 e}. + move=> ev /[dup] /(allP evsin0) /andP[_ /andP[valb valt]] evin c. + rewrite /op0 inE /lexPt /bottom_left_corner=> /eqP -> /=. + by apply/orP; left; apply/inside_box_left_ptsP/(allP evsin0). +have sval0 : + evs != nil -> seq_valid op0 (head dummy_pt [seq point ev | ev <- evs]). + case evseq : evs => [// | ev evs'] _ /=; rewrite andbT. + move: evsin0; rewrite evseq /= => /andP[] /andP[] _ /andP[] ebot etop _. + have betW : forall a b c : R, a < b < c -> a <= b <= c. + by move=> a b c /andP[] h1 h2; rewrite !ltW. + by rewrite /valid_edge !betW. +have cov0 : forall p, all (lexePt p) [seq point ev | ev <- evs] -> + cover_left_of bottom top p op0 cl0. + move=> p limrp q inbox_q qp; apply/orP; left; apply/hasP. + exists (Bcell (leftmost_points bottom top) nil bottom top). + by rewrite /op0 inE eqxx. + rewrite inside_open'E. + apply/andP; split;[ | apply/andP; split]. + - by apply: underW; move: inbox_q=> /andP[] /andP[]. + - by move: inbox_q=> /andP[] /andP[]. + - rewrite /open_limit /=. + case: (ltrP (p_x (right_pt bottom)) (p_x (right_pt top))) => _. + rewrite inside_box_left_ptsP //. + by move: inbox_q => /andP[] _ /andP[] /andP[] _ /ltW ->. + rewrite inside_box_left_ptsP //. + by move: inbox_q => /andP[] _ /andP[] _ /andP[] _ /ltW ->. +have leftlim0 : {in op0, forall c p, inside_box bottom top p -> + left_limit c = p_x p -> + contains_point' p c -> has (inside_closed' p) cl0}. + move=> c + p; rewrite inE -[Bcell _ _ _ _]/(start_open_cell bottom top). + move=> /eqP -> {c}. + move/inside_box_left_ptsP/[swap]. + by rewrite (leftmost_points_max boxwf2)=> ->; rewrite lt_irreflexive. +move: cov0 evsin0 sval0 btm_left0 leftlim0; move=> {stoevs}. +elim: evs op0 cl0 => [ | ev evs' Ih] + op cl main evsin sval btm_left llim clev oute noc clae rfo adj cbtom sortev. + rewrite /= => [][] <- <- p inbox_p. + have lexpp : lexePt p p by rewrite lexePt_eqVlt eqxx. + by rewrite orbC; apply: (main p isT p inbox_p lexpp). +rewrite /=. +case stepeq : (step ev op cl) => [op' cl']. +move=> scaneq. +have inbox_e : inside_box bottom top (point ev). + by apply: (allP evsin); rewrite map_f // inE eqxx. +have := sval isT; rewrite /= => sval'. +have oute' : out_left_event ev by apply: oute; rewrite inE eqxx. +have btm_left' : bottom_left_cells_lex op (point ev). + by apply: btm_left; rewrite inE eqxx. +have cov : cover_left_of bottom top (point ev) op cl. + apply: main=> /=; rewrite lexePt_eqVlt eqxx /=. + move: sortev; rewrite /sorted /=. + rewrite (path_sortedE (@lexPt_trans R)) // => /andP[+ _]. + by apply: sub_all; exact: lexPtW. +have cov' : forall p : pt, + all (lexePt p) [seq point ev0 | ev0 <- evs'] -> + cover_left_of bottom top p op' cl'. + have := step_keeps_cover sortev cbtom adj inbox_e sval' oute' rfo clae clev + noc btm_left' llim stepeq cov. + move=> it p; apply: it. +have evle : forall ev', ev' \in evs' -> lexPt (point ev) (point ev'). + move=> ev' ev'in. + move: sortev=> /=; rewrite (path_sortedE (@lexPt_trans R))=> /andP[]/allP. + by move=> /(_ (point ev')) + _; apply; apply map_f. +have svalr : evs' != [::] -> + seq_valid op' (head dummy_pt [seq point ev0 | ev0 <- evs']). + case evs'eq : evs' => [// | a q] /= _. + have inbox_a : inside_box bottom top (point a). + by apply: (allP evsin); rewrite evs'eq !inE eqxx orbT. + have eva : lexPt (point ev) (point a). + by apply: evle; rewrite evs'eq inE eqxx. + have limra : forall e', e' \in evs' -> lexePt (point a) (point e'). + rewrite evs'eq => e'; rewrite inE => /orP[/eqP -> | e'q ]. + by rewrite lexePt_eqVlt eqxx. + move: sortev=> /=; rewrite evs'eq=> /path_sorted/=; rewrite path_sortedE. + by move=>/andP[]/allP/(_ (point e') (map_f (@point _) e'q))/lexPtW. + exact: lexPt_trans. + have := step_keeps_valid inbox_a inbox_e eva oute' rfo cbtom adj sval' clae + clev limra stepeq. + by []. +have btm_leftr: + {in [seq point e | e <- evs'], forall e, bottom_left_cells_lex op' e}. + have btm_left2 := + step_keeps_left_pts_inf inbox_e oute' rfo sval' adj cbtom clae clev + noc btm_left' stepeq. + by move=> evp /mapP [ev' ev'in ->]; apply/btm_left2/evle. +have evsinr : all (inside_box bottom top) [seq point ev' | ev' <- evs']. + by move: evsin; rewrite /= => /andP[]. +have clevr : close_edges_from_events bottom top evs'. + by move: clev; rewrite /= => /andP[]. +have outer :{in evs', forall ev0 : event, out_left_event ev0}. + by move: oute; apply: sub_in1=> x xin; rewrite inE xin orbT. +have nocr : {in cell_edges op' ++ flatten [seq outgoing i | i <- evs'] &, + no_crossing R}. + move: noc; apply: sub_in2=> x. + rewrite mem_cat=> /orP[]. + move/(step_sub_open_edges cbtom adj sval' oute' inbox_e stepeq)=> it. + by rewrite /= /cell_edges catA -(catA _ _ (outgoing ev)) mem_cat it. + by move=> xinf; rewrite /= !mem_cat xinf !orbT. +have claer : close_alive_edges bottom top op' evs'. + by have := step_keeps_closeness inbox_e oute' rfo cbtom adj sval' clev + clae stepeq. +have rfor : s_right_form op'. + have noc1: {in cell_edges op ++ outgoing ev &, no_crossing R}. + move: noc; apply sub_in2=> x. + rewrite mem_cat=> /orP[it| xino]. + by rewrite /= /cell_edges catA 2!mem_cat it. + by rewrite /= !mem_cat xino !orbT. + by apply: (step_keeps_right_form cbtom adj inbox_e sval' noc1 _ _ stepeq). +have adjr : adjacent_cells op'. + by have := step_keeps_adjacent inbox_e oute' sval' cbtom stepeq adj. +have cbtomr : cells_bottom_top bottom top op'. + by apply: (step_keeps_bottom_top inbox_e sval' adj cbtom oute' stepeq). +have sortev' : sorted (@lexPt R) [seq point x | x <- evs']. + by move: sortev; rewrite /= => /path_sorted. +have llim' : {in op', forall c p, inside_box bottom top p -> + left_limit c = p_x p -> + contains_point' p c -> has (inside_closed' p) cl'}. + by apply: (step_keeps_cover_left_border cbtom + adj inbox_e sval' oute' rfo clae + clev noc btm_left' stepeq llim). +by have := Ih _ _ cov' evsinr svalr btm_leftr llim' clevr outer nocr claer + rfor adjr cbtomr sortev' scaneq. +Qed. + +Lemma middle_disj_last fc cc lcc lc nos lno: + open = fc ++ cc ++ lcc :: lc -> + adjacent_cells (fc ++ nos ++ lno :: lc) -> + s_right_form (fc ++ nos ++ lno :: lc)-> + low (head lno nos) =low (head lcc cc) -> + high lno = high lcc -> + {in [seq high c | c <- nos], forall g, left_pt g == (point e)} -> + {in rcons nos lno &, disjoint_open_cells R} -> + {in fc ++ nos ++ lno :: lc &, disjoint_open_cells R}. +Proof. +move=> ocd adjn rfon lecnct hecnct lefts ndisj. +move: pwo=> /= /andP[] _ pwo'. +have:= disoc adj pwo'. +Qed. + + + +Lemma disjoint_open_parts fc cc lcc lc nos lno : + open = fc ++ cc ++ lcc :: lc -> + close_alive_edges (fc ++ nos ++ lno :: lc) future_events -> + low (head lcc cc) <| high lcc -> + low (head lcc cc) = low (head lno nos) -> + high lcc = high lno -> + {in rcons nos lno &, disjoint_open_cells R} -> + {in fc ++ nos ++ lno :: lc &, disjoint_open_cells R}. +Proof. +move=> ocd clae_new low_high. +have lfcbot : fc != [::] -> low (head dummy_cell fc) = bottom. + move: cbtom; rewrite ocd. + by case: (fc) => [// | /= ca ?] /andP[] /andP[] _ /=/eqP. +have higfc : fc != nil -> high (last dummy_cell fc) = low (head lcc cc). + elim/last_ind : (fc) ocd => [// |s c' _] /= ocd. + move: adj; rewrite ocd cat_rcons last_rcons =>/adjacent_catW[] _ /=. + by case: (cc) => [ | cc0 cc'] /= /andP[] /eqP ->. +move=> le_cnct. +move=> he_cnct. +have adjnew : adjacent_cells (fc ++ nos ++ lno :: lc). + rewrite (_ : fc ++ nos ++ lno :: lc = + fc ++ (rcons nos lno) ++ lc);last first. + by rewrite -cats1 -!catA. + a d m i t. +have rfnew : s_right_form (fc ++ nos ++ lno :: lc). + a d m i t. +apply: (@middle_disj_last _ cc lcc)=> //. + +*) +End working_environment. diff --git a/theories/civt.v b/theories/civt.v index a67007e..0cf0f63 100644 --- a/theories/civt.v +++ b/theories/civt.v @@ -55,7 +55,7 @@ by rewrite ler_pexpn2r// nnegrE// (le_trans x0).*) (*move=> l b; case: l =>[| a l]. - by exists 0; move=> /= x; rewrite mul0r oppr0 addr0 normr0 lexx. - exists (eval_pol (abs_pol l) b) => x px xb /=; rewrite mul0r addr0. - rewrite addrC addKr normrM ger0_norm // mulrC ler_wpmul2r//. + rewrite addrC addKr normrM ger0_norm // mulrC ler_wpM2r//. (* NB(rei): ler_absr_eval_pol? *) (* rewrite (le_trans (ler_absr_eval_pol _ _)) //. by rewrite eval_pol_abs_pol_increase // ger0_abs. diff --git a/theories/conv.v b/theories/conv.v index 03ffb97..46b2a86 100644 --- a/theories/conv.v +++ b/theories/conv.v @@ -68,7 +68,7 @@ apply/andP; split. by apply divr_ge0=>//; move:t01=>/andP[]. have [->|e0] := eqVneq (1 - (1 - t) * (1 - u)) 0; first by rewrite invr0 mulr0; exact ler01. rewrite -{4}(divff e0). -rewrite ler_wpmul2r ?invr_ge0//. +rewrite ler_wpM2r ?invr_ge0//. rewrite mulrBr mulr1 mulrBl -addrA opprD addrA subrr add0r opprB opprK -mulrBl -subr_ge0 -addrA subrr addr0; apply mulr_ge0; last by move:u01=>/andP[]. by move:t01; rewrite in01_onem=>/andP[]. Qed. @@ -157,7 +157,7 @@ move=>/andP[t0 t1] /andP[u0 u1] /andP[v0 v1]; apply/andP; split. apply addr_ge0; apply mulr_ge0=>//. by rewrite subr_ge0. have<-: t + (1-t) = 1 by rewrite addrCA subrr addr0. -apply ler_add; rewrite -subr_ge0. +apply: lerD; rewrite -subr_ge0. rewrite -{1}[t]mulr1 -mulrBr; apply mulr_ge0=>//. by rewrite subr_ge0. by rewrite -{1}[1-t]mulr1 -mulrBr; apply mulr_ge0; rewrite subr_ge0. @@ -209,7 +209,7 @@ have c0: forall x y : R, 0 <= x -> 0 <= y -> (x : R^o) <| t |> y = 0 -> x = 0 /\ by move=>/eqP->. move=>x0 y0 c0. suff: 0 < (x : R^o) <| t |> y by rewrite c0 ltxx. - rewrite /conv -(addr0 0) ; apply ltr_le_add. + rewrite /conv -(addr0 0) ; apply: ltr_leD. by apply mulr_gt0. by apply mulr_ge0=>//; apply ltW. have [|uv0] := eqVneq ((u : R^o) <| t |> v) 0. @@ -225,7 +225,7 @@ End Conv. Section between. Variable R : realType. -Let Plane := pair_vectType (regular_vectType R) (regular_vectType R). +Let Plane : vectType _ := (R^o * R^o)%type. Lemma det_conv (p p' q r : Plane) (t : R) : det (p <| t |> p') q r = (det p q r : R^o) <| t |> det p' q r. @@ -255,13 +255,21 @@ have [q0|q0] := eqVneq q 0%R; first by left. right. move:q0; rewrite -pair_eqE /= negb_and => /orP[|] q0. exists (1 - xcoord r / xcoord q)=>//. - rewrite -convC convrl add0r subr0; apply /eqP; rewrite -pair_eqE; apply /andP; split=>/=; have ->: forall (a: R) (b: (regular_vectType (Real.ringType R))), a *: b = a*b by lazy. - - by rewrite -mulrA [_^-1*_]mulrC divff // mulr1. - - by rewrite mulrC mulrA -e mulrC mulrA [_^-1*_]mulrC divff // mul1r. + rewrite -convC convrl add0r subr0; apply /eqP; rewrite -pair_eqE; apply /andP; split=>/=. + - apply/eqP. + transitivity ((xcoord r / xcoord q) * q.1) => //. + by rewrite -mulrA [_^-1*_]mulrC divff // mulr1. + - apply/eqP. + transitivity ((xcoord r / xcoord q) * q.2) => //. + by rewrite mulrC mulrA -e mulrC mulrA [_^-1*_]mulrC divff // mul1r. exists (1 - ycoord r / ycoord q)=>//. - rewrite -convC convrl add0r subr0; apply /eqP; rewrite -pair_eqE; apply /andP; split=>/=; have ->: forall (a: R) (b: regular_vectType (Real.ringType R)), a *: b = a*b by lazy. -- by rewrite mulrC mulrA e mulrC mulrA [_^-1*_]mulrC divff // mul1r. -- by rewrite -mulrA [_^-1*_]mulrC divff // mulr1. + rewrite -convC convrl add0r subr0; apply /eqP; rewrite -pair_eqE; apply /andP; split=>/=. + - apply/eqP. + transitivity ((ycoord r / ycoord q) * q.1) => //. + by rewrite mulrC mulrA e mulrC mulrA [_^-1*_]mulrC divff // mul1r. + - apply/eqP. + transitivity ((ycoord r / ycoord q) * q.2) => //. + by rewrite -mulrA [_^-1*_]mulrC divff // mulr1. Qed. Definition between (x y z : Plane) := [&& (det x y z == 0)%R, diff --git a/theories/convex.v b/theories/convex.v index 464edc8..e9af65b 100644 --- a/theories/convex.v +++ b/theories/convex.v @@ -1,5 +1,7 @@ -From mathcomp Require Import all_ssreflect all_algebra vector reals ereal classical_sets boolp Rstruct. -From infotheo Require Import convex Reals_ext. +From HB Require Import structures. +From mathcomp Require Import all_ssreflect all_algebra vector mathcomp_extra. +From mathcomp Require Import reals ereal classical_sets boolp Rstruct lra. +From infotheo Require Import ssrR Reals_ext realType_ext fdist convex. Require Import preliminaries. Import Order.POrderTheory Order.TotalTheory GRing.Theory Num.Theory preliminaries. @@ -8,8 +10,6 @@ Local Open Scope ring_scope. Require Import Reals. Local Close Scope N_scope. -Local Close Scope R_scope. -Delimit Scope R_scope with coqR. Delimit Scope nat_scope with N. Delimit Scope int_scope with Z. Delimit Scope ring_scope with R. @@ -25,8 +25,7 @@ Local Open Scope classical_set_scope. Local Open Scope convex_scope. Definition convex_set_of (A : set E) : is_convex_set A -> {convex_set E}. -move=>Aconv. -by exists A; apply CSet.Mixin. +by move=> Aconv; exists A; constructor; constructor. Defined. Lemma is_convex_setI (C D : {convex_set E}) : is_convex_set (C `&` D). @@ -39,76 +38,74 @@ Qed. Lemma hullX (F : convType) (C : set E) (D : set F) : hull (C `*` D) = hull C `*` hull D. Proof. rewrite eqEsubset; split. - move=>+ [n][g][d][gCD]-> =>_. + move=>+ [n][/=g][/=d][gCD]-> =>_. rewrite Convn_pair; split=>/=; - exists n; [exists (fst \o g) | exists (snd \o g)]; exists d; split=> // + [i] _ <- =>_ /=; + exists n; [exists (Datatypes.fst \o g) | exists (Datatypes.snd \o g)]; exists d; split=> // + [i] _ <- =>_ /=; (suff: ((C `*` D) (g i)) by move=>[]); by apply gCD; exists i. -move=>[+ +][]/=[n][g][d][gC->][m][f][e][fD->]=>_ _. +move=>[+ +][]/=[n][g][d][gC->][m][f][e] [fD->]=>_ _. exists (n * m)%N, (fun i=> let (i, j) := split_prod i in (g i, f j)), (fdistmap (unsplit_prod (n:=m)) (d `x e)%fdist); split. move=>+ [i] _ <- =>_. by case: (split_prod i)=>a b; split; [apply gC | apply fD]. rewrite Convn_pair/comp/=; congr pair; apply S1_inj; rewrite !S1_Convn big_prod_ord/=. apply eq_big => // i _. - rewrite -(scale1pt (scalept _ _)) scaleptA// -(FDist.f1 e). - move: (@mulr_suml R_ringType _ (index_enum [finType of 'I_m]) (mem 'I_m) - (fun i => nneg_ff e i) (nneg_ff d i)); rewrite -RmultE => ->. - simple refine (let h : nneg_fun 'I_m := _ in _). - exists (fun j => nneg_ff e j * nneg_ff d i)%coqR=>j. - exact: ssrR.mulR_ge0. - have -> : (\sum_(j in 'I_m) (nneg_ff e j) * (nneg_ff d i) = - \sum_(i in 'I_m) nneg_f h i)%coqR. - by apply eq_big => // j _; rewrite fdist_prodE. + rewrite -(scale1pt (scalept _ _)) scaleptA // -[(1 * d i)%coqR]/(1 * d i) -(FDist.f1 e). + rewrite mulr_suml. + have @h : nneg_fun 'I_m. + (* BUG HB.pack *) + exists (fun j => e j * d i)%coqR => j. + by apply: ssrR.mulR_ge0. + under eq_bigr => j _ do rewrite -[e j * d i]/(h j). rewrite scalept_sum; apply eq_big=>// j _. rewrite /h /= fdistmapE. - have -> : (\sum_(a in [finType of 'I_n * 'I_m] | + have -> : (\sum_(a in {: 'I_n * 'I_m} | a \in preim (@unsplit_prod _ m) (pred1 (Ordinal (unsplit_prodp i j)))) - nneg_ff (fdist_prod d (fun=> e)) a = - \sum_(a in [finType of 'I_n * 'I_m] | a \in pred1 (i, j)) - nneg_ff (fdist_prod d (fun=> e)) a)%coqR. + (fdist_prod d (fun=> e)) a = + \sum_(a in {: 'I_n * 'I_m} | a \in pred1 (i, j)) + (fdist_prod d (fun=> e)) a)%coqR. apply eq_big=>// k; congr andb; rewrite 3!inE. by apply: (eqtype.inj_eq _ k (i, j)); exact: (can_inj (@unsplit_prodK _ _)). rewrite (big_pred1 (i, j))// fdist_prodE/= ssrR.mulRC; congr (scalept _ (S1 (g _))). - by move: (unsplit_prodK (i, j)) => /(congr1 fst)/esym. + by move: (unsplit_prodK (i, j)) => /(congr1 Datatypes.fst)/esym. rewrite (exchange_big_dep xpredT)//=; apply: eq_bigr => j _. -rewrite -(scale1pt (scalept _ _)) scaleptA// -(FDist.f1 d). -move: (@mulr_suml R_ringType _ (index_enum [finType of 'I_n]) (mem 'I_n) - (fun i=> nneg_ff d i) (nneg_ff e j)); rewrite -RmultE => ->. -simple refine (let h : nneg_fun 'I_n := _ in _). - exists (fun i=> nneg_ff d i * nneg_ff e j)%coqR => i. - exact: ssrR.mulR_ge0. -have -> : (\sum_(i in 'I_n) nneg_ff d i * nneg_ff e j = \sum_(i in 'I_n) nneg_f h i)%coqR. - by apply eq_big=>// i _; rewrite fdist_prodE. +rewrite -(scale1pt (scalept _ _)) scaleptA// -[(1 * e j)%coqR]/(1 * e j) -(FDist.f1 d). +rewrite mulr_suml. + +have @h : nneg_fun 'I_n. +(* BUG HB.pack *) + exists (fun i => d i * e j)%coqR => i. + by apply: ssrR.mulR_ge0. +under eq_bigr => i _ do rewrite -[d i * e j]/(h i). rewrite scalept_sum; apply: eq_big => // i _. rewrite /h/= fdistmapE. -have -> : (\sum_(a in [finType of 'I_n * 'I_m] | +have -> : (\sum_(a in {: 'I_n * 'I_m} | a \in preim (unsplit_prod (n:=m)) (pred1 (Ordinal (unsplit_prodp i j)))) - nneg_ff (fdist_prod d (fun=> e)) a = + (fdist_prod d (fun=> e)) a = \sum_(a in - [finType of 'I_n * 'I_m] | a \in pred1 (i, j)) - nneg_ff (FDist.f (fdist_prod d (fun=> e))) a)%coqR. + {: 'I_n * 'I_m} | a \in pred1 (i, j)) + (FDist.f (fdist_prod d (fun=> e))) a)%coqR. apply: eq_big=>// k; congr andb; rewrite 3!inE. by apply: (eqtype.inj_eq _ k (i, j)); exact (can_inj (@unsplit_prodK _ _)). -rewrite (big_pred1 (i, j))// fdist_prodE/= ssrR.mulRC; congr (scalept _ (S1 (f _))). -by move:(unsplit_prodK (i, j))=>/(congr1 snd)/esym. +rewrite (big_pred1 (i, j))// fdist_prodE/=; congr (scalept _ (S1 (f _))). +by move:(unsplit_prodK (i, j))=>/(congr1 Datatypes.snd)/esym. Qed. End convex. - -Lemma add_affine (E : lmodType R_ringType) : affine (fun p : E * E => p.1 + p.2). +Import LmoduleConvex. +Lemma add_affine (E : lmodType R) : affine (fun p : E * E => p.1 + p.2). Proof. move=>p/= [x0 x1] [y0 y1]/=. by rewrite/conv/= addrACA -2!scalerDr. Qed. -Lemma scale_affine (E : lmodType R_ringType) (t : R) : affine (fun x : E => t *: x). +Lemma scale_affine (E : lmodType R) (t : R) : affine (fun x : E => t *: x). Proof. move=> p/= x y. by rewrite/conv/= scalerDr; congr GRing.add; rewrite 2!scalerA mulrC. Qed. Section C. -Variable E F: lmodType R_ringType. +Variable E F: lmodType R. Variable f : {linear E -> F}. Local Open Scope fun_scope. @@ -150,26 +147,41 @@ by rewrite segmentC. Qed. End face. + +(* TODO: rm, will be fixed in infotheo 0.7.1 *) +Module LinearAffine. +Section linear_affine. +Open Scope ring_scope. +Variables (E F : lmodType R) (f : {linear E -> F}). +Import LmoduleConvex. +Let linear_is_affine: affine f. +Proof. by move=>p x y; rewrite linearD 2!linearZZ. Qed. + +#[export] HB.instance Definition _ := isAffine.Build _ _ _ linear_is_affine. + +End linear_affine. +End LinearAffine. +HB.export LinearAffine. + Section face. -Variable E: lmodType R_ringType. +Variable E: lmodType R. Local Open Scope fun_scope. Local Open Scope ring_scope. Local Open Scope convex_scope. -Lemma probinvn1 : probinvn 1 = 2^-1 :> R_numFieldType. +Lemma probinvn1 : probinvn 1 = (1 / 2%R : R)%:pr. Proof. -rewrite /R_numFieldType /GRing.inv /= /Rinvx. -case:ifP=>// /negbFE. -by rewrite/Rdefinitions.IZR intr_eq0. +apply: val_inj => /=. +by rewrite div1R. Qed. -Lemma onem_half: onem 2^-1 = 2^-1. +Lemma onem_half: onem 2^-1 = 2^-1 :> R. Proof. -have ne20: (2 : R_ringType) != 0 by rewrite intr_eq0. -apply (mulfI ne20). -by rewrite mulrBr mulr1 divff// -pmulrn mulr2n -addrA subrr addr0. +rewrite /onem. +rewrite [X in X - _ = _](splitr 1). +by rewrite div1r addrK. Qed. Lemma ext_carac (A : {convex_set E}) (x: E): x \in A -> [<-> x \in ext A; @@ -178,8 +190,11 @@ Lemma ext_carac (A : {convex_set E}) (x: E): x \in A -> [<-> x \in ext A; face A [set x]]. Proof. move=>xA. -have ne20: (2 : R_ringType) != 0 by rewrite intr_eq0. -have ge20: (0 : R_ringType) <= 2 by apply mulrz_ge0=>//; exact ler01. +have ne20: (2 : R) != 0. + rewrite [X in X != _](_ : _ = 2%:R)//. + by rewrite pnatr_eq0. +have ge20: (0 : R) <= 2. + by rewrite ler0n. split. move=>xext u v uA vA xe. move: xext=>/set_mem /(_ u v uA vA). @@ -192,43 +207,44 @@ split. apply /esym; apply h=>//; last by left. rewrite xe convC; congr (v <| _ |> u). apply val_inj=>/=. - rewrite probinvn1 /onem. - by apply/eqP; rewrite subr_eq -(div1r 2) -splitr. + set tmp : R := (1 + 1)%:R. + rewrite (_ : tmp = 2%R)//. + rewrite coqRE. + by rewrite onem_half. move: xe=> -> + _. move=> /(congr1 (fun x => 2 *: x)). - rewrite scalerDr probinvn1 onem_half 2!scalerA divff// 2!scale1r. - by rewrite -pmulrn mulr2n scalerDl scale1r=>/addrI/esym. + rewrite scalerDr probinvn1/=. + rewrite div1R coqRE. + rewrite onem_half 2!scalerA divff// 2!scale1r. + by rewrite scaler_nat mulr2n =>/addrI/esym. split. move=>xext. apply/asboolP=>u v t [uA ux] [vA vx]. split; first by move:(convex_setP A)=>/asboolP; apply. - wlog: u v t xext xA uA ux vA vx / (t : R_ringType) <= 2^-1. + wlog: u v t xext xA uA ux vA vx / Prob.p t <= 2^-1. move=>h. - have [tle|tle] := leP (t : R_ringType) (2^-1); first exact: (h u v t). + have [tle|tle] := leP (Prob.p t) (2^-1); first exact: (h u v t). rewrite convC. apply (h v u (onem t)%:pr)=>//. - rewrite -onem_half; apply ler_sub=>//. + rewrite -onem_half; apply: lerB=>//. exact/ltW. move=>tle. - have t01: ssrR.leRb (Rdefinitions.IZR BinNums.Z0) (2%:R*(t : R_ringType)) && - ssrR.leRb (2*(t : R_ringType)) (Rdefinitions.IZR (BinNums.Zpos 1%AC)). - apply/andP; split; apply/ssrR.leRP/RleP. - apply mulr_ge0=>//. - by apply/RleP/prob_ge0. - by move:tle=>/(ler_wpmul2l ge20); rewrite divff. + have t01: ((Rdefinitions.IZR BinNums.Z0) <= 2%:R * (Prob.p t : R)) && + (2*(Prob.p t : R) <= Rdefinitions.IZR (BinNums.Zpos 1%AC)). + apply/andP; split. + by apply mulr_ge0=>//. + by move:tle=>/(ler_wpM2l ge20); rewrite divff. move=>/esym xE. move: xext=>/(_ (u <| Prob.mk t01 |> v) v). rewrite -convA' convmm. have ->: p_of_rs (Prob.mk t01) (probinvn 1) = t. apply val_inj. rewrite/= p_of_rsE/=. - have tE: (2*(t : R_ringType))/2 = t. + have tE: (2*(Prob.p t : R))/2 = Prob.p t. by rewrite mulrAC divff// mul1r. rewrite -{2}tE. congr Rdefinitions.RbaseSymbolsImpl.Rmult. - rewrite/R_unitRing/GRing.inv/=/Rinvx. - case:ifP=>//. - by rewrite ne20. + by rewrite coqRE//. have wA: u <| Prob.mk t01 |> v \in A. by apply mem_set; move:(convex_setP A)=>/asboolP; apply. move: vA=>/mem_set vA /(_ wA vA xE) /(congr1 (fun x => x-v)). @@ -268,7 +284,7 @@ split => //. by apply (Gface x). Qed. -Definition supporting_hyperplane (A : set E) (f: {linear E -> R^o}) (a: R_ringType) := +Definition supporting_hyperplane (A : set E) (f: {linear E -> R^o}) (a: R) := (exists x, x \in A /\ f x = a) /\ ((forall x, x \in A -> f x <= a) \/ (forall x, x \in A -> a <= f x)). @@ -280,7 +296,7 @@ by rewrite affine_conv -in_setE; apply/mem_convex_set; rewrite in_setE. Qed. (* TOTHINK : lemmas prove is_convex_set but use {convex_set _}. *) -Lemma supporting_hyperplan_face (A : {convex_set E}) (f: {linear E -> R^o}) (a: R_ringType) : +Lemma supporting_hyperplan_face (A : {convex_set E}) (f: {linear E -> R^o}) (a: R) : supporting_hyperplane A f a <-> (exists x, x \in A /\ f x = a) /\ face A (A `&` (f @^-1` [set a])). Proof. @@ -288,32 +304,31 @@ split; move=>[hex hface]; split=>//. wlog: f a hex hface / (forall x : E, x \in A -> f x <= a). move=>h; move: (hface); case=>hf. by apply (h f a). - move: h=>/(_ (GRing.comp_linear f (GRing.opp_linear E)) (- a)). - have hf' (x : E) : x \in A -> GRing.comp_linear f (GRing.opp_linear E) x <= - a. - by move=> xA /=; rewrite -scaleN1r linearZZ scaleN1r ler_oppl opprK; apply hf. - have hex': exists x : E, x \in A /\ GRing.comp_linear f (GRing.opp_linear E) x = - a. + move: h=>/(_ (f \o (@GRing.opp E)) (- a)). + have hf' (x : E) : x \in A -> (f \o (@GRing.opp E)) x <= - a. + by move=> xA /=; rewrite -scaleN1r linearZZ scaleN1r lerNl opprK; apply hf. + have hex': exists x : E, x \in A /\ (f \o (@GRing.opp E)) x = - a. by move: hex=>[x [xA fx]]; exists x; split=>//=; rewrite -fx -scaleN1r linearZZ scaleN1r. move=>/(_ hex' (or_introl hf') hf'); congr (face A (A `&` _)). by rewrite eqEsubset; split=>x /= /eqP; rewrite -scaleN1r linearZZ scaleN1r; [ rewrite eqr_opp | rewrite -eqr_opp ]=>/eqP. move=> hf; apply face'P; split; [ by apply subIsetl | |]. - exact: (is_convex_setI _ (convex_set_of (is_convex_set_preimage _ (convex_set_of (is_convex_set1 (a : GRing.regular_lmodType R_ringType)))))). + exact: (is_convex_setI _ (convex_set_of (is_convex_set_preimage f (set1 a)))). move=> x u v /set_mem [xA xa] uA vA /set_mem [t _ tx] xv; apply mem_set; (split; [ by apply set_mem |]); apply /eqP; rewrite -lte_anti; apply /andP; (split; [ by apply hf |]). - have t0 : (t : R_ringType) != 0. + have t0 : (Prob.p t : R) != 0. by apply/eqP=>/val_inj t0; subst t; move: tx xv; rewrite conv0 => ->; rewrite eqxx. - have tgt : 0 < (t : R_ringType) by rewrite lt0r t0=>/=; exact/RleP. - move: tx=>/(f_equal (fun x=> (t : R_ringType)^-1 *: (x - (onem t) *: v))). + have tgt : 0 < (Prob.p t : R) by rewrite lt0r t0=>/=. + move: tx=>/(f_equal (fun x=> (Prob.p t : R)^-1 *: (x - (onem t) *: v))). rewrite -addrA subrr addr0 scalerA mulVf // scale1r=>->. - rewrite linearZZ linearD xa -scaleNr linearZZ ler_pdivl_mull// addrC -subr_ge0 -addrA -mulNr -{1}[a]mul1r -mulrDl scaleNr -scalerN -mulrDr; apply mulr_ge0. - exact/RleP. + rewrite linearZZ linearD xa -scaleNr linearZZ ler_pdivlMl// addrC -subr_ge0 -addrA -mulNr -{1}[a]mul1r -mulrDl scaleNr -scalerN -mulrDr; apply mulr_ge0 => //. by rewrite addrC Num.Internals.subr_ge0; apply hf. have : forall x y, x \in A -> y \in A -> f x < a -> a < f y -> False. move=> u v uA vA fua afv. move: (Order.POrderTheory.lt_trans fua afv); rewrite -subr_gt0=>fufv. - have t01: ssrR.leRb (Rdefinitions.IZR BinNums.Z0) ((f v - a) / (f v - f u))%R && - ssrR.leRb ((f v - a) / (f v - f u))%R (Rdefinitions.IZR (BinNums.Zpos 1%AC)). - apply/andP; split; apply/ssrR.leRP/RleP. + have t01: (Rdefinitions.IZR BinNums.Z0 <= (f v - a) / (f v - f u))%R && + (((f v - a) / (f v - f u))%R <= Rdefinitions.IZR (BinNums.Zpos 1%AC)). + apply/andP; split. by apply divr_ge0; apply ltW=>//; rewrite subr_gt0. - rewrite ler_pdivr_mulr// mul1r -subr_ge0 opprB addrAC addrCA subrr addr0 subr_ge0. + rewrite ler_pdivrMr// mul1r -subr_ge0 opprB addrAC addrCA subrr addr0 subr_ge0. by apply ltW. move: hface=>/face'P [_ _ /(_ (u <| Prob.mk t01 |> v) u v)]. have inuv: u <| Prob.mk t01 |> v \in segment u v. @@ -322,7 +337,7 @@ have : forall x y, x \in A -> y \in A -> f x < a -> a < f y -> False. rewrite/= affine_conv/=/conv/=. move: fufv; rewrite lt0r=>/andP [fufv _]. apply (mulfI fufv). - rewrite/GRing.regular_lmodType/GRing.scale/=. + rewrite/GRing.scale/=. rewrite mulrDr mulrAC mulrCA mulrAC divff// mulr1. rewrite [onem _ * _]mulrBl mul1r mulrBr mulrAC mulrCA mulrAC divff// mulr1. rewrite -mulrBl opprB addrAC addrCA subrr addr0. @@ -351,35 +366,41 @@ Qed. End face. Section cone. -Variable E: lmodType R_ringType. +Variable E: lmodType R. Local Open Scope fun_scope. Local Open Scope ring_scope. Local Open Scope convex_scope. Definition cone0 (A : set E) := - ([set (t : R_ringType) *: a | t in (@setT Rpos) & a in A] `<=` A)%classic. + ([set (t : R) *: a | t in (@setT Rpos) & a in A] `<=` A)%classic. Definition cone (x: E) (A: set E) := cone0 [set a - x | a in A]%classic. Lemma cone0_convex (A: set E): cone0 A -> (is_convex_set A <-> ([set a+b | a in A & b in A] `<=` A)%classic). Proof. -have ne20: (2 : R_ringType) != 0 by rewrite intr_eq0. -have /RltP/ssrR.ltRP gt20: (0 : R_ringType) < 2 by rewrite ltr0z. +have ne20: (2 : R) != 0. + rewrite [X in X != _](_ : _ = 2%:R)//. + by rewrite pnatr_eq0. +have gt20 : ((0 : R) < 2)%R. + by rewrite ltr0n. move=>Acone; split=>Aconv. move=>x [u uA] [v vA] <-. have uA2: A (2 *: u) by apply Acone; exists (Rpos.mk gt20)=>//; exists u. have vA2: A (2 *: v) by apply Acone; exists (Rpos.mk gt20)=>//; exists v. move:Aconv=>/asboolP/(_ _ _ (probinvn 1) uA2 vA2); congr A. - by rewrite/conv/= probinvn1 onem_half 2!scalerA mulrC divff// 2!scale1r. + rewrite probinvn1/=. + rewrite /conv/=. + rewrite div1R coqRE. + by rewrite onem_half 2!scalerA mulVf// 2!scale1r. apply/asboolP. move=>x y t xA yA. -move:(prob_ge0 t)=>/RleP; rewrite le0r=>/orP; case. +move:(prob_ge0 t); rewrite le0r=>/orP; case. by rewrite/conv/= =>/eqP ->; rewrite scale0r add0r onem0 scale1r. -move=>/RltP/ssrR.ltRP t0; move: (prob_le1 t)=>/RleP; rewrite -subr_ge0 le0r=>/orP; case. +move=> t0; move: (prob_le1 t); rewrite -subr_ge0 le0r=>/orP; case. by rewrite subr_eq0 /conv/= =>/eqP <-; rewrite onem1 scale0r addr0 scale1r. -move=>/RltP/ssrR.ltRP t1; apply Aconv; exists ((t : R_ringType) *: x); +move=> t1; apply Aconv; exists ((Prob.p t : R) *: x); [| exists ((onem t) *: y) ]=>//; apply Acone. by exists (Rpos.mk t0)=>//; exists x. by exists (Rpos.mk t1)=>//; exists y. @@ -389,7 +410,7 @@ Qed. (* TODO: maybe change the 0 <= k i to 0 < k i in the definition of conv. *) Definition cone0_of (A: set E): set E := [set a | exists n (s : 'I_n.+1 -> E) (k: 'I_n.+1 -> Rpos), - \sum_i (k i : R_ringType) *: (s i) = a /\ (range s `<=` A)%classic]. + \sum_i (k i : R) *: (s i) = a /\ (range s `<=` A)%classic]. Lemma cone0_of_cone0 (A: set E): cone0 (cone0_of A). Proof. @@ -398,47 +419,48 @@ rewrite scaler_sumr; exists n, s, (fun i => mulRpos t (k i)); split => //. by apply congr_big=>// i _; apply /esym; apply scalerA. Qed. -Lemma cone0_of_hullE (A: set E): cone0_of A = [set (t : R_ringType) *: a | t in (@setT Rpos) & a in (hull A)]%classic. +Lemma cone0_of_hullE (A: set E): cone0_of A = [set (t : R) *: a | t in (@setT Rpos) & a in (hull A)]%classic. Proof. rewrite eqEsubset; split=>x. - move=>[n [s [k [<- kA]]]]; set t := \sum_i (k i : R_ringType). - have k0' (i : 'I_n.+1) : true -> 0 <= (k i : R_ringType) by move=> _; apply/ltW/RltP/Rpos_gt0. + move=>[n [s [k [<- kA]]]]; set t := \sum_i (k i : R). + have k0' (i : 'I_n.+1) : true -> 0 <= (k i : R) by move=> _; apply/ltW/RltP/Rpos_gt0. have: 0 <= t by apply sumr_ge0. rewrite le0r=>/orP; case. move=>/eqP /psumr_eq0P; move=> /(_ k0') /(_ ord0 Logic.eq_refl) k00; exfalso. by move:(Rpos_gt0 (k ord0))=>/RltP; rewrite k00 ltxx. move=>t0. - have tk0: forall i, Rdefinitions.Rle (Rdefinitions.IZR BinNums.Z0) ([ffun i => t^-1 * k i] i). - by move=>i; rewrite ffunE; apply/RleP/mulr_ge0; [ apply ltW; rewrite invr_gt0 | apply k0' ]. + have tk0: forall i, (Rdefinitions.IZR BinNums.Z0 <= [ffun i => t^-1 * k i] i). + by move=>i; rewrite ffunE; apply/mulr_ge0; [ apply ltW; rewrite invr_gt0 | apply k0' ]. have tk1 : \sum_(i < n.+1) [ffun i => t^-1 * k i] i = 1. transitivity (\sum_(i < n.+1) t^-1 * k i). by apply congr_big=>// i _; rewrite ffunE. rewrite -mulr_sumr mulrC divff//. by move:t0; rewrite lt0r=>/andP[]. - move:(t0)=>/RltP/ssrR.ltRP t0'; exists (Rpos.mk t0')=>//; exists (t^-1 *: \sum_i (k i : R_ringType) *: s i). - exists n.+1, s, (@FDist.make _ (finfun (fun i=> t^-1 * k i)) tk0 tk1); split=> //. + move:(t0)=> t0'; exists (Rpos.mk t0')=>//; exists (t^-1 *: \sum_i (k i : R) *: s i). + exists n.+1, s, (@FDist.make _ _ (finfun (fun i=> t^-1 * k i)) tk0 tk1); split=> //. rewrite scaler_sumr avgnrE. apply congr_big=>// i _. by rewrite scalerA ffunE. by rewrite scalerA divff ?gt_eqF// scale1r. move=>[t /= _] [a [n [s [d [sA ->]]]]] <-. -rewrite avgnrE scaler_sumr (@mathcomp_extra.bigID_idem _ _ _ _ _ _ _ _ (fun i=> 0 < d i)); [| apply addrA | apply addrC | apply addr0 ]. -have ->: \sum_(i | true && ~~ (0 < d i)) (t : R_ringType) *: (d i *: s i) = \sum_(i | true && ~~ (0 < d i)) 0 *: 0. +rewrite avgnrE scaler_sumr. +rewrite (@bigID_idem _ _ _ _ _ _ (fun i=> 0 < d i))/=; [| exact: addr0]. +have ->: \sum_(i | true && ~~ (0 < d i)) (t : R) *: (d i *: s i) = \sum_(i | true && ~~ (0 < d i)) 0 *: 0. apply congr_big=>// i /andP [_]; rewrite lt0r negb_and negbK. - move:(FDist.ge0 d i)=>/RleP->; rewrite orbF=>/eqP->. + move:(FDist.ge0 d i)=>->; rewrite orbF=>/eqP->. by rewrite 2!scale0r GRing.scaler0. rewrite -[\sum_(_ < _ | _) 0 *: 0]scaler_sumr scale0r addr0 -big_filter /=. -remember [seq i <- index_enum [finType of 'I_n] | 0 < d i] as I; move: HeqI=>/esym HeqI. +remember [seq i <- index_enum 'I_n | 0 < d i] as I; move: HeqI=>/esym HeqI. case: I HeqI=> [| i I] HeqI. - exfalso; move: (FDist.f1 d) (oner_neq0 R_ringType); rewrite (@mathcomp_extra.bigID_idem _ _ _ _ _ _ _ _ (fun i=> 0 < d i)); [| apply addrA | apply addrC | apply addr0 ]. + exfalso; move: (FDist.f1 d) (oner_neq0 R); rewrite (@bigID_idem _ _ _ _ _ _ (fun i=> 0 < d i))/=; [|apply addr0 ]. rewrite -big_filter HeqI big_nil/=. - have ->: forall x, Rdefinitions.RbaseSymbolsImpl.Rplus Rdefinitions.RbaseSymbolsImpl.R0 x = 0+x by []. - have ->: Rdefinitions.IZR (BinNums.Zpos 1%AC) = 1 by []. rewrite add0r=><- /eqP; apply. - transitivity (\sum_(i < n | true && ~~ (0 < d i)) (0*0:R_ringType)). + transitivity (\sum_(i < n | true && ~~ (0 < d i)) (0*0:R)). 2: by rewrite -mulr_sumr mul0r. - by apply congr_big=>// i /= dile; move: (FDist.ge0 d i)=>/RleP; rewrite le0r mul0r=>/orP; case=> [ /eqP // | ]; move: dile=>/[swap]->. -have: subseq (i::I) (index_enum [finType of 'I_n]) by rewrite -HeqI; apply filter_subseq. + apply congr_big=>// i /= dile; move: (FDist.ge0 d i); rewrite le0r. + rewrite (negbTE dile) orbF => /eqP ->. + by rewrite mul0R. +have: subseq (i::I) (index_enum 'I_n) by rewrite -HeqI; apply filter_subseq. case: n s d sA i I HeqI=> [| n] s d sA i I HeqI. by inversion i. move=> /subseq_incl; move=> /(_ ord0); rewrite size_index_enum card_ord; move=> [f [fn flt]]. @@ -449,7 +471,7 @@ simple refine (ex_intro _ _ _). simple refine (Rpos.mk _). exact (d (nth ord0 (i :: I) j)). rewrite -HeqI. - apply/ssrR.ltRP/RltP/(@nth_filter _ (fun i=> 0 < d i)). + apply/(@nth_filter _ (fun i=> 0 < d i)). by rewrite HeqI. split. rewrite [in RHS]HeqI. @@ -476,18 +498,18 @@ End cone. Section Fun. Variable E: convType. -Variable f: E -> \bar R_ringType. +Variable f: E -> \bar R. Local Open Scope fun_scope. Local Open Scope ring_scope. Local Open Scope ereal_scope. Local Open Scope convex_scope. -Definition fconvex := forall (x y: E) (t: prob), - f (x <|t|> y) <= EFin (t : R_ringType) * f x + EFin (onem t)%R * f y. +Definition fconvex := forall (x y: E) (t: {prob R}), + f (x <|t|> y) <= EFin (Prob.p t : R) * f x + EFin (onem t)%R * f y. -Definition fconvex_strict := forall (x y: E) (t: oprob), x <> y -> - f (x <|t|> y) < EFin (t : R_ringType) * f x + EFin (onem t)%R * f y. +Definition fconvex_strict := forall (x y: E) (t: oprob R), x <> y -> + f (x <|t|> y) < EFin (Prob.p t : R) * f x + EFin (onem t)%R * f y. Lemma fconvex_max_ext (C: {convex_set E}) (x: E): fconvex_strict -> @@ -498,16 +520,18 @@ Lemma fconvex_max_ext (C: {convex_set E}) (x: E): Proof. move=> fconv xC fxoo xmax. rewrite in_setE/ext/= =>u v /xmax uC /xmax vC /set_mem [t] _ xE; subst x. -move: (prob_ge0 t)=>/RleP; rewrite le0r=>/orP; case. +move: (prob_ge0 t); rewrite le0r=>/orP; case. by move=>/eqP/val_inj ->; right; rewrite conv0. move=>t0. -move: (prob_le1 t)=>/RleP; rewrite -subr_ge0 le0r=>/orP; case. - have->: Rdefinitions.IZR (BinNums.Zpos 1%AC) = Prob.p (1%R)%:pr by []. - by rewrite subr_eq0=>/eqP/val_inj <-; left; rewrite conv1. +move: (prob_le1 t); rewrite -subr_ge0 le0r=>/orP; case. + rewrite subr_eq0=>/eqP t1. + rewrite (_ : t = 1%:pr)//; last first. + by apply/val_inj. + by left; rewrite conv1. rewrite subr_gt0=>t1. -have t01: ssrR.ltRb (Rdefinitions.IZR BinNums.Z0) t && - ssrR.ltRb t (Rdefinitions.IZR (BinNums.Zpos 1%AC)). - by apply/andP; split; apply/ssrR.ltRP/RltP. +have t01: (Rdefinitions.IZR BinNums.Z0 < Prob.p t)%R && + (Prob.p t < Rdefinitions.IZR (BinNums.Zpos 1%AC))%R. + by apply/andP; split. have [->|/eqP uv] := eqVneq u v; first by rewrite convmm; left. move:(fconv u v (OProb.mk t01) uv)=>/=. have fle: (Prob.p t)%:E * f u + (onem (Prob.p t))%:E * f v <= f (u <|t|> v). @@ -515,8 +539,8 @@ have fle: (Prob.p t)%:E * f u + (onem (Prob.p t))%:E * f v <= f (u <|t|> v). rewrite -ge0_muleDl ?lee_fin /onem ?RminusE -?EFinD. - by rewrite addrCA subrr addr0 mul1e. - by apply ltW. - - by rewrite subr_ge0; apply/RleP/prob_le1. - apply (@lee_add R_realDomainType); rewrite (@lee_pmul2l R_realDomainType)//= lte_fin. + - by rewrite subr_ge0; apply/prob_le1. + apply (@lee_add R); rewrite (@lee_pmul2l R)//= lte_fin. by rewrite subr_gt0. by move=>/(Order.POrderTheory.le_lt_trans fle); rewrite ltxx. Qed. diff --git a/theories/counterclockwise.v b/theories/counterclockwise.v index fd273f2..461feb6 100644 --- a/theories/counterclockwise.v +++ b/theories/counterclockwise.v @@ -1,6 +1,6 @@ Require Export axiomsKnuth. From mathcomp Require Import all_ssreflect ssralg matrix ssrnum vector reals. -From mathcomp Require Import normedtype order. +From mathcomp Require Import normedtype order lra. Set Implicit Arguments. Unset Strict Implicit. @@ -24,7 +24,7 @@ Local Open Scope ring_scope. Section Plane. Variable R : realType. -Definition Plane := pair_vectType (regular_vectType R) (regular_vectType R). +Definition Plane : vectType _ := (R^o * R^o)%type. (* ------------------ Definitions ------------------- *) @@ -89,7 +89,11 @@ Definition swap (p : Plane) := (p.2, p.1). Lemma det_scalar_productE (p q r: Plane): det p q r = scalar_product (q-p) (rotate (r-p)). -Proof. by rewrite develop_det /scalar_product /=; ring. Qed. +Proof. +rewrite develop_det /scalar_product /=. +rewrite /xcoord /ycoord /=. +ring. +Qed. Lemma scalar_productC (p q: Plane): scalar_product p q = scalar_product q p. Proof. by rewrite /scalar_product /= [p.1*_]mulrC [p.2*_]mulrC. Qed. @@ -176,7 +180,7 @@ Lemma scalar_product_swap (p q : Plane) : Proof. by rewrite swap_sym swap_swap. Qed. Lemma det_swap (p q r : Plane) : det (swap p) (swap q) (swap r) = - det p q r. -Proof. by rewrite 2!develop_det/swap/=; ring. Qed. +Proof. by rewrite 2!develop_det/swap/= /xcoord/ycoord/=; ring. Qed. Lemma decompose_base (p q : Plane) : q != 0 -> p = (scalar_product p q) / (scalar_product q q) *: q + @@ -246,7 +250,7 @@ case p0: (p == 0). case q0: (q == 0). move: q0=>/eqP q0; subst q. exists (1, 0); split. - by rewrite negb_and; apply/orP; left=>/=; apply oner_neq0. + by rewrite negb_and; apply/orP; left=>/=; apply: oner_neq0. by rewrite -(scale0r (0 : Plane)) scalar_productZR mul0r. exists (rotate q); split. apply/eqP=>/pair_equal_spec [q2 /eqP]; rewrite oppr_eq0=>/eqP q1. @@ -329,7 +333,7 @@ rewrite ltNge oppr_le0; apply /negP=>trp. suff: 0 < det t q r * det t s p + det t r p * det t s q + det t p q * det t s r. by rewrite convex_combination ltxx. rewrite addrC. -apply ltr_paddr; [| by apply mulr_gt0]. +apply ltr_wpDr; [| by apply mulr_gt0]. by apply addr_ge0; apply mulr_ge0=>//; apply ltW. Qed. @@ -347,7 +351,7 @@ Proof. rewrite /ccw 3!det_scalar_productE/scalar_product/= !mulrN !subr_gt0 -![(pivot : R *l R) < _]subr_gtlex0 {1 2 3}/lt/=/ProdLexiOrder.lt/= !implybE -!ltNge !le_eqVlt ![(_==_)||_]orbC -!Bool.orb_andb_distrib_r=>/orP; case=>p0. move=>/orP; case=>q0. move=>/orP; case=>r0. - rewrite -(ltr_pdivr_mull _ _ p0) mulrA -(ltr_pdivl_mulr _ _ q0) [_^-1*_]mulrC -(ltr_pdivr_mull _ _ q0) mulrA -(ltr_pdivl_mulr _ _ r0) [_^-1*_]mulrC -(ltr_pdivr_mull _ _ p0) mulrA -(ltr_pdivl_mulr _ _ r0) [_^-1*_]mulrC=>qlt rlt; exact (lt_trans qlt rlt). + rewrite -(ltr_pdivrMl _ _ p0) mulrA -(ltr_pdivlMr _ _ q0) [_^-1*_]mulrC -(ltr_pdivrMl _ _ q0) mulrA -(ltr_pdivlMr _ _ r0) [_^-1*_]mulrC -(ltr_pdivrMl _ _ p0) mulrA -(ltr_pdivlMr _ _ r0) [_^-1*_]mulrC=>qlt rlt; exact (lt_trans qlt rlt). move:r0=>/andP[/eqP<- r0]. by rewrite 2!mulr0 pmulr_rgt0// pmulr_rgt0//. move:q0=>/andP[/eqP<- q0]/orP; case. diff --git a/theories/desc.v b/theories/desc.v index af0a51e..30e5ffa 100644 --- a/theories/desc.v +++ b/theories/desc.v @@ -1,5 +1,5 @@ From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice fintype order. -From mathcomp Require Import binomial bigop ssralg poly ssrnum ssrint rat. +From mathcomp Require Import binomial bigop ssralg poly ssrnum ssrint rat archimedean. From mathcomp Require Import polyrcf. Require Import pol. @@ -649,7 +649,7 @@ Definition inv2 (p : {poly R}) := (* initial definition said nothing on b *) Definition one_root1 (p : {poly R}) (a b : R) := - exists c d k, + exists c d k, [/\ [&& a < c, c < d, d < b & 0 < k], (pos_in_interval a c (horner p)), (neg_in_interval1 d b (horner p)) & @@ -672,9 +672,9 @@ Proof. rewrite /slope_bounded; move =>x0 kf0 incf y z /andP [xy yz]. rewrite -[z * _] (addrNK (z * f y)) -mulrBr -addrA -mulrBl mulrDl (mulrC (f y)). move: (le_trans xy yz) => xz. -rewrite ler_add2r; apply: le_trans (_ : z * (k * (z - y)) <= _). - by rewrite - mulrA ler_wpmul2r // mulr_ge0 // subr_ge0. -by rewrite ler_wpmul2l ? incf ?xy ? yz//;apply:(le_trans x0). +rewrite lerD2r; apply: le_trans (_ : z * (k * (z - y)) <= _). + by rewrite - mulrA ler_wpM2r // mulr_ge0 // subr_ge0. +by rewrite ler_wpM2l ? incf ?xy ? yz//;apply:(le_trans x0). Qed. (* Note that {poly R} is automatically converted into (seq R) *) @@ -682,7 +682,7 @@ Qed. Lemma all_pos_positive (p : {poly R}) x: all_ge0 p -> 0 <= x -> p.[x] >= 0. Proof. -move=> h x0; rewrite horner_coef. +move=> h x0; rewrite horner_coef. apply: sumr_ge0 => [] [i his _] /=. apply: mulr_ge0; rewrite ?exprn_ge0 //; apply: (allP h); exact: mem_nth. Qed. @@ -693,8 +693,8 @@ Lemma all_pos_increasing (p : {poly R}): Proof. move=> posp x y le0x le0y lexy; rewrite !horner_coef. apply: ler_sum => [] [i ihs] /= _. -apply: ler_wpmul2l => //; first by apply: (allP posp); exact: mem_nth. -by apply: ler_expn2r. +apply: ler_wpM2l => //; first by apply: (allP posp); exact: mem_nth. +by apply: lerXn2r. Qed. Lemma one_root1_uniq p a b: one_root1 p a b -> @@ -773,14 +773,14 @@ Lemma one_root2_shift p a b: Proof. move=> [ck [/andP [x1a kp] neg sl]]. exists (a + ck.1,ck.2); split. - by rewrite ltr_add2l x1a kp. + by rewrite ltrD2l x1a kp. move=> x /= abxax1; rewrite -(addrNK a x) - horner_shift_poly. - by rewrite neg // ltr_subr_addl ler_subl_addl. + by rewrite neg // ltrBrDl lerBlDl. move=> x y /= axy. have aux: y - x = y - a - (x - a). by rewrite opprD addrAC -!addrA opprK addrN addr0. rewrite -{2} (addrNK a x) -{2} (addrNK a y) -!(horner_shift_poly a _) aux. -by apply: sl; rewrite ? ler_add2r // ler_subr_addr addrC. +by apply: sl; rewrite ?lerD2r // lerBrDr addrC. Qed. Lemma one_root1_shift p a b c: @@ -789,16 +789,16 @@ Lemma one_root1_shift p a b c: Proof. move=> [x1 [x2 [k [/and4P [ax1 x1x2 x2b kp] pos neg sl]]]]. exists (c + x1); exists (c + x2); exists k. -rewrite ! ltr_add2l; split => //; first by apply /and4P. +rewrite !ltrD2l; split => //; first by apply /and4P. move=> x cp; rewrite - (addrNK c x). - rewrite -horner_shift_poly pos ? ler_sub_addl ? ltr_sub_addl //. + rewrite -horner_shift_poly pos ? lerBDl ? ltrBDl //. move=> x cp; rewrite - (addrNK c x). - by rewrite -horner_shift_poly neg // ltr_subr_addl ltr_subl_addl. + by rewrite -horner_shift_poly neg // ltrBrDl ltrBlDl. move=> x y cx1x xy ycx2. have aux: y - x = y - c - (x - c). by rewrite [x + _]addrC opprD opprK addrA addrNK. rewrite -{2} (addrNK c x) -{2} (addrNK c y) aux -!(horner_shift_poly c _). -by rewrite sl ? ler_add2r // ?ler_subr_addr? ler_subl_addr // addrC. +by rewrite sl ?lerD2r // ?lerBrDr? lerBlDr // addrC. Qed. Lemma one_root1_scale p a b c: @@ -808,20 +808,20 @@ Proof. move=> cp [x1 [x2 [k [/and4P [ax1 x1x2 x2b kp] pos neg sl]]]]. exists (c * x1); exists (c * x2); exists (k / c). have tc : 0 < c^-1 by rewrite invr_gt0. -rewrite !(ltr_pmul2l cp). +rewrite !(ltr_pM2l cp). have t: forall z, z = c * (z / c). by move=> z; rewrite [c * _]mulrC mulfVK //;move: cp;rewrite lt0r => /andP []. split => //; first by apply/and4P; split => //; apply:mulr_gt0. move=> x cpp; rewrite (t x) - horner_scaleX_poly; apply: pos. - by rewrite ltr_pdivl_mulr // mulrC ler_pdivr_mulr //(mulrC x1). + by rewrite ltr_pdivlMr // mulrC ler_pdivrMr //(mulrC x1). move=> x cpp. rewrite (t x) -horner_scaleX_poly neg //. - by rewrite ltr_pdivl_mulr // mulrC ltr_pdivr_mulr // (mulrC b). + by rewrite ltr_pdivlMr // mulrC ltr_pdivrMr // (mulrC b). move=> x y cx1x xy ycx2; rewrite -mulrA mulrDr mulrN ![c^-1 * _]mulrC {2}(t x) {2}(t y) -!(horner_scaleX_poly _ p); apply: sl. - by rewrite ler_pdivl_mulr // mulrC. - by rewrite ler_wpmul2r // ltW. -by rewrite ler_pdivr_mulr // mulrC. + by rewrite ler_pdivlMr // mulrC. + by rewrite ler_wpM2r // ltW. +by rewrite ler_pdivrMr // mulrC. Qed. End DescOnOrderedField. @@ -836,7 +836,7 @@ Lemma desc_l4 (p: {poly R}) : alternate_1 p -> inv2 p. Proof. move: p;elim/poly_ind => [| p a ih]; first by rewrite/alternate_1 polyseq0. have desc_c: alternate_1 (a%:P) -> inv2 (a%:P). - rewrite polyseqC;case (a==0) => //=; case ha: (0< a) => // _. + rewrite polyseqC;case: (a==0) => //=; case ha: (0< a) => // _. move=> eps eps0; exists (eps / a); split. by move => y _ _; rewrite !hornerC. by move => y1 y2 _ _ _ ; rewrite !hornerC. @@ -851,7 +851,7 @@ move => haposp eps eps0; rewrite /inv2 /=. by rewrite -cons_poly_def polyseq_cons sp /= ltW. move/all_pos_inv/(_ eps eps0)=> [x [h1x h2x /andP[h3x h4x]]]; exists x. have xp:= ltW h3x. - split => //; rewrite h3x h4x !hornerE ltr_spaddr // mulr_ge0 //. + split => //; rewrite h3x h4x !hornerE ltr_pwDr // mulr_ge0 //. by rewrite all_pos_positive. (* case a < 0 *) rewrite -oppr_gt0 in ha. @@ -866,10 +866,10 @@ rewrite -oppr_gt0 in ha. have qsincr: forall t d, x <= t -> 0 < d -> q.[t] < q.[t+d]. move => t d xt dp; rewrite !hornerE. set w := _ + _. - have aux: t <= t+d by rewrite - {1}(addr0 t) ler_add2l ltW. + have aux: t <= t+d by rewrite - {1}(addr0 t) lerD2l ltW. have xtd:= (le_trans xt aux). - rewrite mulrDr -addrAC addrC ltr_spaddl ?(mulr_gt0 (ppos _ xtd) dp)//. - rewrite !ler_add2r (ler_pmul2r (lt_le_trans xp xt)). + rewrite mulrDr -addrAC addrC ltr_pwDl ?(mulr_gt0 (ppos _ xtd) dp)//. + rewrite !lerD2r (ler_pM2r (lt_le_trans xp xt)). by apply:H2 => //. have qincr: forall t, x<=t -> {in <=%R t &, pol_increasing q}. move => t xt u v ut vt; rewrite le_eqVlt; case /orP => uv. @@ -879,9 +879,9 @@ rewrite -oppr_gt0 in ha. move: (H2 _ _ (lexx x) yx' yx') => lepxpy. have yge0: 0 <= y by rewrite ltW // (lt_le_trans xp yx'). have posval : 0 <= q.[y]. - rewrite !hornerE -(addNr a) /= ler_add2r /=. - apply: (@le_trans _ _ (p.[x] * y)); last by rewrite ler_wpmul2r. - rewrite // mulrC - ler_pdivr_mulr // ltW //. + rewrite !hornerE -(addNr a) /= lerD2r /=. + apply: (@le_trans _ _ (p.[x] * y)); last by rewrite ler_wpM2r. + rewrite // mulrC - ler_pdivrMr // ltW //. set r := ('X * q). have negval' : r.[x] < 0 by rewrite 2!hornerE pmulr_rlt0. have posval' : 0 <= r.[y] by rewrite 2! hornerE mulr_ge0. @@ -892,36 +892,36 @@ rewrite -oppr_gt0 in ha. move /and5P => [/and3P [_ _ smallv] /and3P[xd dv v'y] _ posv _]. have {xd dv} xv : x < v by apply: le_lt_trans xd dv. have pv : 0 < v by apply: lt_trans xv. - move: posv; rewrite 2! hornerE -{1} (mulr0 v) (ler_pmul2l pv) => posv. + move: posv; rewrite 2! hornerE -{1} (mulr0 v) (ler_pM2l pv) => posv. move: (pol_cont r v he1) => [d' dp' pd']. pose d := half d'. have dp : d > 0 by rewrite half_gt0. have dd' : d < d' by apply: half_ltx. - have vvd : v < v + d by rewrite ltr_addl /=. + have vvd : v < v + d by rewrite ltrDl /=. have xvd : x < v + d by apply: lt_trans vvd. have lvd : 0 < p.[v + d] by apply: ppos; exact: ltW. move => {y yx val yx' posval posval' v'y lepxpy yge0}. have pa: le_below_x (v + d) (horner q). - move => y y0 yvd; rewrite !hornerE ler_add2r /=. + move => y y0 yvd; rewrite !hornerE lerD2r /=. case cmp: (y <= x); last first. have cmp': x <= y by rewrite ltW // ltNge cmp. apply: le_trans (_ : p.[v + d] * y <= _). - by apply: ler_wpmul2r => //; apply: H2 => //;apply: (le_trans cmp'). - by rewrite ler_wpmul2l // ltW. + by apply: ler_wpM2r => //; apply: H2 => //;apply: (le_trans cmp'). + by rewrite ler_wpM2l // ltW. apply: le_trans (_ : p.[x] * y <= _). - by rewrite ler_wpmul2r //; apply: H1. + by rewrite ler_wpM2r //; apply: H1. apply: le_trans (_ : p.[x] * (v + d) <= _); last first. - rewrite ler_wpmul2r //; first exact: le_trans yvd. + rewrite ler_wpM2r //; first exact: le_trans yvd. rewrite H2 //; first (by apply: (lexx x)); by apply:ltW. - by rewrite ler_wpmul2l // ltW. + by rewrite ler_wpM2l // ltW. exists (v + d). rewrite (le_lt_trans posv (qsincr _ _ (ltW xv) dp)) (lt_trans pv vvd). split => //=; first by apply: qincr; apply: ltW. rewrite - (double_half epsilon). apply: le_trans (_ : ((half epsilon) + r.[v+d] -r.[v]) <= _). rewrite [ half epsilon + _] addrC -addrA. - rewrite [r.[v + d]] hornerE hornerX ler_addl subr_ge0 //. - rewrite -! addrA ler_add2l. + rewrite [r.[v + d]] hornerE hornerX lerDl subr_ge0 //. + rewrite -!addrA lerD2l. have aux:`|(v+d) - v| < d' by rewrite (addrC v) addrK ger0_norm// ltW. by move: (ltW (pd' _ aux)) => /ler_normlP [_]. (* case a = 0 *) @@ -934,7 +934,7 @@ have aux: forall w, 0 <=w -> 0 <= p.[w] -> {in <=%R w &, pol_increasing p} -> {in <=%R w &, pol_increasing ((p * 'X))}. move => w wz pwz H s t sw tw st; rewrite !hornerE. move: (H _ _ sw tw st) (le_trans pwz (H _ _ (lexx w) sw sw)) => pa pb. - by apply:(ler_pmul pb (le_trans wz sw) pa st). + by apply:(ler_pM pb (le_trans wz sw) pa st). set w:= (Num.min x v); exists w. have wc: w = x \/ w = v. by rewrite /w /minr; case: ifPn; [left|right]. @@ -946,17 +946,17 @@ split. apply: (pmul2w1 tp (ltW pw0) tw). move: tp tw;case wc=> ->; [apply: plx | apply: plv]. by apply: aux; [apply: ltW | by apply: ltW| case wc => ->]. -move: lpve; rewrite (ler_pdivl_mulr _ _ gx0) => lpve. +move: lpve; rewrite (ler_pdivlMr _ _ gx0) => lpve. case /orP:(le_total x v)=> xv; rewrite /w/=. move/min_idPr : (xv); rewrite minC => ->. apply: le_trans lpve; rewrite mulrA. - rewrite (ler_pmul2r gx0);apply: (ler_pmul (ltW gx0) (ltW gpx0) xv). + rewrite (ler_pM2r gx0);apply: (ler_pM (ltW gx0) (ltW gpx0) xv). exact:(pmonx _ _ (lexx x) xv xv). move/min_idPr : (xv) => ->. apply: le_trans lpve. rewrite mulrA. -by rewrite (ler_pmul2l (mulr_gt0 gv0 gpv0) v x). +by rewrite (ler_pM2l (mulr_gt0 gv0 gpv0) v x). Qed. Lemma desc (p: {poly R}): alternate p -> one_root2 p 0. @@ -982,7 +982,7 @@ case: (ltrP a 0) => ha alt1. move:(slope_product_x (ltW xp) (lexx 0) slp xyz). move/andP :xyz => [xy yz]. rewrite mulr0 add0r; apply: le_trans. - by apply: (ler_wpmul2r _ (pmon _ _ (lexx x) xy xy)); rewrite subr_ge0. + by apply: (ler_wpM2r _ (pmon _ _ (lexx x) xy xy)); rewrite subr_ge0. move: alt1; case a0 : (a == 0) => // alt1; move: (eqP a0) => a00. clear ha a0. move: (IHl alt1) => [v1k []] {IHl}. @@ -993,8 +993,8 @@ have posk' : 0 < k' by apply: half_gt0; apply: mulr_gt0. set u := (- p.[v1]) / k. move: (maxS 0 u); set v:= Num.max 0 _ => /andP [pa pb]. set v2:= v1 + v +1. -have v0: 0 <= v by rewrite le_maxr lexx. -have v1v2: v1 < v2 by rewrite /v2 - addrA (ltr_addl v1). +have v0: 0 <= v by rewrite le_max lexx. +have v1v2: v1 < v2 by rewrite /v2 - addrA (ltrDl v1). have pos1:0 <= p.[v1 + v]. move: (kpos); rewrite lt0r => /andP [ kne0 _]. move: kpos; rewrite - invr_gt0 => kpos. @@ -1002,11 +1002,11 @@ have pos1:0 <= p.[v1 + v]. by rewrite addr0 - oppr_le0 - (pmulr_lle0 _ kpos). case/orP:(le_total u 0); [ | move => up]. by rewrite leNgt caf. - have aa: v1 <= v1 <= v1 + u by rewrite lexx ler_addl. - rewrite - (ler_addr (- p.[v1]));apply: le_trans (incr _ _ aa). + have aa: v1 <= v1 <= v1 + u by rewrite lexx lerDl. + rewrite -(lerDr (- p.[v1]));apply: le_trans (incr _ _ aa). by rewrite (addrC v1) addrK /u (mulrC _ (k^-1)) mulVKf //. have pos : 0 < p.[v2]. - have hh: v1 <= v1 + v <= v1 + v + 1 by rewrite !ler_addl v0 ler01. + have hh: v1 <= v1 + v <= v1 + v + 1 by rewrite !lerDl v0 ler01. apply: (le_lt_trans pos1);rewrite -subr_gt0. by apply: (lt_le_trans _ (incr _ _ hh)); rewrite addrAC addrN add0r mulr1. clear v0 pos1 pa pb. @@ -1030,8 +1030,8 @@ rewrite ! horner_cons a00 !addr0 (mulrC _ x) (mulrC _ y). have: (v1 * k + p.[x]) * (y - x) <= y * p.[y] - x * p.[x]. apply:(slope_product_x (ltW v1pos) (ltW kpos) incr). by rewrite xy (le_trans v1x1 x1x). -apply: le_trans; rewrite ler_wpmul2r //; first by rewrite subr_ge0. -rewrite mulrC - (double_half (k * v1 )) -/k' - addrA ler_addl. +apply: le_trans; rewrite ler_wpM2r //; first by rewrite subr_ge0. +rewrite mulrC - (double_half (k * v1 )) -/k' - addrA lerDl. rewrite - (opprK k') addrC subr_gte0 (le_trans x1close) // -subr_gte0. have: k * (x - x1) <= p.[x] - p.[x1] by apply: incr =>//; rewrite x1x v1x1. by apply : le_trans; apply: mulr_ge0 => //; rewrite ?(ltW kpos) ?subr_ge0. @@ -1049,21 +1049,21 @@ have x10 : 0 < x1 by apply: lt_trans x1gt1; exact: ltr01. set y' := x1 - q.[x1] / k. have nx1 : q.[x1] < 0 by rewrite neg //x1gt1 lexx. have knz: k != 0 by move: kp; rewrite lt0r; case /andP =>[]. -have y'1: x1 < y' by rewrite /y' ltr_addl oppr_gt0 pmulr_llt0 // ?invr_gt0. +have y'1: x1 < y' by rewrite /y' ltrDl oppr_gt0 pmulr_llt0 // ?invr_gt0. have y'pos : 0 <= q.[y']. have aux: x1 <= x1 <= y' by rewrite (lexx x1) (ltW y'1). - rewrite - (ler_add2r (- q.[x1])) add0r; apply: le_trans (sl _ _ aux). + rewrite -(lerD2r (- q.[x1])) add0r; apply: le_trans (sl _ _ aux). by rewrite /y' (addrC x1) addrK mulrN mulrC mulfVK. move: (@diff_xn_ub R deg 1); set u := _ *+ _; move => up. set u':= Num.max 1 u. -have uu': u <= u' by rewrite le_maxr lexx orbT. -have u1: 1 <= u' by rewrite le_maxr lexx. +have uu': u <= u' by rewrite le_max lexx orbT. +have u1: 1 <= u' by rewrite le_max lexx. have u'0 : 0 < u' by rewrite (lt_le_trans ltr01). have divu_ltr : forall x, 0 <= x -> x / u' <= x. - move => x x0; rewrite ler_pdivr_mulr // ler_pemulr //. + move => x x0; rewrite ler_pdivrMr // ler_peMr //. have y'0: 0 < y' by apply: lt_trans y'1. pose y := y' + 1. -have y'y : y' < y by rewrite /y ltr_addl. +have y'y : y' < y by rewrite /y ltrDl. have y1 : x1 < y by apply: lt_trans y'1 _. have ypos : 0 < q.[y]. have aux: x1 <= y' <= y by rewrite (ltW y'1) (ltW y'y). @@ -1086,18 +1086,18 @@ move: (pol_lip q (z:=y)); set c := (norm_pol q^`()).[y] => cp. have cp0 : 0 < c. move: (lt_le_trans nega posb'); rewrite - subr_gt0 => dp. move: (ltW (le_lt_trans b'y' y'y)) => pb. - move: y0; rewrite -oppr_lt0 => yn0. + move: y0; rewrite -(oppr_lt0 y) => yn0. move: (ltW (lt_trans yn0 (lt_le_trans x10 x1a))) => pa. move: (cp _ _ pa (ltW ab) pb); rewrite (gtr0_norm dp) => dp'. by move: (lt_le_trans dp dp'); rewrite pmulr_lgt0 // subr_gt0. set b := Num.min y (b' +(half e1)/c). -have blty: b <= y by rewrite /b le_minl lexx. +have blty: b <= y by rewrite /b ge_min lexx. have b'b: b' < b. - rewrite lt_minr (le_lt_trans b'y' y'y) /= - ltr_subl_addl addrN. + rewrite lt_min (le_lt_trans b'y' y'y) /= - ltrBlDl addrN. by rewrite (divr_gt0 (half_gt0 e1p) cp0). have clb:c * (b - b') < e1. apply: le_lt_trans (half_ltx e1p). - by rewrite - (ler_pdivl_mull _ _ cp0) mulrC ler_subl_addl le_minl lexx orbT. + by rewrite -(ler_pdivlMl _ _ cp0) mulrC lerBlDl ge_min lexx orbT. pose n := (size p).-1. have a0 : 0 < a by apply: lt_le_trans x1a. have b'0 : 0 < b' by apply: lt_trans ab. @@ -1116,7 +1116,7 @@ have res1:pos_in_interval 0 b^-1 (horner p). rewrite -[x]invrK -sgr_cp0 - inv_mono ?invr_gt0 // sgr_cp0. rewrite (le_lt_trans posb') // -subr_gte0 /=. have b'x : b' < x^-1. - by rewrite inv_comp// (le_lt_trans xb)// ltf_pinv. + by rewrite inv_comp// (le_lt_trans xb)// ltf_pV2. have aa:x1 <= b' <= x^-1 by rewrite (ltW (le_lt_trans x1a ab)) (ltW b'x). by apply:lt_le_trans (sl _ _ aa); rewrite mulr_gt0 // subr_gt0. have res2: neg_in_interval1 a^-1 1 (horner p). @@ -1134,7 +1134,7 @@ have res2: neg_in_interval1 a^-1 1 (horner p). by rewrite mulr_gt0 // subr_gt0. exists b^-1, a^-1, k'. split => //. - rewrite k'p ibp ltf_pinv// (inv_compr ltr01 a0) invr1. + rewrite k'p ibp ltf_pV2// (inv_compr ltr01 a0) invr1. by rewrite (lt_trans ab b'b) (lt_le_trans x1gt1 x1a). move => x z bvx xz zav. rewrite le_eqVlt in xz; move/orP: xz => [xz | xz]. @@ -1167,32 +1167,32 @@ set t2 := t3 * _. pose k1 := -k'; pose k2 := k' + k'. have k2p : k2 = (k * x1 ^+ 2 * y ^-1 ^+ s) by apply: double_half. rewrite (_ : k' = k1 + k2); last by rewrite /k1 /k2 addrA addNr add0r. -have xzi: z^-1 < x^-1 by rewrite ltf_pinv. +have xzi: z^-1 < x^-1 by rewrite ltf_pV2. have pa : x1 <= z^-1. - by rewrite (le_trans x1a)// -(invrK a)// lef_pinv// posrE invr_gt0. + by rewrite (le_trans x1a)// -(invrK a)// lef_pV2// posrE invr_gt0. have pb: x1 <= x^-1 by rewrite (ltW (le_lt_trans pa xzi)). have pc: 0 <= k * (x^-1 - z^-1) by apply: ltW;rewrite(mulr_gt0 kp) // subr_gt0. have pdd:(x1 <= z^-1 <= x^-1) by rewrite pa (ltW xzi). have pd:= (sl _ _ pdd). have t3p:= le_trans pc pd. have pe : 0 <= y^-1 <= z. - by rewrite invr_ge0 ltW //= (le_trans _ (ltW xz))// (le_trans _ bvx)// lef_pinv. + by rewrite invr_ge0 ltW //= (le_trans _ (ltW xz))// (le_trans _ bvx)// lef_pV2. case /andP: (pow_monotone s pe) => _ hh. -have maj' : t3 * y^-1 ^+ s <= t3 * z^+ s by rewrite ler_wpmul2l. -rewrite mulrDl; apply: ler_add; last first. +have maj' : t3 * y^-1 ^+ s <= t3 * z^+ s by rewrite ler_wpM2l. +rewrite mulrDl; apply: lerD; last first. apply: le_trans maj'; rewrite /t3 k2p mulrAC. - rewrite ler_pmul2r; last by apply: exprn_gt0; rewrite invr_gt0. + rewrite ler_pM2r; last by apply: exprn_gt0; rewrite invr_gt0. apply: le_trans pd. - rewrite ![k * _]mulrC mulrAC ler_pmul2r //. + rewrite ![k * _]mulrC mulrAC ler_pM2r //. have xn0 : (x != 0) by move: x0; rewrite lt0r; case /andP =>[]. have zn0 : (z != 0) by move: z0; rewrite lt0r; case /andP =>[]. have xVn0 : (x^-1 != 0) by move: x0; rewrite -invr_gt0 lt0r; case /andP =>[]. rewrite -[x^-1](mulfK zn0) -(mulrC z) - (mulrA z _ _). rewrite -{2}[z^-1](mulfK xn0) -(mulrA _ x _)(mulrCA _ x). rewrite (mulrC z^-1) -mulrBl (mulrC (z - x)). - rewrite ler_pmul2r /=; last by rewrite subr_gte0. - apply: le_trans (_ : x1 / z <= _); first rewrite ler_pmul2l //=. - by rewrite ler_pmul2r ?invr_gt0. + rewrite ler_pM2r /=; last by rewrite subr_gte0. + apply: le_trans (_ : x1 / z <= _); first rewrite ler_pM2l //=. + by rewrite ler_pM2r ?invr_gt0. move:(ltW xz) => xz'. have xzexp : (x ^+ s - z ^+ s) <= 0. have aux: 0 <=x <= z by rewrite xz' ltW//. @@ -1201,33 +1201,33 @@ have xzexp' : (z ^+ s - x ^+ s) >= 0 by rewrite subr_ge0 - subr_le0. rewrite /t1 /k1 /k' {maj' t2 t3}. case: (lerP 0 ( q.[x^-1])) => sign; last first. apply: le_trans (_ : 0 <= _). - by rewrite mulNr lter_oppl oppr0 mulr_ge0 //?(ltW k'p)// subr_gte0 /= ltW. + by rewrite mulNr lterNl oppr0 mulr_ge0 //?(ltW k'p)// subr_gte0 /= ltW. by rewrite mulr_le0 // ltW. -rewrite mulNr lter_oppl -mulNr opprD opprK addrC. +rewrite mulNr lterNl -mulNr opprD opprK addrC. have rpxe : q.[x^-1] <= e. - have bvx' : x^-1 <= b by rewrite -(invrK b)// lef_pinv. + have bvx' : x^-1 <= b by rewrite -(invrK b)// lef_pV2. apply: (@le_trans _ _ q.[b]). have aux:(x1 <= x^-1 <= b) by rewrite pb bvx'. rewrite -subr_ge0 /= ;apply: le_trans (sl _ _ aux). rewrite mulr_ge0 ?subr_gte0 // ltW //. rewrite -[_ _ b]addr0 -(addrN (q).[b']) addrA. - rewrite (addrC ( _ b)) -addrA - (double_half e) (ler_add clb')//. + rewrite (addrC ( _ b)) -addrA -(double_half e) (lerD clb')//. have yb: - y <= b' by apply: ltW; apply: lt_trans b'0; rewrite oppr_lt0. move: (le_trans (cp b' b yb (ltW b'b) blty) (ltW clb)). by move /ler_normlP => [_]. apply: le_trans (_ : (z^+ s - x ^+ s) * e <= _). - by rewrite ler_wpmul2l // ?subr_gte0. + by rewrite ler_wpM2l // ?subr_gte0. have un0 : (u' != 0) by move: u'0; rewrite lt0r; case /andP =>[]. rewrite [_ * e]mulrC; apply: le_trans (_ : e * (u' * (z - x)) <= _)=> /=. - apply: ler_wpmul2l; first exact: ltW. + apply: ler_wpM2l; first exact: ltW. apply: (@le_trans _ _ (u * (z - x))). have xm1: -1 <= x by exact: (ltW (lt_trans (ltrN10 R) x0)). have a1 : 1 <= a by apply: (ltW (lt_le_trans x1gt1 x1a)). rewrite - (ger0_norm xzexp'); apply: (up _ _ xm1 xz'). apply: le_trans zav _. by rewrite invr_le1 // unitf_gt0. - by rewrite ler_pmul2r // subr_gte0. -rewrite mulrA ler_pmul2r; last by rewrite subr_gte0. + by rewrite ler_pM2r // subr_gte0. +rewrite mulrA ler_pM2r; last by rewrite subr_gte0. rewrite /= /e divfK ?lterr //. Qed. diff --git a/theories/desc1.v b/theories/desc1.v index 8458ce5..f1724f0 100644 --- a/theories/desc1.v +++ b/theories/desc1.v @@ -174,7 +174,7 @@ have dnz: d != 0 by move: etc; rewrite /d; case s => // s' l' /= /andP []. rewrite addnC addnA addnC; move: (hr etc). rewrite -sgr_gt0 - (sgr_gt0 (c*b)) - sgr_lt0 ! sgrM. rewrite /sgr - if_neg - (if_neg (c==0))- (if_neg (b==0)) bnz dnz cnz. -by case (d<0); case (b<0); case (c<0); rewrite ?mulrNN ? mulr1 ?mul1r ?ltr01 +by case: (d<0); case: (b<0); case: (c<0); rewrite ?mulrNN ? mulr1 ?mul1r ?ltr01 ?ltrN10 ? ltr10 ? ltr0N1 ?addn0 ? addnS ?addn0//=; move => ->. Qed. @@ -594,7 +594,9 @@ have q2: all (root q) l. have [r qv rq]:= (Hrec q q0 q1 ul q2). exists r => //; rewrite {1} pv {1} qv mulrAC; congr (_ * _). rewrite big_cons mulrC; congr (_ * _). -rewrite 2! (big_nth 0) 2! big_mkord; apply: eq_bigr => i _. +rewrite (big_nth 0). +rewrite [in RHS](big_nth 0). +rewrite 2!big_mkord; apply: eq_bigr => i _. set b := l`_i;congr (_ ^+ _). have rb: root q b by apply /(allP q2); rewrite mem_nth //. have nr: ~~ root (('X - a%:P) ^+ \mu_a p) b. diff --git a/theories/desc2.v b/theories/desc2.v index e621a0e..0dc145e 100644 --- a/theories/desc2.v +++ b/theories/desc2.v @@ -197,7 +197,7 @@ have dnz: d != 0 by move: etc; rewrite /d; case s => // s' l' /= /andP []. rewrite addnC addnA addnC; move: (hr etc). rewrite -sgr_gt0 - (sgr_gt0 (c*b)) - sgr_lt0 ! sgrM. rewrite /sgr - if_neg - (if_neg (c==0))- (if_neg (b==0)) bnz dnz cnz. -by case (d<0); case (b<0); case (c<0); rewrite ?mulrNN ? mulr1 ?mul1r ?ltr01 +by case: (d<0); case: (b<0); case: (c<0); rewrite ?mulrNN ? mulr1 ?mul1r ?ltr01 ?ltrN10 ? ltr10 ? ltr0N1 ?addn0 ? addnS ?addn0//=; move => ->. Qed. @@ -282,7 +282,9 @@ have q2: all (root q) l. have [r qv rq]:= (Hrec q q0 q1 ul q2). exists r => //; rewrite {1} pv {1} qv mulrAC; congr (_ * _). rewrite big_cons mulrC; congr (_ * _). -rewrite 2! (big_nth 0) 2! big_mkord; apply: eq_bigr => i _. +rewrite (big_nth 0). +rewrite [RHS](big_nth 0). +rewrite 2! big_mkord; apply: eq_bigr => i _. set b := l`_i;congr (_ ^+ _). have rb: root q b by apply /(allP q2); rewrite mem_nth //. have nr: ~~ root (('X - a%:P) ^+ \mu_a p) b. diff --git a/theories/door_crossing.v b/theories/door_crossing.v index 3605d6c..7067e18 100644 --- a/theories/door_crossing.v +++ b/theories/door_crossing.v @@ -1,4 +1,5 @@ -From mathcomp Require Import all_ssreflect all_algebra all_real_closed reals. +From HB Require Import structures. +From mathcomp Require Import all_ssreflect all_algebra all_real_closed archimedean reals. From mathcomp.algebra_tactics Require Import ring lra. Require Import casteljau convex counterclockwise intersection. @@ -13,15 +14,14 @@ Local Open Scope ring_scope. Section sandbox. -Lemma poly_coord {R : rcfType} - (c : pair_vectType (regular_vectType R) (regular_vectType R)) +Lemma poly_coord {R : rcfType} + (c : (R^o * R^o)%type) (p : {poly R}) (t : R) : p.[t] *: c = c.1 * p.[t] *: (1, 0) + c.2 * p.[t] *: (0, 1). Proof. congr (_, _); rewrite /= !scaler0 ?addr0 ?add0r mulrC /GRing.scale /=; ring. Qed. - Variable R : reals.Real.type. (* This version differs from the one in the hulls development to avoid @@ -47,7 +47,7 @@ Proof. by rewrite /= /conv addrC. Qed. bezier c 2 t = (bernp 0 1 2 0) *: c 0%N. *) Lemma bezier_bernstein2 c t : - bezier c 2 t = + bezier c 2 t = \sum_(i < 3) (bernp 0 1 2 i).[t] *: c i. Proof. rewrite !big_ord_recr big_ord0 /= add0r. @@ -87,9 +87,9 @@ rewrite -!addrA -!scalerDl. congr (_ *: _ + _ *: _); ring. Qed. -Record edge := Bedge +Record edge := Bedge { left_pt : Plane R; - right_pt : Plane R; + right_pt : Plane R; edge_cond : left_pt.1 < right_pt.1}. Record cell := @@ -161,7 +161,7 @@ Qed. Fail Check (fun (x : vert_edge) (l : seq vert_edge) => x \in l). -Canonical vert_edge_eqType := EqType vert_edge (EqMixin vert_edge_eqP). +HB.instance Definition _ := hasDecEq.Build _ vert_edge_eqP. Fixpoint seq_to_intervals_aux [A : Type] (a : A) (s : seq A) := match s with @@ -177,12 +177,12 @@ end. Definition cell_safe_exits_left (c : cell) : seq vert_edge := let lx := (seq.head dummy_pt (left_pts c)).1 in - map (fun p => Build_vert_edge lx (fst p).2 (snd p).2) + map (fun p => Build_vert_edge lx (p.1).2 (p.2).2) (seq_to_intervals (left_pts c)). Definition cell_safe_exits_right (c : cell) : seq vert_edge := let lx := (seq.head dummy_pt (right_pts c)).1 in - map (fun p => Build_vert_edge lx (fst p).2 (snd p).2) + map (fun p => Build_vert_edge lx (p.1).2 (p.2).2) (seq_to_intervals (rev (right_pts c))). Definition dummy_vert_edge := @@ -192,7 +192,7 @@ Definition on_vert_edge (p : Plane R) (v : vert_edge) : bool := (p.1 == ve_x v) && (ve_bot v < p.2 < ve_top v). Check fun (v : vert_edge) (l : seq vert_edge) => v \in l. -Check fun (v : vert_edge)(c : cell) => +Check fun (v : vert_edge)(c : cell) => v \in cell_safe_exits_left c. Lemma detDM2 (l p1 p2 q1 q2 r1 r2 : R) : @@ -286,7 +286,7 @@ have vxright : ve_x v = right_limit c. elim/last_ind: (right_pts c) rightn0 samexr => [ // | lh e1 Ih] _ /=. elim/last_ind: lh Ih => [ // | lh e2 _] Ih samexr. rewrite last_rcons !rev_rcons/=. - rewrite inE=> /orP[/eqP -> /= | vin]. + rewrite inE=> /orP[/eqP -> /= | vin]. by rewrite (eqP (samexr e1 _)) // mem_rcons inE eqxx. rewrite (eqP (samexr e1 _)); last by rewrite mem_rcons inE eqxx. rewrite -(eqP (samexr e2 _)); last by rewrite !(mem_rcons, inE) eqxx ?orbT. @@ -397,7 +397,7 @@ have vxright : ve_x v = right_limit c. elim/last_ind: (right_pts c) rightn0 samexr => [ // | lh e1 Ih] _ /=. elim/last_ind: lh Ih => [ // | lh e2 _] Ih samexr. rewrite last_rcons !rev_rcons/=. - rewrite inE=> /orP[/eqP -> /= | vin]. + rewrite inE=> /orP[/eqP -> /= | vin]. by rewrite (eqP (samexr e1 _)) // mem_rcons inE eqxx. rewrite (eqP (samexr e1 _)); last by rewrite mem_rcons inE eqxx. rewrite -(eqP (samexr e2 _)); last by rewrite !(mem_rcons, inE) eqxx ?orbT. @@ -447,8 +447,8 @@ have -> : head dummy_pt (rcons l e2) = head dummy_pt (rcons (rcons l e2) e1). by case lq : l. by rewrite rev_rcons 2!headI /=. Qed. - -Lemma vert_projr (p q r : Plane R) : + +Lemma vert_projr (p q r : Plane R) : p.1 != q.1 -> (det p q r == 0) = (r.2 == q.2 + (r.1 - q.1) / (q.1 - p.1) * (q.2 - p.2)). Proof. @@ -466,7 +466,7 @@ rewrite invrN !(mulrN, mulNr). rewrite mulfVK //; ring. Qed. -Lemma vert_projl (p q r : Plane R) : +Lemma vert_projl (p q r : Plane R) : p.1 != q.1 -> (det p q r == 0) = (r.2 == p.2 + (r.1 - p.1) / (q.1 - p.1) * (q.2 - p.2)). Proof. @@ -498,9 +498,9 @@ move: (cok)=> /andP[] leftn0 /andP[] samexl /andP[] sortl /andP[] lonh _. rewrite /point_strictly_under_edge. set l := ((right_pt (high c)).1 - p.1) / ((right_pt (high c)).1 - (left_pt (high c)).1). -set q := ((right_pt (high c)).1 - l * +set q := ((right_pt (high c)).1 - l * ((right_pt (high c)).1 - (left_pt (high c)).1), - (right_pt (high c)).1 - l * + (right_pt (high c)).1 - l * ((right_pt (high c)).2 - (left_pt (high c)).2)). case pq : p => [p1 p2]. case lq : (left_pt (high c)) => [q1 q2]. @@ -761,7 +761,7 @@ have [P1 | P2] := ltrP t u. have t'int : 0 <= t' < 1. apply/andP; split. rewrite /t'; apply divr_ge0; lra. - rewrite /t' ltr_pdivr_mulr; lra. + rewrite /t' ltr_pdivrMr; lra. have tt' : t = t' * u by rewrite /t' mulfVK. have := bezier2_dichotomy_l (f3pt p1 p2 p3) t' u; rewrite -tt' /bzt => ->. set p2' := p2 <| u |> p1. @@ -776,7 +776,7 @@ have [P1 | P2] := ltrP t u. have sgp1 : sgz (det p1 (left_pt (high c1)) (right_pt (high c1))) = -1. by apply:ltr0_sgz; move: p1in=> /andP[] /andP[]. have sgp2' : sgz - ((det p2 (left_pt (high c1)) (right_pt (high c1)) : R ^o) <|u|> + ((det p2 (left_pt (high c1)) (right_pt (high c1)) : R ^o) <|u|> det p1 (left_pt (high c1)) (right_pt (high c1))) = -1. apply: conv_num_sg=> //. apply: ltr0_sgz; exact p2belh1. @@ -791,7 +791,7 @@ have [P1 | P2] := ltrP t u. have sgp1 : sgz (det p1 (left_pt (low c1)) (right_pt (low c1))) = 1. by apply:gtr0_sgz; move: p1in=> /andP[] /andP[] _; rewrite -ltNge. have sgp2' : sgz - ((det p2 (left_pt (low c1)) (right_pt (low c1)) : R ^o) <|u|> + ((det p2 (left_pt (low c1)) (right_pt (low c1)) : R ^o) <|u|> det p1 (left_pt (low c1)) (right_pt (low c1))) = 1. apply: conv_num_sg=> //. apply: gtr0_sgz; rewrite ltNge; exact p2abol1. @@ -836,7 +836,7 @@ have [t1 | tn1] := eqVneq t 1. have t'int : 0 < t' < 1. rewrite /t'; apply/andP; split. apply: divr_gt0; lra. - by rewrite ltr_pdivr_mulr; lra. + by rewrite ltr_pdivrMr; lra. set p1' := bezier (f3pt p1 p2 p3) 2 u. set p2' := p3 <| u |> p2. rewrite [bezier _ 2 _](_ : _ = (p3 <| t' |> p2') <| t' |> (p2' <| t' |> p1')); @@ -847,7 +847,7 @@ rewrite /point_strictly_under_edge !det_conv. have sgp3 : sgz (det p3 (left_pt (high c2)) (right_pt (high c2))) = -1. by apply:ltr0_sgz; move: p3in=> /andP[] /andP[]. have sgp2' : sgz - ((det p3 (left_pt (high c2)) (right_pt (high c2)) : R ^o) <|u|> + ((det p3 (left_pt (high c2)) (right_pt (high c2)) : R ^o) <|u|> det p2 (left_pt (high c2)) (right_pt (high c2))) = -1. apply: conv_num_sg=> //. apply: ltr0_sgz; exact p2belh2. @@ -862,7 +862,7 @@ apply/andP; split. have sgp3 : sgz (det p3 (left_pt (low c2)) (right_pt (low c2))) = 1. by apply: gtr0_sgz; move: p3in=> /andP[] /andP[] _; rewrite -ltNge. have sgp2' : sgz - ((det p3 (left_pt (low c2)) (right_pt (low c2)) : R ^o) <|u|> + ((det p3 (left_pt (low c2)) (right_pt (low c2)) : R ^o) <|u|> det p2 (left_pt (low c2)) (right_pt (low c2))) = 1. apply: conv_num_sg=> //. by apply: gtr0_sgz; rewrite ltNge; exact p2abol2. @@ -904,7 +904,7 @@ Qed. Definition midpoint (a b : Plane R) := a <| 1/2 |> b. -Definition mkedge_aux (a b : Plane R) : {e : edge | +Definition mkedge_aux (a b : Plane R) : {e : edge | forall h : a.1 < b.1, e = Bedge h}. case (boolP (a.1 < b.1)). move=> h; exists (Bedge h)=> h0. @@ -923,7 +923,7 @@ rewrite /mkedge; case: (mkedge_aux a b)=> v Pv /=; apply: Pv. Qed. Fixpoint check_bezier_ccw (fuel : nat) (v : vert_edge) - (a b c : Plane R) : + (a b c : Plane R) : option bool := match fuel with | O => None @@ -934,7 +934,7 @@ match fuel with else if point_under_edge top_edge (mkedge a b) || point_under_edge top_edge (mkedge b c) - then + then Some false else let b' := midpoint a b in @@ -1003,7 +1003,7 @@ rewrite det_scalar_productE /rotate /scalar_product /= mulrN. by rewrite mulrC; congr (_ - _); rewrite mulrC. Qed. -Lemma height_bezier2 (a b c p : Plane R) t: +Lemma height_bezier2 (a b c p : Plane R) t: a.1 < b.1 < c.1 -> (* p is the vertical projection of bezier ... t on the straight line ab *) det a b p = 0 -> @@ -1030,11 +1030,11 @@ have tmp1 : t ^ 2 * c'.2 * (b.1 - a.1) = by rewrite /= mulrDl (mulrAC _ _ (b.1 - a.1)) mulfVK. rewrite !bezier_step_conv /=. have tmp x (y : R^o) : x *: y = x * y by []. -rewrite !tmp tmp1. +rewrite !tmp tmp1 /=. ring. Qed. -Lemma safe_bezier_ccw_corner_side (a b c : Plane R) (v : vert_edge) +Lemma safe_bezier_ccw_corner_side (a b c : Plane R) (v : vert_edge) (u : R): ccw a b c -> a.1 < b.1 < c.1 -> @@ -1074,9 +1074,10 @@ set p' := (p.1, (left_pt e).2 + (p.1 - (left_pt e).1) / have := diff_vert_y ecnd'=> /(_ p p' erefl) /eqP. rewrite subr_eq=> /eqP ->; rewrite /p' /=. rewrite addrA (addrC _ (left_pt e).2) -!addrA. -rewrite ler_add2. -rewrite addrC -ler_subr_addl mulrAC addrN. -rewrite pmulr_lle0 // invr_gt0; lra. +rewrite lerD2. +rewrite addrC -lerBrDl mulrAC addrN. +rewrite pmulr_lle0 // invr_gt0/=. +by rewrite subr_gt0. Qed. Lemma safe_bezier_ccw (a b c : Plane R) (v : vert_edge) (u : R) : @@ -1128,3 +1129,5 @@ apply: conv_num_ltr=> //. by rewrite det_inverse oppr_lte0 -det_cyclique. by rewrite mkedgeE /= det_alternate. Qed. + +End sandbox. diff --git a/theories/encompass.v b/theories/encompass.v index f81fe6c..b5dc593 100644 --- a/theories/encompass.v +++ b/theories/encompass.v @@ -111,7 +111,7 @@ End spec. Module SpecKA (KA : KnuthAxioms). Section Dummy. Variable R : realType. -Let plane := pair_vectType (regular_vectType R) (regular_vectType R). +Let plane : vectType _ := (R^o * R^o)%type. Let oriented := KA.OT (R:=R). Let Ax1 := KA.Axiom1 (R:=R). diff --git a/theories/events.v b/theories/events.v new file mode 100644 index 0000000..454b308 --- /dev/null +++ b/theories/events.v @@ -0,0 +1,515 @@ +From HB Require Import structures. +From mathcomp Require Import all_ssreflect all_algebra. +Require Export Field. +Require Import math_comp_complements. +Require Import generic_trajectories points_and_edges. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Require Import NArithRing. +Import Order.TTheory GRing.Theory Num.Theory Num.ExtraDef Num. + +Open Scope ring_scope. + +Section working_environment. + +Variable R : realFieldType. + +Notation pt := (pt R). +Notation edge := (edge R). +Notation p_x := (p_x R). +Notation p_y := (p_y R). + +Notation event := (event R edge). +Notation point := (point R edge). +Notation outgoing := (outgoing R edge). + +Definition event_eqb (ea eb : event) : bool := + (point ea == point eb :> pt) && (outgoing ea == outgoing eb). + +Lemma event_eqP : Equality.axiom event_eqb. +Proof. +rewrite /Equality.axiom. +move => [pta outa] [ptb outb] /=. +rewrite /event_eqb/=. +have [/eqP <- | /eqP anb] := boolP (pta == ptb :> pt). + have [/eqP <- | /eqP anb] := boolP (outa == outb). + by apply: ReflectT. + by apply : ReflectF => [][]. +by apply: ReflectF=> [][]. +Qed. + +HB.instance Definition _ := hasDecEq.Build _ event_eqP. + +Notation Bevent := (Bevent _ _). +(* As in insertion sort, the add_event function assumes that event are + sorted in evs (lexicographically, first coordinate, then second coordinate + of the point. On the other hand, no effort is made to sort the various + edges in each list. *) +Fixpoint add_event (p : pt) (e : edge) (inc : bool) (evs : seq event) : + seq event := + match evs with + | nil => if inc then [:: Bevent p [::]] + else [:: Bevent p [:: e]] + | ev1 :: evs' => + let p1 := point ev1 in + if p == p1 then + if inc then Bevent p1 (outgoing ev1) :: evs' + else Bevent p1 (e :: outgoing ev1) :: evs' else + if p_x p < p_x p1 then + if inc then + Bevent p [::] :: evs else + Bevent p [:: e] :: evs + else if (p_x p == p_x p1) && (p_y p < p_y p1) then + if inc then + Bevent p [::] :: evs else + Bevent p [:: e] :: evs else + ev1 :: add_event p e inc evs' + end. + +Lemma add_event_step (p : pt) (e : edge) (inc : bool) (evs : seq event) : + add_event p e inc evs = + match evs with + | nil => if inc then [:: Bevent p [::]] + else [:: Bevent p [:: e]] + | ev1 :: evs' => + let p1 := point ev1 in + if p == p1 then + if inc then Bevent p1 (outgoing ev1) :: evs' + else Bevent p1 (e :: outgoing ev1) :: evs' else + if p_x p < p_x p1 then + if inc then + Bevent p [::] :: evs else + Bevent p [:: e] :: evs + else if (p_x p == p_x p1) && (p_y p < p_y p1) then + if inc then + Bevent p [::] :: evs else + Bevent p [:: e] :: evs else + ev1 :: add_event p e inc evs' + end. +Proof. by case: evs. Qed. + +(* We should be able to prove that the sequence of events produced by + edges to events is sorted lexicographically on the coordinates of + the points. *) +Fixpoint edges_to_events (s : seq edge) : seq event := + match s with + | nil => nil + | e :: s' => + add_event (left_pt e) e false + (add_event (right_pt e) e true (edges_to_events s')) + end. + +Section proof_environment. +Variable bottom top : edge. + +Definition lexPtEv (e1 e2 : event) : bool := + lexPt (point e1) (point e2). + +Definition lexePtEv (e1 e2 : event) : bool := + lexePt (point e1) (point e2). + +Definition event_close_edge ed ev : bool := +right_pt ed == point ev. + +Definition end_edge edge events : bool := + has (event_close_edge edge) events. + +Definition close_out_from_event ev future : bool := + all (fun edge => end_edge edge future) (outgoing ev). + +Fixpoint close_edges_from_events events : bool := + match events with + | [::] => true + | ev :: future_events => close_out_from_event ev future_events && close_edges_from_events future_events + end. + +Lemma close_edges_from_events_step events : + close_edges_from_events events = match events with + | [::] => true + | ev :: future_events => close_out_from_event ev future_events && close_edges_from_events future_events + end. +Proof. by case: events. Qed. + +Lemma lexPtEv_trans : transitive lexPtEv. +Proof. by move=> e2 e1 e3; rewrite /lexPtEv; apply: lexPt_trans. Qed. + +Lemma lexePtEv_trans : transitive lexePtEv. +Proof. by move=> e1 e2 e3; rewrite /lexePtEv; apply: lexePt_trans. Qed. + +Lemma event_close_edge_on g e: + event_close_edge g e -> (point e) === g. +Proof. by move=> /eqP <-; apply: right_on_edge. Qed. + +Definition out_left_event ev := + {in outgoing ev, forall e, left_pt e == point(ev)}. + +Lemma outleft_event_sort e : + out_left_event e -> + forall ed, ed \in sort (@edge_below R) (outgoing e) -> left_pt ed == point e. +Proof. +move=> outleft ed edin; apply: outleft. +by have <- := perm_mem (permEl (perm_sort (@edge_below _) (outgoing e))). +Qed. + +Lemma close_out_from_event_sort event future : + close_out_from_event event future -> + all (end_edge^~ future) (sort (@edge_below R) (outgoing event)). +Proof. +move/allP=> outP; apply/allP=> x xin; apply outP. +by have <- := perm_mem (permEl (perm_sort (@edge_below R) (outgoing event))). +Qed. + +Definition events_to_edges := flatten \o (map outgoing). + +Lemma events_to_edges_cons e evs : + events_to_edges (e :: evs) = outgoing e ++ events_to_edges evs. +Proof. by []. Qed. + +Lemma out_left_event_on e : + out_left_event e -> {in outgoing e, forall g, point e === g}. +Proof. +move=> outs g gin; rewrite -(eqP (outs _ gin)); apply: left_on_edge. +Qed. + +Lemma sort_edge_below_sorted s : + {in s &, @no_crossing _} -> + sorted (@edge_below R) (sort (@edge_below R) s). +Proof. +move=> noc. +have /sort_sorted_in : {in s &, total (@edge_below _)}. + by move=> x1 x2 x1in x2in; apply/orP/noc. +by apply; apply: allss. +Qed. + +Lemma sorted_outgoing le he e : + valid_edge le (point e) -> + valid_edge he (point e) -> + point e >>> le -> + point e <<< he -> + out_left_event e -> + {in le :: he :: outgoing e &, no_crossing R} -> + sorted (@edge_below R) (le :: sort (@edge_below R) (outgoing e)). +Proof. + set ctxt := (le :: he :: _); move=> vl hl above under outs noc. +have lein : le \in ctxt by rewrite /ctxt inE eqxx. +have hein : he \in ctxt by rewrite /ctxt !inE eqxx ?orbT. +have osub : {subset outgoing e <= ctxt}. + by move=> g gin; rewrite /ctxt !inE gin ?orbT. +have [ls us noc''] := + outgoing_conditions above under lein hein vl hl osub noc outs. +have /sort_sorted_in tmp : {in le :: outgoing e &, total (@edge_below R)}. + move=> e1 e2; rewrite !inE =>/orP[/eqP -> |e1in ]/orP[/eqP -> |e2in]. + - by rewrite edge_below_refl. + - by rewrite ls. + - by rewrite ls ?orbT. + by apply/orP/noc''. +rewrite /=; case oeq : (sort (@edge_below R) (outgoing e)) => [// | g1 gs] /=. +rewrite ls; last first. + have <- := perm_mem (permEl (perm_sort (@edge_below R) (outgoing e))). + by rewrite oeq inE eqxx. +rewrite -[X in is_true X]/(sorted _ (g1 :: gs)) -oeq tmp //. +by apply/allP=> x xin /=; apply/orP; right; exact: xin. +Qed. + +Definition events_non_inner (evs : seq event) := + {in evs &, + forall ev1 ev2, + {in outgoing ev1, forall g, non_inner g (point ev2)}}. + +Lemma add_event_preserve_first p e inc ev evs : + (0 < size (add_event p e inc (ev :: evs)))%N /\ + (point (head ev (add_event p e inc (ev :: evs))) = p \/ + point (head ev (add_event p e inc (ev :: evs))) = point ev). +Proof. +rewrite /=. +case: ev => [p1 o1]. +have [/eqP -> | /eqP pnp1] := boolP(p == p1). + by split; case: inc => //=; left. +have [pltp1 /= | pnltp1] := boolP(p_x p < p_x p1). + split. + by case: inc. + by case:inc; left. +have [/eqP pxqpx1 /= | pxnpx1 /=] := boolP (p_x p == p_x p1). + have [/eqP pyltpy1 /= | pynltpy1 /=] := boolP (p_y p < p_y p1). + by case:inc; (split;[ | left]). + by split;[ | right]. +by split;[ | right]. +Qed. + +Lemma add_event_sort p e inc evs : sorted lexPtEv evs -> + sorted lexPtEv (add_event p e inc evs). +Proof. +elim: evs => [ | ev1 evs Ih /=]. + by case: inc. +move=> path_evs. +have [/eqP pp1 | /eqP pnp1] := boolP(p == point ev1). + case: inc Ih. + by case: evs path_evs => [ | ev2 evs']. + by case: evs path_evs => [ | ev2 evs']. +move/path_sorted/Ih: (path_evs) {Ih} => Ih. +have [ pltp1 | pnltp1] /= := boolP(p_x p < p_x (point ev1)). + by case: inc {Ih}=> /=; (apply/andP; split=> //); rewrite /lexPtEv /lexPt /= pltp1. +have [/eqP pp1 | pnp1'] /= := boolP (p_x p == p_x (point ev1)). + have pyneq : p_y p != p_y (point ev1). + apply/eqP=> pp1'; case pnp1. + move: p (point ev1) {pnp1 Ih pnltp1} pp1 pp1'. + by move=> [a b][c d] /= -> ->. + have [ pltp1 | pnltp1'] /= := boolP(p_y p < p_y (point ev1)). + by case: (inc); rewrite /= path_evs andbT /lexPtEv /lexPt /= pp1 eqxx pltp1 orbT. + have p1ltp : p_y (point ev1) < p_y p. + by rewrite ltNge le_eqVlt negb_or pyneq pnltp1'. + case evseq : evs => [ | [p2 o2] evs2]. + by case: (inc)=> /=; rewrite /lexPtEv /lexPt /= pp1 eqxx p1ltp orbT. + rewrite -evseq. + case aeq : (add_event p e inc evs) => [ | e' evs3]. + have := add_event_preserve_first p e inc + (Bevent p2 o2) evs2. + by rewrite -evseq aeq => [[]]. + case: (add_event_preserve_first p e inc + (Bevent p2 o2) evs2)=> _. + rewrite -evseq aeq /= => [] [eqp | eqp2]. + apply/andP; split; last by move: Ih; rewrite aeq. + by rewrite /lexPtEv /lexPt eqp pp1 eqxx p1ltp orbT. + apply/andP; split; last by move: Ih; rewrite aeq. + move: path_evs; rewrite evseq /= andbC => /andP[] _. + by rewrite /lexPtEv /= eqp2. +have p1ltp : p_x (point ev1) < p_x p. + by rewrite ltNge le_eqVlt negb_or pnp1' pnltp1. +case evseq : evs => [ | [p2 o2] evs2]. + by case: (inc)=> /=; rewrite /lexPtEv /lexPt /= p1ltp. +case aeq : (add_event p e inc evs) => [ | e' evs3]. + case: (add_event_preserve_first p e inc + (Bevent p2 o2) evs2). + by rewrite -evseq aeq. +case: (add_event_preserve_first p e inc + (Bevent p2 o2) evs2) => _. +have path_e'evs3 : path lexPtEv e' evs3 by move: Ih; rewrite aeq. +rewrite -evseq aeq /= => [][e'p | e'p2]; rewrite path_e'evs3 andbT. + by rewrite /lexPtEv /lexPt e'p p1ltp. +by move: path_evs; rewrite evseq /= andbC /lexPtEv e'p2=> /andP[]. +Qed. + +Lemma sorted_edges_to_events s : + sorted (@lexPt R) [seq point x | x <- edges_to_events s]. +Proof. +have /mono_sorted -> : {mono point : x y / lexPtEv x y >-> lexPt x y} by []. +by elim: s => [ | g s Ih] //=; do 2 apply: add_event_sort. +Qed. + +End proof_environment. + +Lemma add_event_preserve_ends p e inc evs ed : + end_edge ed evs -> + end_edge ed (add_event p e inc evs). +Proof. +rewrite /end_edge /=. +elim: evs => [// | ev evs Ih] /= /orP[|]; + repeat (case: ifP => _); + rewrite /=/event_close_edge /=; try (move=> -> //); rewrite ?orbT //. +by move=> ?; rewrite Ih ?orbT. +Qed. + +Lemma add_event_inc evs ed : + end_edge ed (add_event (right_pt ed) ed true evs). +Proof. +elim: evs => [ | ev evs Ih] /=. + by rewrite /end_edge /event_close_edge eqxx. +case: ifP=> [/eqP <- | ]. + by rewrite /end_edge /= /event_close_edge /= eqxx. +repeat (case: ifP=> _); rewrite /end_edge/=/event_close_edge ?eqxx //. +move=> _; move: Ih; rewrite /end_edge/=/event_close_edge => ->. +by rewrite !orbT. +Qed. + +Lemma close_edges_from_events_inc evs p ed : + close_edges_from_events evs -> + close_edges_from_events (add_event p ed true evs). +Proof. +elim: evs => /= [ // | ev evs Ih /andP [clev clevs]]. +move: Ih=> /(_ clevs) Ih. +case: ifP=> _ /=; first by rewrite clevs andbT; exact clev. +case: ifP=> _ /=; first by rewrite clevs andbT; exact clev. +case: ifP=> _ /=; first by rewrite clevs andbT; exact clev. +rewrite Ih andbT. +apply/allP=> ed' edin'. +move: (allP clev ed' edin'). +by move=> it; rewrite add_event_preserve_ends // /end_edge it. +Qed. + +Lemma add_edge_close_edges_from_events evs ed : + close_edges_from_events evs -> + close_edges_from_events + (add_event (left_pt ed) ed false (add_event (right_pt ed) ed true evs)). +Proof. +have no_eq : left_pt ed == right_pt ed = false. + by apply/negP=> /eqP abs_eq; have := edge_cond ed; rewrite abs_eq ltxx. +elim: evs => [/= _ | ev evs Ih]. + rewrite no_eq edge_cond /=. + by rewrite /close_out_from_event /= /end_edge/=/event_close_edge eqxx. +move=> tmp; rewrite /= in tmp; case/andP: tmp=> [clev clevs]. +move: Ih=> /(_ clevs) Ih. +have : end_edge ed (add_event (right_pt ed) ed true (ev :: evs)). + by apply: add_event_inc. +rewrite [add_event (right_pt _) _ _ _]add_event_step. +lazy zeta. +case: ifP=> [/eqP <- /= | cnd1]. + rewrite no_eq edge_cond /=. + rewrite /close_out_from_event /= /end_edge/=/event_close_edge. + rewrite eqxx /= clevs andbT=> _; exact: clev. +case: ifP=> cnd2 /=. + rewrite no_eq edge_cond /=. + rewrite /close_out_from_event /= => -> /=; rewrite clevs andbT; exact: clev. +case: ifP=> cnd3 ended /=. + rewrite no_eq edge_cond. + rewrite close_edges_from_events_step. + apply/andP; split; last by rewrite /= clev clevs. + by move: ended; rewrite /= /close_out_from_event /= andbT. +case: ifP=> cnd4. + rewrite close_edges_from_events_step /close_out_from_event/=. + rewrite close_edges_from_events_inc ?andbT ?clevs //. + apply/andP; split; last first. + apply/allP=> x xin. + move/allP: clev=> /(_ x xin) closed. + by rewrite add_event_preserve_ends ?orbT. + by rewrite add_event_inc. +case: ifP=> cnd5. + rewrite close_edges_from_events_step; apply/andP; split. + by move: ended; rewrite /= /close_out_from_event /= andbT. + rewrite close_edges_from_events_step; apply/andP; split. + apply/allP=> x xin; apply: add_event_preserve_ends. + by move/allP: clev=> /(_ x xin). + by apply: close_edges_from_events_inc. +case: ifP=> cnd6. + rewrite close_edges_from_events_step; apply/andP; split. + by move: ended; rewrite /close_out_from_event /= andbT. + rewrite close_edges_from_events_step; apply/andP; split. + apply/allP=> x xin; apply: add_event_preserve_ends. + by move/allP: clev=> /(_ x xin). + by apply: close_edges_from_events_inc. +rewrite close_edges_from_events_step; apply/andP; split. + rewrite /close_out_from_event. + apply/allP=> x xin. + do 2 apply:add_event_preserve_ends. + by move/allP: clev; apply. +by apply: Ih. +Qed. + +Lemma edges_to_events_wf (bottom top : edge)(s : seq edge) : + close_edges_from_events (edges_to_events s). +Proof. +elim : s => [ // | e s Ih /=]. +by apply: add_edge_close_edges_from_events. +Qed. + +Lemma edges_to_events_no_loss (s : seq edge) : + perm_eq s (events_to_edges (edges_to_events s)). +Proof. +have add_inc evs p ed: + perm_eq (events_to_edges evs) + (events_to_edges (add_event p ed true evs)). + elim: evs => [/= | ev evs Ih]; first by apply: perm_refl. + rewrite /events_to_edges /=. + by repeat (case: ifP=> _ //=); rewrite perm_cat2l Ih. +have add_out evs p ed: + perm_eq (ed :: events_to_edges evs) + (events_to_edges (add_event p ed false evs)). + elim: evs => [/= | ev evs]; first by apply: perm_refl. + rewrite /events_to_edges /= => Ih. + repeat (case: ifP => //=); move => ? ? ?. + rewrite -[ed :: outgoing ev ++ _]/([:: ed] ++ outgoing ev ++ _). + by rewrite perm_catCA perm_cat2l Ih. +elim: s => /= [// | ed s Ih]; rewrite -(perm_cons ed) in Ih. +apply/(perm_trans Ih)/(perm_trans _ (add_out _ (left_pt ed) _)). +by rewrite perm_cons; apply: add_inc. +Qed. + +Lemma edges_to_events_no_crossing s : + {in s &, no_crossing R} -> + {in events_to_edges (edges_to_events s) &, no_crossing R}. +Proof. +by apply: sub_in2=> x; rewrite (perm_mem (edges_to_events_no_loss s)). +Qed. + +Lemma out_left_add_event p g b evs: + p = (if b then right_pt g else left_pt g) -> + {in evs, forall ev, out_left_event ev} -> + {in add_event p g b evs, forall ev, out_left_event ev}. +Proof. +move=> ->. +elim: evs => [ | ev evs Ih] acc. + move=> /= ev; case:b; rewrite inE => /eqP -> e //=. + by rewrite inE => /eqP ->; rewrite eqxx. +rewrite /=; case: ifP=> [/eqP pev | ] ev'. + case bval: (b); rewrite /= inE => /orP[/eqP ev'ev | ev'inevs]. + - have -> : ev' = ev by rewrite ev'ev; case: (ev). + by apply: acc; rewrite inE eqxx. + - by apply: acc; rewrite inE ev'inevs orbT. + - move=> g2; rewrite ev'ev /= inE=> /orP[/eqP -> | ]. + * by rewrite -pev bval eqxx. + by apply: acc; rewrite inE eqxx. + by apply: acc; rewrite inE ev'inevs orbT. +case: ifP => [athead | later]. + case bval: (b) => ev2; rewrite inE => /orP[]. + - by move/eqP=> -> g2. + - by apply: acc. + - by move/eqP=> -> g2 /=; rewrite inE=> /eqP ->; rewrite eqxx. + by apply: acc. +case: ifP => [athead' | later']. + case bval: (b) => ev2; rewrite inE => /orP[]. + - by move/eqP=> -> g2. + - by apply: acc. + - by move/eqP=> -> g2 /=; rewrite inE=> /eqP ->; rewrite eqxx. + by apply: acc. +move=> ev2; rewrite inE=> /orP[/eqP -> | ev2intl]. + by apply: acc; rewrite inE eqxx. +apply: Ih=> //. +by move=> ev3 ev3in; apply: acc; rewrite inE ev3in orbT. +Qed. + +Lemma out_left_edges_to_events s: + {in edges_to_events s, forall ev, out_left_event ev}. +Proof. +elim: s => [// | g s Ih] /=. +have Ih' := @out_left_add_event (right_pt g) g true _ erefl Ih. +by have Ih'' := @out_left_add_event (left_pt g) g false _ erefl Ih'. +Qed. + +Lemma add_event_point_subset (s : mem_pred pt) p g b evs : + {subset ([seq point ev | ev <- evs] : seq pt) <= s} -> + p \in s -> + {subset ([seq point ev | ev <- add_event p g b evs] : seq pt) <= s}. +Proof. +elim: evs => [ | ev evs Ih]. + by move=> _ pin /=; case: ifP => /= bval p'; rewrite inE=> /eqP ->. +move=> cnd pin. + have cnd' : {subset ([seq point ev' | ev' <- evs] : seq pt) <= s}. + by move=> p' p'in; apply: cnd; rewrite inE p'in orbT. +have Ih' := Ih cnd' pin; clear Ih. +have evin : point ev \in s by apply: cnd; rewrite !inE eqxx. +rewrite /=; (repeat (case: ifP=> _))=> p'; rewrite /= !inE; + (repeat(move=>/orP[])); try solve[move=> /eqP -> // | by apply: cnd']. +apply: Ih'. +Qed. + +Lemma edges_to_events_subset (s : mem_pred pt) (gs : seq edge) : + {subset [seq left_pt g | g <- gs] <= s} -> + {subset [seq right_pt g | g <- gs] <= s} -> + {subset ([seq point ev | ev <- edges_to_events gs] : seq pt) <= s}. +Proof. +elim: gs => [// | g gs Ih]. +rewrite /=. +move=> cndl cndr. +have cndl' : {subset [seq left_pt g | g <- gs] <= s}. + by move=> x xin; apply: cndl; rewrite inE xin orbT. +have cndr' : {subset [seq right_pt g | g <- gs] <= s}. + by move=> x xin; apply: cndr; rewrite inE xin orbT. +have cndleft : left_pt g \in s by apply: cndl; rewrite inE eqxx. +have cndright : right_pt g \in s by apply: cndr; rewrite inE eqxx. +have Ih' := Ih cndl' cndr'; clear Ih. +by apply: add_event_point_subset;[apply: add_event_point_subset | ]. +Qed. + +End working_environment. diff --git a/theories/extraction_command.v b/theories/extraction_command.v index ab2c479..5c0ee72 100644 --- a/theories/extraction_command.v +++ b/theories/extraction_command.v @@ -1,4 +1,4 @@ -From trajectories Require Import smooth_trajectories. +From trajectories Require Import generic_trajectories smooth_trajectories. Require Import QArith. Extraction "smooth_trajectories" smooth_point_to_point example_bottom example_top diff --git a/theories/generic_trajectories.v b/theories/generic_trajectories.v index 30e997d..8ea815c 100644 --- a/theories/generic_trajectories.v +++ b/theories/generic_trajectories.v @@ -1,5 +1,6 @@ From mathcomp Require Import all_ssreflect. -Require Import ZArith List String OrderedType OrderedTypeEx FMapAVL. +Require Import ZArith (* List *) String OrderedType OrderedTypeEx FMapAVL. +Require Import shortest_path. Notation head := seq.head. Notation sort := path.sort. @@ -31,8 +32,6 @@ Notation sort := path.sort. Notation seq := list. -Module natmap := FMapAVL.Make Nat_as_OT. - Section generic_implementation. (* In the original development R has type numFieldType and the various @@ -52,6 +51,10 @@ Notation "x - y" := (R_sub x y). Notation "x + y" := (R_add x y). +Notation "x / y" := (R_div x y). + +Variable pt_distance : R -> R -> R -> R -> R. + Variable R1 : R. Let R0 := R_sub R1 R1. @@ -79,7 +82,7 @@ Definition dummy_pt := ({| p_x := R1; p_y := R1|}). Definition dummy_edge := Bedge dummy_pt dummy_pt. -Definition dummy_cell := +Definition dummy_cell := {| left_pts := nil; right_pts := nil; low := dummy_edge; high := dummy_edge|}. Definition dummy_event := @@ -146,11 +149,11 @@ Definition valid_edge e p := (R_leb (p_x (left_pt e)) (p_x p)) && (* TODO: check again the mathematical formula after replacing the infix *) (* operations by prefix function calls. *) Definition vertical_intersection_point (p : pt) (e : edge) : option pt := - if valid_edge e p then + if valid_edge e p then Some(Bpt (p_x p) (R_add (R_mul (R_sub (p_x p) (p_x (left_pt e))) (R_div (R_sub (p_y (right_pt e)) (p_y (left_pt e))) - (R_sub (p_x (right_pt e)) (p_x (left_pt e))))) + (R_sub (p_x (right_pt e)) (p_x (left_pt e))))) (p_y (left_pt e)))) else None. @@ -190,9 +193,9 @@ Notation "p <<< g" := (point_strictly_under_edge p g) (at level 70, no associativity). Definition edge_below (e1 : edge) (e2 : edge) : bool := -(point_under_edge (left_pt e1) e2 && +(point_under_edge (left_pt e1) e2 && point_under_edge (right_pt e1) e2) -|| (negb (point_strictly_under_edge (left_pt e2) e1) && +|| (negb (point_strictly_under_edge (left_pt e2) e1) && negb (point_strictly_under_edge (right_pt e2) e1)). Definition contains_point (p : pt) (c : cell) : bool := @@ -202,8 +205,8 @@ Definition close_cell (p : pt) (c : cell) := match vertical_intersection_point p (low c), vertical_intersection_point p (high c) with | None, _ | _, None => c - | Some p1, Some p2 => - Bcell (left_pts c) (no_dup_seq (p1 :: p :: p2 :: nil)) (low c) (high c) + | Some p1, Some p2 => + Bcell (left_pts c) (no_dup_seq (p2 :: p :: p1 :: nil)) (low c) (high c) end. Definition closing_cells (p : pt) (contact_cells: seq cell) : seq cell := @@ -215,7 +218,7 @@ Definition pvert_y (p : pt) (e : edge) := | None => R0 end. -Fixpoint opening_cells_aux (p : pt) (out : seq edge) (low_e high_e : edge) +Fixpoint opening_cells_aux (p : pt) (out : seq edge) (low_e high_e : edge) : seq cell * cell := match out with | [::] => @@ -249,7 +252,7 @@ if open_cells is c :: q then else None. -Fixpoint open_cells_decomposition_rec open_cells pt : +Fixpoint open_cells_decomposition_rec open_cells pt : seq cell * seq cell * cell * seq cell := if open_cells is c :: q then if contains_point pt c then @@ -279,9 +282,7 @@ Record scan_state := Definition update_closed_cell (c : cell) (p : pt) : cell := let ptseq := right_pts c in - let newptseq := - (belast (head dummy_pt ptseq) (behead ptseq)) ++ - [:: p; seq.last dummy_pt ptseq] in + let newptseq := seq.head dummy_pt ptseq :: p :: behead ptseq in Bcell (left_pts c) newptseq (low c) (high c). Definition set_left_pts (c : cell) (l : seq pt) := @@ -337,7 +338,7 @@ Definition step (st : scan_state) (e : event) : scan_state := let p := point e in let '(Bscan op1 lsto op2 cls cl lhigh lx) := st in if negb (same_x p lx) then - let '(first_cells, contact_cells, last_contact, last_cells, + let '(first_cells, contact_cells, last_contact, last_cells, lower_edge, higher_edge) := open_cells_decomposition (op1 ++ lsto :: op2) p in simple_step first_cells contact_cells last_cells last_contact @@ -349,7 +350,7 @@ Definition step (st : scan_state) (e : event) : scan_state := let first_cells := op1 ++ lsto :: fc' in simple_step first_cells contact_cells last_cells last_contact low_edge higher_edge cls cl e - else if p <<< lhigh then + else if p <<< lhigh then let new_closed := update_closed_cell cl (point e) in let (new_opens, new_lopen) := update_open_cell lsto e in Bscan (op1 ++ new_opens) new_lopen op2 cls new_closed lhigh lx @@ -427,79 +428,8 @@ Definition edges_to_cells bottom top edges := complete_process (edges_to_events edges) bottom top. (* SECOND PART : computing a path in the cell graph *) -(* This code is taken from github.com/ybertot/breadth_first_search. - the proof of this code is probably complete in that repository. *) - -Section bfs. - -Variable (state move : Type). -Variable (state_fmap : Type). -Variable find : state_fmap -> state -> option move. -Variable add : state_fmap -> state -> move -> state_fmap. -Variable (step : state -> list (state * move)). -Variable (state_eq_dec : forall s1 s2 : state, {s1 = s2}+{s1 <> s2}). - -Variable map_order : state_fmap -> state_fmap -> Prop. -Hypothesis map_order_wf : well_founded map_order. -Hypothesis add_order : forall map s v, - find map s = None -> map_order (add map s v) map. -Hypothesis map_order_trans : forall map2 map1 map3, - map_order map1 map2 -> map_order map2 map3 -> map_order map1 map3. - -Fixpoint bfs_aux (w w2 : list (state * move)) - (sufficient : state) - (settled : state_fmap) : (list (state * move) * state_fmap) := -match w with -| (s, m) :: w' => - match find settled s with - | Some _ => bfs_aux w' w2 sufficient settled - | None => - if state_eq_dec s sufficient then - (nil, add settled s m) - else - bfs_aux w' (step s ++ w2) sufficient (add settled s m) - end -| nil => (w2, settled) -end. - -Fixpoint bfs (fuel : nat) (w : list (state * move)) (settled : state_fmap) - (sufficient : state) - (round : nat) : - (state_fmap * nat) + (list (state * move) * state_fmap) := - match fuel with - | O => inr (w, settled) - | S p => - match bfs_aux w nil sufficient settled with - | (nil, s) => inl (s, round) - | (w, s) => bfs p w s sufficient (round + 1) - end - end. - - (* We then explain how we build a path using the database. *) -Fixpoint make_path (db : state_fmap) -(targetb : state -> bool) (play : state -> move -> option state) -(x : state) (fuel : nat) := -match fuel with -| O => None -| S p => -if targetb x then - Some nil -else - match find db x with - | None => None - | Some m => - match play x m with - | Some y => - match make_path db targetb play y p with - | None => None - | Some l => Some (m :: l) - end - | None => None - end - end -end. - -End bfs. +(* To compute a path that has reasonable optimzation, we compute a shortest *) +(* path between reference points chosen inside doors. *) (* defining the connection relation between adjacent cells. Two cells are adjacent when it is possible to move from one cell directly to the @@ -513,6 +443,9 @@ Definition vert_edge_eqb (v1 v2 : vert_edge) := let: Build_vert_edge v2x v2t v2b := v2 in R_eqb v1x v2x && R_eqb v1t v2t && R_eqb v1b v2b. +(* the lists of points left_pts and right_pts for each cell define the + extremities of the doors, but we wish to have a list of all doors, + obtained by making intervals between two points. *) Fixpoint seq_to_intervals_aux [A : Type] (a : A) (s : seq A) := match s with | nil => nil @@ -528,108 +461,223 @@ end. (* Vertical edges are collected from the left_pts and right_pts sequences. *) Definition cell_safe_exits_left (c : cell) : seq vert_edge := let lx := p_x (head dummy_pt (left_pts c)) in - map (fun p => Build_vert_edge lx (p_y (fst p)) (p_y (snd p))) + map (fun p => Build_vert_edge lx (p_y (fst p)) (p_y (snd p))) (seq_to_intervals (left_pts c)). Definition cell_safe_exits_right (c : cell) : seq vert_edge := let lx := p_x (head dummy_pt (right_pts c)) in - map (fun p => Build_vert_edge lx (p_y (fst p)) (p_y (snd p))) - (seq_to_intervals (rev (right_pts c))). - -Definition all_doors (cells : seq cell) : seq (vert_edge * nat) := - List.concat - (List.map (fun i => List.map (fun v => (v, i)) - (cell_safe_exits_right (nth i cells dummy_cell))) - (seq.iota 0 (List.length cells))). + map (fun p => Build_vert_edge lx (p_y (fst p)) (p_y (snd p))) + (seq_to_intervals (right_pts c)). + +(* The index_seq function is a trick to circumvent the absence of a mapi + function in Coq code. It makes it possible to build a list of pairs, + where each element is annotated with its position in the list. *) +Definition index_seq {T : Type} (s : list T) : list (nat * T) := + zip (iota 0 (size s)) s. + +(* Given a set of cells (given as a sequence), we wish to construct all + the vertical edges (called doors) connecting two cells, and we wish each + door to contain information about the cells they are connected to, here + their rank in the sequence of cells. *) + +Definition door := (vert_edge * nat * nat)%type. + +Definition cells_to_doors (s : list cell) := + let indexed_s := index_seq s in + let vert_edges_and_right_cell := + flatten (map (fun '(i, c) => + (map (fun v => (v, i))) (cell_safe_exits_left c)) + indexed_s) in + let vert_edges_and_both_cells := + flatten (map (fun '(v, i) => + (map (fun '(i', c') => (v, i, i')) + (filter (fun '(i', c') => + existsb (vert_edge_eqb v) (cell_safe_exits_right c')) + indexed_s))) + vert_edges_and_right_cell) in + vert_edges_and_both_cells. -Definition door_right_cell (cells : seq cell) (v : vert_edge) := - find (fun i => existsb (fun v' => vert_edge_eqb v v') - (cell_safe_exits_left (nth i cells dummy_cell))) - (seq.iota 0 (List.length cells)). +Definition on_vert_edge (p : pt) (v : vert_edge) : bool := + R_eqb (p_x p) (ve_x v) && R_ltb (ve_bot v) (p_y p) && + R_ltb (p_y p) (ve_top v). Definition vert_edge_midpoint (ve : vert_edge) : pt := {|p_x := ve_x ve; p_y := R_div ((R_add (ve_top ve) (ve_bot ve))) R2|}. + +(* When a vertical edge contains the source or the target, we wish this + point to be considered as the reference point for that edge. *) +Definition vert_edge_to_reference_point (s t : pt) (v : vert_edge) := + if on_vert_edge s v then s + else if on_vert_edge t v then t + else vert_edge_midpoint v. + +(* Each door has one or two neighboring cells, the neighboring doors + are those doors that share one of these neighboring cells. Here we only + want to know the index of the neighbors. We make sure to avoid including + the current door in the neighbors. *) +Definition one_door_neighbors + (indexed_doors : seq (nat * door)) + (i_d : nat * door) : list nat := + match i_d with + | (j, (v0, i0, i'0)) => + map fst + (filter (fun '(vi, (v, i, i')) => (Nat.eqb i i0 || Nat.eqb i i'0 || + Nat.eqb i' i0 || Nat.eqb i' i'0) && (negb (Nat.eqb j vi))) + indexed_doors) + end. + +Definition left_limit (c : cell) := p_x (seq.head dummy_pt (left_pts c)). -(* connection from left to right is obtained by computing an intersection. *) -Definition lr_connected (c1 c2 : cell) : bool := - existsb (fun v => existsb (fun v' => vert_edge_eqb v v') - (cell_safe_exits_left c2)) - (cell_safe_exits_right c1). +Definition right_limit c := p_x (seq.head dummy_pt (right_pts c)). -Definition bi_connected c1 c2 := - lr_connected c1 c2 || lr_connected c2 c1. +Definition cmp_option := cmp_option _ R_ltb. + +Definition strict_inside_closed p c := + negb (point_under_edge p (low c)) && + point_strictly_under_edge p (high c) && + (R_ltb (left_limit c) (p_x p) && + (R_ltb (p_x p) (right_limit c))). + +(* For each extremity, we check whether it is already inside an existing + door. If it is the case, we need to remember the index of that door. + If the extremity is not inside a door, then we create a fictitious door, + where the neighboring cells both are set to the one cell containing this + point. *) +Definition add_extremity_reference_point + (indexed_cells : seq (nat * cell)) + (p : pt) (doors : seq door) := + let purported_index := + seq.find (fun '(v, _, _) => on_vert_edge p v) doors in + if purported_index < size doors then + (doors, purported_index) + else + let '(i, c) := + head (size indexed_cells, dummy_cell) + (filter (fun '(i', c') => strict_inside_closed p c') indexed_cells) in + (rcons doors ({|ve_x := p_x p; ve_top := p_y p; ve_bot := p_y p|}, i, i), size doors). + +(* This function makes sure that the sequence of doors contains a door + for each of the extremities, adding new doors when needed. It returns + the updated sequence of doors and the indexes for the doors containing + each of the extremities. *) +Definition doors_and_extremities (indexed_cells : seq (nat * cell)) + (doors : seq door) (s t : pt) : seq door * nat * nat := + let '(d_s, i_s) := + add_extremity_reference_point indexed_cells s doors in + let '(d_t, i_t) := + add_extremity_reference_point indexed_cells t d_s in + (d_t, i_s, i_t). + +(* In the end the door adjacency map describes the graph in which we + want to compute paths. *) +Definition door_adjacency_map (doors : seq door) : + seq (seq nat) := + let indexed_doors := index_seq doors in + map (fun i_d => one_door_neighbors indexed_doors i_d) indexed_doors. Definition dummy_vert_edge := {| ve_x := R0; ve_top := R0; ve_bot := R0|}. -Definition bfs_find : natmap.t nat -> nat -> option nat := - (fun m k => natmap.find k m). - -Definition bfs_add : natmap.t nat -> nat -> nat -> natmap.t nat := - (fun m k v => natmap.add k v m). - -Definition reverse_step cells cell_i : seq (nat * nat) := - map (fun i => (i, cell_i)) - (filter (fun c_i => bi_connected (nth c_i cells dummy_cell) - (nth cell_i cells dummy_cell)) - (seq.iota 0 (List.length cells))). - -(* To compute a path between two cells we use as input the list of cells - and indices of two cells in this list (source and target). This builds - a table. This table construction is interrupted as soon as a path - from source_i to target_i is found, and this path is guaranteed to be - of minimal length in terms of numbers of cells encountered. The result - is in a sum type, where only the right variant would mean that no path - has been found before exhaustion of some fuel. But here, it is assumed - that the fuel (length of cells) is going to be enough to find all cells - connected to target_i. *) -Definition cell_connection_table (cells : seq cell) (source_i target_i : nat) := - bfs _ _ _ bfs_find bfs_add (reverse_step cells) eq_nat_dec - (List.length cells) ((target_i, target_i) :: nil) (natmap.empty nat) - source_i 0. - -Definition cell_path (cells : seq cell) (source_i target_i : nat) : - option (seq nat) := - match cell_connection_table cells source_i target_i with - | inr _ => None - | inl (table, _) => - make_path _ _ _ bfs_find table (fun c_i => Nat.eqb c_i target_i) - (fun n1 n2 => Some n2) source_i (List.length cells) +Definition dummy_door := (dummy_vert_edge, 0, 0). + +(* To compute the distance between two doors, we compute the distance + between the reference points. TODO: this computation does not take + into account the added trajectory to go to a safe point inside the + cell where the doors are vertically aligned. *) +Definition distance (doors : seq door) (s t : pt) + (i j : nat) := + let '(v1, _, _) := seq.nth dummy_door doors i in + let '(v2, _, _) := seq.nth dummy_door doors j in + let p1 := vert_edge_to_reference_point s t v1 in + let p2 := vert_edge_to_reference_point s t v2 in + pt_distance (p_x p1) (p_y p1) (p_x p2) (p_y p2). + +(* The function cells_too_doors_graph constructs the graph with + weighted edges. *) +Definition cells_to_doors_graph (cells : seq cell) (s t : pt) := + let regular_doors := cells_to_doors cells in + let indexed_cells := index_seq cells in + let '(full_seq_of_doors, i_s, i_t) := + doors_and_extremities indexed_cells regular_doors s t in + let adj_map := door_adjacency_map full_seq_of_doors in + let neighbors_and_distances := + [seq [seq (j, distance full_seq_of_doors s t i j) | j <- neighbors] + | '(i, neighbors) <- index_seq adj_map] in + (full_seq_of_doors, neighbors_and_distances, i_s, i_t). + +(* We can now call the shortest path algorithm, where the nodes are + door indices. *) +Definition node := nat. + +Definition empty := @nil (node * seq node * option R). + +(* The shortest graph algorithm relies on a priority queue. We implement + such a queue by maintaining a sorted list of nodes. *) +Notation priority_queue := (list (node * seq node * option R)). + +Definition node_eqb := Nat.eqb. + +(* To find a element in the priority queue, we just traverse the list + until we find one node that that the same index. *) +Fixpoint gfind (q : priority_queue) n := + match q with + | nil => None + | (n', p, d) :: tl => if node_eqb n' n then Some (p, d) else gfind tl n end. -(* Given two cells, we define the door from one cell to the other to - be the common edge between these cells. In example known so far, there - is only one such door, but this may change in the future. For now, we - take arbitrarily the first one we find (the top one or the bottom one - depending on the exits are ordered). If the two cells are not adjacent, - dummy_vert_edge is returned. Maybe this should be made safer by returning - an option type. *) -Definition lr_door (c1 c2 : cell) : vert_edge := - head dummy_vert_edge - (filter (fun x => existsb (fun x' => vert_edge_eqb x x') - (cell_safe_exits_left c2)) (cell_safe_exits_right c1)). - -Definition left_limit (c : cell) := p_x (seq.last dummy_pt (left_pts c)). - -Definition right_limit c := p_x (seq.last dummy_pt (right_pts c)). - -(* This function is like lr_door, but it is more precise, as it - can be applied when the doors are connected but not lr_connected as it - returns None in case the two given cells are not adjacent. *) -Definition common_vert_edge (c1 c2 : cell) : option vert_edge:= - if R_eqb (right_limit c1) (left_limit c2) then - find (fun v => existsb (fun v' => vert_edge_eqb v v') - (cell_safe_exits_left c2)) - (cell_safe_exits_right c1) - else - find (fun v => existsb (fun v' => vert_edge_eqb v v') - (cell_safe_exits_left c1)) - (cell_safe_exits_right c2). +(* To remove an element, we traverse the list. Note that we only remove + the first instance. *) +Fixpoint remove (q : priority_queue) n := + match q with + | nil => nil + | (n', p', d') :: tl => + if node_eqb n' n then + tl + else + (n', p', d') :: remove tl n + end. + +(* To insert a new association in the priority queue, we are careful to + insert the node in the right place comparing the order. *) +Fixpoint insert (q : priority_queue) n p d := + match q with + | nil => (n, p, d) :: nil + | (n', p', d') :: tl => + if cmp_option d d' then + (n, p, d) :: q + else + (n', p', d') :: insert tl n p d + end. + +Definition update q n p d := + insert (remove q n) n p d. + +Definition pop (q : priority_queue) : + option (node * seq node * option R * priority_queue) := + match q with + | nil => None + | v :: tl => Some (v, tl) + end. + +(* This function takes as input the sequence of cells, the source and + target points. It returns a tuple containing: + - the graph of doors, + this graph is a sequence of pairs, where the first component is + is door, and the second component is the sequence of nodes + - the path, when it exists, + - the index of the doors containing the source and targt points *) +Definition c_shortest_path cells s t := + let '(adj, i_s, i_t) := cells_to_doors_graph cells s t in + (adj, shortest_path R R0 R_ltb R_add node node_eqb + (seq.nth [::] adj.2) i_s i_t _ empty + gfind update pop (iota 0 (size adj.2)), i_s, i_t). Definition midpoint (p1 p2 : pt) : pt := {| p_x := R_div (R_add (p_x p1) (p_x p2)) R2; p_y := R_div (R_add (p_y p1) (p_y p2)) R2|}. +(* The center of the cell is computed using the middle of the high edge + the middle of the low edge, and their middle. *) Definition cell_center (c : cell) := midpoint (midpoint (seq.last dummy_pt (left_pts c)) @@ -637,209 +685,166 @@ Definition cell_center (c : cell) := (midpoint (head dummy_pt (left_pts c)) (seq.last dummy_pt (right_pts c))). +(* Each point used in the doors is annotated with the doors on which they + are and the cells they connect. The last information may be useless + since we have now door information. *) Record annotated_point := - Apt { apt_val : pt; cell_indices : seq nat}. + Apt { apt_val : pt; door_index : option nat; cell_indices : seq nat}. + +(* This value (1/16) of margin is suitable for the demo environment. In real + life, this should be a parameter of the algorithm. *) +Definition margin := R1 / ((R1 + R1) * + (R1 + R1) * (R1 + R1) * (R1 + R1) * (R1 * R1)). + + +(* Given two points p1 and p2 on a side of a cell, this computes a point + inside the cell that is a sensible intermediate point to move from p1 + to p2 while staying safely inside the cell. *) +Definition safe_intermediate_point_in_cell (p1 p2 : pt) (c : cell) + (ci : nat) := + let new_x := p_x (cell_center c) in + let new_y := R_div (R_add (p_y p1) (p_y p2)) R2 in + if R_ltb new_x (p_x p1) then + let new_pt := {|p_x := p_x p1 - margin; p_y := new_y|} in + if strict_inside_closed new_pt c then + Apt new_pt None (ci :: nil) + else + Apt (cell_center c) None (ci :: nil) + else + let new_pt := {|p_x := p_x p1 + margin; p_y := new_y|} in + if strict_inside_closed new_pt c then + Apt new_pt None (ci :: nil) + else + Apt (cell_center c) None (ci :: nil). -Definition on_vert_edge (p : pt) (v : vert_edge) : bool := - R_eqb (p_x p) (ve_x v) && R_ltb (ve_bot v) (p_y p) && - R_ltb (p_y p) (ve_top v). -(* This function assumes a straight line to the door is safe. For annotations - it supposes the first cell index corresponds to the cell containing p. - It returns nil if there is no door, and nil or a faulty edge if - the other conditions are not met. *) -Definition point_to_door (cells : seq cell) (p : annotated_point) (c1i c2i : nat) : - seq (annotated_point * annotated_point) := -let c1 := nth c1i cells dummy_cell in -let c2 := nth c2i cells dummy_cell in -match common_vert_edge c1 c2 with - Some v => - if (R_eqb (p_x (apt_val p)) (ve_x v)) && negb (on_vert_edge (apt_val p) v) then - (p, Apt (cell_center c1) (c1i::nil)) :: - (Apt (cell_center c1) (c1i :: nil), Apt (vert_edge_midpoint v) (c1i :: c2i :: nil)) :: nil +(* When two neighbor doors are aligned vertically, they have a neighboring + cell in common. This can be computed by looking at the intersection + between their lists of neighboring cells. *) +Definition intersection (s1 s2 : seq nat) := + [seq x | x <- s1 & existsb (fun y => Nat.eqb x y) s2]. + +Definition common_index (s1 s2 : seq nat) := + let intersect := intersection s1 s2 in + seq.head 0 intersect. + +Definition door_to_annotated_point s t (d : door) + (door_index : nat) := + let p' := vert_edge_to_reference_point s t d.1.1 in + let annot := + if Nat.eqb d.1.2 d.2 then [:: d.2] else [:: d.1.2 ; d.2] in + Apt p' (Some door_index) annot. + +Fixpoint a_shortest_path (cells : seq cell) + (doors : seq door * seq (seq (nat * R))) + s t (p : annotated_point) (path : seq node) := + match path with + | nil => [:: p] + | p'i :: tlpath => + let d' := seq.nth dummy_door doors.1 p'i in + let a_p' := door_to_annotated_point s t d' p'i in + if R_eqb (p_x (apt_val p)) (p_x (apt_val a_p')) then + let ci := common_index (cell_indices p) (cell_indices a_p') in + let p_extra : annotated_point := + safe_intermediate_point_in_cell (apt_val p) (apt_val a_p') + (seq.nth dummy_cell cells ci) ci in + p :: p_extra :: a_shortest_path cells doors s t a_p' tlpath else - (p, Apt (vert_edge_midpoint v) (c1i :: c2i :: nil)) :: nil -| None => nil -end. + p :: a_shortest_path cells doors s t a_p' tlpath + end. Definition path_reverse (s : seq (annotated_point * annotated_point)) := List.map (fun p => (snd p, fst p)) (List.rev_append s nil). -(* This function creates a safe path from the door between - c1 and c2 and the door between c2 and c3. When op1 and op2 - are not provided, midpoints are used as path anchors, - when p1 and p2 are provided they are used instead. - This function assumes that p1 and p2 are members of the - respective doors (c1-c2) and (c2-c3) *) -Definition to_next_door (op1 op2 : option pt) - (cells : seq cell) - (c1i c2i c3i : nat) : seq (annotated_point * annotated_point) := -let c2 := nth c2i cells dummy_cell in -let p1 := match op1 with - | Some p1 => p1 - | None => - match common_vert_edge (nth c1i cells dummy_cell) c2 with - | Some v => vert_edge_midpoint v - | None => dummy_pt - end - end in -let p2 := match op2 with - | Some p2 => p2 - | None => - match common_vert_edge c2 (nth c3i cells dummy_cell) with - | Some v => vert_edge_midpoint v - | None => dummy_pt - end - end in -if R_eqb (p_x p1) (p_x p2) then - let intermediate_point := - Apt (cell_center c2) (c2i :: nil) in - (Apt p1 (c1i :: c2i :: nil), intermediate_point) :: - (intermediate_point, Apt p2 (c2i :: c3i :: nil)) :: nil -else - (Apt p1 (c1i :: c2i :: nil), Apt p2 (c2i :: c3i :: nil)) :: nil. - -(* Given a sequence of cells c_i, and a sequence of indices i1, i2, ... - (where the ... are refered to as tl), we want to create a list of - points, making it possible to move from door to door so that the all - all list of points is describes a broken line moving from the door - between i1 and i2 to the door between the last two elements of - (i1, i2, & tl). Adding paths to the first and last doors will make it - easy to have a path from any point in cell i1 to any point in the last - cell of (i1, i2, & tl). when optional points are provided, they - are points in the first and last door. *) -Fixpoint door_to_door (cells : seq cell) - (i1 i2 : nat) (opt_source opt_target : option pt)(tl : seq nat) : - seq (annotated_point * annotated_point) := - match tl with - | nil => nil - | i3 :: nil => - to_next_door opt_source opt_target cells i1 i2 i3 - | i3 :: tl' => - let tail_path := door_to_door cells i2 i3 None opt_target tl' in - to_next_door opt_source None cells i1 i2 i3 ++ tail_path - end. - -(* This function computes a path (broken line) between a point - in a cell and a point in another cell, going through the midpoint of - the door between the two cells. the points are annotated with the - constraint they have to satisfied: the cells of which they have to - be members of. This annotation is important because smoothing will - replace these points with other points that have to satisfy the same - constraint. *) -Definition path_adjacent_cells (cells : seq cell) (source target : pt) - (source_i target_i : nat) : option (seq (annotated_point * annotated_point)) := - let source_cell := nth source_i cells dummy_cell in - let target_cell := nth target_i cells dummy_cell in - match common_vert_edge source_cell target_cell with - | Some v => - Some ((Apt source (source_i :: nil), - Apt (vert_edge_midpoint v) (source_i :: target_i :: nil)) :: - (Apt (vert_edge_midpoint v) (source_i :: target_i :: nil), - Apt target (target_i :: nil)) :: nil) - | None => None - end. - -Definition strict_inside_closed p c := - negb (point_under_edge p (low c)) && - point_strictly_under_edge p (high c) && - (R_ltb (left_limit c) (p_x p) && - (R_ltb (p_x p) (right_limit c))). - -(* find_origin_cells returns a list of cell indices. *) -(* If the list is empty, it should mean that the point is not in the - safe part of the work space (it is either outside the box or on - one of the obstacle edges). If the list has only one element, - the point is inside the indexed cell. If the list has two - elements, this means that the point is in the door between the - two indexed cells. *) -Definition find_origin_cells (cells : seq cell) (p : pt) : seq nat := - match find (fun i => strict_inside_closed p (nth i cells dummy_cell)) - (seq.iota 0 (List.length cells)) with - | Some n => n :: nil - | None => - head nil - (List.map (fun av => snd av :: - match door_right_cell cells (fst av) with - | Some rc => rc :: nil - | None => nil - end) - (filter (fun av => on_vert_edge p (fst av)) (all_doors cells))) - end. - -Definition intersection (s1 s2 : seq nat) := - filter (fun e => existsb (fun e' => Nat.eqb e e') - s2) s1. - -Definition point_to_point - (cells : seq cell) (source target : pt) : - option (seq (annotated_point * annotated_point)) := -let source_is := find_origin_cells cells source in -let target_is := find_origin_cells cells target in -if Nat.ltb 0 (List.length source_is) && Nat.ltb 0 (List.length target_is) then - if Nat.ltb 0 (List.length (intersection source_is target_is)) then - Some ((Apt source source_is, Apt target target_is) :: nil) - else - let ocp := cell_path cells (head 0%nat source_is) (head 0%nat target_is) in - match ocp with - Some cp => - (* The first element of the path is (head 0 source_is), *) - if 2 <=? List.length cp then - (* looking - at a length larger than 2 actually means the path has at least 3 fenceposts - and at least 2 intervals: - head source_is (nth 0 cp 0) (nth 1 cp 0) - so there are (at least) 2 doors. *) - if existsb (Nat.eqb (nth 0 cp 0%nat)) source_is then - (* It can only be the case that the source is on a door, and - that the two cells concerned with the first hop are the - two cells of this door. In this case, there is no need - to draw a first path element from from the source point to the - vertical edge midpoint, since the first point is already - on the door, and that the target is not in the second cell - of the path, so the length of cp is strictly larger than 2 *) - if existsb (Nat.eqb (nth (List.length cp - 2) cp 0%nat)) target_is then - (* Here target_is is in the penultimate cell of the path *) - Some (door_to_door cells (head 0%nat source_is) (nth 0 cp 0%nat) - (Some source) (Some target) (seq.behead cp (* (seq.behead cp) *))) - else - Some (door_to_door cells (head 0%nat source_is) (nth 0 cp 0%nat) (Some source) None - (seq.behead cp) ++ - path_reverse (point_to_door cells (Apt target target_is) - (nth (List.length cp - 1) cp 0%nat) - (nth (List.length cp - 2) cp 0%nat))) +Definition intersect_vert_edge (p1 p2 : pt) (ve : vert_edge) : pt := + Bpt (ve_x ve) + (p_y p1 + (ve_x ve - p_x p1) / (p_x p2 - p_x p1) * (p_y p2 - p_y p1)). + +Definition optim_three (doors : seq door) (p1 p2 p3 : annotated_point) := + let p1' := apt_val p1 in + let p3' := apt_val p3 in + if p2 is Apt p2' (Some d_i) cells then + let d := (seq.nth dummy_door doors d_i).1.1 in + if R_ltb (p_x p1') (ve_x d) && R_ltb (ve_x d) (p_x p3') then + if R_ltb R0 (area3 p1' p2' p3') then + if R_ltb R0 (area3 p1' p3' (Bpt (ve_x d) (ve_top d))) then + let p2_2 := intersect_vert_edge p1' p3' d in + Apt p2_2 (Some d_i) cells else - if existsb (Nat.eqb (nth ((List.length cp) - 2) cp 0%nat)) target_is then - Some ((point_to_door cells (Apt source source_is) (head 0%nat source_is) - (nth 0 cp 0%nat)) ++ - door_to_door cells (head 0%nat source_is) (nth 0 cp 0%nat) None (Some target) - (seq.behead cp)) + if R_ltb (ve_bot d) (ve_top d - margin) then + Apt (Bpt (ve_x d) (ve_top d - margin)) (Some d_i) cells else - Some (point_to_door cells (Apt source source_is) (head 0%nat source_is) (nth 0 cp 0%nat) ++ - door_to_door cells (head 0%nat source_is) (nth 0 cp 0%nat) None None - (seq.behead cp) ++ - path_reverse (point_to_door cells (Apt target target_is) - (nth (List.length cp - 1) cp 0%nat) - (nth (List.length cp - 2) cp 0%nat))) + p2 else - (* if cp has length 1, then there is only one door. if one of the - point is on the door, it can be connected to the other, *) - match common_vert_edge (nth (head 0%nat source_is) cells dummy_cell) - (nth (head 0%nat target_is) cells dummy_cell) with - | Some v => - if on_vert_edge source v || on_vert_edge target v then - Some ((Apt source source_is, Apt target target_is) :: nil) - else - Some (point_to_door cells (Apt source source_is) (head 0%nat source_is) - (head 0%nat target_is) ++ - path_reverse (point_to_door cells (Apt target target_is) - (head 0%nat source_is) (head 0%nat target_is))) - | None => None - end - | None => None + if R_ltb (area3 p1' p3' (Bpt (ve_x d) (ve_bot d))) R0 then + let p2_2 := intersect_vert_edge p1' p3' d in + Apt p2_2 (Some d_i) cells + else + if R_ltb (ve_bot d + margin) (ve_top d) then + Apt (Bpt (ve_x d) (ve_bot d + margin)) (Some d_i) cells + else + p2 + else if R_ltb (p_x p3') (ve_x d) && R_ltb (ve_x d) (p_x p1') then + if R_ltb R0 (area3 p1' p2' p3') then + if R_ltb R0 (area3 p1' p3' (Bpt (ve_x d) (ve_bot d))) then + let p2_2 := intersect_vert_edge p1' p3' d in + Apt p2_2 (Some d_i) cells + else + if R_ltb (ve_bot d + margin) (ve_top d) then + Apt (Bpt (ve_x d) (ve_bot d + margin)) (Some d_i) cells + else + p2 + else + if R_ltb (area3 p1' p3' (Bpt (ve_x d) (ve_top d))) R0 then + let p2_2 := intersect_vert_edge p1' p3' d in + Apt p2_2 (Some d_i) cells + else + if R_ltb (ve_bot d) (ve_top d - margin) then + Apt (Bpt (ve_x d) (ve_top d - margin)) (Some d_i) cells + else + p2 + else + p2 + else + p2. + +Fixpoint local_improvements (doors : seq door) + (p : seq (annotated_point * annotated_point)) : + seq (annotated_point * annotated_point) := +match p with +| (p1, p2) :: ((_ , p3) :: _) as tl => + match local_improvements doors tl with + | [::] => p + | (_, p3') :: tl' => + let p2' := optim_three doors p1 p2 p3' in + (p1, p2') :: (p2', p3') :: tl' end -else -None. +| _ => p +end. + +Definition source_to_target + (cells : seq cell) (source target : pt) : + option (seq door * + seq (annotated_point * annotated_point)) := + let '(doors, opath, i_s, i_t) := + c_shortest_path cells source target in + if Nat.eqb i_s i_t then + Some (doors.1, [:: (Apt source None [::], Apt target None [::])]) + else + let last_point := + door_to_annotated_point source target + (seq.nth dummy_door doors.1 i_t) i_t in + if opath is Some path then + match a_shortest_path cells doors source target + last_point path with + | nil => None + | a :: tl => + Some(doors.1, + local_improvements doors.1 + (path_reverse (seq_to_intervals_aux a tl))) + end + else + None. (* THIRD PART: Producing a smooth trajectory. *) (* We produce a smooth trajectory by replacing every angle by a Bezier curve. @@ -857,9 +862,9 @@ None. Fixpoint break_segments (s : seq (annotated_point * annotated_point)) : seq (annotated_point * annotated_point) := match s with - | (Apt p1 a1, Apt p2 a2) :: tl => - (Apt p1 a1, Apt (midpoint p1 p2) (intersection a1 a2)) :: - (Apt (midpoint p1 p2) (intersection a1 a2), Apt p2 a2) :: + | (Apt p1 door_index1 a1, Apt p2 door_index2 a2) :: tl => + (Apt p1 door_index1 a1, Apt (midpoint p1 p2) None (intersection a1 a2)) :: + (Apt (midpoint p1 p2) None (intersection a1 a2), Apt p2 door_index2 a2) :: break_segments tl | nil => nil end. @@ -923,12 +928,12 @@ Fixpoint check_bezier_ccw (fuel : nat) (v : vert_edge) match fuel with | O => None | S p => - let top_edge := Bpt (ve_x v) (ve_top v) in - if negb (point_under_edge top_edge (Bedge a c)) then + let top_of_edge := Bpt (ve_x v) (ve_top v) in + if negb (point_under_edge top_of_edge (Bedge a c)) then Some true else if - point_under_edge top_edge (Bedge a b) || - point_under_edge top_edge (Bedge b c) + point_under_edge top_of_edge (Bedge a b) || + point_under_edge top_of_edge (Bedge b c) then Some false else @@ -955,12 +960,12 @@ Fixpoint check_bezier_cw (fuel : nat) (v : vert_edge) match fuel with | O => None | S p => - let bot_edge := Bpt (ve_x v) (ve_bot v) in - if point_strictly_under_edge bot_edge (Bedge a c) then + let bot_of_edge := Bpt (ve_x v) (ve_bot v) in + if point_strictly_under_edge bot_of_edge (Bedge a c) then Some true else if - negb (point_strictly_under_edge bot_edge (Bedge a b)) || - negb (point_strictly_under_edge bot_edge (Bedge b c)) + negb (point_strictly_under_edge bot_of_edge (Bedge a b)) || + negb (point_strictly_under_edge bot_of_edge (Bedge b c)) then Some false else @@ -996,19 +1001,14 @@ end. Definition fuel_constant := 20. Fixpoint check_curve_element_and_repair - (fuel : nat) (cells : seq cell) (e : curve_element) : + (fuel : nat) doors (e : curve_element) : seq curve_element := match e with | straight p1 p2 => straight p1 p2 :: nil | bezier p1 p2 p3 => - if Nat.eqb (List.length (cell_indices p2)) 2 then - let i1 := nth 0 (cell_indices p2) 0%nat in - let i2 := nth 1 (cell_indices p2) 0%nat in - let vedge := match common_vert_edge - (nth i1 cells dummy_cell) (nth i2 cells dummy_cell) with - Some v => v - | None => dummy_vert_edge - end in + if door_index p2 is Some n then + let vedge := + (seq.nth dummy_door doors n).1.1 in let e' := (if R_ltb (p_x (apt_val p1)) (p_x (apt_val p2)) then bezier p1 p2 p3 @@ -1030,16 +1030,17 @@ match e with match fuel with | S p => straight p1 - (Apt (midpoint (apt_val p1) (apt_val p2)) (cell_indices p1)) + (Apt (midpoint (apt_val p1) (apt_val p2)) + None (cell_indices p1)) :: - check_curve_element_and_repair p cells - (bezier (Apt (midpoint (apt_val p1) (apt_val p2)) + check_curve_element_and_repair p doors + (bezier (Apt (midpoint (apt_val p1) (apt_val p2)) None (cell_indices p1)) p2 - (Apt (midpoint (apt_val p2) (apt_val p3)) (cell_indices p3))) + (Apt (midpoint (apt_val p2) (apt_val p3)) None (cell_indices p3))) ++ straight (Apt (midpoint (apt_val p2) (apt_val p3)) - (cell_indices p3)) p3 :: nil + None (cell_indices p3)) p3 :: nil | _ => straight p1 p2 :: straight p2 p3 :: nil end @@ -1051,13 +1052,25 @@ end. Definition smooth_from_cells (cells : seq cell) (initial final : pt) : seq curve_element := - match point_to_point cells initial final with - | Some s => List.concat - (List.map (check_curve_element_and_repair fuel_constant cells) + match source_to_target cells initial final with + | Some (doors, s) => + List.concat + (List.map (check_curve_element_and_repair fuel_constant doors) (smoothen (break_segments s))) | None => nil end. +(* This function only computes the piecewise straight line trajectory, + starting from the sequence of edges and the source and target. *) +Definition point_to_point (bottom top : edge) (obstacles : seq edge) + (initial final : pt) : seq curve_element := + let cells := edges_to_cells bottom top obstacles in + match source_to_target cells initial final with + | Some (doors, s) => + List.map (fun '(a, b) => straight a b) s + | None => nil + end. + (* This function wraps up all operations: - constructing the cells - constructing the broken line diff --git a/theories/hulls.v b/theories/hulls.v index 507361d..650a1be 100644 --- a/theories/hulls.v +++ b/theories/hulls.v @@ -40,7 +40,7 @@ Implicit Types X Y : set A. Lemma subset_hull X : X `<=` hull X. Proof. move=> x xX; rewrite /hull; exists 1%N, (fun=> x), (fun=>1%R). -split=> //; first by move=>_; exact ler01. +split=> //. - by rewrite big_ord_recl big_ord0 addr0. - by move=> d [i _ <-]. - by rewrite big_ord_recl big_ord0 scale1r addr0. @@ -256,14 +256,14 @@ wlog: l lu ls ll f f0 f1 i ilt / l`_i == 0%R. move=>h. set l' := [seq x - l`_i | x <- l]. have subl': forall a b, (a < size l) -> (b < size l) -> l'`_a - l'`_b = l`_a - l`_b. - by move=>a b al bl; rewrite (nth_map (GRing.zero _))// (nth_map (GRing.zero _))// opprD [-_ - - _]addrC -!addrA; congr GRing.add; rewrite addrA subrr add0r. + by move=>a b al bl; rewrite (nth_map 0)// (nth_map 0)// opprD [-_ - - _]addrC -!addrA; congr GRing.add; rewrite addrA subrr add0r. suff: (0%:R <= det l'`_i l'`_(Zp_succ (Ordinal ilt)) (\sum_(i0 < size l) f i0 *: l'`_i0))%R. congr (_ <= _)%R; rewrite 2!det_scalar_productE; congr (scalar_product _ (rotate _)). - by apply subl'=>//; case: (Zp_succ (Ordinal ilt)). - - rewrite [l'`_i](nth_map (GRing.zero _))// subrr subr0 -[l`_i]scale1r. + - rewrite [l'`_i](nth_map 0)// subrr subr0 -[l`_i]scale1r. have->: (1 = 1%:R)%R by []. rewrite -f1 scaler_suml -sumrB; apply congr_big=>// [[j jlt]] _. - by rewrite -scalerBr (nth_map (GRing.zero _)). + by rewrite -scalerBr (nth_map 0). move:h=>/(_ l'); rewrite size_map; apply. - rewrite map_inj_uniq=>//; apply addIr. - by []. @@ -280,7 +280,7 @@ wlog: l lu ls ll f f0 f1 i ilt / l`_i == 0%R. by move:ll; rewrite Spec.encompassll_spec=>// /andP[_] /forallP /(_ (Ordinal alt)) /forallP /(_ (Ordinal blt)) /forallP /(_ (Ordinal clt)) /implyP /(_ abc); rewrite /ccw_KA.OT /ccw det_scalar_productE. - apply f0. - exact f1. - - by rewrite (nth_map (GRing.zero _))// subrr. + - by rewrite (nth_map 0)// subrr. move=>/eqP li0; rewrite li0 det_sum; apply sumr_ge0=>[[j jlt]] _. rewrite det_scalar_productE 2!subr0 rotateZ scalar_productZR; apply mulr_ge0. apply f0. diff --git a/theories/infra.v b/theories/infra.v index 125f04f..710e47a 100644 --- a/theories/infra.v +++ b/theories/infra.v @@ -1,3 +1,4 @@ +From HB Require Import structures. From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq order. From mathcomp Require Import choice fintype finfun ssrfun bigop ssralg. (*Require Import orderedalg.*) @@ -34,8 +35,7 @@ Proof. rewrite /eqp; case e: ((p ?= q))%positive=> // _; exact: Pcompare_Eq_eq. Qed. -Canonical Structure eqp_Mixin := EqMixin eqpP. -Canonical Structure eqp_eqType := Eval hnf in EqType positive eqp_Mixin. +HB.instance Definition _ := hasDecEq.Build _ eqpP. Definition p_unpickle n := Some (Pos.pred (P_of_succ_nat n)). @@ -45,22 +45,19 @@ Proof. by rewrite pred_o_P_of_succ_nat_o_nat_of_P_eq_id. Qed. -Definition p_countMixin := CountMixin p_pick_cancel. -Definition p_choiceMixin := CountChoiceMixin p_countMixin. +HB.instance Definition _ := @PCanIsCountable _ _ _ _ p_pick_cancel. -Canonical Structure p_choiceType := +(*Canonical Structure p_choiceType := Eval hnf in ChoiceType positive p_choiceMixin. Canonical Structure p_countType := - Eval hnf in CountType positive p_countMixin. + Eval hnf in CountType positive p_countMixin.*) (* Structures on Z *) Lemma eqzP : Equality.axiom Zeq_bool. Proof. by move=> z1 z2; apply: (iffP idP); move/Zeq_is_eq_bool. Qed. -Canonical Structure Z_Mixin := EqMixin eqzP. -Canonical Structure Z_eqType := Eval hnf in EqType Z Z_Mixin. - +HB.instance Definition _ := hasDecEq.Build _ eqzP. Definition z_code (z : Z) := match z with @@ -99,6 +96,9 @@ Proof. by move=> x; rewrite /z_pickle /z_unpickle pickleK z_codeK. Qed. +HB.instance Definition _ := @PCanIsCountable _ _ _ _ z_pick_cancel. + +(* Definition z_countMixin := CountMixin z_pick_cancel. Definition z_choiceMixin := CountChoiceMixin z_countMixin. @@ -106,7 +106,7 @@ Canonical Structure z_choiceType := Eval hnf in ChoiceType Z z_choiceMixin. Canonical Structure z_countType := Eval hnf in CountType Z z_countMixin. - +*) Lemma ZplusA : associative Zplus. Proof. by exact Zplus_assoc. Qed. @@ -123,11 +123,7 @@ Proof. exact Zplus_opp_l. Qed. Lemma ZplusrN : right_inverse 0%Z Z.opp Zplus. Proof. exact Zplus_opp_r. Qed. -Definition Z_zmodMixin := - ZmodMixin ZplusA ZplusC Zplus0 ZplusNr. - -Canonical Structure Z_zmodType := - Eval hnf in ZmodType Z Z_zmodMixin. +HB.instance Definition _ := @GRing.isZmodule.Build Z _ _ _ ZplusA ZplusC Zplus0 ZplusNr. (* Z Ring *) Lemma ZmultA : associative Zmult. @@ -151,16 +147,12 @@ Proof. exact: Zmult_plus_distr_r. Qed. Lemma nonzeroZ1 : 1%Z != 0%Z. Proof. by []. Qed. -Definition Z_ringMixin := - RingMixin ZmultA Zmult1q Zmultq1 Zmult_addl Zmult_addr nonzeroZ1. - -Canonical Structure Z_ringType := - Eval hnf in RingType Z Z_ringMixin. +HB.instance Definition _ := @GRing.Zmodule_isRing.Build Z _ _ ZmultA Zmult1q Zmultq1 Zmult_addl Zmult_addr nonzeroZ1. Lemma ZmultC : commutative Zmult. Proof. exact: Zmult_comm. Qed. -Canonical Structure Z_comRingType := ComRingType Z ZmultC. +HB.instance Definition _ := @GRing.Ring_hasCommutativeMul.Build Z ZmultC. (* Warning : an antisymmetric an a transitive predicates are present in loaded Relations.Relation_Definition *) @@ -202,12 +194,7 @@ Qed. Lemma Zinv_out : {in predC Zunit, Zinv =1 id}. Proof. exact. Qed. -Definition Z_comUnitRingMixin := ComUnitRingMixin ZmulV unitZPl Zinv_out. - -Canonical Structure Z_unitRingType := - Eval hnf in UnitRingType Z Z_comUnitRingMixin. - -Canonical Structure Z_comUnitRing := Eval hnf in [comUnitRingType of Z]. +HB.instance Definition _ := GRing.ComRing_hasMulInverse.Build Z ZmulV unitZPl Zinv_out. Lemma Z_idomain_axiom : forall x y : Z, x * y = 0 -> (x == 0) || (y == 0). @@ -216,7 +203,7 @@ move=> x y; rewrite -[x * y]/(Zmult x y); move/Zmult_integral; case=> -> //=. by rewrite eqxx orbT. Qed. -Canonical Structure Z_iDomain := Eval hnf in IdomainType Z Z_idomain_axiom. +HB.instance Definition _ := @GRing.ComUnitRing_isIntegral.Build Z Z_idomain_axiom. Lemma Zlt_def (x y : Z) : (x erefl) (fun _ _ => erefl) Zle_bool_antisymb Zle_bool_transb Zle_total. - -Canonical z_porderType := POrderType Z_display Z Z_OrderedRingMixin2. -Canonical z_latticeType := LatticeType Z Z_OrderedRingMixin2. -Canonical z_distrLatticeType := DistrLatticeType Z Z_OrderedRingMixin2. -Canonical z_orderType := OrderType Z Z_OrderedRingMixin2. +HB.instance Definition _ := + @Order.isOrder.Build Z_display Z _ _ _ _ Zlt_def (fun _ _ => erefl) (fun _ _ => erefl) Zle_bool_antisymb Zle_bool_transb Zle_total. (*Canonical Structure Z_OrderedRingType := Eval hnf in OIdomainType Z Z_OrderedRingMixin. diff --git a/theories/intersection.v b/theories/intersection.v index 7baa8d0..74335e7 100644 --- a/theories/intersection.v +++ b/theories/intersection.v @@ -56,7 +56,7 @@ Proof. by rewrite/intersect separateCr; congr andb; apply separateCl. Qed. Lemma intersect_correct a b c d : intersect a b c d -> exists p, between p a b && between p c d. Proof. -have sm t u : t *: (u : regular_lmodType R) = t * u by []. +have sm t u : t *: (u : R^o) = t * u by []. wlog abc0: a b c d / 0 <= det a b c. move=>h. case ge0: (0 <= det a b c); first by apply h. @@ -109,7 +109,7 @@ Qed. Lemma intersect_complete a b c d : (exists p, between p a b && between p c d) -> intersect a b c d. Proof. -have sm: forall t u, t *: (u : regular_lmodType R) = t*u by []. +have sm: forall t u, t *: (u : R^o) = t*u by []. move:a b c d. suff: forall a b c d, (exists p : counterclockwise.Plane R, between p a b && between p c d) -> separate a b c d. move=> h a b c d abcd; apply/andP; split; apply h=>//. @@ -232,8 +232,8 @@ wlog : a b t u lab t01 ltab u01 luab / (t == 0) && (u == 1). apply/negP => /intersect_correct[p]/andP[pl pab]. move: (lab i) => /negP; apply; apply intersect_complete. exists p; apply/andP; split=>//; refine (between_trans _ _ pab). - by apply between_conv; eexists; apply/andP; split => //. - by apply between_conv; eexists; apply/andP; split => //. + by apply between_conv; exists u; apply/andP; split => //. + by apply between_conv; exists t; apply/andP; split => //. - by apply in010. - by rewrite conv0. - by apply in011. @@ -299,7 +299,7 @@ have : [exists i : 'I_(size l), det l`_i l`_i.+1mod (b <| sup I |> a) <= 0]. have tfin : (fine (mine t 1%:E))%:E = mine t 1%:E. apply/(@fineK R)/fin_numP; split; apply/negP=>/eqP tinf. suff : (-oo < mine t 1)%E by rewrite tinf ltxx. - rewrite ltxI; apply/andP; split; last by apply ltNye. + rewrite ltxI; apply/andP; split; last by apply: ltNye. by apply ereal_meets_gt=>// i _; apply ltNye. suff : (mine t 1 < +oo)%E by rewrite tinf ltxx. by rewrite ltIx [(1 < +oo)%E]ltey orbT. @@ -307,7 +307,7 @@ have : [exists i : 'I_(size l), det l`_i l`_i.+1mod (b <| sup I |> a) <= 0]. have t01: in01 (fine (mine t 1%E)). apply/andP; split; rewrite -lee_fin tfin; last by rewrite lteIx le_refl orbT. rewrite ltexI; apply/andP; split; last by rewrite lee_fin ler01. - apply: meets_ge => i abgt; rewrite lee_fin; apply: (mulr_ge0 (la _)). + apply: Order.TLatticeTheory.meets_ge => i abgt; rewrite lee_fin; apply: (mulr_ge0 (la _)). by apply ltW; rewrite invr_gt0 -2![det l`_i _ _]det_cyclique. apply: sup_upper_bound => //; apply/andP; split => //. rewrite encompass_all_index l0/=; apply/forallP => i. @@ -318,7 +318,7 @@ have : [exists i : 'I_(size l), det l`_i l`_i.+1mod (b <| sup I |> a) <= 0]. rewrite -subr_ge0 -(pmulr_lge0 _ abgt0) mulrBl subr_ge0 -mulrA divff// mulr1. rewrite -lee_fin tfin leIx; apply/orP; left. rewrite ![det _ l`_i _]det_cyclique /t. - by move:abgt0; rewrite invr_gt0=>abgt; exact: meets_inf. + by move:abgt0; rewrite invr_gt0=>abgt; exact: Order.TLatticeTheory.meets_inf. rewrite {2}[det a _ _]det_cyclique (le_trans _ (la i))// mulr_ge0_le0 //. by move:t01 => /andP[]. move=> /existsP[i] iable0. diff --git a/theories/isolate.v b/theories/isolate.v index 362f268..2270bb4 100644 --- a/theories/isolate.v +++ b/theories/isolate.v @@ -1,5 +1,6 @@ +From HB Require Import structures. From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice fintype order. -From mathcomp Require Import div finfun bigop prime binomial ssralg finset fingroup finalg. +From mathcomp Require Import div finfun bigop prime binomial ssralg finset fingroup finalg archimedean. From mathcomp Require Import mxalgebra perm zmodp matrix ssrint. (*From mathcomp Require Import (*refinements NB(rei) funperm*).*) From mathcomp Require Import seq rat. @@ -147,7 +148,7 @@ Section count_root_correct. Variable R : archiFieldType. -Definition R' := RealAlg.alg_of_rcfType R. +(*TODO(rei, gave up when moving to MathComp 2): Definition R' : archiFieldType := (R : rcfType).*) (* Lemma count_root_correct0 n (l : seq rat) q d (a b: R') : @@ -168,9 +169,9 @@ have twon0 : (1 + 1 != 0 :> R'). have twoV : forall a, a = a/(1 + 1) + a/(1+1) :> R'. by move=> y; rewrite -mulrDl -(mulr1 y) -mulrDr mulrK // mulr1. have altm : a < (a + b)/(1 + 1). - by rewrite {1}[a]twoV mulrDl ltr_add2l ltr_pmul2r // invr_gt0. + by rewrite {1}[a]twoV mulrDl ltr_add2l ltr_pM2r // invr_gt0. have mltb : (a + b)/(1 + 1) < b. - by rewrite {2}[b]twoV mulrDl ltr_add2r ltr_pmul2r // invr_gt0. + by rewrite {2}[b]twoV mulrDl ltr_add2r ltr_pM2r // invr_gt0. have mna : (a + b)/(1 + 1) != a. by apply/negP => ma; move:altm; rewrite ltr_neqAle eq_sym ma. have mnb : (a + b)/(1 + 1) != b. @@ -318,13 +319,13 @@ case: (In d a ((a + b) / (1+1)) (dicho_l d l) (l1++acc)) => [l2 l2q]. by exists (l2++l1); rewrite l1q l2q -!catA. Qed.*) -Canonical root_info_eqMixin (R : eqType) := EqMixin (root_info_eqP R). +HB.instance Definition _ := hasDecEq.Build _ (root_info_eqP R). -Canonical root_info_eqType (R : eqType) := +(*Canonical root_info_eqType (R : eqType) := Eval hnf in EqType (root_info R) (root_info_eqMixin R). Arguments root_info_eqP {R x y}. -Prenex Implicits root_info_eqP. +Prenex Implicits root_info_eqP.*) (* NB(rei): typing issue with {realclosure _} @@ -353,11 +354,11 @@ have rbman0 : ratr b - ratr a != 0 :> RealAlg.alg_of_rcfType R. by rewrite subr_eq0 eq_sym. have twogt0 : 0 < 1 + 1 :> rat by apply: addr_gt0; rewrite ltr01 . have a1b1 : (a + b)/(1+1) < b :> rat. - rewrite -(ltr_pmul2r twogt0) mulfVK. + rewrite -(ltr_pM2r twogt0) mulfVK. by rewrite mulrDr mulr1 ltr_add2r. by move: twogt0; rewrite ltr_neqAle eq_sym=>/andP; case. have a2b2 : a < (a + b)/(1+1) :> rat. - rewrite -(ltr_pmul2r twogt0) mulfVK. + rewrite -(ltr_pM2r twogt0) mulfVK. by rewrite mulrDr mulr1 ltr_add2l. by move: twogt0; rewrite ltr_neqAle eq_sym=>/andP; case. have rmbd: (ratr a + ratr b)/(1+1) != ratr b :> RealAlg.alg_of_rcfType R. diff --git a/theories/math_comp_complements.v b/theories/math_comp_complements.v new file mode 100644 index 0000000..a65e6de --- /dev/null +++ b/theories/math_comp_complements.v @@ -0,0 +1,291 @@ +From mathcomp Require Import all_ssreflect all_algebra. +Require Export Field. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Require Import NArithRing. +Import Order.TTheory GRing.Theory Num.Theory Num.ExtraDef Num. + +Open Scope ring_scope. + +Fixpoint seq_subst {A : eqType}(l : seq A) (b c : A) : seq A := + match l with + | nil => nil + | a :: tl => + if a == b then (c :: seq_subst tl b c) else (a :: seq_subst tl b c) + end. + +Lemma mem_seq_subst {A : eqType} (l : seq A) b c x : + x \in (seq_subst l b c) -> (x \in l) || (x == c). +Proof. +elim: l => [// | a l Ih]. +rewrite /=. +by case: ifP => [] ?; rewrite !inE=> /orP[ | /Ih /orP[] ] ->; rewrite ?orbT. +Qed. + +Lemma seq_subst_eq0 {A : eqType} (l : seq A) b c : + (seq_subst l b c == [::]) = (l == [::]). +Proof. by case : l => [ | a l] //=; case: ifP. Qed. + +Lemma seq_subst_cat {A : eqType} (l1 l2 : seq A) b c : + seq_subst (l1 ++ l2) b c = seq_subst l1 b c ++ seq_subst l2 b c. +Proof. +elim: l1 => [ // | a l1 Ih] /=. +by case: ifP=> [ab | anb]; rewrite Ih. +Qed. + +Lemma last_in_not_nil (A : eqType) (e : A) (s : seq A) : +s != [::] -> last e s \in s. +Proof. +case : s => [//= | c q ] /= _. +by rewrite mem_last. +Qed. + +Lemma head_in_not_nil (A : eqType) (e : A) (s : seq A) : +s != [::] -> head e s \in s. +Proof. +case : s => [//= | c q ] /= _. +by rewrite inE eqxx. +Qed. + +Lemma middle_seq_not_nil (A : eqType) (a b c : seq A) : +b != [::] -> +a ++ b ++ c != [::]. +Proof. +rewrite -size_eq0 => /negP sizebneq0 /=. +apply /negP. +rewrite -size_eq0 !size_cat /= !addn_eq0 . +apply /negP /andP => [] /andP . +move => /andP [] _ /andP [] sizebeq0. +by rewrite sizebeq0 in sizebneq0. +Qed. + +Lemma rcons_neq0 (A : Type) (z : A) (s : seq A) : (rcons s z) <> nil. +Proof. +by case : s. +Qed. + +Lemma head_rcons (A : Type) (d l : A) (s : seq A) : + head d (rcons s l) = head l s. +Proof. by case: s. Qed. + +Lemma allcons [T : predArgType] + (f : T -> bool) a q' : all f (a :: q') = f a && all f q'. +Proof. by []. Qed. + +Definition cutlast (T : Type) (s : seq T) := +match s with | a :: s => belast a s | [::] => [::] end. + +Lemma last_seq2 (T : Type) (def a : T) (s : seq T) : + s <> nil -> last def (a :: s) = last def s. +Proof. +by case: s => [// | b s] _ /=. +Qed. + +Lemma behead_cutlasteq (T : Type) a (s : seq T) : + (1 < size s)%N -> s = head a s :: rcons (cutlast (behead s)) (last a s). +Proof. +by case: s => [ | b [ | c s]] //= _; congr (_ :: _); rewrite -lastI. +Qed. + +Lemma cutlast_subset (T : eqType) (s : seq T) : {subset cutlast s <= s}. +Proof. +rewrite /cutlast; case: s => [// | a s]. +elim: s a => [ // | b s Ih /=] a e; rewrite inE=> /orP[/eqP -> | ein]. + by rewrite inE eqxx. +by rewrite inE Ih ?orbT. +Qed. + +Lemma behead_subset (T : eqType) (s : seq T) : {subset behead s <= s}. +Proof. by case: s => [ | a s] // e /=; rewrite inE orbC => ->. Qed. + +Lemma sorted_catW (T : Type) (r : rel T) s s' : + (sorted r (s ++ s')) -> sorted r s && sorted r s'. +Proof. +case: s => [// | a s] /=. +by rewrite cat_path => /andP[] ->; apply: path_sorted. +Qed. + +Lemma sorted_rconsE (T : Type) (leT : rel T) s y: + transitive leT -> sorted leT (rcons s y) -> all (leT^~ y) s. +Proof. +move=> tr; elim: s=> [ | init s Ih] //=. +by rewrite (path_sortedE tr) all_rcons => /andP[] /andP[] -> _. +Qed. + +Lemma uniq_map_injective (T T' : eqType) (f : T -> T') (s : seq T) : + uniq [seq f x | x <- s] -> {in s &, injective f}. +Proof. +elim: s => [ // | a s Ih] /= /andP[fan uns]. +move=> e1 e2; rewrite !inE => /orP[/eqP -> | e1s ] /orP[/eqP -> | e2s] feq //. + by move: fan; rewrite feq; case/negP; apply/mapP; exists e2. + by move: fan; rewrite -feq; case/negP; apply/mapP; exists e1. +by apply: Ih. +Qed. + +Lemma mem_seq_split (T : eqType) (x : T) (s : seq T) : + x \in s -> exists s1 s2, s = s1 ++ x :: s2. +Proof. +by move=> /splitPr [s1 s2]; exists s1, s2. +Qed. + +Section transitivity_proof. + +Variables (T : eqType) (r : rel T) (s1 s2 : mem_pred T). + +Hypothesis s1tr : {in s1 & &, transitive r}. +Hypothesis s2tr : {in s2 & &, transitive r}. +Hypothesis s1s2 : {in s1 & s2, forall x y, r x y && ~~ r y x}. + +Lemma two_part_trans : {in predU s1 s2 & &, transitive r}. +Proof. +move=> x2 x1 x3 /orP[x2ins1 | x2ins2] /orP[x1ins1 | x1ins2] + /orP[x3ins1 | x3ins2]; + try solve[move=> ?; apply:s1tr=> // | + move=> ?; apply: s2tr => // | + move=> ? ?; apply: (proj1 (andP (s1s2 _ _))) => //]. +- by move=> r12 r23; move: (s1s2 x2ins1 x1ins2); rewrite r12 andbF. +- by move=> r12 r23; move: (s1s2 x2ins1 x1ins2); rewrite r12 andbF. +- by move=> r12 r23; move: (s1s2 x3ins1 x2ins2); rewrite r23 andbF. +- by move=> r12 r23; move: (s1s2 x3ins1 x2ins2); rewrite r23 andbF. +Qed. + +End transitivity_proof. + +Section abstract_subsets_and_partition. + +Variable cell : eqType. +Variable sub : cell -> cell -> Prop. +Variable exclude : cell -> cell -> Prop. + +Variable close : cell -> cell. + +Hypothesis excludeC : forall c1 c2, exclude c1 c2 -> exclude c2 c1. +Hypothesis exclude_sub : + forall c1 c2 c3, exclude c1 c2 -> sub c3 c1 -> exclude c3 c2. + +Lemma add_map (s1 : pred cell) (s2 : seq cell) : + all (predC s1) s2 -> + {in s2, forall c, sub (close c) c} -> + {in predU s1 (mem s2) &, forall c1 c2, c1 = c2 \/ exclude c1 c2} -> + {in predU s1 (mem [seq close c | c <- s2]) &, + forall c1 c2, c1 = c2 \/ exclude c1 c2}. +Proof. +have symcase : forall (s : pred cell) (s' : seq cell), + all (predC s) s' -> + {in s', forall c, sub (close c) c} -> + {in predU s (mem s') &, forall c1 c2, c1 = c2 \/ exclude c1 c2} -> + forall c1 c2, s c1 -> c2 \in s' -> exclude c1 (close c2). + move=> s s' dif clsub exc c1 c2 sc1 c2s'. + apply/excludeC/(exclude_sub _ (clsub _ _)); last by []. + have := exc c2 c1; rewrite 2!inE c2s' orbT inE sc1 => /(_ isT isT). + by move=> -[abs | //]; have := allP dif _ c2s'; rewrite inE abs sc1. +move=> s1nots2 clsub oldx g1 g2. +rewrite inE => /orP[g1old | /mapP[co1 co1in g1c]]; + rewrite inE => /orP[g2old |/mapP[co2 co2in g2c ]]. +- by apply: oldx; rewrite inE ?g1old ?g2old. +- by right; rewrite g2c; apply: (symcase _ _ s1nots2 clsub oldx). +- by right; rewrite g1c; apply excludeC; apply: (symcase _ _ s1nots2 clsub oldx). +have [/eqP co1co2 | co1nco2] := boolP(co1 == co2). + by left; rewrite g1c g2c co1co2. +right; rewrite g1c; apply/(exclude_sub _ (clsub _ _)); last by []. +rewrite g2c; apply/excludeC/(exclude_sub _ (clsub _ _)); last by []. +have := oldx co2 co1; rewrite !inE co2in co1in !orbT=> /(_ isT isT). +by case=> [abs | //]; case/negP: co1nco2; rewrite abs eqxx. +Qed. + +Lemma add_new (s s2 : pred cell) : + {in s &, forall c1 c2, c1 = c2 \/ exclude c1 c2} -> + {in s & s2, forall c1 c2, exclude c1 c2} -> + {in s2 &, forall c1 c2, c1 = c2 \/ exclude c1 c2} -> + {in predU s s2 &, forall c1 c2, c1 = c2 \/ exclude c1 c2}. +Proof. +move=> oldx bipart newx c1 c2. +rewrite inE=> /orP[c1old | c1new] /orP[c2old | c2new]. +- by apply: oldx. +- by right; apply: bipart. +- by right; apply/excludeC/bipart. +by apply: newx. +Qed. + +End abstract_subsets_and_partition. + +Section subset_tactic. + +Lemma all_sub [T : eqType] [p : pred T] [s1 s2 : seq T] : + {subset s1 <= s2} -> all p s2 -> all p s1. +Proof. by move=> subs as2; apply/allP=> x xin; apply/(allP as2)/subs. Qed. + +Lemma subset_consl [T : eqType] (x : T) (s s': seq T) : + x \in s' -> {subset s <= s'} -> {subset (x :: s) <= s'}. +Proof. +by move=> xin ssub g; rewrite inE=> /orP[/eqP -> // | ]; apply: ssub. +Qed. + +Lemma subset_catl [T : eqType] (s1 s2 s' : seq T) : + {subset s1 <= s'} -> {subset s2 <= s'} -> {subset s1 ++ s2 <= s'}. +Proof. +move=> s1sub s2sub g; rewrite mem_cat=>/orP[];[apply: s1sub | apply s2sub]. +Qed. + +Lemma subset_catrl [T : eqType] [s s1 s2 : seq T] : + {subset s <= s1} -> {subset s <= s1 ++ s2}. +Proof. by move=> ssub g gn; rewrite mem_cat ssub. Qed. + +Lemma subset_catrr [T : eqType] [s s1 s2 : seq T] : + {subset s <= s2} -> {subset s <= s1 ++ s2}. +Proof. by move=> ssub g gn; rewrite mem_cat ssub ?orbT. Qed. + +Lemma subset_id [T : eqType] [s : seq T] : {subset s <= s}. +Proof. by move=> x. Qed. + +Lemma subset_head [T : eqType] [s1 s2 : seq T] [x : T] : + {subset (x :: s1) <= s2} -> head x s1 \in s2. +Proof. +by move=> Sub; apply: Sub; case: s1=> [ | a ?] /=; rewrite !inE eqxx ?orbT. +Qed. + +End subset_tactic. + +Ltac subset_tac := + trivial; + match goal with + | |- {subset ?x <= ?x} => apply: subset_id + | |- {subset (_ :: _) <= _} => apply: subset_consl; subset_tac + | |- {subset (_ ++ _) <= _} => apply: subset_catl; subset_tac + | |- {subset _ <= _ ++ _} => + solve[(apply: subset_catrl; subset_tac)] || + (apply: subset_catrr; subset_tac) + | |- {subset _ <= _} => + let g := fresh "g" in let gin := fresh "gin" in + move=> g gin; rewrite !(mem_cat, inE, cat_rcons); + rewrite ?eqxx ?gin ?orbT //; subset_tac + | |- is_true (?x \in (?x :: _)) => rewrite inE eqxx; done + | |- is_true (head _ (rcons _ _) \in _) => rewrite head_rcons; subset_tac + | |- is_true (head _ _ \in _) => apply: subset_head; subset_tac + | |- is_true (_ \in (_ :: _)) => rewrite inE; apply/orP; right; subset_tac + | |- is_true (_ \in (_ ++ _)) => rewrite mem_cat; apply/orP; + (solve [left; subset_tac] || (right; subset_tac)) + end. + +Section mapi. + +(* TODO: This might be useful one day, because it is used intensively in the + trajectory computation, but not so much in cell decomposition. *) +Definition mapi [T U : Type] (f : T -> Datatypes.nat -> U) (s : seq T) := + map (fun p => f p.1 p.2) (zip s (iota 0 (size s))). + +Lemma nth_mapi [T U : Type] (f : T -> Datatypes.nat -> U) (s : seq T) n d d' : + (n < size s)%N -> + nth d' (mapi f s) n = f (nth d s n) n. +Proof. +rewrite /mapi. +rewrite -[X in f _ X]addn0. +elim: s n 0%N => [ | el s Ih] [ | n] m //=. + rewrite ltnS=> nlt. +by rewrite addSn -addnS; apply: Ih. +Qed. + +End mapi. diff --git a/theories/no_crossing.v b/theories/no_crossing.v index 0d81e85..5e71a20 100644 --- a/theories/no_crossing.v +++ b/theories/no_crossing.v @@ -104,7 +104,7 @@ Definition have_crossing (e1 e2 : edge) : bool := else (* The two edges are parallel. They may still touch. *) if negb (Qeq_bool - (area3 (left_pt e1) (left_pt e2) (right_pt e2)) 0) then + (area3 _ Qplus Qminus Qmult (left_pt e1) (left_pt e2) (right_pt e2)) 0) then true else (Qlt_bool (p_x (left_pt e2)) (p_x (left_pt e1)) && @@ -256,8 +256,10 @@ Lemma cnt14 : Proof. easy. Qed. Import String. +(* Compute example_test (List.concat (List.map outgoing evs14)) (Bpt 1.2 (-0.8)) (Bpt (-1) (0.4)) nil. +*) Compute (concat " " (postscript_header ++ display_edge 300 400 70 example_bottom :: diff --git a/theories/opening_cells.v b/theories/opening_cells.v new file mode 100644 index 0000000..9a70026 --- /dev/null +++ b/theories/opening_cells.v @@ -0,0 +1,1430 @@ +From mathcomp Require Import all_ssreflect all_algebra. +Require Export Field. +Require Import math_comp_complements + generic_trajectories points_and_edges events cells. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Require Import NArithRing. +Import Order.TTheory GRing.Theory Num.Theory Num.ExtraDef Num. + +Open Scope ring_scope. + +Section working_environment. + +Variable R : realFieldType. + +Notation pt := (pt R). +Notation p_x := (p_x R). +Notation p_y := (p_y R). +Notation Bpt := (Bpt R). +Notation edge := (edge R). +Notation event := (event R edge). +Notation point := (point R edge). +Notation outgoing := (outgoing R edge). + +Notation cell := (cell R edge). +Notation low := (low R edge). +Notation high := (high R edge). +Notation left_pts := (left_pts R edge). +Notation right_pts := (right_pts R edge). + +Notation dummy_pt := (dummy_pt R 1). +Notation dummy_edge := (dummy_edge R). +Notation dummy_cell := (dummy_cell R 1 edge (@unsafe_Bedge R)). + +(* +Fixpoint opening_cells_aux (p : pt) (out : seq edge) (low_e high_e : edge) + : seq cell * cell := + match out with + | [::] => + let op0 := vertical_intersection_point p low_e in + let op1 := vertical_intersection_point p high_e in + match (op0,op1) with + |(None,_) |(_,None)=> ([::], dummy_cell) + |(Some(p0),Some(p1)) => + ([::] , Bcell (no_dup_seq ([:: p1; p; p0])) [::] low_e high_e) + end + | c::q => + let op0 := vertical_intersection_point p low_e in + let (s, nc) := opening_cells_aux p q c high_e in + match op0 with + | None => ([::], dummy_cell) + | Some(p0) => + (Bcell (no_dup_seq([:: p; p0])) [::] low_e c :: s, nc) + end +end. +*) + +Definition opening_cells_aux := + opening_cells_aux R eq_op le +%R (fun x y => x - y) *%R (fun x y => x / y) + 1 edge (@unsafe_Bedge R) (@left_pt R) (@right_pt R). + +Lemma opening_cells_aux_eqn p out low_e high_e : + opening_cells_aux p out low_e high_e = + match out with + | [::] => + let op0 := vertical_intersection_point p low_e in + let op1 := vertical_intersection_point p high_e in + match (op0,op1) with + |(None,_) |(_,None)=> ([::], dummy_cell) + |(Some(p0),Some(p1)) => + ([::] , Bcell _ _ (no_dup_seq ([:: p1; p; p0])) [::] low_e high_e) + end + | c::q => + let op0 := vertical_intersection_point p low_e in + let (s, nc) := opening_cells_aux p q c high_e in + match op0 with + | None => ([::], dummy_cell) + | Some(p0) => + (Bcell _ _ (no_dup_seq([:: p; p0] : seq pt)) [::] low_e c :: s, nc) + end +end. +Proof. by case: out. Qed. + +Definition opening_cells (p : pt) (out : seq edge) (l h : edge) : seq cell := + let (s, c) := opening_cells_aux p (sort (@edge_below R) out) l h in + rcons s c. + +Section proof_environment. +Variables bottom top : edge. + +Notation extra_bot := (extra_bot bottom). +Notation close_alive_edges := (close_alive_edges bottom top). +Notation cells_bottom_top := (cells_bottom_top bottom top). +Notation inside_box := (inside_box bottom top). +Notation open_cell_side_limit_ok := (@open_cell_side_limit_ok R). +Notation seq_low_high_shift := (@seq_low_high_shift R). +Notation cover_left_of := (@cover_left_of _ bottom top). + +Section opening_cells. + +Lemma opening_cells_left p out le he : + {in out, forall g, left_pt g == p} -> + valid_edge le p -> + valid_edge he p -> + {in opening_cells p out le he, forall c, left_limit c = p_x p}. +Proof. +move=> outl vle vhe; rewrite /opening_cells. +rewrite /opening_cells_aux. +have : forall g, g \in sort (@edge_below _) out -> left_pt g == p. + by move=> g; rewrite mem_sort; apply: outl. +elim: (sort _ _) le vle => [ | g1 gs Ih] le vle {}outl c /=. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite /= pvertE // pvertE //=. + by case: ifP=> _; case: ifP=> _; rewrite inE /left_limit => /eqP ->. +have outl' : forall g, g \in gs -> left_pt g == p. + by move=> g gin; apply outl; rewrite inE gin orbT. +rewrite /=. +have vg1 : valid_edge g1 p. + by rewrite -(eqP (outl g1 _)) ?valid_edge_left // inE eqxx. +move: Ih; case oca_eq : (generic_trajectories.opening_cells_aux _ _ _ _) => [s c'] /(_ _ vg1 outl'). +rewrite oca_eq => Ih. +rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). +rewrite pvertE //=. +rewrite inE => /orP[/eqP -> | ]; first by rewrite /left_limit; case : ifP. +by apply: Ih. +Qed. + +Lemma opening_cells_low_diff_high p out le he : + {in out, forall g, left_pt g == p} -> + uniq out -> + valid_edge le p -> + valid_edge he p -> + p >>> le -> + p <<< he -> + {in opening_cells p out le he, forall g, low g != high g}. +Proof. +move=> outl u vle vhe pal puh; rewrite /opening_cells. +have {outl} : {in sort (@edge_below _) out, forall g, left_pt g == p}. + by move=> g; rewrite mem_sort; apply: outl. +have {u} : uniq (sort (@edge_below _) out) by rewrite sort_uniq. +move=> u outl. +have : le != head he (sort (@edge_below _) out). + case: (sort _ _) outl => [ | g1 gs] /=. + move=> _; apply/eqP=> abs; move: puh; rewrite -abs strict_nonAunder// andbC. + by rewrite (negbTE pal). + move=> /(_ g1 (mem_head _ _)) /eqP lg1q; apply/eqP=> abs. + by move: pal; rewrite abs under_onVstrict -lg1q ?valid_edge_left ?left_on_edge. +elim: (sort _ _) le vle {pal} u outl => [ | g1 gs Ih] le /= vle + + ledif. + rewrite /= => _ _. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite (pvertE vle) (pvertE vhe). + by case: ifP=> _; case: ifP=> _ /= g; rewrite inE=> /eqP -> /=. +move=> /andP[] gnin u outl. +have /eqP lg1q : left_pt g1 == p by apply: outl; rewrite inE eqxx. +have {}outl : {in gs, forall g, left_pt g == p}. + by move=> g gin; apply: outl; rewrite inE gin ?orbT. +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). +rewrite (pvertE vle). +have vg1 : valid_edge g1 p by rewrite -lg1q valid_edge_left. +have g1nhe : g1 != he. + apply/eqP=> abs. + by move: puh; rewrite -abs strict_nonAunder // -lg1q ?left_on_edge. +have g1dif : g1 != head he gs. + apply/eqP=> abs; move: gnin. + have : head he gs \in he :: gs. + by case: (gs) => [ | ? ?]; rewrite /= !inE !eqxx ?orbT. + rewrite -abs inE=> /orP[/eqP {}abs _ | ->]; last by []. + by rewrite abs eqxx in g1nhe. +have := Ih g1 vg1 u outl g1dif; rewrite oca_eq=> {}Ih. +move=> g; rewrite /= inE=> /orP [/eqP -> /= | ]; first by []. +apply: Ih. +Qed. + +Lemma opening_cells_seq_edge_shift p s c oe le he : + {in oe, forall g, left_pt g == p} -> + valid_edge le p -> valid_edge he p -> + opening_cells_aux p oe le he = (s, c) -> + le :: [seq high i | i <- rcons s c] = + rcons [seq low i | i <- rcons s c] he. +Proof. +move=> + + vh. +elim: oe le s c => [ | g1 oe Ih] le s c leftg vl /=. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + by rewrite pvertE // pvertE // => -[] <- <- /=. +have vg1 : valid_edge g1 p. + by rewrite -(eqP (leftg g1 _)) ?valid_edge_left // inE eqxx. +have leftg' : {in oe, forall g, left_pt g == p}. + by move=> g gin; apply: leftg; rewrite inE gin orbT. +have := Ih _ _ _ leftg' vg1; case: (opening_cells_aux _ _ _ _)=> [s' c']. +move=> /(_ s' c' erefl) {}Ih. +rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). +by rewrite pvertE // => - [] <- <- /=; congr (_ :: _). +Qed. + +Lemma opening_cells_aux_subset c' s' c p s le he: + valid_edge le p -> valid_edge he p -> + {in s, forall g, left_pt g == p} -> + opening_cells_aux p s le he = (s', c') -> + c \in rcons s' c' -> + (low c \in le :: s) && (high c \in he :: s). +Proof. +move=> + vhe. +elim: s c' s' le => [ | g1 s Ih] c' s' le /= vle lsp. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite pvertE // pvertE // => - [] <- <-. + by do 2 (case: ifP=> _); rewrite /= inE=> /eqP -> /=; rewrite !inE !eqxx. +have vg1 : valid_edge g1 p. + by rewrite -(eqP (lsp g1 _)) ?valid_edge_left // inE eqxx. +have lsp' : {in s, forall g, left_pt g == p}. + by move=> g gin; rewrite lsp // inE gin orbT. +have := Ih _ _ _ vg1 lsp'; case: (opening_cells_aux _ _ _ _)=> [s1 c1]. +move=> /(_ _ _ erefl) {} Ih. +rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). +rewrite pvertE // => - [] <- <- /=; rewrite inE=> /orP[/eqP -> /= | ]. + by rewrite !inE ?eqxx ?orbT. +rewrite inE; move=>/Ih/andP[] ->; rewrite orbT andTb. +by rewrite !inE orbCA => ->; rewrite orbT. +Qed. + + +(*TODO : check all uses of opening_cells_aux_subset for potential uses + of this simpler lemma. *) +Lemma opening_cells_subset c p s le he : + valid_edge le p -> valid_edge he p -> + {in s, forall g, left_pt g == p} -> + c \in opening_cells p s le he -> + (low c \in le :: s) && (high c \in he :: s). +Proof. +move=> vle vhe lsp. +rewrite /opening_cells. +case oca_eq : (opening_cells_aux _ _ _ _) => [so co] cin. +have lsp' : {in sort (@edge_below _) s, forall g, left_pt g == p}. + by move=> g; rewrite mem_sort; apply: lsp. +have := opening_cells_aux_subset vle vhe lsp' oca_eq cin. +by rewrite !inE !mem_sort. +Qed. + +(* +Lemma opening_cells_aux_nnil p s le he : + valid_edge le p -> valid_edge he p -> + {in s, forall g, left_pt g == p} -> + opening_cells_aux p s le he != nil. +Proof. +by move=> + vhe; case: s => [ | g1 s] vle lsp; rewrite /= pvertE // ?pvertE. +Qed. +*) + +Lemma opening_cells_aux_high p s le he : + valid_edge le p -> valid_edge he p -> + {in s, forall g, left_pt g == p} -> + [seq high i | i <- (opening_cells_aux p s le he).1] = s. +Proof. +move=> vle vhe lsp. +elim: s le vle lsp => [ | g1 s Ih] le vle lsp. + rewrite /= -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + by rewrite /= pvertE // pvertE. +have vg1 : valid_edge g1 p. + by rewrite -(eqP (lsp g1 _)) ?valid_edge_left // inE eqxx. +have lsp' : {in s, forall g, left_pt g == p}. + by move=> g gin; apply: lsp; rewrite inE gin orbT. +rewrite /= -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). +rewrite pvertE //. +by have := Ih _ vg1 lsp'; case: (opening_cells_aux _ _ _ _) => [s' c'] /= ->. +Qed. + +Lemma opening_cells_aux_high_last p s le he : + valid_edge le p -> valid_edge he p -> + {in s, forall g, left_pt g == p} -> + high (opening_cells_aux p s le he ).2 = he. +Proof. +move=> + vhe; elim: s le => [ /= | g1 s Ih] le vle lsp. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + by rewrite pvertE // pvertE. +have vg1 : valid_edge g1 p. + by rewrite -(eqP (lsp g1 _)) ?valid_edge_left // inE eqxx. +have lsp' : {in s, forall g, left_pt g == p}. + by move=> g gin; apply: lsp; rewrite inE gin orbT. +have := Ih _ vg1 lsp'. +rewrite /= -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). +rewrite pvertE //. +by case : (opening_cells_aux _ _ _ _) => [s' c']. +Qed. + +Lemma opening_cells_high p s le he : + valid_edge le p -> valid_edge he p -> + {in s, forall g, left_pt g == p} -> + [seq high i | i <- opening_cells p s le he] = + rcons (sort (@edge_below R) s) he. +Proof. +move=> vle vhe lsp; rewrite /opening_cells. +have lsp' : + {in sort (@edge_below _) s, forall g, left_pt g == p}. + move=> g; rewrite mem_sort; apply: lsp. +move: (lsp') => /opening_cells_aux_high => /(_ _ _ vle vhe). +move: lsp' => /opening_cells_aux_high_last => /(_ _ _ vle vhe). +case: (opening_cells_aux _ _ _ _) => [s' c'] /=. +by rewrite map_rcons => -> ->. +Qed. + +Lemma opening_cells_aux_right_form (ctxt s : seq edge) (p : pt) le he + s' c' : +p >>= le -> p <<< he -> valid_edge le p -> valid_edge he p -> +le \in ctxt -> he \in ctxt -> +le <| he -> {in s, forall g, left_pt g == p} -> +{in ctxt &, (@no_crossing R)} -> +{subset s <= ctxt} -> +path (@edge_below R) le s -> +opening_cells_aux p s le he = (s', c') -> +s_right_form (rcons s' c'). +Proof. +move=> + ph + vh + hin + + noc + +. +elim: s le s' c' => [ | g1 edges IH] le s' c' + pabove vle lin lowhigh outs allin sorted_e /=. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + by rewrite pvertE // pvertE // => -[] <- <- /=; rewrite andbT. +rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). +rewrite pvertE //. +have outs' : {in edges, forall g, left_pt g == p}. + by move=> g gin; apply outs; rewrite inE gin orbT. +have allin' : {subset edges <= ctxt}. + by move=> g gin; rewrite allin // inE gin orbT. +have sorted_e' : path (@edge_below R) g1 edges. + by apply: (path_sorted sorted_e). +have /eqP gl : left_pt g1 == p by rewrite outs // inE eqxx. +have g1belowhigh : g1 <| he. + have gin' : g1 \in ctxt by rewrite allin // inE eqxx. + have/no_crossingE := noc g1 he gin' hin. + by rewrite gl=>/(_ vh)=> -[]/(_ ph). +have pong : p === g1 by rewrite -gl left_on_edge. +have paboveg1 : p >>= g1 + by rewrite strict_nonAunder ?pong //; case/andP: pong. +move: (sorted_e) => /=/andP[] leg1 _. +have g1in : g1 \in ctxt by rewrite allin // inE eqxx. +have vg1 : valid_edge g1 p. + by rewrite -(eqP (outs g1 _)) ?valid_edge_left // inE eqxx. +have := IH g1 _ _ paboveg1 vg1 g1in g1belowhigh outs' allin' sorted_e'. +case: (opening_cells_aux _ _ _ _) => [s1 c1] - /(_ _ _ erefl) {} IH /=. +by move=> [] <- <- /=; rewrite leg1. +Qed. + +Lemma opening_cells_right_form p s low_e high_e : +valid_edge low_e p -> +valid_edge high_e p -> +p >>= low_e -> p <<< high_e -> +low_e <| high_e -> +{in s, forall g, left_pt g == p} -> +{in s, forall g, low_e <| g} -> +{in s, forall g, g <| high_e} -> +{in s &, (@no_crossing R)} -> +s_right_form (opening_cells p s low_e high_e). +Proof. +move=> vl vh pabove punder lowhigh outs alla allb noc; apply/allP. +have noc' : {in low_e :: high_e :: s &, (@no_crossing R)}. + move=> e1 e2; rewrite !inE !orbA =>/orP[e1lh |e1in ]/orP[e2lh |e2in]. + by apply/orP;move:e1lh e2lh=> /orP[]/eqP -> /orP[]/eqP ->; + rewrite ?edge_below_refl ?lowhigh ?orbT. + - by move: e1lh=> /orP[]/eqP ->;apply/orP; + rewrite/below_alt ?alla ?allb ?orbT. + - by move: e2lh=> /orP[]/eqP ->; apply/orP; + rewrite/below_alt ?alla ?allb ?orbT. + by apply: noc. +have sorted_e : sorted (@edge_below R) (sort (@edge_below R) s). + by apply: sort_edge_below_sorted. +have /sub_in1/= trsf : {subset sort (@edge_below R) s <= s}. + by move=> x; rewrite mem_sort. +move/trsf:outs => {}outs. +have [lin hin] : (low_e \in [:: low_e, high_e & s]) /\ + (high_e \in [:: low_e, high_e & s]). + by split; rewrite !inE eqxx ?orbT. +have slho : {subset (sort (@edge_below _) s) <= + [:: low_e, high_e & s]}. + by move=> x; rewrite mem_sort => xin; rewrite !inE xin ?orbT. +move=> x xin. +have srt : sorted (@edge_below R) (low_e :: sort (@edge_below R) s). + case sq : (sort (@edge_below R) s) => [// | a tl]. + rewrite -[sorted _ _]/((low_e <| a) && sorted (@edge_below R) (a :: tl)). + rewrite -sq sorted_e andbT alla //. + by rewrite -(mem_sort (@edge_below _)) sq inE eqxx. +have := (opening_cells_aux_right_form _ _ _ _ lin hin lowhigh outs). +move: xin; rewrite /opening_cells. +case: (opening_cells_aux _ _ _ _) => [s1 c1] xin - /(_ s1 c1). +move=> /(_ _ _ _ _ _ _ _ erefl) => it. +by apply: (allP (it _ _ _ _ _ _ _) x xin). +Qed. + +Lemma lower_edge_new_cells e low_e high_e: +forall new_open_cells, +valid_edge low_e (point e) -> +valid_edge high_e (point e) -> +opening_cells (point e) (outgoing e) low_e high_e = new_open_cells -> +low (head dummy_cell new_open_cells) = low_e. +Proof. +move=> vle vhe. +rewrite /opening_cells. +case : (sort (@edge_below R) (outgoing e)) => [/= |/= c q] newop. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + by rewrite pvertE // pvertE //= => <- /=. +rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). +rewrite pvertE //. +by case: (opening_cells_aux _ _ _ _) => [s1 c1] /= => <- /=. +Qed. + +Lemma opening_cells_not_nil out le he p : + opening_cells p out le he != [::]. +Proof. +rewrite /opening_cells; case: (opening_cells_aux _ _ _ _) => [s1 c1]. +apply/eqP/rcons_neq0. +Qed. + +Lemma higher_edge_new_cells e low_e high_e: +out_left_event e -> +valid_edge low_e (point e) -> valid_edge high_e (point e) -> +forall new_open_cells, +opening_cells (point e) (outgoing e) low_e high_e = + new_open_cells -> +high (last dummy_cell new_open_cells) = high_e. +Proof. +rewrite /opening_cells. +move=> /outleft_event_sort outl vle vhe. +have := opening_cells_aux_high_last vle vhe outl. +case : (opening_cells_aux _ _ _ _) => [s1 c1] <- ? <-. +by rewrite last_rcons. +Qed. + +Lemma opening_cells_close event low_e high_e future : +valid_edge low_e (point event) -> +valid_edge high_e (point event) -> +out_left_event event -> +end_edge_ext bottom top low_e future -> +end_edge_ext bottom top high_e future -> +close_out_from_event event future -> +close_alive_edges (opening_cells (point event) (outgoing event) low_e high_e) + future. +Proof. +rewrite /opening_cells. +move=> vle vhe oute A B /close_out_from_event_sort; move: A B. +have : {in sort (@edge_below _) (outgoing event), + forall g, left_pt g == (point event)}. + by move=> g; rewrite mem_sort; apply: oute. +move : low_e vle. +elim : (sort (@edge_below R) (outgoing event)) => [| g1 q Ih] /= + le vle oute' endl endh. + move=> _. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + by rewrite pvertE // pvertE //= endl endh. +move => /andP[] endg1 allend. +have oute1 : {in q, forall g, left_pt g == point event}. + by move=> g gin; apply oute'; rewrite inE gin orbT. +have vg1 : valid_edge g1 (point event). + by rewrite -(eqP (oute' g1 _)) ?valid_edge_left // inE eqxx. +have:= Ih g1 vg1 oute1 (end_edgeW _ _ endg1) endh allend. +case : (opening_cells_aux _ _ _ _) => [s1 c1] => {}Ih. +rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). +by rewrite pvertE //= endl (end_edgeW _ _ endg1) Ih. +Qed. + +Lemma opening_valid e low_e high_e: +out_left_event e -> +valid_edge low_e (point e) -> +valid_edge high_e (point e) -> +seq_valid (opening_cells (point e) (outgoing e) low_e high_e) (point e). +Proof. +move=> + + vhe. +rewrite /opening_cells. +move/outleft_event_sort. +move : low_e. +elim : (sort (@edge_below R) (outgoing e)) => [/= | c q IH] low_e outl vle. + rewrite /=. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + by rewrite pvertE // pvertE //= vle vhe. +rewrite /=. +rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). +rewrite pvertE //. +have vc : valid_edge c (point e). + by rewrite -(eqP (outl c _)) ?valid_edge_left // inE eqxx. +have outl1 : forall g, g \in q -> left_pt g == point e. + by move=> g gin; rewrite outl // inE gin orbT. +have := IH c outl1 vc. +case: (opening_cells_aux _ _ _ _) => [s1 c1] {} Ih /=. +by rewrite vle vc Ih. +Qed. + +Lemma adjacent_opening_aux p s le he news newc : + valid_edge le p -> valid_edge he p -> + {in s, forall g, left_pt g == p} -> + opening_cells_aux p s le he = (news, newc) -> + adjacent_cells (rcons news newc) /\ + (low (head dummy_cell (rcons news newc)) = le). +Proof. +move=> + vhe. +elim: s le news newc => [ | g s Ih] le news newc /= vle oute. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + by rewrite pvertE // pvertE // => - [] <- <- /=. +have vg : valid_edge g p. + by rewrite -(eqP (oute g _)) ?valid_edge_left // inE eqxx. +have oute' : {in s, forall g, left_pt g == p}. + by move=> g' gin; rewrite oute // inE gin orbT. +case oca_eq: (opening_cells_aux _ _ _ _) => [s1 c1]. +have := Ih g s1 c1 vg oute' oca_eq => -[] Ih1 Ih2 {Ih}. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite pvertE // => - [] <- <- /=; split;[ | done]. +case: (s1) Ih1 Ih2 => [ | a s'] /=. + by move=> _ ->; rewrite eqxx. +by move=> -> ->; rewrite eqxx. +Qed. + +Lemma adjacent_opening p s le he: + valid_edge le p -> valid_edge he p -> + {in s, forall g, left_pt g == p} -> + adjacent_cells (opening_cells p s le he). +Proof. +move=> vle vhe lefts. +have lefts' : {in sort (@edge_below _) s, forall g, left_pt g == p}. + by move=> g; rewrite mem_sort; apply: lefts. +rewrite /opening_cells; case oca_eq: (opening_cells_aux _ _ _ _) => [so co]. +by have [] := adjacent_opening_aux vle vhe lefts' oca_eq. +Qed. + +Lemma opening_cells_last_lexePt e low_e high_e c : +out_left_event e -> +~~(point e <<< low_e) -> point e <<< high_e -> +valid_edge low_e (point e)-> valid_edge high_e (point e) -> +{in (rcons (low_e::(sort (@edge_below R) (outgoing e))) high_e) &, no_crossing R} -> +low_e <| high_e -> + c \in (opening_cells (point e) (outgoing e) low_e high_e) -> + lexePt (last dummy_pt (left_pts c)) (point e). +Proof. +rewrite /opening_cells. +move => /outleft_event_sort outlefte eabl eunh lowv highv. +elim : (sort (@edge_below R) (outgoing e)) low_e eabl lowv outlefte => [/= | c' q IH] low_e eabl lowv outlefte nc linfh. + have := pvertE highv; set high_p := Bpt _ _ => hp. + have := pvertE lowv; set low_p := Bpt _ _ => lp. + have := intersection_on_edge lp=> [][] poel lx_eq. + have := intersection_on_edge hp=> [][] poeh hx_eq. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite lp hp. + rewrite lx_eq in hx_eq. + have y_ineq := order_below_viz_vertical lowv highv lp hp linfh. + rewrite inE => /eqP ->. + case: ifP. + rewrite -[pt_eqb R eq_op high_p (point e)]/(high_p == (point e) :> pt). + move=> /eqP <-. + rewrite -[pt_eqb R eq_op high_p low_p]/(high_p == low_p :> pt). + case : ifP => [/eqP <-/=|/= _]. + by rewrite /lexePt eqxx le_refl orbT . + by rewrite /lexePt hx_eq eqxx y_ineq /= orbT. + rewrite /lexePt. + rewrite -[pt_eqb _ _ _ _]/(high_p == point e :> pt). + rewrite -[pt_eqb _ _ _ _]/(point e == low_p :> pt). + case : ifP => [/eqP <-/=|/=_ ]. + by rewrite eqxx le_refl /= orbT. + rewrite lx_eq eqxx. + have -> : p_y low_p <= p_y (point e). + by rewrite leNgt -(strict_under_edge_lower_y lx_eq poel). + by rewrite orbT. +rewrite /= . +have cin : c' \in c' :: q. + by rewrite inE eqxx. +have c'v: (valid_edge c' (point e)). + apply valid_edge_extremities. + by rewrite outlefte // cin. +have einfc' : ~~ (point e <<< c'). + apply : onAbove. + have := outlefte c' cin => /eqP <-. + apply : left_on_edge. +have outq: (forall e0 : edge, e0 \in q -> left_pt e0 == point e). + move => e0 ein. + apply outlefte. + by rewrite inE ein orbT. +have c'infh : c' <| high_e. + have := nc high_e c'. + rewrite /= !inE !mem_rcons !inE !eqxx !orbT /= => /(_ isT isT). + move=> /below_altC/no_crossingE. + have := outlefte c' cin => /eqP ->. + rewrite highv eunh => [] /(_ isT) [a _]. + by apply: a. +have nc' : {in (rcons (c'::q) high_e) &, no_crossing R}. + move => e1 e2 e1in e2in. + apply nc. + by rewrite inE e1in orbT. + by rewrite inE e2in orbT. +rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). +have := pvertE lowv; set low_p := Bpt _ _ => lp. +rewrite lp. +have := intersection_on_edge lp=> [][] poel lx_eq. +case oca_eq : (opening_cells_aux _ _ _ _) => [so co]. +rewrite -[pt_eqb _ _ (point e) low_p]/(point e == low_p :> pt). +case : ifP=> [/eqP <-/=|/= _]. + rewrite inE => /orP [/eqP -> /=|]. + by rewrite lexePt_refl. + have := IH c' einfc' c'v outq nc' c'infh. + by rewrite oca_eq. +rewrite inE => /orP [/eqP -> /=|]. + have : p_y low_p <= p_y (point e). + by rewrite leNgt -(strict_under_edge_lower_y lx_eq poel). + rewrite /lexePt lx_eq eqxx=> ->. + by rewrite orbT. +have := IH c' einfc' c'v outq nc' c'infh. +by rewrite oca_eq. +Qed. + +Arguments pt_eqb : simpl never. + +Lemma opening_cells_aux_side_limit e s le he s' c': + valid_edge le e -> valid_edge he e -> + e >>= le -> e <<< he -> + {in s, forall g, left_pt g == e} -> + opening_cells_aux e s le he = (s', c') -> + all open_cell_side_limit_ok (rcons s' c'). +Proof. +move=> + vh. +elim : s le s' c'=> [ | g s Ih] le s' c' /= vl above under lg. + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + rewrite -[generic_trajectories.vertical_intersection_point + _ _ _ _ _ _ _ _ _ _ _]/(vertical_intersection_point _ _). + have := pvertE vl; set p1 := Bpt _ _ => /[dup] vip1 ->. + have := pvertE vh; set p2 := Bpt _ _ => /[dup] vip2 ->. + rewrite /open_cell_side_limit_ok => -[] <- <- /=. + have [v1 on1 x1] : [/\ valid_edge le p1, p1 === le & p_x e = p_x p1]. + by have [on1 xp] := intersection_on_edge vip1. + have [v2 on2 x2] : [/\ valid_edge he p2, p2 === he & p_x e = p_x p2]. + by have [on2 xp] := intersection_on_edge vip2. + have p2ne : p2 != e :> pt. + apply/eqP=> A; have := strict_under_edge_lower_y x2 on2. + by rewrite under => /esym; rewrite ltNge A lexx. + rewrite -[pt_eqb _ _ p2 e]/(p2 == e :> pt). + rewrite -[pt_eqb _ _ e p1]/(e == p1 :> pt). + rewrite (negbTE p2ne); case: ifP => [p1ise | p1ne] /=; + move: on1 on2; rewrite ?(eqP p2ise) -?(eqP p1ise) => on1 on2; + rewrite ?eqxx ?on1 ?on2 ?(eqP p2ise) -?(eqP p1ise) -?x1 -?x2 + ?eqxx ?andbT //=. + have euh : e <<= he by apply: underW. + rewrite lt_neqAle. + have tmp:= (under_edge_lower_y x2 on2). + rewrite (eqP p1ise) /p1 /p2 /= in tmp; rewrite -tmp {tmp}. + rewrite -/p1 -(eqP p1ise) euh andbT. + apply/negP=> A; case/negP: p2ne; rewrite pt_eqE (eqP p1ise) /=. + by rewrite (eqP A) !eqxx. + rewrite -(strict_under_edge_lower_y x2 on2) under /=. + rewrite ltNge le_eqVlt negb_or. + rewrite -(strict_under_edge_lower_y x1 on1) above andbT. + by apply/negP=> A;case/negbT/negP:p1ne; rewrite pt_eqE -?x1 (eqP A) !eqxx. +have /eqP lgg : left_pt g == e by apply: lg; rewrite inE eqxx. +rewrite + -[generic_trajectories.vertical_intersection_point _ _ _ _ _ _ _ _ _ _ _] + /(vertical_intersection_point _ _). +have := pvertE vl; set p1 := Bpt _ _ => /[dup] vip1 ->. +have [v1 on1 x1] : [/\ valid_edge le p1, p1 === le & p_x e = p_x p1]. + by have [on1 xp] := intersection_on_edge vip1. +have eong : e === g by rewrite -(eqP (lg g _)) ?inE ?eqxx // left_on_edge. +case oca_eq : (opening_cells_aux _ _ _ _) => [so co] [] <- <-. +rewrite /=; apply/andP; split. + rewrite /open_cell_side_limit_ok. + rewrite -[pt_eqb _ _ e p1]/(e == p1 :> pt). + case: ifP=> [eisp1 | enp1] /=; + rewrite -?x1 !eqxx on1 -?(eqP eisp1) ?eong ?andbT //=. + rewrite ltNge le_eqVlt negb_or. + rewrite -(strict_under_edge_lower_y x1 on1) above andbT. + by apply/negP=> A; case/negP: enp1; rewrite pt_eqE (eqP A) x1 ?eqxx. +apply/allP=> c cintl. +suff/allP/(_ c cintl) : all open_cell_side_limit_ok (rcons so co) by []. +apply: (Ih g) => //. +- by apply: valid_edge_extremities; rewrite lg ?inE ?eqxx. +- by apply: onAbove. +by move: lg; apply: sub_in1 => g' gin; rewrite inE gin orbT. +Qed. + +Lemma opening_cells_side_limit e s le he : + valid_edge le e -> valid_edge he e -> + e >>= le -> e <<< he -> + {in s, forall g, left_pt g == e} -> + all open_cell_side_limit_ok (opening_cells e s le he). +Proof. +move=> vle vhe ea eu lefts. +have lefts' : {in sort (@edge_below _) s, forall g, left_pt g == e}. + by move=> g; rewrite mem_sort; apply: lefts. +have := opening_cells_aux_side_limit vle vhe ea eu lefts'. +rewrite /opening_cells. +case oca_eq : (opening_cells_aux _ _ _ _) => [so co]. +by apply. +Qed. + +Lemma fan_edge_below_trans (s : seq edge) p : + {in s, forall g, left_pt g == p} -> + {in s & &, transitive (@edge_below R)}. +Proof. +move=> lcnd g1 g2 g3 g1in g2in g3in. +by apply: trans_edge_below_out (eqP (lcnd _ _))(eqP (lcnd _ _))(eqP (lcnd _ _)). +Qed. + +Lemma opening_cells_pairwise' e le he : + point e >>> le -> + point e <<< he -> + out_left_event e -> + {in le :: he :: outgoing e &, no_crossing R} -> + valid_edge le (point e) -> + valid_edge he (point e) -> + pairwise (@edge_below _) + [seq high x | x <- (opening_cells (point e) (outgoing e) le he)]. +Proof. +move=> pal puh oute noc vle vhe; rewrite /opening_cells. +have oute' := outleft_event_sort oute. +have lein : le \in le :: he :: sort (@edge_below _) (outgoing e) by subset_tac. +have hein : he \in le :: he :: sort (@edge_below _) (outgoing e) by subset_tac. +have subo' : {subset sort (@edge_below _) (outgoing e) <= + le :: he :: sort (@edge_below _) (outgoing e)} by subset_tac. +have sub' : (le :: he :: sort (@edge_below _) (outgoing e)) =i (le :: he :: (outgoing e)). + by move=> g; rewrite !inE mem_sort. +have noc' : {in le :: he :: sort (@edge_below _) (outgoing e) &, no_crossing R}. + by move=> g1 g2; rewrite !sub'; apply: noc. +case oca_eq : opening_cells_aux => [s' c]. +rewrite pairwise_map pairwise_rcons -pairwise_map /=. +have [_ it _]:= outgoing_conditions pal puh lein hein vle vhe subo' noc' oute'. +have := opening_cells_aux_high vle vhe oute'; rewrite oca_eq /= => highsq. + apply/andP; split. + rewrite [X in is_true X] + (_ : _ = all (fun x => x <| high c) [seq high x | x <- s']); last first. + by rewrite all_map. + have := opening_cells_aux_high_last vle vhe oute'; rewrite oca_eq /= => ->. + by rewrite highsq; apply/allP. +rewrite highsq. +have loc_trans : {in sort (@edge_below _) (outgoing e) & &, + transitive (@edge_below _)}. + by apply: (@fan_edge_below_trans _ (point e)). +have /sort_edge_below_sorted : {in outgoing e &, no_crossing _}. + by move=> x y xin yin; apply: noc; subset_tac. +by rewrite (sorted_pairwise_in loc_trans (allss _)). +Qed. + +Lemma opening_cells_contains_point e le he nos: + valid_edge le (point e) -> + valid_edge he (point e) -> + point e >>> le -> + point e <<< he -> + out_left_event e -> + opening_cells (point e) (outgoing e) le he = nos -> + {in nos, forall c, contains_point (point e) c}. +Proof. +move=> vle vhe pal puh oute oceq. +have oute' := outleft_event_sort oute. +have := opening_cells_aux_subset vle vhe oute'. +move: oceq; rewrite /opening_cells. +case oca_eq : (opening_cells_aux _ _ _ _)=> [nos' lno'] <- /(_ _ _ _ erefl). +move=> main x xin; rewrite contains_pointE. +move: (main x xin); rewrite !inE=> /andP[] lows highs. +apply/andP; split. + move: lows=> /orP[/eqP -> | /oute'/eqP <-]; first by rewrite underWC. + by rewrite left_pt_above. +move: highs=> /orP[/eqP -> | /oute'/eqP <-]; first by rewrite underW. +by rewrite left_pt_below. +Qed. + +Lemma opening_cells_last_left_pts e le he : + valid_edge le (point e) -> + valid_edge he (point e) -> + out_left_event e -> + outgoing e != nil -> + point e <<< he -> + left_pts (opening_cells_aux (point e) (sort (@edge_below _) (outgoing e)) + le he).2 + = Bpt (p_x (point e)) (pvert_y (point e) he) :: point e :: nil. +Proof. +move=> vle vhe oute onn puh. +have oute' := outleft_event_sort oute. +have puh' : p_y (point e) < pvert_y (point e) he. + by rewrite -strict_under_pvert_y. +have pdif : Bpt (p_x (point e)) (pvert_y (point e) he) != point e :> pt. + rewrite pt_eqE negb_and /=; apply/orP; right; rewrite eq_sym. + by move: puh'; rewrite lt_neqAle => /andP[] ->. +case ogeq : (sort _ (outgoing e)) (mem_sort (@edge_below _) (outgoing e)) => + [ | fog ogs] // . + move=> abs; case ogeq' : (outgoing e) onn => [ | f q] //=. + by suff : f \in [::];[rewrite in_nil | rewrite abs ogeq' inE eqxx]. +move=> elems. +have lf : left_pt fog = point e. + by move: oute'; rewrite ogeq=> oute2; apply/eqP/oute2; rewrite inE eqxx. +have vf : valid_edge fog (point e) by rewrite valid_edge_extremities // lf eqxx. +rewrite opening_cells_aux_eqn. +rewrite /= pvertE //. +have : {subset ogs <= outgoing e} by move=> x xin; rewrite -elems inE xin orbT. +move: (fog) lf vf {ogeq elems}. +elim : (ogs) le {vle} => [ | f q Ih] //= => le fog1 lfog1 vf1 qsubo. + rewrite + -[generic_trajectories.vertical_intersection_point _ _ _ _ _ _ _ _ _ _ _] + /(vertical_intersection_point _ _). + rewrite + -[generic_trajectories.vertical_intersection_point _ _ _ _ _ _ _ _ _ _ _] + /(vertical_intersection_point _ _). + rewrite pvertE // pvertE //=. + rewrite -[pt_eqb _ _ _ (point e)]/(_ == point e :> pt). + rewrite (negbTE pdif). + have -> : pvert_y (point e) fog1 = p_y (point e). + by apply on_pvert; rewrite -lfog1 left_on_edge. + rewrite -[pt_eqb _ _ (point e) _]/(point e == _ :> pt). + rewrite pt_eqE /= !eqxx /=; congr (_ :: _ :: _); apply/(@eqP pt). + by rewrite pt_eqE /= !eqxx. +case oca_eq: (opening_cells_aux _ _ _ _) => [s c]. +rewrite + -[generic_trajectories.vertical_intersection_point _ _ _ _ _ _ _ _ _ _ _] + /(vertical_intersection_point _ _). +rewrite pvertE //=. +have lfq : left_pt f = point e. + by apply/eqP/oute'; rewrite mem_sort qsubo // inE eqxx. +have vf : valid_edge f (point e). + by apply: valid_edge_extremities; rewrite lfq eqxx. +have qsub : {subset q <= outgoing e}. + by move=> x xin; apply: qsubo; rewrite inE xin orbT. +by have := Ih le f lfq vf qsub; rewrite oca_eq /=. +Qed. + +Lemma opening_cells_aux_absurd_case e le he (s : seq edge) : + valid_edge le (point e) -> + valid_edge he (point e) -> + s != [::] -> + {in s, forall g, left_pt g == point e} -> + (opening_cells_aux (point e) (sort (@edge_below _) s) le he).1 != [::]. +Proof. +move=> vle vhe + outs; case sq : s => [ // | a s'] _. +case ssq : (sort (@edge_below _) s) => [ | b s2]. + by suff : a \in [::];[ | rewrite -ssq mem_sort sq inE eqxx]. +rewrite opening_cells_aux_eqn. +rewrite -sq ssq /= pvertE //. +by case oca_eq : (opening_cells_aux _ _ _ _). +Qed. + +(* TODO : complain that there is no sort_eq0 lemma with statement + (sort r l == [::]) = (l == [::]) *) + +Lemma opening_cells_1 e le he: + outgoing e != [::] -> + valid_edge le (point e) -> + valid_edge he (point e) -> + out_left_event e -> + exists fno nos lno, opening_cells (point e) (outgoing e) le he = + fno :: rcons nos lno. +Proof. +move=> ogn vle vhe oute. +rewrite /opening_cells. +have := opening_cells_aux_absurd_case vle vhe ogn oute. +set x := (opening_cells_aux _ _ _ _). +case x => [ [ | fno nos] lno] // _. +by exists fno, nos, lno. +Qed. + +Lemma opening_cells_in p' s le he : + valid_edge le p' -> valid_edge he p' -> + {in s, forall g, left_pt g == p'} -> + {in opening_cells p' s le he, forall c, p' \in (left_pts c : seq pt)}. +Proof. +move=> + vhe outp. +rewrite /opening_cells. +have {outp} : {in sort (@edge_below _) s, forall g, left_pt g == p'}. + by move=> g; rewrite mem_sort; apply: outp. +elim: (sort _ _) le => [ | g gs Ih] le. + move=> _ /= vle g. + rewrite + -[generic_trajectories.vertical_intersection_point _ _ _ _ _ _ _ _ _ _ _] + /(vertical_intersection_point _ _). + rewrite + -[generic_trajectories.vertical_intersection_point _ _ _ _ _ _ _ _ _ _ _] + /(vertical_intersection_point _ _). + rewrite (pvertE vle) (pvertE vhe) !inE => /eqP ->. + do 2 rewrite -[pt_eqb _ _ _ _]/(_ == _ :> pt). + case: ifP=> []; case: ifP=> [] /=. + move=> /eqP -> // /eqP <-. + by rewrite (@mem_head pt). + by rewrite (@mem_head pt). + move=> /eqP <-; rewrite (@in_cons pt). + by rewrite (@mem_head pt) orbT. + (* was by move=> /eqP <-; rewrite !inE eqxx orbT. *) + by rewrite (@in_cons pt) (@mem_head pt) orbT. +move=> outp vl. +have lgq : left_pt g = p' by apply/eqP; apply: (outp _ (mem_head _ _)). +have vg : valid_edge g p' by rewrite -lgq valid_edge_left. +have {}outp : {in gs, forall g, left_pt g == p'}. + by move=> g' gin; apply: outp; rewrite inE gin orbT. +have {}Ih := Ih g outp vg. +rewrite /=. +rewrite + -[generic_trajectories.vertical_intersection_point _ _ _ _ _ _ _ _ _ _ _] + /(vertical_intersection_point _ _). +rewrite /= (pvertE vl); case oca_eq : (opening_cells_aux _ _ _ _)=> [nos lno]. +move: Ih; rewrite oca_eq /= => Ih. +move=> c; rewrite inE=> /orP[/eqP -> /= |]; last by apply: Ih. +case: ifP; last by rewrite (@mem_head pt). +rewrite -[pt_eqb _ _ _ _]/(_ == _ :> pt). +by move=> /eqP <-; rewrite (@mem_head pt). +Qed. + +Lemma last_opening_cells_left_pts_prefix e le he nos lno : + valid_edge le (point e) -> + valid_edge he (point e) -> + point e <<< he -> + out_left_event e -> + opening_cells_aux (point e) (sort (@edge_below _) (outgoing e)) le he = + (nos, lno) -> + (1 < size (left_pts lno))%N /\ + take 2 (left_pts lno) = + [:: Bpt (p_x (point e)) (pvert_y (point e) he); (point e)] . +Proof. +move=> + vh puh oute. +have := outleft_event_sort oute. +elim: (sort _ _) nos lno le => [ | g s Ih] nos lno le /= oute' vl. + do 2 rewrite -/(vertical_intersection_point _ _). + rewrite (pvertE vl) (pvertE vh) => -[nosq lnoq]. + rewrite -lnoq /=. + rewrite -/(_ == point e) -/(point e == _). + set ph := (X in X == point e); set pl := (X in point e == X). + rewrite -/ph -/pl. + have /negbTE -> : ph != point e. + rewrite pt_eqE negb_and /ph /= eqxx /=. + move: puh. + by rewrite (strict_under_pvert_y vh) lt_neqAle eq_sym=> /andP[]. + split; first by case: (_ == _). + by have [-> | enqpl] := eqVneq (point e) pl. +rewrite -/(vertical_intersection_point _ _). +rewrite (pvertE vl). +case oca_eq : (opening_cells_aux _ _ _ _) => [nos1 lno1] [_ <-]. +have oute1 : forall ed, ed \in s -> left_pt ed == point e. + by move=> ed edin; apply: oute'; rewrite inE edin orbT. +have vg : valid_edge g (point e). + by rewrite -(eqP (oute' g _)) ?valid_edge_left // inE eqxx. +by apply: (Ih nos1 lno1 g oute1 vg oca_eq). +Qed. + +Lemma last_opening_cells_safe_side_char e le he pp nos lno : + outgoing e != [::] -> + valid_edge le (point e) -> + valid_edge he (point e) -> + point e <<< he -> + out_left_event e -> + opening_cells (point e) (outgoing e) le he = rcons nos lno -> + in_safe_side_left pp lno = + [&& p_x pp == p_x (point e), p_y (point e) < p_y pp & pp <<< he]. +Proof. +move=> ogn0 vle vhe puh oute oeq. +have oute' := outleft_event_sort oute. +have oca_eq: + (opening_cells_aux (point e) (sort (@edge_below _) (outgoing e)) le he) = + (nos, lno). + move: oeq; rewrite /opening_cells; case: (opening_cells_aux _ _ _ _)=> [a b]. + by move/eqP; rewrite eqseq_rcons=> /andP[] /eqP -> /eqP ->. +have lnoin : lno \in opening_cells (point e) (outgoing e) le he. + by rewrite oeq mem_rcons mem_head. +rewrite /in_safe_side_left. +have := opening_cells_left oute vle vhe lnoin=> ->. +have [/eqP samex /= | ] := boolP (p_x pp == p_x (point e)); last by []. +have highlno : high lno = he. + by have := opening_cells_aux_high_last vle vhe oute'; rewrite oca_eq. +rewrite highlno [in RHS]andbC. +have := opening_cells_1 ogn0 vle vhe oute => -[fno [nos' [lno' oeq']]]. +have [nosq lnoq] : nos = fno :: nos' /\ lno = lno'. + move: oeq'; rewrite oeq -[fno :: rcons _ _]/(rcons (fno :: _) _) => /eqP. + by rewrite eqseq_rcons => /andP[] /eqP -> /eqP ->. +have llnoq : low lno = high (last fno nos'). + have := adjacent_opening vle vhe oute; rewrite oeq'. + rewrite /= -cats1 cat_path=> /andP[] _ /=. + by rewrite andbT lnoq eq_sym=> /eqP. +have /oute lfnoq : high (last fno nos') \in outgoing e. + have := opening_cells_high vle vhe oute; rewrite oeq'. + have := size_sort (@edge_below _) (outgoing e). +(* TODO : should use some lemma here *) + rewrite -(mem_sort (@edge_below _)); case: (sort _ _) => [ | w w'] //=. + by move=>/eqP; rewrite eq_sym size_eq0 (negbTE ogn0). + move=> _ [] <-; rewrite map_rcons=> /eqP. + rewrite eqseq_rcons => /andP[] /eqP <- _. + by elim/last_ind: (nos') => [ | ? ? _]; +rewrite ?mem_head // last_rcons inE map_rcons mem_rcons mem_head orbT. +have eonl : point e === low lno by rewrite llnoq -(eqP lfnoq) left_on_edge. +have ppal : (pp >>> low lno) = (p_y (point e) < p_y pp). + have := under_edge_lower_y samex eonl => ->. + by rewrite -ltNge. +rewrite ppal. +have := opening_cells_last_left_pts vle vhe oute ogn0 puh. +rewrite oca_eq /= => ->. +have [ppuh /= | ] := boolP (pp <<< he); last by []. +have [ppae /= | ] := boolP (p_y (point e) < p_y pp); last by []. +rewrite !(@in_cons pt) !pt_eqE /=. +have vpphe : valid_edge he pp by rewrite (same_x_valid _ samex). +rewrite -(same_pvert_y vpphe samex). +move: ppuh; rewrite (strict_under_pvert_y vpphe) lt_neqAle=> /andP[]. +move=> /negbTE -> _. +move: ppae; rewrite lt_neqAle eq_sym=> /andP[] /negbTE -> _. +by rewrite !andbF. +Qed. + +Lemma opening_cells_first_left_pts e le he : + valid_edge le (point e) -> + outgoing e != nil -> + point e >>> le -> + left_pts + (head dummy_cell + (opening_cells_aux (point e) (sort (@edge_below _) (outgoing e)) + le he).1) + = point e :: Bpt (p_x (point e)) (pvert_y (point e) le) :: nil. +Proof. +move=> vle onn pal. +set W := sort _ _. +have sgt0 : (0 < size W)%N by rewrite /W size_sort; case : (outgoing e) onn. +case Wq : W sgt0 => [ // | g1 gs'] _ /=. +case oca_eq : (opening_cells_aux _ _ _ _) => [nos lno]. +rewrite + -[generic_trajectories.vertical_intersection_point _ _ _ _ _ _ _ _ _ _ _] + /(vertical_intersection_point _ _). +rewrite pvertE //=. +rewrite -[pt_eqb _ _ _ _]/(_ == _ :> pt). +case: ifP=> // samept. +have := pvert_on vle; rewrite -(eqP samept) => onle. +have /andP[/eqP pf _] := onle. +by move: pal; rewrite underE pf le_eqVlt eqxx. +Qed. + +Lemma first_opening_cells_side_char e le he pp fno nos lno : + outgoing e != [::] -> + valid_edge le (point e) -> + valid_edge he (point e) -> + point e >>> le -> + out_left_event e -> + opening_cells (point e) (outgoing e) le he = rcons (fno :: nos) lno -> + in_safe_side_left pp fno = + [&& p_x pp == p_x (point e), p_y pp < p_y (point e) & pp >>> le]. +Proof. +move=> ogn0 vle vhe pal oute oeq. +have oute' := outleft_event_sort oute. +have oca_eq: + (opening_cells_aux (point e) (sort (@edge_below _) (outgoing e)) le he) = + ((fno :: nos), lno). + move: oeq; rewrite /opening_cells; case: (opening_cells_aux _ _ _ _)=> [a b]. + by move/eqP; rewrite eqseq_rcons=> /andP[] /eqP -> /eqP ->. +have fnoin : fno \in opening_cells (point e) (outgoing e) le he. + by rewrite oeq mem_rcons !inE eqxx orbT. +rewrite /in_safe_side_left. +have := opening_cells_left oute vle vhe fnoin=> ->. +have [/eqP samex /= | ] := boolP (p_x pp == p_x (point e)); last by []. +have lowfno : low fno = le. + by rewrite (lower_edge_new_cells vle vhe oeq). +rewrite lowfno. +have /oute hfnoq : high fno \in outgoing e. + have := opening_cells_high vle vhe oute; rewrite oeq /=. + have := size_sort (@edge_below _) (outgoing e). +(* TODO : should use some lemma here *) + rewrite -(mem_sort (@edge_below _)); case: (sort _ _) => [ | w w'] //=. + by move=>/eqP; rewrite eq_sym size_eq0 (negbTE ogn0). + move=> _ [] <-; rewrite map_rcons=> /eqP. + rewrite eqseq_rcons => /andP[] /eqP <- _. + by rewrite mem_head. +have eonh : point e === high fno by rewrite -(eqP hfnoq) left_on_edge. +have ppue : (pp <<< high fno) = (p_y pp < p_y (point e)). + by have := strict_under_edge_lower_y samex eonh. +rewrite ppue. +have := opening_cells_first_left_pts he vle ogn0 pal. +rewrite oca_eq /= => ->. +have [{}ppue /= | ] := boolP (p_y pp < p_y (point e)); last by []. +have [ppal /= | ] := boolP (pp >>> le); last by []. +rewrite !(@in_cons pt) !pt_eqE. +have vpple : valid_edge le pp by rewrite (same_x_valid _ samex). +rewrite -(same_pvert_y vpple samex). +move: ppal; rewrite (under_pvert_y vpple) le_eqVlt negb_or=> /andP[]. +move=> /negbTE -> _. +move: ppue; rewrite lt_neqAle=> /andP[] /negbTE -> _. +by rewrite !andbF. +Qed. + +Lemma middle_opening_cells_side_char e le he pp fno nos lno : + outgoing e != [::] -> + valid_edge le (point e) -> + valid_edge he (point e) -> + out_left_event e -> + opening_cells (point e) (outgoing e) le he = rcons (fno :: nos) lno -> + ~~ has (in_safe_side_left pp) nos. +Proof. +move=> ogn0 vle vhe oute oeq. +have oute' := outleft_event_sort oute. +have oca_eq: + (opening_cells_aux (point e) (sort (@edge_below _) (outgoing e)) le he) = + ((fno :: nos), lno). + move: oeq; rewrite /opening_cells; case: (opening_cells_aux _ _ _ _)=> [a b]. + by move/eqP; rewrite eqseq_rcons=> /andP[] /eqP -> /eqP ->. +rewrite -all_predC; apply/allP=> c cino /=. +have cin : c \in opening_cells (point e) (outgoing e) le he. + by rewrite oeq mem_rcons !(inE, mem_cat) cino !orbT. +rewrite /in_safe_side_left. +have := opening_cells_left oute vle vhe cin=> ->. +have [samex /= | ] := boolP (p_x pp == p_x (point e)); last by []. +have /oute hc : high c \in outgoing e. + have := opening_cells_high vle vhe oute; rewrite oeq /=. + have := size_sort (@edge_below _) (outgoing e). +(* TODO : should use some lemma here *) + rewrite -(mem_sort (@edge_below _)); case: (sort _ _) => [ | w w'] //=. + by move=>/eqP; rewrite eq_sym size_eq0 (negbTE ogn0). + move=> _ [] <-; rewrite map_rcons=> /eqP. + rewrite eqseq_rcons => /andP[] /eqP <- _. + by rewrite inE map_f ?orbT. +have /oute lc : low c \in outgoing e. + have := opening_cells_high vle vhe oute; rewrite oeq /=. + have /= := opening_cells_seq_edge_shift oute' vle vhe oca_eq. + move=> [] _ -> /eqP; rewrite eqseq_rcons=> /andP[] /eqP + _. + rewrite -(mem_sort (@edge_below _)) => <-. + by rewrite map_f // mem_rcons inE cino orbT. +have eonh : point e === high c by rewrite -(eqP hc) left_on_edge. +have eonl : point e === low c by rewrite -(eqP lc) left_on_edge. +have := strict_under_edge_lower_y (eqP samex) eonh=> ->. +have := under_edge_lower_y (eqP samex) eonl=> ->. +by rewrite le_eqVlt negb_or -!andbA andbCA; case: (_ < _); rewrite !andbF. +Qed. + +Lemma single_opening_cell_side_char e le he pp : + valid_edge le (point e) -> + valid_edge he (point e) -> + point e >>> le -> + point e <<< he -> + outgoing e = [::] -> + has (in_safe_side_left pp) (opening_cells (point e) (outgoing e) le he) = + ([&& p_x pp == p_x (point e), pp >>> le & p_y pp < p_y (point e)] || + [&& p_x pp == p_x (point e), pp <<< he & p_y (point e) < p_y pp]). +Proof. +move=> vle vhe pal puh og0. +have oute : out_left_event e by move=> g; rewrite og0 in_nil. +have [ppe | ppne] := eqVneq (pp : pt) (point e). + rewrite ppe !lt_irreflexive !andbF. + apply /negbTE; rewrite -all_predC; apply/allP=> c cin /=. + have einl := opening_cells_in vle vhe oute cin. + by rewrite /in_safe_side_left einl !andbF. +have := opening_cells_left oute vle vhe. +rewrite og0 /opening_cells /=. +do 2 rewrite + -[generic_trajectories.vertical_intersection_point _ _ _ _ _ _ _ _ _ _ _] + /(vertical_intersection_point _ _). +rewrite (pvertE vle) (pvertE vhe) /= orbF. +set c := Bcell _ _ _ _. +move=> /(_ _ (mem_head _ _)). +rewrite /in_safe_side_left /= => ->. +have [/eqP samex /= | ] := boolP (p_x pp == p_x (point e)); last by []. +rewrite andbCA. +have puhy : p_y (point e) < pvert_y (point e) he. + by rewrite -(strict_under_pvert_y vhe). +have paly : pvert_y (point e) le < p_y (point e). + by rewrite ltNge -(under_pvert_y vle). +do 2 rewrite -[pt_eqb _ _ _ _]/(_ == _ :> pt). +rewrite !pt_eqE /= eqxx /=. +move: (puhy); rewrite lt_neqAle eq_sym=> /andP[] /negbTE -> _. +move: (paly); rewrite lt_neqAle eq_sym=> /andP[] /negbTE -> _. +have vpple : valid_edge le pp by rewrite (same_x_valid _ samex). +have vpphe : valid_edge he pp by rewrite (same_x_valid _ samex). + +have [ | pa] := lerP (p_y pp) (p_y (point e)); rewrite ?(andbF, orbF). + rewrite le_eqVlt => /orP[/eqP samey | /[dup] pu ->]. + by case/negP: ppne; rewrite pt_eqE samex samey !eqxx. + have [ppale | _] := boolP (pp >>> le); last by []. + have -> : pp <<< he. + rewrite (strict_under_pvert_y vpphe). + rewrite (same_pvert_y vpphe samex). + by apply: (lt_trans pu); rewrite -(strict_under_pvert_y vhe). + rewrite /=. + have ppaly : pvert_y (point e) le < p_y pp. + rewrite -(same_pvert_y vpple samex). + by rewrite ltNge -(under_pvert_y vpple). + rewrite !(@in_cons pt). + rewrite (negbTE ppne) !pt_eqE /=. + move: ppaly; rewrite lt_neqAle eq_sym=> /andP[] /negbTE -> _. + have ppuhy : p_y pp < pvert_y (point e) he. + by apply: (lt_trans pu). + move: ppuhy; rewrite lt_neqAle => /andP[] /negbTE -> _. + by rewrite !andbF. +move=> {c}. +rewrite ltNge le_eqVlt pa orbT andbF andbT /=. +have [ppuhe | _] := boolP (pp <<< he); last by rewrite andbF. +have ppale : pp >>> le. + rewrite (under_pvert_y vpple). + rewrite (same_pvert_y vpple samex) -ltNge. + by apply: (lt_trans _ pa); rewrite ltNge -(under_pvert_y vle). +rewrite /=. +have ppaly : pvert_y (point e) le < p_y pp. + rewrite -(same_pvert_y vpple samex). + by rewrite ltNge -(under_pvert_y vpple). +rewrite !(@in_cons pt) (negbTE ppne) !pt_eqE /=. +move: ppaly; rewrite lt_neqAle eq_sym=> /andP[] /negbTE -> _. +have ppuhy : p_y pp < pvert_y (point e) he. + rewrite -(same_pvert_y vpphe samex). + by rewrite -(strict_under_pvert_y vpphe). + move: ppuhy; rewrite lt_neqAle => /andP[] /negbTE -> _. +by rewrite ppale !andbF. +Qed. + +Lemma opening_cells_aux_uniq (q : pt) l g1 g2 r1 r2: + uniq l -> + g2 \notin l -> + {in l, forall g, left_pt g == q} -> + valid_edge g1 q -> + valid_edge g2 q -> + opening_cells_aux q l g1 g2 = (r1, r2) -> + uniq (rcons r1 r2). +Proof. +move=> ul g2nin ol v1 v2 oca_eq. +have lg2 := opening_cells_aux_high_last v1 v2 ol. +have lg1 := opening_cells_aux_high v1 v2 ol. +apply: (@map_uniq _ _ high). +rewrite map_rcons rcons_uniq. +rewrite oca_eq /= in lg2 lg1. +by rewrite lg2 lg1 g2nin ul. +Qed. + +(* TODO : move to points_and_edges. *) +Lemma half_point_valid (g : edge) (p1 p2 : pt) : + valid_edge g p1 -> valid_edge g p2 -> + valid_edge g (Bpt ((p_x p1 + p_x p2) / 2) ((p_y p1 + p_y p2) / 2)). +Proof. +rewrite /valid_edge; move=> /andP[] vp1l vp1r /andP[] vp2l vp2r /=. +have cst2gt0 : (0 < 2 :> R) by apply: addr_gt0. +apply/andP; split. + rewrite -(ler_pM2r cst2gt0) -mulrA mulVf ?mulr1; last by apply: lt0r_neq0. + by rewrite mulrDr !mulr1 lerD. +rewrite -(ler_pM2r cst2gt0) -mulrA mulVf ?mulr1; last by apply: lt0r_neq0. +by rewrite mulrDr !mulr1 lerD. +Qed. + +Lemma half_between (x y : R) : x < y -> x < (x + y) / 2 < y. +Proof. +move=> xy. +have cst2gt0 : (0 < 2 :> R) by apply: addr_gt0. +apply/andP; split. + rewrite -(ltr_pM2r cst2gt0) -mulrA mulVf ?mulr1; last by apply: lt0r_neq0. + by rewrite mulrDr !mulr1 ler_ltD. +rewrite -(ltr_pM2r cst2gt0) -mulrA mulVf ?mulr1; last by apply: lt0r_neq0. +by rewrite mulrDr !mulr1 ltr_leD. +Qed. + +Lemma half_between_edges (g1 g2 : edge) p : + valid_edge g1 p -> valid_edge g2 p -> p >>= g1 -> p <<< g2 -> + (Bpt (p_x p) ((pvert_y p g1 + pvert_y p g2) / 2)) >>> g1 /\ + (Bpt (p_x p) ((pvert_y p g1 + pvert_y p g2) / 2)) <<< g2. +Proof. +move=> vg1 vg2 pal puh; set p1 := Bpt _ _. +have samex : p_x p1 = p_x p by []. +have v1g1 : valid_edge g1 p1 by rewrite (same_x_valid _ samex). +have v1g2 : valid_edge g2 p1 by rewrite (same_x_valid _ samex). +rewrite (under_pvert_y v1g1) (strict_under_pvert_y v1g2) -ltNge; apply/andP. +apply: half_between. +have := puh; rewrite (strict_under_pvert_y vg2); apply: le_lt_trans. +by rewrite leNgt -(strict_under_pvert_y vg1). +Qed. + +Lemma opening_cells_non_empty e le he: + valid_edge le (point e) -> + valid_edge he (point e) -> + point e >>> le -> + point e <<< he -> + out_left_event e -> + uniq (outgoing e) -> + {in [:: le, he & outgoing e] &, forall e1 e2, inter_at_ext e1 e2} -> + {in opening_cells (point e) (outgoing e) le he, forall c p, + valid_edge (low c) p -> valid_edge (high c) p -> + p_x (point e) < p_x p -> + exists q, [&& q >>> low (close_cell p c), q <<< high (close_cell p c)& + left_limit (close_cell p c) < p_x q < + right_limit (close_cell p c)]}. +Proof. +move=> vle vhe pal puh oute une noc. +rewrite /opening_cells. +have : {subset le :: sort (@edge_below _) (outgoing e) <= + [:: le, he & outgoing e]}. + move=> g; rewrite inE mem_sort=> /orP[/eqP -> | ]; first by subset_tac. + by move=> gin; rewrite !inE gin !orbT. +have := outleft_event_sort oute. +have : sorted (@edge_below _) (le :: (sort (@edge_below _) (outgoing e))). + by apply: (sorted_outgoing vle vhe _ _ _ (inter_at_ext_no_crossing noc)). +have : uniq (le :: sort (@edge_below _) (outgoing e)). + rewrite /= sort_uniq une andbT. + rewrite mem_sort; apply/negP=> /oute /eqP abs. + by move: pal; rewrite under_onVstrict // -abs left_on_edge. +elim: (sort _ _) {-6} (le) vle (underWC pal)=> [ | g1 gs Ih] le' vle' pale'. + move=> _ _ _ sub0. +rewrite opening_cells_aux_eqn. + rewrite /= (pvertE vle') (pvertE vhe) /=. + set c0 := (X in [:: X])=> ?; rewrite inE => /eqP -> p vlp vhp pxgt. + (* point p0 has no guarantee concerning the vertical position. *) + set p0 := Bpt ((p_x (point e) + p_x p) / 2) ((p_x (point e) + p_x p) / 2). + have vlp0 : valid_edge le' p0 by apply: half_point_valid. + set p1 := Bpt (p_x p0)(pvert_y p0 le'). + have vlp1 : valid_edge le' p1 by apply: half_point_valid. + have vhp1 : valid_edge he p1 by apply: half_point_valid. + have p1onle' : p1 === le' by apply: (pvert_on vlp0). + have hein : he \in [:: le, he & outgoing e] by subset_tac. + have le'in : le' \in [:: le, he & outgoing e] by apply: sub0; subset_tac. + have ba' : inter_at_ext le' he by apply: noc. + have ba : below_alt le' he by apply: (inter_at_ext_no_crossing noc). + have le'bhe : le' <| he. + by apply: (edge_below_from_point_above ba vle' vhe). + have p1uh : p1 <<< he. + have p1ule' : p1 <<= le' by rewrite (under_onVstrict vlp1) p1onle'. + have : p1 <<= he by apply: (order_edges_viz_point' vlp1). + rewrite (under_onVstrict vhp1)=> /orP[p1onhe |]; last by []. + case: ba'=> [lqh | ]; first by move: pale'; rewrite lqh puh. + move=> /(_ _ p1onle' p1onhe). + rewrite !inE=> /orP[] /eqP abs. + move: vle'; rewrite /valid_edge=> /andP[] + _; rewrite -abs. + rewrite leNgt=> /negP[]. + by have := half_between pxgt=> /andP[] + _; apply. + move: vlp; rewrite /valid_edge=> /andP[] _; rewrite -abs. + rewrite leNgt=> /negP[]. + by have := half_between pxgt=> /andP[] _ +. + have p1ale' : p1 >>= le' by rewrite (strict_nonAunder vlp1) p1onle'. + have := half_between_edges vlp1 vhp1 p1ale' p1uh. + set q := Bpt (p_x p1) ((pvert_y p1 le' + pvert_y p1 he) / 2). + move=> []qal quh. + exists q. + have [-> -> _] := close_cell_preserve_3sides p c0. + rewrite right_limit_close_cell // left_limit_close_cell qal quh. + have := half_between pxgt=> /andP[] keepit ->; rewrite andbT /=. + rewrite /c0/=. + by case: ifP=>[] _; case: ifP=> [] _ /=; rewrite /left_limit /= keepit. +move=> uns srt out sub /=. +case oca_eq: opening_cells_aux => [s c]. +rewrite + -[generic_trajectories.vertical_intersection_point _ _ _ _ _ _ _ _ _ _ _] + /(vertical_intersection_point _ _). +rewrite (pvertE vle') /=. +set c0 := Bcell _ _ _ _ _ _. +move=> c1; rewrite inE=> /orP[/eqP -> | c1in] p /= vlp vhc pxgt; last first. + have lg1 : left_pt g1 = (point e). + by have := out _ (mem_head _ _) => /eqP <-. + have vg1 : valid_edge g1 (point e) by rewrite -lg1 valid_edge_left. + have ag1 : point e >>= g1 by rewrite -lg1 left_pt_above. + have out' : forall ed, ed \in gs -> left_pt ed == point e. + by move=> ed edin; apply: out; rewrite inE edin orbT. + have sub' : {subset g1 :: gs <= [:: le, he & outgoing e]}. + by move=> g gin; apply: sub; rewrite inE gin orbT. + have c1in' : c1 \in (let (s0, c2) := opening_cells_aux (point e) gs g1 he in + rcons s0 c2). + by rewrite oca_eq. + have srt' : sorted (@edge_below _) (g1 :: gs) by move: srt=> /= /andP[] _. + have un' : uniq (g1 :: gs) by move: uns=> /= /andP[]. + by apply: (Ih g1 vg1 ag1 un' srt' out' sub' _ c1in'). +have [-> -> _] := close_cell_preserve_3sides p c0. +rewrite right_limit_close_cell // left_limit_close_cell. +set p0 := Bpt ((p_x (point e) + p_x p) / 2) ((p_x (point e) + p_x p) / 2). +have vlp0 : valid_edge le' p0 by apply: half_point_valid. +set p1 := Bpt (p_x p0) (pvert_y p0 le'). +have vlp1 : valid_edge le' p1 by apply: half_point_valid. +have lg1 : left_pt g1 = point e by apply/eqP/out/mem_head. +have vg1 : valid_edge g1 (point e) by rewrite -lg1 valid_edge_left. +have vhp1 : valid_edge g1 p1 by apply: half_point_valid. +have p1onle' : p1 === le' by apply: (pvert_on vlp0). +have g1in : g1 \in [:: le, he & outgoing e] by apply: sub; subset_tac. +have le'in : le' \in [:: le, he & outgoing e] by apply: sub; subset_tac. +have ba' : inter_at_ext le' g1 by apply: noc. +have ba : below_alt le' g1 by apply: (inter_at_ext_no_crossing noc). +have le'bhe : le' <| g1 by move: srt=> /= /andP[]. +have p1ug1 : p1 <<< g1. + have p1ule' : p1 <<= le' by rewrite (under_onVstrict vlp1) p1onle'. + have : p1 <<= g1. + by apply: (order_edges_viz_point' vlp1). + rewrite (under_onVstrict vhp1)=> /orP[p1ong1 |]; last by []. + case: ba'=> [lqg1 | ]; first by move: uns; rewrite lqg1 /= inE eqxx. + move=> /(_ _ p1onle' p1ong1). + rewrite !inE=> /orP[] /eqP abs. + move: vle'; rewrite /valid_edge=> /andP[] + _; rewrite -abs. + rewrite leNgt=> /negP[]. + by have := half_between pxgt=> /andP[] + _; apply. + move: vlp; rewrite /valid_edge=> /andP[] _; rewrite -abs. + rewrite leNgt=> /negP[]. + by have := half_between pxgt=> /andP[] _ +. +have p1ale' : p1 >>= le' by rewrite (strict_nonAunder vlp1) p1onle'. +have := half_between_edges vlp1 vhp1 p1ale' p1ug1. +set q := Bpt (p_x p1) ((pvert_y p1 le' + pvert_y p1 g1) / 2). +move=> []qal qug1. +exists q. +have := half_between pxgt=> /andP[] keepit ->; rewrite andbT /=. +rewrite /c0/= qal qug1 /=. +by case: ifP=> [] _ /=; rewrite /left_limit /= keepit. +Qed. + +End opening_cells. + +End proof_environment. + +End working_environment. diff --git a/theories/points_and_edges.v b/theories/points_and_edges.v new file mode 100644 index 0000000..1c19412 --- /dev/null +++ b/theories/points_and_edges.v @@ -0,0 +1,2698 @@ +From HB Require Import structures. +From mathcomp Require Import all_ssreflect all_algebra. +Require Export Field. +Require Import math_comp_complements. +Require Import generic_trajectories. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Require Import NArithRing. +Import Order.TTheory GRing.Theory Num.Theory Num.ExtraDef Num. + +Open Scope ring_scope. + +Section working_context. + +Variable (R : realFieldType). + +Definition pt := pt R. +Notation Bpt := (Bpt _). +Notation "p .x" := (generic_trajectories.p_x _ p) + (at level 2, left associativity, format "p .x"). +Notation "p .y" := (generic_trajectories.p_y _ p) + (at level 2, left associativity, format "p .y"). + +Lemma pt_eqP : Equality.axiom (pt_eqb R eq_op). +Proof. +rewrite /Equality.axiom. +move=> [a_x a_y] [b_x b_y]; rewrite /pt_eqb/=. +have [/eqP <-|/eqP anb] := boolP (a_x == b_x). + have [/eqP <- | /eqP anb] := boolP (a_y == b_y). + by apply: ReflectT. + by apply : ReflectF => [][]. +by apply: ReflectF=> [][]. +Qed. + +HB.instance Definition _ := hasDecEq.Build _ pt_eqP. + +Lemma pt_eqE (p1 p2 : pt) : (p1 == p2) = (p1.x == p2.x) && (p1.y == p2.y). +Proof. by move: p1 p2 => [? ?][? ?]. Qed. + +Record edge := Bedge {left_pt : pt; right_pt : pt; + _ : left_pt.x < right_pt.x}. + +Definition edge_eqb (e1 e2 : edge) : bool := + let: Bedge a1 b1 p1 := e1 in + let: Bedge a2 b2 p2 := e2 in + (a1 == a2) && (b1 == b2). + +Lemma edge_cond (e : edge) : (left_pt e).x < (right_pt e).x. +Proof. by move: e => [l r c]. Qed. + +Lemma edge_eqP : Equality.axiom edge_eqb. +Proof. +move=> [a1 b1 p1] [a2 b2 p2] /=. +have [/eqP a1a2 | /eqP a1na2] := boolP (a1 == a2). + have [/eqP b1b2 | /eqP b1nb2] := boolP (b1 == b2). + move: p1 p2. rewrite -a1a2 -b1b2 => p1 p2. + rewrite (eqtype.bool_irrelevance p1 p2). + by apply: ReflectT. + by apply: ReflectF=> [][]. +by apply: ReflectF=>[][]. +Qed. + +HB.instance Definition _ := hasDecEq.Build _ edge_eqP. + +Notation area3 := + (area3 R +%R (fun x y => x - y) *%R). + +(* returns true if p is under e *) +Definition point_under_edge := + point_under_edge R le +%R (fun x y => x - y) *%R 1 edge + left_pt right_pt. + +Definition point_strictly_under_edge := + point_strictly_under_edge R eq_op le +%R (fun x y => x - y) *%R 1 edge + left_pt right_pt. + +Lemma R_ltb_lt x y : R_ltb R eq_op le x y = (x < y). +Proof. by rewrite /R_ltb -lt_neqAle. Qed. + +Lemma strictE p e : + point_strictly_under_edge (*R eq_op le +%R + (fun x y => x - y) *%R 1 edge left_pt right_pt *) p e = + (area3 p (left_pt e) (right_pt e) < 0). +Proof. +by rewrite /point_strictly_under_edge/generic_trajectories.point_strictly_under_edge R_ltb_lt subrr. +Qed. + +Lemma underE p e : + point_under_edge (* R le +%R + (fun x y => x - y) *%R 1 edge left_pt right_pt *) p e = + (area3 p (left_pt e) (right_pt e) <= 0). +Proof. +by rewrite /point_under_edge/generic_trajectories.point_under_edge subrr. +Qed. + +Notation "p '<<=' e" := (point_under_edge p e)( at level 70, no associativity). +Notation "p '<<<' e" := (point_strictly_under_edge p e)(at level 70, no associativity). + +Notation "p '>>=' e" := (~~(point_strictly_under_edge p e))( at level 70, no associativity). +Notation "p '>>>' e" := (~~(point_under_edge p e))(at level 70, no associativity). + +Section ring_sandbox. + +Definition R' := (R : Type). + +Let mul : R' -> R' -> R' := @GRing.mul _. +Let add : R' -> R' -> R' := @GRing.add _. +Let sub : R' -> R' -> R' := (fun x y => x - y). +Let opp : R' -> R' := @GRing.opp _. +Let zero : R' := 0. +Let one : R' := 1. + + +Let R2_theory := + @mk_rt R' zero one add mul sub opp + (@eq R') + (@add0r R) (@addrC R) (@addrA R) (@mul1r R) (@mulrC R) + (@mulrA R) (@mulrDl R) (fun x y : R' => erefl (x - y)) (@addrN R). + +Add Ring R2_Ring : R2_theory. + +Ltac mc_ring := +rewrite ?mxE /= ?(expr0, exprS, mulrS, mulr0n) -?[@GRing.add _]/add + -?[@GRing.mul _]/mul + -?[@GRing.opp _]/opp -?[1]/one -?[0]/zero; +match goal with |- @eq ?X _ _ => change X with R' end; +ring. + +Let inv : R' -> R' := @GRing.inv _. +Let div : R' -> R' -> R' := fun x y => mul x (inv y). + +Definition R2_sft : field_theory zero one add mul sub opp div inv (@eq R'). +Proof. +constructor. +- exact R2_theory. +- have // : one <> zero by apply/eqP; rewrite oner_eq0. +- have // : forall p q : R', div p q = mul p (inv q) by []. +- have // : forall p : R', p <> zero -> mul (inv p) p = one. + by move=> *; apply/mulVf/eqP. +Qed. + +Add Field Qfield : R2_sft. + +Ltac mc_field := +rewrite ?mxE /= ?(expr0, exprS, mulrS, mulr0n) -?[@GRing.add _]/add + -?[@GRing.mul _]/mul -[@GRing.inv _]/inv + -?[@GRing.opp _]/opp -?[1]/one -?[0]/zero; +match goal with |- @eq ?X _ _ => change X with R' end; +field. + +Example field_playground (x y : R' ) : x != 0 -> y != 0 -> (x * y) / (x * y) = 1. +Proof. +move=> xn0 yn0; mc_field. +by split; apply/eqP. +Qed. + +(* returns true if p is under A B *) +Definition pue_f (a_x a_y b_x b_y c_x c_y : R') : R' := + b_x * c_y + a_x * b_y + c_x * a_y - + b_x * a_y - a_x * c_y - c_x * b_y. + +Lemma pue_f_o p_x p_y a_x a_y b_x b_y: pue_f p_x p_y a_x a_y b_x b_y = - pue_f b_x b_y a_x a_y p_x p_y. +Proof. + rewrite /pue_f. + mc_ring. +Qed. + +Lemma pue_f_c p_x p_y a_x a_y b_x b_y: pue_f p_x p_y a_x a_y b_x b_y = pue_f b_x b_y p_x p_y a_x a_y. +Proof. + rewrite /pue_f. + mc_ring. +Qed. + +Lemma pue_f_inter p_x a_x a_y b_x b_y : b_x != a_x -> + pue_f p_x ((p_x - a_x)* ((b_y - a_y)/(b_x - a_x)) + a_y) a_x a_y b_x b_y = 0. +Proof. +rewrite /pue_f. +rewrite -subr_eq0 => h. +set slope := (_ / _). + +rewrite (mulrDr b_x). +rewrite (mulrDr a_x). +apply/eqP. +rewrite -(orbF (_ == 0)). +rewrite -(negbTE h). +rewrite -mulf_eq0 . +rewrite ! ( mulrBl (b_x - a_x), fun x y => mulrDl x y (b_x - a_x)). + +rewrite /slope !mulrA !mulfVK //. +apply/eqP; mc_ring. +Qed. + +Lemma pue_f_inters p_x p_y a_x a_y b_x b_y : b_x != a_x -> p_y = ((p_x - a_x) * ((b_y - a_y) / (b_x - a_x)) + a_y) -> +pue_f p_x p_y a_x a_y b_x b_y = 0. +Proof. +move => h ->. +by apply pue_f_inter; rewrite h. + + +Qed. + +Lemma pue_f_eq p_x p_y a_x a_y : pue_f p_x p_y p_x p_y a_x a_y = 0. +Proof. by rewrite /pue_f /=; mc_ring. Qed. + +Lemma pue_f_two_points p_x p_y a_x a_y : + pue_f p_x p_y p_x p_y a_x a_y = 0 /\ + pue_f p_x p_y a_x a_y p_x p_y = 0 /\ + pue_f p_x p_y a_x a_y a_x a_y = 0. +Proof. +split. + by rewrite pue_f_eq. +split. + by rewrite (pue_f_c p_x p_y a_x a_y p_x p_y) pue_f_eq. +by rewrite -(pue_f_c a_x a_y a_x a_y p_x p_y) pue_f_eq. +Qed. + +Lemma pue_f_vert p_y a_x a_y b_x b_y : + pue_f a_x a_y b_x b_y b_x p_y = (b_x - a_x) * (p_y - b_y). +Proof. by rewrite /pue_f; mc_ring. Qed. + +Lemma ax4 p_x p_y q_x q_y r_x r_y t_x t_y : + pue_f t_x t_y q_x q_y r_x r_y + + pue_f p_x p_y t_x t_y r_x r_y + + pue_f p_x p_y q_x q_y t_x t_y = pue_f p_x p_y q_x q_y r_x r_y. +Proof. by rewrite /pue_f; mc_ring. Qed. + +Lemma pue_f_linear l a b c d e f : +l * pue_f a b c d e f = pue_f a (l*b) c (l*d) e (l*f). +Proof. +rewrite /pue_f. +mc_ring. +Qed. + +Lemma pue_f_on_edge_y a_x a_y b_x b_y m_x m_y : + pue_f m_x m_y a_x a_y b_x b_y = 0 -> + (b_x - a_x) * m_y = m_x * (b_y -a_y)- (a_x * b_y - b_x *a_y). +Proof. +move=> abmeq0. +apply/eqP; rewrite -subr_eq0; apply/eqP. +by rewrite -abmeq0 /pue_f; mc_ring. +Qed. + +Lemma pue_f_on_edge a_x a_y b_x b_y c_x c_y d_x d_y m_x m_y : + pue_f m_x m_y a_x a_y b_x b_y = 0 -> + (b_x - a_x) * pue_f m_x m_y c_x c_y d_x d_y = + (m_x - a_x) * pue_f b_x b_y c_x c_y d_x d_y + + (b_x - m_x) * pue_f a_x a_y c_x c_y d_x d_y. +Proof. +move=> on_ed. +rewrite pue_f_linear /pue_f (pue_f_on_edge_y on_ed). +mc_ring. +Qed. + +Lemma pue_f_triangle_on_edge a_x a_y b_x b_y p_x p_y p'_x p'_y : + pue_f p'_x p'_y a_x a_y b_x b_y = 0 -> + (b_x - a_x) * pue_f p'_x p'_y a_x a_y p_x p_y = + (p'_x - a_x) * pue_f b_x b_y a_x a_y p_x p_y . +Proof. +move=> on_ed. +rewrite pue_f_linear /pue_f (pue_f_on_edge_y on_ed). +mc_ring. +Qed. + +Lemma pue_f_triangle_on_edge' a_x a_y b_x b_y p_x p_y p'_x p'_y : + pue_f p'_x p'_y a_x a_y b_x b_y = 0 -> + (b_x - a_x) * pue_f p'_x p'_y p_x p_y b_x b_y = + (b_x - p'_x) * pue_f a_x a_y p_x p_y b_x b_y . +Proof. +move => on_ed. +rewrite pue_f_linear /pue_f (pue_f_on_edge_y on_ed). +mc_ring. +Qed. + +Lemma pue_f_on_edge_same_point a_x a_y b_x b_y p_x p_y p_x' p_y': + a_x != b_x -> + pue_f p_x p_y a_x a_y b_x b_y = 0 -> + pue_f p_x' p_y' a_x a_y b_x b_y = 0 -> + p_x = p_x' -> p_y = p_y'. +Proof. +move=> axnbx puep0 puep'0. +have pyeq := pue_f_on_edge_y puep0. +have p'yeq := pue_f_on_edge_y puep'0. +move=> xxs; have yys : (b_x - a_x) * p_y = (b_x - a_x) * p_y'. + by rewrite pyeq xxs p'yeq. +move: (axnbx); rewrite eq_sym -subr_eq0. +by move=> /mulfI; exact. +Qed. + +Lemma pue_f_ax5 p_x p_y q_x q_y a_x a_y b_x b_y c_x c_y : + pue_f p_x p_y a_x a_y b_x b_y * + pue_f p_x p_y q_x q_y c_x c_y + + pue_f p_x p_y b_x b_y c_x c_y * + pue_f p_x p_y q_x q_y a_x a_y = + pue_f p_x p_y a_x a_y c_x c_y * + pue_f p_x p_y q_x q_y b_x b_y. +Proof. +rewrite /pue_f; mc_ring. +Qed. + +Lemma pue_f_triangle_decompose a_x a_y b_x b_y c_x c_y d_x d_y : + pue_f a_x a_y c_x c_y d_x d_y = 0 -> + pue_f a_x a_y b_x b_y c_x c_y = + pue_f a_x a_y b_x b_y d_x d_y + + pue_f b_x b_y c_x c_y d_x d_y. +Proof. +move=> online. +rewrite -(ax4 _ _ _ _ _ _ d_x d_y). +rewrite addrC; congr (_ + _). +by rewrite addrC pue_f_o pue_f_c online oppr0 add0r -pue_f_c. +Qed. + +Definition mkmx2 (a b c d : R) := + \matrix_(i < 2, j < 2) + if (i == ord0) && (j == ord0) then a + else if i == ord0 then b + else if j == ord0 then c else d. + +Definition mkcv2 (a b : R) := \col_(i < 2) if i == ord0 then a else b. + +Lemma det_mkmx2 a_x a_y b_x b_y : + \det(mkmx2 a_x a_y b_x b_y) = a_x * b_y - a_y * b_x. +Proof. +rewrite /mkmx2 (expand_det_row _ ord0) big_ord_recr /= big_ord1 /=. +by rewrite /cofactor /= expr0 expr1 mulNr !mul1r !det_mx11 !mxE /= mulrN. +Qed. + +Lemma line_intersection a_x a_y b_x b_y c_x c_y d_x d_y : + c_x != d_x -> + 0 < pue_f c_x c_y a_x a_y b_x b_y -> + pue_f d_x d_y a_x a_y b_x b_y < 0 -> + exists p_x p_y, + pue_f p_x p_y a_x a_y b_x b_y = 0 /\ + pue_f p_x p_y c_x c_y d_x d_y = 0 /\ + (forall q_x q_y, pue_f q_x q_y a_x a_y b_x b_y = 0 -> + pue_f q_x q_y c_x c_y d_x d_y = 0 -> p_x = q_x /\ p_y = q_y). +Proof. +move=> cltd cabove cunder. +set A := a_y - b_y; set B := b_x - a_x; set C := \det(mkmx2 a_x a_y b_x b_y). +have puef1_id x y : pue_f x y a_x a_y b_x b_y = A * x + B * y + C. + by rewrite /A /B /C det_mkmx2 /pue_f; mc_ring. +set D := c_y - d_y; set E := d_x - c_x; set F := \det(mkmx2 c_x c_y d_x d_y). +have puef2_id x y : pue_f x y c_x c_y d_x d_y = D * x + E * y + F. + by rewrite /D /E /F det_mkmx2 /pue_f; mc_ring. +set M := mkmx2 A B D E. +set V1 := mkcv2 (b_x - a_x) (b_y - a_y). +set V2 := mkcv2 (d_x - c_x) (d_y - c_y). +have sys_to_mx_eqn : + forall x y, (A * x + B * y + C = 0 /\ D * x + E * y + F = 0) <-> + (M *m mkcv2 x y + mkcv2 C F = 0). + move=> x y; split. + move=> [eq1 eq2]; apply/matrixP=> i j. + rewrite !mxE big_ord_recr /= big_ord1 /= !mxE. + by case : j => [ [ | j ] ] //= _; case : i => [ [ | [ | i]]]. + move/matrixP=> mxq. + split. + have := mxq (Ordinal (isT : (0 < 2)%N)) (Ordinal (isT : (0 < 1)%N)). + by rewrite !mxE big_ord_recr /= big_ord1 /= !mxE. + have := mxq (Ordinal (isT : (1 < 2)%N)) (Ordinal (isT : (0 < 1)%N)). + by rewrite !mxE big_ord_recr /= big_ord1 /= !mxE. +set sol := - (M ^-1 *m mkcv2 C F) : 'cV_2. +have soleq : sol = mkcv2 (sol ord0 ord0) (sol ord_max ord0). + apply/matrixP=> [][[ | [ | i]]] // ip [ [ | j]] // jp; rewrite /= !mxE /=; + (rewrite (_ : Ordinal jp = ord0); last apply: val_inj=> //). + by rewrite (_ : Ordinal ip = ord0); last apply: val_inj. + by rewrite (_ : Ordinal ip = ord_max); last apply: val_inj. +have detm : \det M != 0. + have dets : \det M = A * E - D * B. + rewrite (expand_det_col _ ord0) big_ord_recr /= big_ord1 !mxE /= /cofactor. + by rewrite !det_mx11 /= expr1 expr0 !mulNr !mulrN !mul1r !mxE. + have -> : \det M = pue_f d_x d_y a_x a_y b_x b_y - + pue_f c_x c_y a_x a_y b_x b_y. + by rewrite dets /pue_f /A /B /D /E; mc_ring. + rewrite subr_eq0; apply/eqP=> abs; move: cabove cunder; rewrite abs=> ca cu. + by have := lt_trans ca cu; rewrite ltxx. +have Munit : M \in unitmx by rewrite unitmxE unitfE. +have solm : M *m sol + mkcv2 C F = 0. + rewrite /sol mulmxN mulmxA mulmxV; last by rewrite unitmxE unitfE. + by rewrite mul1mx addNr. +move: (solm); rewrite soleq -sys_to_mx_eqn => [][sol1 sol2]. +exists (sol ord0 ord0), (sol ord_max ord0). +split; first by rewrite puef1_id. +split; first by rewrite puef2_id. +move=> qx qy; rewrite puef1_id puef2_id=> tmp1 tmp2; have := conj tmp1 tmp2. +rewrite sys_to_mx_eqn addrC => /addr0_eq solmq {tmp1 tmp2}. +suff/matrixP mq : mkcv2 qx qy = sol. + by split; rewrite -?(mq ord0 ord0) -?(mq ord_max ord0) mxE. +by rewrite /sol -mulmxN solmq mulKmx. +Qed. + +Lemma pue_f_eq_slopes ax ay bx b_y mx my : + pue_f mx my ax ay bx b_y = + (my - ay) * (bx - ax) - (mx - ax) * (b_y - ay) /\ + pue_f mx my ax ay bx b_y = + -((b_y - my) * (bx - ax) - (bx - mx) * (b_y - ay)). +Proof. +split; rewrite /pue_f; mc_ring. +Qed. + +Lemma edge_and_left_vertical_f px py qx qy ax ay : + px < ax -> px = qx -> + (0 < pue_f px py qx qy ax ay) = (qy < py). +Proof. +move=> edge_cond <-. +rewrite [X in (0 < X)](_ : _ = (ax - px) * (py - qy)); last first. + by rewrite /pue_f; mc_ring. +by rewrite pmulr_rgt0 subr_gt0. +Qed. + +Lemma edge_and_right_vertical_f px py qx qy ax ay : + ax < px -> px = qx -> (0 < pue_f px py qx qy ax ay) = (py < qy). +Proof. +move=> edge_cond <-. +rewrite [X in (0 < X)](_ : _ = (px - ax) * (qy - py)); last first. + by rewrite /pue_f; mc_ring. +by rewrite pmulr_rgt0 subr_gt0. +Qed. + +End ring_sandbox. + +Lemma area3E a b c : area3 a b c = + pue_f a.x (a.y) b.x (b.y) c.x (c.y). +Proof. by case: a b c=> [a_x a_y] [b_x b_y] [c_x c_y]. Qed. + +Lemma area3_opposite a b d: area3 d a b = - area3 b a d. +Proof. + move: a b d => [ax ay] [b_x b_y] [dx dy]/=. + apply :pue_f_o. +Qed. + +Lemma area3_cycle a b d : area3 d a b = area3 b d a. +Proof. + move: a b d => [ax ay] [b_x b_y] [dx dy]/=. + apply :pue_f_c. +Qed. + +Lemma area3_vert a b c : (b.x = c.x) -> + area3 a b c = (b.x - a.x) * (c.y - b.y). +Proof. +move: a b c => [ax ay] [b_x b_y] [cx cy]/= <-. +exact: pue_f_vert. +Qed. + +Lemma ax4_three_triangles p q r t : + area3 t q r + area3 p t r + area3 p q t = area3 p q r. +Proof. +move : p q r t => [px py] [q_x q_y] [rx ry] [t_x t_y]/= . +exact: ax4. +Qed. + +Lemma area3_two_points a b : + area3 a a b = 0 /\ + area3 a b a = 0 /\ + area3 a b b = 0. +Proof. +move : a b => [ax ay] [b_x b_y] /=. +exact: pue_f_two_points. +Qed. + +Lemma area3_on_edge a b c d m : + area3 m a b = 0 -> + (b.x - a.x) * area3 m c d = + (m.x - a.x) * area3 b c d + (b.x - m.x) * area3 a c d. +Proof. +move : a b c d m => [ax ay] [b_x b_y] [cx cy] [dx dy] [mx my]/=. +apply: pue_f_on_edge. +Qed. + +Lemma area3_on_edge_y a b m : + area3 m a b = 0 -> + (b.x - a.x) * m.y = m.x * (b.y - a.y) - (a.x * b.y - b.x * a.y). +Proof. +move : a b m => [ax ay] [b_x b_y] [mx my]/=. +exact: pue_f_on_edge_y. +Qed. + +Lemma area3_triangle_on_edge a b p p' : + area3 p' a b = 0 -> + (b.x - a.x) * area3 p' a p = + (p'.x - a.x) * area3 b a p. +Proof. +move : a b p p' => [ax ay] [b_x b_y] [px py] [p'x p'y] /=. +exact: pue_f_triangle_on_edge. +Qed. + +Definition subpoint (p : pt) := + Bpt (p.x) (p.y - 1). + +Lemma edge_and_left_vertical (p q a : pt) : + p.x < a.x -> p.x = q.x -> + (0 < area3 p q a) = (q.y < p.y). +Proof. +case: p=> [px py]; case: a=> [ax ay]; case: q=> [qx qy] /=. +by move=> c1 c2; apply edge_and_left_vertical_f. +Qed. + +Lemma edge_and_left_vertical_eq (p q a : pt) : + p.x < a.x -> p.x = q.x -> + (area3 p q a == 0) = (p == q). +Proof. +move=> edge_cond vert_cond. +apply/idP/idP; last first. + by move/eqP ->; rewrite (area3_two_points q a).1. +move=> abs; suff : p.y = q.y. + by move: vert_cond {edge_cond abs}; case: p=> [? ?]; case q=> [? ?]/= <- <-. +apply: le_anti. rewrite (leNgt (p.y) (q.y)). +rewrite -(edge_and_left_vertical edge_cond vert_cond) (eqP abs). +have ec' : q.x < a.x by rewrite -vert_cond. +rewrite leNgt -(edge_and_left_vertical ec' (esym vert_cond)). +by rewrite area3_opposite -area3_cycle (eqP abs) oppr0 ltxx. +Qed. + +Lemma edge_and_right_vertical (p q a : pt) : + a.x < p.x -> p.x = q.x -> + (0 < area3 p q a) = (p.y < q.y). +Proof. +case: p=> [px py]; case: a=> [ax ay]; case: q=> [qx qy] /=. +by move=> c1 c2; apply: edge_and_right_vertical_f. +Qed. + +Lemma point_sub_right (p a : pt) : + (p.x < a.x) -> 0 < area3 p (subpoint p) a. +Proof. +move=> edge_cond. +rewrite edge_and_left_vertical //; rewrite /subpoint /= lterBDr cprD. +by rewrite ltr01. +Qed. + +Lemma underW p e : + (p <<< e) -> + (p <<= e). +Proof. +move=> /andP[] _ it; exact: it. +Qed. + +Lemma underWC p e : +~~ (p <<= e) -> ~~ (p <<< e). +Proof. by move/negP=> it; apply/negP=> it'; case: it; apply : underW. Qed. + +Definition valid_edge := + generic_trajectories.valid_edge R le edge left_pt right_pt. + +Lemma valid_edge_extremities e0 p: + (left_pt e0 == p) || (right_pt e0 == p) -> + valid_edge e0 p. +Proof. +rewrite /valid_edge/generic_trajectories.valid_edge. +by move => /orP [/eqP eq |/eqP eq ]; +rewrite -eq lexx ?andbT /= {eq} ltW // ; case : e0 . +Qed. + +Lemma valid_edge_left g : valid_edge g (left_pt g). +Proof. +by apply: valid_edge_extremities; rewrite eqxx. +Qed. + +Lemma valid_edge_right g : valid_edge g (right_pt g). +Proof. +by apply: valid_edge_extremities; rewrite eqxx orbT. +Qed. + +Definition point_on_edge (p : pt) (e : edge) : bool := + (area3 p (left_pt e) (right_pt e) == 0) && valid_edge e p. + +Notation "p '===' e" := (point_on_edge p e) (at level 70, no associativity). + +Definition edge_below (e1 : edge) (e2 : edge) : bool := +((left_pt e1 <<= e2) && (right_pt e1 <<= e2)) +|| (~~ (left_pt e2 <<< e1) && ~~ (right_pt e2<<< e1)). + +Notation "e1 '<|' e2" := (edge_below e1 e2)( at level 70, no associativity). + +Definition below_alt (e1 : edge) (e2 : edge) := + edge_below e1 e2 \/ edge_below e2 e1. + +Lemma edge_below_refl e : e <| e. +Proof. +apply/orP; left. +rewrite 2!underE. +rewrite (proj1 (area3_two_points _ _)). +by rewrite (proj1 (proj2 (area3_two_points _ _))) lexx. +Qed. + +Lemma below_altC e1 e2 : below_alt e1 e2 <-> below_alt e2 e1. +Proof. by rewrite /below_alt or_comm. Qed. + +Lemma below_altN e1 e2 : below_alt e1 e2 -> ~~(e2 <| e1) -> e1 <| e2. +Proof. by move=> []// ->. Qed. + +Definition inter_at_ext (e1 e2 : edge) := + e1 = e2 \/ + forall p, p === e1 -> p === e2 -> p \in [:: left_pt e1; right_pt e1]. + +Definition inter_at_ext' (e1 e2 : edge) := + e1 = e2 \/ + forall p, p === e2 -> p === e1 -> p \in [:: left_pt e2; right_pt e2]. + +Lemma inter_at_ext_sym (s : seq edge) : + {in s &, forall e1 e2, inter_at_ext e1 e2} -> + {in s &, forall e1 e2, inter_at_ext' e1 e2}. +Proof. +move=> cnd e1 e2 e1in e2in; case: (cnd e2 e1 e2in e1in). + by move=> ->; left. +by move=> subcnd; right=> p pe2 pe1; apply: subcnd. +Qed. + +Definition no_crossing := forall e1 e2, below_alt e1 e2. + +Definition no_crossing' : Prop := + forall e e' : edge, + valid_edge e (left_pt e') -> +(left_pt e' <<< e -> e' <| e) /\ +(~ (left_pt e' <<= e) -> e <| e'). + +Lemma left_on_edge e : left_pt e === e. +Proof. +move : e => [ l r inE]. +rewrite /point_on_edge //=. +have [->/= _] := area3_two_points l r. +rewrite eqxx/=. +by apply/andP; split => //; exact: ltW. +Qed. + +Lemma right_on_edge e : right_pt e === e. +Proof. +move : e => [ l r inE]. +rewrite /point_on_edge //=. +have [_ [->/= _]] := area3_two_points r l. +rewrite eqxx/=. +by apply/andP; split => //; exact: ltW. +Qed. + +Lemma point_on_edge_above low_e high_e a : + a === high_e -> + ~~ (left_pt high_e <<< low_e) -> + ~~ (right_pt high_e <<< low_e) -> + ~~ (a <<< low_e). +Proof. +move : high_e => [lr hr inH] /=. +rewrite /point_on_edge /valid_edge => /andP [] /= /eqP poea /andP [] linfa ainfr. +have pf := area3_on_edge (left_pt low_e) (right_pt low_e) poea. +rewrite /point_strictly_under_edge. +rewrite /generic_trajectories.point_strictly_under_edge subrr. +rewrite !R_ltb_lt -!leNgt => llrllh llrllrh. +have diffa : lr.x - a.x <= 0 by rewrite subr_cp0. +have diffb : hr.x - a.x >= 0 by rewrite subr_cp0. +have difflh : lr.x - hr.x < 0 by rewrite subr_cp0. +rewrite -(ler_nM2l difflh _ 0) mulr0 -opprB mulNr oppr_le0 pf. +by rewrite addr_ge0 // mulr_ge0 // subr_ge0. +Qed. + +Lemma point_on_edge_above_strict low_e high_e a : + a === high_e -> + left_pt high_e >>> low_e -> + right_pt high_e >>> low_e -> + a >>> low_e. +Proof. +move : high_e => [lr hr inH] /=. +rewrite /point_on_edge /valid_edge => /andP [] /= /eqP poea /andP [] linfa ainfr. +have pf := area3_on_edge (left_pt low_e) (right_pt low_e) poea. +rewrite /point_under_edge -!ltNge !subrr => llrllh llrllrh. +have diffa : lr.x - a.x <= 0 by rewrite subr_cp0. +have diffb : hr.x - a.x >= 0 by rewrite subr_cp0. +have difflh : lr.x - hr.x < 0 by rewrite subr_cp0. +rewrite -(ltr_nM2l difflh _ 0) mulr0 -opprB mulNr oppr_lt0 pf. +have addr_le_gt0 (x y : R) : 0 <= x -> 0 < y -> 0 < x + y. + move=> xge0 ygt0; rewrite -(add0r 0). + by apply: ler_ltD. +move: diffa; rewrite le_eqVlt=> /orP[ | diffa]; last first. + rewrite addrC addr_le_gt0 // ?mulr_gt0 ?mulr_ge0 //. + by rewrite ltW. + by rewrite subr_gt0 -subr_lt0. +rewrite subr_eq0=> /eqP /[dup] lraq <-; rewrite subrr mul0r add0r. +by rewrite mulr_gt0 // subr_gt0. +Qed. + +Lemma point_on_edge_under low_e high_e a : + a === (low_e) -> + left_pt low_e <<= high_e -> + right_pt low_e <<= high_e -> + a <<= high_e. +Proof. +move : low_e => [lr hr inH] /=. +rewrite /point_on_edge /valid_edge => /andP [] /= /eqP poea /andP [] linfa ainfr. +have pf := area3_on_edge (left_pt high_e) (right_pt high_e) poea. +rewrite /point_under_edge /generic_trajectories.point_under_edge !subrr=> llrllh llrllrh. +have diffa : lr.x - a.x <= 0 by rewrite subr_cp0. +have diffb : hr.x - a.x >= 0 by rewrite subr_cp0. +have difflh : lr.x - hr.x < 0 by rewrite subr_cp0. +rewrite -(ler_nM2r difflh 0 _) mul0r mulrC -opprB mulNr pf opprD. +by rewrite addr_ge0 // -mulNr mulr_le0 // oppr_le0 subr_cp0. +Qed. + +Lemma point_on_edge_under_strict high_e low_e a : + a === low_e -> + left_pt low_e <<< high_e -> + right_pt low_e <<< high_e -> + a <<< high_e. +Proof. +move : low_e => [lr hr inH] /=. +rewrite /point_on_edge /valid_edge => /andP [] /= /eqP poea /andP [] linfa ainfr. +have pf := area3_on_edge (left_pt high_e) (right_pt high_e) poea. +rewrite /point_strictly_under_edge. +rewrite/generic_trajectories.point_strictly_under_edge. +rewrite !R_ltb_lt !subrr=> llrllh llrllrh. +have diffa : lr.x - a.x <= 0 by rewrite subr_cp0. +have diffb : hr.x - a.x >= 0 by rewrite subr_cp0. +have difflh : lr.x - hr.x < 0 by rewrite subr_cp0. +rewrite -(ltr_nM2l difflh 0) mulr0 -opprB mulNr oppr_gt0 pf. +have addr_le_lt0 (x y : R) : x <= 0 -> y < 0 -> x + y < 0. + by move=> xle0 ylt0; rewrite -(add0r 0) ler_ltD. +move: diffa; rewrite le_eqVlt=> /orP[ | diffa]; last first. + rewrite addrC addr_le_lt0 // ?nmulr_llt0 ?mulr_ge0_le0 //. + by rewrite ltW. + by rewrite subr_gt0 -subr_lt0. +rewrite subr_eq0=> /eqP /[dup] lraq <-; rewrite subrr mul0r add0r. +by rewrite nmulr_llt0 // subr_gt0. +Qed. + +Lemma not_strictly_above' low_e high_e p': + ~~ (left_pt (high_e) <<< low_e) -> + ~~ (right_pt (high_e) <<< low_e) -> + p' === high_e -> (right_pt (low_e)).x = p'.x -> + right_pt (low_e) <<= high_e . +Proof. +move : low_e => [ll lr inL] /=. +move => pablh pabrh poep' eqxp'p. +have /= puefcpp' := area3_vert (left_pt (Bedge inL)) eqxp'p . +have := (point_on_edge_above poep' pablh pabrh ). +rewrite strictE. +rewrite -area3_cycle -leNgt puefcpp' underE. +have inle : lr.x - ll.x > 0 by rewrite subr_cp0. +rewrite (pmulr_rge0 _ inle) => inp'lr. +have <- := ax4_three_triangles lr (left_pt high_e) (right_pt high_e) p'. +move : poep'. +rewrite /point_on_edge=> /andP [] /eqP pue0 valp'. +rewrite pue0. +have := (area3_vert (right_pt high_e) eqxp'p ). +rewrite -area3_cycle eqxp'p => ->. +move : valp'. +rewrite /valid_edge => /andP [] xlhp' xrhp'. +have xrhp'0: p'.x - (right_pt high_e).x <= 0 by rewrite subr_cp0. +rewrite add0r -oppr_ge0 opprD /= addr_ge0//. + by rewrite -mulNr mulr_ge0 // oppr_ge0. +have := area3_vert (left_pt high_e) eqxp'p. +rewrite -area3_opposite area3_cycle eqxp'p => ->. +have xlhp'0: p'.x - (left_pt high_e).x >= 0 by rewrite subr_cp0. +by rewrite mulr_ge0. +Qed. + +Lemma under_above_on e p : valid_edge e p -> p <<= e -> p >>= e -> p === e. +Proof. +move=> v u a; apply/andP; split => //. +apply/eqP/le_anti/andP;split. + by move: u; rewrite /point_under_edge /generic_trajectories.point_under_edge !subrr. +move: a; rewrite /point_strictly_under_edge. +rewrite /generic_trajectories.point_strictly_under_edge subrr. +by rewrite R_ltb_lt leNgt=> it; exact: it. +Qed. + +(* returns the point of the intersection between a vertical edge + intersecting p and the edge e if it exists, None if it doesn't *) + +Definition vertical_intersection_point (p : pt) (e : edge) : option pt := + vertical_intersection_point R le +%R (fun x y => x - y) *%R + (fun x y => x / y) edge left_pt right_pt p e. + +Lemma vertical_none p e : + ~~ valid_edge e p -> vertical_intersection_point p e = None. +Proof. +move: p e => [px py] [[ax ay] [b_x b_y] ab] h /=. +rewrite /vertical_intersection_point. +rewrite /generic_trajectories.vertical_intersection_point /=. +by rewrite /valid_edge in h; rewrite (negbTE h). +Qed. + +Lemma vertical_correct p e : + match vertical_intersection_point p e with + None => ~~ valid_edge e p | Some(i) => i === e end. +Proof. +move: p e => [ptx pty] [[ax ay] [bx b_y] /=ab] . +rewrite /vertical_intersection_point/valid_edge. +rewrite /generic_trajectories.vertical_intersection_point. +case : ifP => /= h ; last by []. +have: ax != bx by rewrite neq_lt ab. +set py := ((b_y - ay) / (bx - ax) * ptx + (ay - (b_y - ay) / (bx - ax) * ax)). +move => h2. +rewrite /point_on_edge . +apply/andP; split; last exact h. +apply/eqP. +apply pue_f_inters => //. +by rewrite eq_sym. +Qed. + +Lemma exists_point_valid e p : + valid_edge e p -> + exists p', vertical_intersection_point p e = Some p'. +Proof. +have := vertical_correct p e. +case : (vertical_intersection_point p e)=> [vp |//= a b]. + rewrite /point_on_edge => a b. + by exists vp. +exists p. +by rewrite b in a. +Qed. + +Lemma intersection_on_edge e p p' : + vertical_intersection_point p e = Some p' -> + p' === e /\ p.x = p'.x. +Proof. +have := vertical_correct p e. +case vert : (vertical_intersection_point p e)=> [vp |//=]. +move: vert. +rewrite /vertical_intersection_point. +rewrite /generic_trajectories.vertical_intersection_point. +case : (generic_trajectories.valid_edge _ _ _ _ _ e p) => [| //]. +move => [] /= vpq poe [] <-. +by rewrite poe -vpq. +Qed. + +Lemma not_strictly_under' low_e high_e p' : + left_pt (low_e) <<= high_e -> + right_pt (low_e) <<= high_e -> +(* This is an alternative way to say + valid_edge low_e (right_pt high_e) *) + p' === low_e -> (right_pt (high_e)).x = p'.x -> + ~~ (right_pt (high_e) <<< low_e). +Proof. +move : high_e => [hl hr inH] /=. +move => pablh pabrh poep' eqxp'p. +have /= puefcpp' := area3_vert (left_pt (Bedge inH)) eqxp'p . +have := point_on_edge_under poep' pablh pabrh. +rewrite underE strictE. +rewrite -area3_cycle. +rewrite -leNgt puefcpp'. +have inle : hr.x - hl.x > 0 by rewrite subr_cp0. +rewrite (pmulr_rle0 _ inle ) => inp'hr. +have <- := ax4_three_triangles hr (left_pt low_e) (right_pt low_e) p'. +move : poep'. +rewrite /point_on_edge=> /andP [] /eqP pue0 valp'. +rewrite pue0. +have := area3_vert (right_pt low_e) eqxp'p. +rewrite -area3_cycle eqxp'p => ->. +move : valp'. +rewrite /valid_edge => /andP [] xlhp' xrhp'. +have xrhp'0 : p'.x - (right_pt low_e).x <= 0 by rewrite subr_cp0. +rewrite add0r addr_ge0// ?mulr_le0//. +have := area3_vert (left_pt low_e) eqxp'p. +rewrite area3_opposite -area3_cycle eqxp'p => /eqP; rewrite eqr_oppLR => /eqP ->. +by rewrite -mulNr mulr_le0 // oppr_le0 subr_cp0. +Qed. + +Lemma pue_right_edge e p : (right_pt e).x = p.x -> + (p <<= e) = (p.y - (right_pt e).y <= 0). +Proof. +move : e p => [[ax ay][bx b_y] /= inE] [px py] /=. +rewrite /point_under_edge/generic_trajectories.point_under_edge /= => <-/=. +have := pue_f_vert py ax ay bx b_y. +rewrite pue_f_c /pue_f => ->. +rewrite -subr_cp0 -opprB oppr_lt0 in inE. +by rewrite subrr (pmulr_rle0 _ inE) . +Qed. + +Lemma psue_right_edge e p : (right_pt e).x = p.x -> + (p <<< e) = (p.y - (right_pt e).y < 0). +Proof. +move : e p => [[ax ay][bx b_y] /= cnd] [px py] /=. +rewrite /point_strictly_under_edge/generic_trajectories.point_strictly_under_edge /=. +rewrite R_ltb_lt => <- /=. +have := pue_f_vert py ax ay bx b_y. +rewrite pue_f_c /pue_f => ->. +rewrite -subr_gt0 in cnd. +by rewrite subrr (pmulr_rlt0 _ cnd). +Qed. + +Lemma pue_left_edge e p : (left_pt e).x = p.x -> + (p <<= e) = (0 <= (left_pt e).y - p.y). +Proof. +move : e p => [[ax ay][bx b_y] /= inE] [px py] /=. +rewrite /point_under_edge. +rewrite /generic_trajectories.point_under_edge /= => <- /=. +have := pue_f_vert ay bx b_y ax py. +rewrite -pue_f_c /pue_f => ->. +rewrite -subr_cp0 in inE. +by rewrite subrr (nmulr_rle0 _ inE). +Qed. + +Lemma psue_left_edge e p : (left_pt e).x = p.x -> + (p <<< e) = (0 < (left_pt e).y - p.y). +Proof. +move: e p => [[ax ay][bx b_y] /= cnd] [px py] /= <- /=. +rewrite /point_strictly_under_edge. +rewrite /generic_trajectories.point_strictly_under_edge /=. +rewrite R_ltb_lt. +have := pue_f_vert ay bx b_y ax py. +rewrite -pue_f_c /pue_f => ->. +rewrite -subr_cp0 in cnd. +by rewrite subrr (nmulr_rlt0 _ cnd). +Qed. + +Lemma not_strictly_under low_e high_e : + left_pt low_e <<= high_e -> + right_pt low_e <<= high_e -> + valid_edge low_e (right_pt high_e) -> + ~~ (right_pt high_e <<< low_e). +Proof. +move => pableft pabright valright. +have [p' vip] := exists_point_valid valright. +have := intersection_on_edge vip => [][] poep' eqx. +by apply: not_strictly_under' pableft pabright poep' eqx. +Qed. + +Lemma not_strictly_above low_e high_e : + ~~ (left_pt high_e <<< low_e) -> + ~~ (right_pt high_e <<< low_e) -> + valid_edge high_e (right_pt low_e) -> + right_pt low_e <<= high_e. +Proof. +move => pableft pabright valright. +have [p' vip] := exists_point_valid valright. +have := intersection_on_edge vip => [][] poep' eqx. +by apply: not_strictly_above' pableft pabright poep' eqx. +Qed. + +Lemma on_edge_same_point e p p': + p === e -> p' === e -> + p.x = p'.x -> p.y = p'.y. +Proof. +move : e => [l r ec]. +rewrite /point_on_edge /= => /andP [] p0 _ /andP[] p'0 _. +have dif : l.x != r.x. + by apply/eqP=> abs; move: ec; rewrite abs ltxx. +move: l r p0 p'0 dif {ec}=> [a_x a_y][b_x b_y] /eqP p0 /eqP p'0 dif. +move: p p' p0 p'0 => [x y] [x' y'] puep0 puep'0. +exact: pue_f_on_edge_same_point dif puep0 puep'0. +Qed. + +Lemma strict_under_edge_lower_y r r' e : + r.x = r'.x -> r' === e -> (r <<< e) = (r.y < r'.y). +Proof. +move=> rr' rone. +have valre : valid_edge e r. + by case/andP: rone; rewrite /valid_edge/generic_trajectories.valid_edge rr'. +move: (valre)=> /andP[] + _; rewrite le_eqVlt=> /orP[/eqP atl| inr]. + have req : r' = left_pt e. + have rltr : r'.x < (right_pt e).x by rewrite -rr' -atl edge_cond. + have /esym := edge_and_left_vertical_eq rltr (esym (etrans atl rr')). + by move/andP: rone => [] -> _ /eqP. + by move/psue_left_edge : atl; rewrite subr_gt0 -req. +have rue' : (r <<< e) = (area3 r (left_pt e) r' < 0). + move: rone=> /andP[] /[dup] tmp /eqP /area3_triangle_on_edge + _ => /(_ r). +(* TODO : fix area3_triangle_on_edge for cycle *) + rewrite (area3_opposite (left_pt _)). + rewrite (area3_opposite (left_pt _) _ (right_pt _)) !mulrN. + move=> /eqP; rewrite eqr_opp => /eqP signcond. + move: (edge_cond e); rewrite -subr_gt0 => /pmulr_rlt0 <-. + rewrite signcond pmulr_rlt0; last by rewrite subr_gt0 -rr'. + rewrite /point_strictly_under_edge. + by rewrite /generic_trajectories.point_strictly_under_edge subrr R_ltb_lt. +have inr' : (left_pt e).x < r'.x by rewrite -rr'. +have /psue_right_edge : (right_pt (Bedge inr')).x = r.x by rewrite /= rr'. +rewrite rue' subr_lt0. +rewrite /point_strictly_under_edge. +by rewrite /generic_trajectories.point_strictly_under_edge subrr R_ltb_lt. +Qed. + +Lemma under_onVstrict e p : valid_edge e p -> + (p <<= e) = (p === e) || (p <<< e). +Proof. +move=> valep. +rewrite /point_under_edge /point_strictly_under_edge /point_on_edge. +rewrite /generic_trajectories.point_strictly_under_edge R_ltb_lt. +rewrite /generic_trajectories.point_under_edge subrr. +by rewrite valep andbT -le_eqVlt. +Qed. + +Lemma onAbove e p : p === e -> ~~ (p <<< e). +Proof. +rewrite /point_on_edge /point_strictly_under_edge. +rewrite /generic_trajectories.point_strictly_under_edge R_ltb_lt subrr. +by move=> /andP[/eqP -> valep]; rewrite ltxx. +Qed. + +Lemma strict_nonAunder e p : valid_edge e p -> + (p <<< e) = (~~ (p === e)) && (p <<= e). +Proof. +move=> valep. +rewrite /point_strictly_under_edge /point_on_edge /point_under_edge. +rewrite /generic_trajectories.point_strictly_under_edge R_ltb_lt. +rewrite /generic_trajectories.point_under_edge !subrr. +by rewrite valep andbT lt_neqAle. +Qed. + +Lemma under_edge_strict_lower_y (r r' : pt) e : + r.x = r'.x -> r != r' -> r <<= e -> r' === e -> r.y < r'.y. +Proof. +move=> xs nq under on'. +have vr : valid_edge e r. + by move: on'; rewrite /valid_edge/generic_trajectories.valid_edge xs=> /andP[]. +move: under; rewrite (under_onVstrict vr)=> /orP[on | ]. + by case/negP: nq; rewrite pt_eqE (on_edge_same_point on on') xs// !eqxx. +by rewrite (strict_under_edge_lower_y xs). +Qed. + +Lemma above_edge_strict_higher_y (r r' : pt) e : + r.x = r'.x -> r != r' -> r >>= e -> r' === e -> r'.y < r.y. +Proof. +move=> xs nq above on'. +have vr : valid_edge e r. + by move: on'; rewrite /valid_edge/generic_trajectories.valid_edge xs=> /andP[]. +move: above; rewrite (strict_under_edge_lower_y xs on') // -leNgt le_eqVlt. +move/orP=> [/eqP ys | //]. +by case/negP: nq; rewrite pt_eqE xs ys !eqxx. +Qed. + +Lemma under_edge_lower_y r r' e : + r.x = r'.x -> r' === e -> (r <<= e) = (r.y <= r'.y). +Proof. +move=> rr' rone. +have valre : valid_edge e r. + by case/andP: rone; rewrite /valid_edge/generic_trajectories.valid_edge rr'. +move: (valre)=> /andP[] + _; rewrite le_eqVlt=> /orP[/eqP atl| inr]. + have req : r' = left_pt e. + have rltr : r'.x < (right_pt e).x by rewrite -rr' -atl edge_cond. + have /esym := edge_and_left_vertical_eq rltr (esym (etrans atl rr')). + by move/andP: rone => [] -> _ /eqP. + by move/pue_left_edge: atl; rewrite subr_ge0 -req. +have rue' : (r <<= e) = (area3 r (left_pt e) r' <= 0). + move: rone=> /andP[] /[dup] tmp /eqP /area3_triangle_on_edge + _ => /(_ r). +(* TODO : fix area3_triangle_on_edge for cycle *) + rewrite (area3_opposite (left_pt _)). + rewrite (area3_opposite (left_pt _) _ (right_pt _)) !mulrN. + move=> /eqP; rewrite inj_eq; last by apply: oppr_inj. + move/eqP => signcond. + move: (edge_cond e); rewrite -subr_gt0 => /pmulr_rle0 <-. + rewrite /point_under_edge/generic_trajectories.point_under_edge subrr. + by rewrite signcond pmulr_rle0; last rewrite subr_gt0 -rr'. +have inr' : (left_pt e).x < r'.x by rewrite -rr'. +rewrite /point_under_edge/generic_trajectories.point_under_edge subrr. +have /pue_right_edge : (right_pt (Bedge inr')).x = r.x by rewrite /= rr'. +move: rue'. +rewrite /point_under_edge/generic_trajectories.point_under_edge subrr=> rue'. +by rewrite rue' subr_le0. +Qed. + +Lemma aligned_trans a a' b p : a.x != b.x -> + area3 a' a b = 0 -> area3 p a b = 0 -> area3 p a' b = 0. +Proof. +rewrite -area3_cycle. +move=> bna /[dup] /area3_triangle_on_edge proc a'ab pab. +apply/eqP. +have /mulfI/inj_eq <- : a.x - b.x != 0 by rewrite subr_eq0. +by rewrite -area3_cycle -(proc _) area3_cycle pab !mulr0. +Qed. + +Lemma area3_change_ext a b a' b' p : + a.x < b.x -> a'.x < b'.x -> + area3 a' a b = 0 -> area3 b' a b = 0 -> + sg (area3 p a b) = sg (area3 p a' b'). +Proof. +move=> altb altb' ona onb. +have /area3_triangle_on_edge := ona => /(_ p) ona'. +have /area3_triangle_on_edge := onb => /(_ p) onb0. +have /area3_triangle_on_edge : area3 b' a' a = 0. + have bna : b.x != a.x by case: ltrgtP altb. + by rewrite (aligned_trans bna) // area3_opposite; + apply/eqP; rewrite oppr_eq0 area3_cycle; exact/eqP. +move=>/(_ p) onb'. +have difab : 0 < b.x - a.x by rewrite subr_gt0. +have difab' : 0 < b'.x - a'.x by rewrite subr_gt0. +have [ | | aa' ] := ltrgtP (a.x) (a'.x); last first. +- set w := Bedge altb. + have/on_edge_same_point tmp : a === Bedge altb by exact: left_on_edge. + have/(tmp _) : a' === Bedge altb. + rewrite /point_on_edge ona /valid_edge/generic_trajectories.valid_edge. + rewrite eqxx/=. + by rewrite /= -aa' lexx ltW. + rewrite aa' => /(_ erefl) ays. + have aa : a = a' by move: (a) (a') aa' ays=> [? ?][? ?] /= -> ->. + rewrite -aa area3_opposite [in RHS]area3_opposite. + rewrite -[RHS]mul1r -(gtr0_sg difab) -sgrM mulrN onb0 [X in _ - X]aa' -mulrN. + by rewrite sgrM (gtr0_sg difab') mul1r. +- rewrite -subr_gt0=> xalta'; rewrite -[RHS]mul1r -(gtr0_sg xalta') -sgrM. + rewrite [in RHS]area3_opposite mulrN onb' -mulrN sgrM (gtr0_sg difab'). + rewrite -area3_opposite -[in RHS]area3_cycle. + rewrite -(gtr0_sg difab) -sgrM ona' [in RHS]area3_opposite. + by rewrite mulrN -mulNr opprB sgrM (gtr0_sg xalta') mul1r. +rewrite -subr_lt0=> xa'lta; apply/esym. +rewrite area3_opposite -[X in -X]mul1r -mulNr sgrM sgrN1. +rewrite -(ltr0_sg xa'lta) -sgrM onb' sgrM (gtr0_sg difab'). +rewrite area3_opposite -area3_cycle sgrN mulrN -(gtr0_sg difab). +rewrite -sgrM ona' -sgrN -mulNr opprB sgrM (ltr0_sg xa'lta). +by rewrite area3_opposite sgrN mulrN mulNr opprK mul1r. +Qed. + +Lemma under_low_imp_under_high low_e high_e p : + left_pt low_e <<= high_e -> + right_pt low_e <<= high_e -> + valid_edge low_e p -> + valid_edge high_e p -> + p <<= low_e -> p <<= high_e. +Proof. +move : low_e high_e => [ll lr inL] [hl hr inH] /= pulh purh vallow valhigh. +have [p' vip] := exists_point_valid vallow. +have := intersection_on_edge vip => [][] poep' eqx'. +have [p'' vip'] := exists_point_valid valhigh. +have := intersection_on_edge vip' => [][] poep'' eqx''{vip' vip}. +have := poep''. +have := poep'. + +rewrite /point_on_edge /valid_edge + /generic_trajectories.valid_edge => /andP [] /= poepf' /andP [] + linfp' p'infr /andP [] /= poepf'' /andP [] linfp'' p''infr. + +rewrite -area3_cycle in poepf'. +rewrite -eqx' in linfp' p'infr. +rewrite -eqx'' in linfp'' p''infr. +move => puep. + +have ydiff : p.y <= p'.y by rewrite -(under_edge_lower_y eqx' poep'). + +rewrite eqx' in eqx''. +have puep' := point_on_edge_under poep' pulh purh. +have y'diff : p'.y <= p''.y by rewrite -(under_edge_lower_y eqx'' poep''). +have y''diff : p.y <= p''.y by rewrite (le_trans ydiff y'diff). +rewrite -eqx' in eqx''. +have := ax4_three_triangles p hl hr p''. +have pHleq := area3_vert hl eqx''. +have /eqP pHreq := (area3_vert hr eqx''). +rewrite -area3_cycle in pHreq. +rewrite area3_opposite -area3_cycle in pHleq. + +move : poepf'' pHreq => /eqP -> /eqP -> . +have : area3 p hl p'' = - ((p.x - hl.x) * (p''.y - p.y)) by rewrite -pHleq opprK. +move => ->. +rewrite add0r -mulrBl. +rewrite [x in (x - _) * _ = _] addrC. +rewrite addrKA opprK. + +rewrite /= {pulh purh vallow valhigh poep' poep'' poepf' puep puep'}. +rewrite underE. +rewrite addrC. +have inH' := inH. +rewrite -subr_cp0 in inH'. +rewrite -subr_ge0 in y''diff. +move => <-. +by rewrite nmulr_rle0. +Qed. + +Lemma under_low_imp_strict_under_high low_e high_e p : + left_pt low_e <<= high_e -> + right_pt low_e <<= high_e -> + valid_edge low_e p -> + valid_edge high_e p -> + p <<< low_e -> p <<< high_e. +Proof. +move : low_e high_e => [ll lr inL] [hl hr inH] /=. +move => pulh purh vallow valhigh. +have [p' vip] := exists_point_valid vallow. +have := intersection_on_edge vip => [][] poep' eqx'. +have [p'' vip'] := exists_point_valid valhigh. +have := intersection_on_edge vip' => [][] poep'' eqx''{vip' vip}. +have := poep''. +have := poep'. + +rewrite /point_on_edge /valid_edge => /andP [] /= poepf' /andP [] + linfp' p'infr /andP [] /= poepf'' /andP [] linfp'' p''infr. + +rewrite -area3_cycle in poepf'. +rewrite -eqx' in linfp' p'infr. +rewrite -eqx'' in linfp'' p''infr. +move => puep. + +have ydiff : p.y < p'.y by rewrite -(strict_under_edge_lower_y eqx' poep'). + +rewrite eqx' in eqx''. +have puep' := point_on_edge_under poep' pulh purh. +have y'diff : p'.y <= p''.y by rewrite -(under_edge_lower_y eqx'' poep''). +have y''diff : p.y < p''.y by rewrite (lt_le_trans ydiff y'diff). +rewrite -eqx' in eqx''. +have := ax4_three_triangles p hl hr p''. +have pHleq := area3_vert hl eqx''. +have /eqP pHreq := area3_vert hr eqx''. +rewrite -area3_cycle in pHreq. +rewrite area3_opposite -area3_cycle in pHleq. + +move : poepf'' pHreq => /eqP -> /eqP -> . +have : area3 p hl p'' = - ((p.x - hl.x) * (p''.y - p.y)). + by rewrite -pHleq opprK. +move => ->. +rewrite add0r -mulrBl. +rewrite [x in (x - _) * _ = _]addrC. +rewrite addrKA opprK. + +rewrite /= {pulh purh vallow valhigh poep' poep'' poepf' puep puep'}. +rewrite addrC. +have inH' := inH. +rewrite -subr_cp0 in inH'. +rewrite -subr_gt0 in y''diff. +rewrite strictE => <-. +by rewrite nmulr_rlt0. +Qed. + +Lemma under_low_imp_under_high_bis low_e high_e p : + ~~ (left_pt high_e <<< low_e) -> + ~~ (right_pt high_e <<< low_e) -> + valid_edge low_e p -> + valid_edge high_e p -> + p <<= low_e -> p <<= high_e. +Proof. +move : low_e high_e => [ll lr inL] [hl hr inH] . +move => pabhl pabhr vallow valhigh. +have [p' vip] := exists_point_valid vallow. +have := intersection_on_edge vip => [][] poep' eqx'. +have [p'' vip'] := exists_point_valid valhigh. +have := intersection_on_edge vip' => [][] poep'' eqx''{vip' vip}. +have := poep''. +have := poep'. + +rewrite /point_on_edge /valid_edge => /andP [] /= poepf' /andP [] + linfp' p'infr /andP [] /= poepf'' /andP [] linfp'' p''infr. + +rewrite -area3_cycle in poepf'. +rewrite -eqx' in linfp' p'infr. +rewrite -eqx'' in linfp'' p''infr. +move => /= puep. + +have ydiff : p.y <= p'.y by rewrite -(under_edge_lower_y eqx' poep'). +rewrite eqx' in eqx''. +symmetry in eqx''. +have pabp' := point_on_edge_above poep'' pabhl pabhr. +have y'diff : p'.y <= p''.y by rewrite leNgt -(strict_under_edge_lower_y eqx'' poep'). +have y''diff : p.y <= p''.y by rewrite (le_trans ydiff y'diff). +rewrite -eqx' in eqx''. +have := ax4_three_triangles p hl hr p''. +have /eqP pHleq := (area3_vert hl eqx''). +have pHreq := area3_vert hr eqx''. + +rewrite area3_opposite in pHreq. +rewrite area3_cycle in pHleq. + +move : poepf'' pHleq => /eqP -> /eqP -> . +have : area3 p p'' hr = - ((p''.x - hr.x) * (p.y - p''.y)) by rewrite -pHreq opprK. +move => ->. +rewrite add0r addrC -mulrBl. +rewrite [x in (x - _) * _ = _]addrC. +rewrite addrKA opprK. + +rewrite /= {pabhl pabhr vallow valhigh poep' poep'' poepf' puep pabp'}. +rewrite addrC. +have inH' := inH. +rewrite -subr_gte0 in inH'. +rewrite -subr_le0 in y''diff. +rewrite underE => <-. +by rewrite pmulr_rle0. +Qed. + +Lemma under_low_imp_strict_under_high_bis low_e high_e p : + ~~ (left_pt high_e <<< low_e) -> + ~~ (right_pt high_e <<< low_e) -> + valid_edge low_e p -> + valid_edge high_e p -> + p <<< low_e -> p <<< high_e. +Proof. +move : low_e high_e => [ll lr inL] [hl hr inH] . +move => pabhl pabhr vallow valhigh. +have [p' vip] := exists_point_valid vallow. +have := intersection_on_edge vip => [][] poep' eqx'. +have [ p'' vip'] := exists_point_valid valhigh. +have := intersection_on_edge vip' => [][] poep'' eqx''{vip' vip}. +have := poep''. +have := poep'. + +rewrite /point_on_edge /valid_edge => /andP [] /= poepf' /andP [] + linfp' p'infr /andP [] /= poepf'' /andP [] linfp'' p''infr. + +rewrite -area3_cycle in poepf'. +rewrite -eqx' in linfp' p'infr. +rewrite -eqx'' in linfp'' p''infr. +move => /= puep. + +have ydiff : p.y < p'.y by rewrite -(strict_under_edge_lower_y eqx' poep'). + +rewrite eqx' in eqx''. +symmetry in eqx''. +have pabp' := point_on_edge_above poep'' pabhl pabhr. +have y'diff : p'.y <= p''.y + by rewrite leNgt -(strict_under_edge_lower_y eqx'' poep'). +have y''diff : p.y < p''.y by rewrite (lt_le_trans ydiff y'diff). +rewrite -eqx' in eqx''. +have := ax4_three_triangles p hl hr p''. +have /eqP pHleq := (area3_vert hl eqx''). +have pHreq := (area3_vert hr eqx''). + +rewrite area3_opposite in pHreq. +rewrite area3_cycle in pHleq. + +move : poepf'' pHleq => /eqP -> /eqP -> . +have : area3 p p'' hr = - ((p''.x - hr.x) * (p.y - p''.y)). + by rewrite -pHreq opprK. +move => ->. +rewrite add0r addrC -mulrBl. +rewrite [x in (x - _) * _ = _]addrC. +rewrite addrKA opprK. + +rewrite /= {pabhl pabhr vallow valhigh poep' poep'' poepf' puep pabp'}. +rewrite addrC. +have inH' := inH. +rewrite -subr_gte0 in inH'. +rewrite -subr_lt0 in y''diff. +rewrite strictE => <-. +by rewrite pmulr_rlt0. +Qed. + +Lemma order_edges_viz_point' low_e high_e p : +valid_edge low_e p -> valid_edge high_e p -> +low_e <| high_e -> +p <<= low_e -> p <<= high_e. +Proof. +move => vallow valhigh. +have := (exists_point_valid vallow ) . +have := (exists_point_valid valhigh ) => [][] ph verhigh [] pl verlow. +have := intersection_on_edge verlow => [][] poepl eqxl. +have := intersection_on_edge verhigh => [][] poeph eqxh. +rewrite /edge_below => /orP [] /andP []. + move => pueplow puephigh. + apply (under_low_imp_under_high pueplow puephigh vallow valhigh). +move => pabpleft pabpright. + apply (under_low_imp_under_high_bis pabpleft pabpright vallow valhigh). +Qed. + +Lemma order_edges_strict_viz_point' low_e high_e p : +valid_edge low_e p -> valid_edge high_e p -> +low_e <| high_e -> +p <<< low_e -> p <<< high_e. +Proof. +move => vallow valhigh. +have := (exists_point_valid vallow ) . +have := (exists_point_valid valhigh ) => [][] ph verhigh [] pl verlow. +have := intersection_on_edge verlow => [][] poepl eqxl. +have := intersection_on_edge verhigh => [][] poeph eqxh. +rewrite /edge_below => /orP [] /andP []. + set A := left_pt low_e. + set B := right_pt low_e. + move => pueplow puephigh. + move => inf0. + have:= inf0; rewrite strictE. + move=> /ltW; rewrite -/A -/B => infeq0. + have := (under_low_imp_strict_under_high pueplow puephigh vallow valhigh inf0). + by rewrite strictE. +move=> pueplow puephigh. +move=> inf0. +by have := (under_low_imp_strict_under_high_bis pueplow puephigh vallow valhigh inf0). +Qed. + +Lemma edge_dir_intersect p1 p2 e1 : + p1.x != p2.x -> + ~~ (p1 <<= e1) -> p2 <<< e1 -> + exists p, area3 p (left_pt e1) (right_pt e1) = 0 /\ + area3 p p1 p2 = 0 /\ + (forall q, area3 q (left_pt e1) (right_pt e1) = 0 -> + area3 q p1 p2 = 0 -> p = q). +Proof. +move=> dif12. +rewrite underE. +rewrite area3E -ltNge => ca. +rewrite strictE. +rewrite area3E => cu. +have [px [py []]] := line_intersection dif12 ca cu. +rewrite -/((Bpt px py).y); set py' := ((Bpt px py).y). +rewrite -/((Bpt px py).x) /py' {py'}. +move: ca cu; rewrite -4!area3E=> ca cu on_line1 [] on_line2 uniq. +exists (Bpt px py); rewrite on_line1 on_line2;split;[ | split]=> //. +by move=> [qx qy]; rewrite !area3E=> /uniq => U; move=> {}/U[] /= -> ->. +Qed. + +Lemma intersection_middle_au e1 e2 : + ~~ (left_pt e2 <<= e1) -> right_pt e2 <<< e1 -> + exists p, area3 p (left_pt e1) (right_pt e1) = 0 /\ p === e2. +Proof. +move=> /[dup] ca; rewrite -ltNge subrr=> ca' /[dup] cu cu'. +rewrite strictE in cu'. +have le2xnre2x : (left_pt e2).x != (right_pt e2).x. + by have := edge_cond e2; rewrite lt_neqAle=> /andP[]. +have [p [p1 [p2 pu]]] := edge_dir_intersect le2xnre2x ca cu. +exists p; rewrite p1; split=> //. +rewrite /point_on_edge p2 eqxx /= /valid_edge. +rewrite /generic_trajectories.valid_edge. +have ol2 := p2. +have := area3_on_edge (left_pt e1) (right_pt e1) ol2 => /=. +rewrite p1 mulr0 => /esym/eqP; rewrite addrC addr_eq0 -mulNr opprB=> /eqP signcond. +case : (ltP (p.x) ((right_pt e2).x)). + move=>/[dup]/ltW ->; rewrite andbT -subr_gt0 -subr_le0. + rewrite -(pmulr_lgt0 _ ca') signcond. + by rewrite nmulr_lgt0 // => /ltW. +move=>/[dup] re2lp. +rewrite -subr_le0 -(pmulr_lle0 _ ca') signcond. +by rewrite nmulr_lle0 // subr_ge0=> /(le_trans re2lp); rewrite leNgt edge_cond. +Qed. + +Lemma intersection_middle_ua e1 e2 : + left_pt e2 <<< e1 -> ~~(right_pt e2 <<= e1) -> + exists p, area3 p (left_pt e1) (right_pt e1) = 0 /\ p === e2. +Proof. +move=> /[dup] cu cu' /[dup] ca; rewrite -ltNge subrr=> ca'. +rewrite strictE in cu'. +have re2xnle2x : (right_pt e2).x != (left_pt e2).x. + by have := edge_cond e2; rewrite lt_neqAle eq_sym=> /andP[]. +have [p [p1 [p2 pu]]] := edge_dir_intersect re2xnle2x ca cu. +move: p2; rewrite area3_opposite area3_cycle => /eqP. +rewrite oppr_eq0=> /[dup] /eqP ol2 p2. +exists p; rewrite p1; split=> //. +rewrite /point_on_edge p2/= /valid_edge. +rewrite /generic_trajectories.valid_edge. +have := area3_on_edge (left_pt e1) (right_pt e1) ol2 => /=. +rewrite p1 mulr0 => /esym/eqP; rewrite addrC addr_eq0 -mulNr opprB=> /eqP signcond. +case : (ltP (p.x) ((right_pt e2).x)). + move=>/[dup]/ltW ->; rewrite andbT -subr_gt0 -subr_le0. + rewrite -(nmulr_llt0 _ cu') signcond. + by rewrite pmulr_llt0 // => /ltW. +move=>/[dup] re2lp. +rewrite -subr_le0 -(nmulr_lge0 _ cu') signcond. +by rewrite pmulr_lge0 // subr_ge0=> /(le_trans re2lp); rewrite leNgt edge_cond. +Qed. + +Definition lexPt (p1 p2 : pt) : bool := + (p1.x < p2.x) || ((p1.x == p2.x) && (p1.y < p2.y)). + +Definition lexePt (p1 p2 : pt) : bool := + (p1.x < p2.x) || ((p1.x == p2.x) && (p1.y <= p2.y)). + +Lemma lexPtW p1 p2 : lexPt p1 p2 -> lexePt p1 p2. +Proof. +rewrite /lexPt /lexePt =>/orP [-> //=| /andP [] -> y_ineq]. +rewrite ltW //. +by rewrite orbT. +Qed. + +Lemma lexePtNgt (p1 p2 : pt) : lexePt p1 p2 = ~~lexPt p2 p1. +Proof. +rewrite /lexePt /lexPt negb_or negb_and. +rewrite andb_orr -leNgt (andbC (_ <= _)) (eq_sym (p2.x)) -lt_neqAle. +rewrite -leNgt (le_eqVlt (p1.x)). +by case: (p1.x < p2.x) => //; rewrite ?orbF //=. +Qed. + +Lemma lexPtNge (p1 p2 : pt) : lexPt p1 p2 = ~~lexePt p2 p1. +Proof. +rewrite /lexePt /lexPt. +rewrite negb_or -leNgt negb_and (eq_sym (p2.x)) andb_orr (andbC (_ <= _)). +rewrite -lt_neqAle le_eqVlt -ltNge. +by case: (p1.x < p2.x); rewrite // ?orbF. +Qed. + +Lemma lexePt_eqVlt (p1 p2 :pt) : lexePt p1 p2 = (p1 == p2) || lexPt p1 p2. +Proof. +rewrite /lexePt /lexPt. +case: (ltrgtP (p1.x) (p2.x))=> cnd; rewrite ?orbT //= ?orbF. + by apply/esym/negP=> /eqP p1p2; move: cnd; rewrite p1p2 ltxx. +apply/idP/idP. + rewrite orbC le_eqVlt=> /orP[/eqP | ->// ]. + move: cnd; case: p1 => [a b]; case: p2 => [c d]/= -> ->. + by rewrite eqxx orbT. +by move/orP=> [/eqP -> // | /ltW]. +Qed. + +Lemma lexPt_irrefl : irreflexive lexPt. +Proof. +move=> x; apply/negP=> /[dup] abs. +by rewrite lexPtNge lexePt_eqVlt abs orbT. +Qed. + +Lemma lexePt_refl : reflexive lexePt. +Proof. +rewrite /reflexive /lexePt=> p. +by rewrite eqxx le_refl /= orbT. +Qed. + +Lemma lexPt_trans : transitive lexPt. +Proof. + rewrite /transitive /lexPt => p2 p1 p3 => /orP [xineq /orP [xineq2| /andP []/eqP <- yineq]|/andP []/eqP -> yineq /orP [-> //|/andP [] /eqP -> yineq2]] . + by rewrite (lt_trans xineq xineq2). + by rewrite xineq. + by rewrite (lt_trans yineq yineq2) eqxx orbT. +Qed. + +Lemma lexePt_lexPt_trans p1 p2 p3 : +lexePt p1 p2 -> lexPt p2 p3 -> lexPt p1 p3. +Proof. +rewrite /lexePt /lexPt => /orP [x_ineq|/andP [] /eqP -> y_ineq /orP [-> // |/andP []/eqP -> y_s]]. + have : lexPt p1 p2. + by rewrite /lexPt x_ineq. + by apply lexPt_trans. +by rewrite( le_lt_trans y_ineq y_s) eqxx /= orbT. +Qed. + +Lemma lexPt_lexePt_trans p1 p2 p3 : +lexPt p1 p2 -> lexePt p2 p3 -> lexPt p1 p3. +Proof. +move/[swap]. +rewrite /lexePt /lexPt => /orP [x_ineq|/andP [] /eqP -> y_ineq /orP [-> // |/andP []/eqP -> y_s]]. + have : lexPt p2 p3. + by rewrite /lexPt x_ineq. + move/[swap]; apply lexPt_trans. +by rewrite( lt_le_trans y_s y_ineq) eqxx /= orbT. +Qed. + +Lemma lexePt_trans : transitive lexePt. +move => p2 p1 p3; rewrite lexePt_eqVlt => /orP[/eqP-> // | p1p2] p2p3. +by apply/lexPtW/(lexPt_lexePt_trans p1p2). +Qed. + +Lemma lexePt_xW p1 p2 : lexePt p1 p2 -> p1.x <= p2.x. +Proof. +by rewrite /lexePt=> /orP[/ltW | /andP [/eqP -> _]]. +Qed. + +Lemma on_edge_lexePt_left_pt (p : pt) g : + p === g -> lexePt (left_pt g) p. +Proof. +move=> on. +have : (left_pt g).x <= p.x by move: on=> /andP[] _ /andP[]. +rewrite le_eqVlt=> /orP[/eqP/esym /[dup] samex' samex | xlt ]. + have/eqP samey := on_edge_same_point on (left_on_edge _) samex. + have -> : p = left_pt g. + by apply/eqP; rewrite pt_eqE samex' samey !eqxx. + by apply: lexePt_refl. +by rewrite /lexePt xlt. +Qed. + +Lemma trans_edge_below_out p e1 e2 e3 : + left_pt e1 = p -> left_pt e2 = p -> left_pt e3 = p -> + e1 <| e2 -> e2 <| e3 -> e1 <| e3. +Proof. +case: e1 => [d [a_x a_y] /= cpa]. +case: e2 => [d' [b_x b_y] /= cpb]. +case: e3 => [d'' [c_x c_y] /= cpc] dp d'p d''p. +rewrite /edge_below !underE !strictE. +rewrite !area3E; simpl left_pt; simpl right_pt. +move: cpa cpb cpc; rewrite dp d'p d''p {dp d'p d''p}. +case: p=> [px py]; simpl p_x; simpl p_y=> cpa cpb cpc. +move=> c1' c2'. +have c1 : 0 <= pue_f px py a_x a_y b_x b_y. + move: c1'; rewrite !(pue_f_eq _ _ _ _) lexx ltxx !andTb -leNgt. + by rewrite pue_f_o oppr_lte0 (pue_f_c px)=> /orP[]. +have c2 : 0 <= pue_f px py b_x b_y c_x c_y. + move: c2'; rewrite !(pue_f_eq _ _ _ _) lexx ltxx !andTb -leNgt. + by rewrite pue_f_o oppr_lte0 (pue_f_c px)=> /orP[]. +move=> {c1' c2'}. +apply/orP; left. +rewrite (pue_f_eq _ _ _ _) lexx andTb pue_f_o -pue_f_c oppr_lte0. +set p := Bpt px py. +have aright : 0 < area3 p (subpoint p) (Bpt a_x a_y). + by apply: point_sub_right. +have bright : 0 < area3 p (subpoint p) (Bpt b_x b_y). + by apply: point_sub_right. +have cright : 0 < area3 p (subpoint p) (Bpt c_x c_y). + by apply: point_sub_right. +rewrite area3E in aright; simpl p_x in aright; simpl p_y in aright. +rewrite area3E in bright; simpl p_x in bright; simpl p_y in bright. +rewrite area3E in cright; simpl p_x in cright; simpl p_y in cright. +rewrite -(pmulr_lge0 _ bright) -pue_f_ax5. +by apply: addr_ge0; rewrite pmulr_lge0. +Qed. + +Lemma no_crossingE e1 e2 : + below_alt e1 e2 -> valid_edge e2 (left_pt e1) -> + (left_pt e1 <<< e2 -> e1 <| e2) /\ (~~(left_pt e1 <<= e2) -> e2 <| e1). +Proof. +move=> nc ve. +case: (exists_point_valid ve) => [p pP]. +move: (intersection_on_edge pP)=> [pone2 px]. +move: (pone2); rewrite /point_on_edge=> /andP[] pone2' vp. +have xbnd1 : (left_pt e2).x <= (left_pt e1).x by case/andP: ve. +have xbnd2 : (left_pt e1).x <= (right_pt e2).x by case/andP: ve. +have dify : ((left_pt e1 <<< e2) \/ (~~(left_pt e1 <<= e2))) -> (left_pt e1).y != p.y. + move=> disj; apply/negP=> /eqP A. + have {A}-A : p = left_pt e1 by case: (p) (left_pt e1) px A=> [? ?][? ?]/= -> ->. + by move: disj; rewrite under_onVstrict // strict_nonAunder // -A pone2; case. +have pone2'': pue_f ((left_pt e2).x) ((left_pt e2).y) + ((right_pt e2).x) ((right_pt e2).y) + (p.x) (p.y) = 0. + rewrite -pue_f_c; move: pone2'; rewrite area3E pue_f_c. + by move/eqP. +move: (edge_cond e2); rewrite -(subr_gt0 (_.x))=> ce2. +have dife2 : 0 < (right_pt e2).x - (left_pt e2).x. + by move: (edge_cond e2); rewrite -(subr_gt0 (_.x)). +have dife2' : (right_pt e2).x - (left_pt e2).x != 0. + by move: dife2; rewrite lt_neqAle eq_sym=> /andP[]. +have plp2 : (left_pt e2).x = (left_pt e1).x -> p = left_pt e2. + move=> c; have:= on_edge_same_point pone2 (left_on_edge _). + rewrite c px => /(_ erefl); move: px c. + by case: (p) (left_pt e2)=> [? ?][? ?]/= <- <- ->. +have prp2 : (right_pt e2).x = (left_pt e1).x -> p = right_pt e2. + move=> c; have:= on_edge_same_point pone2 (right_on_edge _). + rewrite c px => /(_ erefl); move: px c. + by case: (p) (right_pt e2)=> [? ?][? ?]/= <- <- ->. +have main : (0 < area3 (left_pt e1) (left_pt e2) (right_pt e2)) = + (p.y < (left_pt e1).y). + move: xbnd1; rewrite le_eqVlt=> /orP[/eqP atleft | notleft ]. + have pisl : p = left_pt e2 by apply: plp2. + move: atleft; rewrite -pisl=> atleft; rewrite edge_and_left_vertical //. + by rewrite -atleft pisl (edge_cond e2). + have fact1 : (0 < p.x - (left_pt e2).x) by rewrite subr_gt0 -px. + rewrite -(pmulr_rgt0 _ fact1) area3_opposite mulrN. + rewrite -(area3_triangle_on_edge (left_pt e1) (eqP pone2')) -mulrN. + rewrite -area3_opposite area3_cycle pmulr_rgt0 //. + by apply: edge_and_right_vertical; rewrite -px. +have arith : forall (a b : R), a <= 0 -> b <= 0 -> a + b <= 0. + clear=> a b al0 bl0. + by rewrite -lerBrDr (le_trans al0) // lerBrDr add0r. +have case1 : left_pt e1 <<< e2 -> e1 <| e2. + move=> below; case:(nc) => // /orP[]; last by rewrite below. + move/andP=> []le2b re2b. + have pyne1 : (left_pt e1).y != p.y by apply: dify; left. + have ys : (left_pt e1).y < p.y. + rewrite ltNge le_eqVlt -main negb_or eq_sym pyne1 /= -leNgt le_eqVlt. + by move: (below); rewrite strictE orbC => ->. + have : 0 < area3 p (left_pt e1) (right_pt e1). + by rewrite edge_and_left_vertical // -px (edge_cond e1). + rewrite -(pmulr_rgt0 _ ce2). + rewrite (area3_on_edge (left_pt e1) (right_pt e1) (eqP pone2')). + rewrite ltNge arith //. + apply: mulr_ge0_le0; first by rewrite -px subr_ge0. + by move: re2b; rewrite underE -area3_cycle. + apply: mulr_ge0_le0; first by rewrite -px subr_ge0. + by move: le2b; + rewrite /point_under_edge/generic_trajectories.point_under_edge subrr. +suff case2 : ~~(left_pt e1 <<= e2) -> e2 <| e1 by []. +move=> above; case: (nc) => // /orP[]; first by rewrite (negbTE above). +rewrite !strictE -!leNgt => /andP[] le2a re2a. +have pyne1 : (left_pt e1).y != p.y by apply: dify; right. +have ys : p.y < (left_pt e1).y. + by rewrite -main;move: (above); rewrite /point_under_edge -ltNge subrr. +have : 0 < area3 (left_pt e1) p (right_pt e1). + by rewrite edge_and_left_vertical // (edge_cond e1). +rewrite area3_opposite -area3_cycle. +rewrite -(pmulr_rgt0 _ dife2) mulrN. +rewrite (area3_on_edge (left_pt e1) (right_pt e1) (eqP pone2')). +by rewrite oppr_gt0 ltNge addr_ge0 // mulr_ge0 // -px subr_ge0. +Qed. + + +Lemma inter_at_ext_no_crossing (s : seq edge) : + {in s &, forall e1 e2, inter_at_ext e1 e2} -> + {in s &, no_crossing}. +Proof. +move=> nc e1 e2 e1in e2in. +have nc' := inter_at_ext_sym nc. +have ceq : e1 = e2 -> below_alt e1 e2. + move=> <-; left; apply/orP; left; rewrite !underE. + rewrite (fun a b => proj1 (area3_two_points a b)). + rewrite (fun a b => proj1 (proj2 (area3_two_points a b))). + by rewrite lexx. +have [/eqP/ceq // | e1ne2] := boolP(e1 == e2). +have [/eqP | {}nc ] := nc _ _ e1in e2in; first by rewrite (negbTE e1ne2). +have [/eqP | {}nc' ] := nc' _ _ e1in e2in; first by rewrite (negbTE e1ne2). +have [ | ] := boolP(e1 <| e2); first by left. +have [ | ] := boolP(e2 <| e1); first by right. +rewrite /edge_below. +rewrite !negb_or. rewrite 4!negb_and !negbK. +rewrite /edge_below !underE. +rewrite !strictE => noc. +suff [it | [p [pone1 pone2]]] : + below_alt e1 e2 \/ exists p, p === e1 /\ p === e2; first by []. + have : p \in [:: left_pt e1; right_pt e1] by apply: nc. + rewrite !inE=> pext. + set other := if p == left_pt e1 then right_pt e1 else left_pt e1. + have dif : right_pt e1 != left_pt e1. + apply/eqP=> abs. + move: (edge_cond e1); rewrite lt_neqAle eq_sym => /andP[]. + by rewrite abs eqxx. + have [ u' | /underWC a'] := boolP (other <<= e2). + left; apply/orP; left. + move: (pone2) u'=> /andP[] _ /under_onVstrict. + rewrite pone2 /= /other. + by move: pext=> /orP[] /eqP -> ->; rewrite ?eqxx ?(negbTE dif) ?andbT. + right; apply/orP; right. + move: (pone2) a'=> /andP[] _/strict_nonAunder; rewrite pone2 /= /other. + by move: pext=>/orP[]/eqP -> ->; rewrite ?eqxx ?(negbTE dif)=> ->. +move: noc {nc nc'} => /andP[] /orP[le2a | re2a]. + have le2a' : left_pt e2 >>> e1. + by rewrite /point_under_edge/generic_trajectories.point_under_edge subrr. + have [ re2u | re2a _] := boolP(right_pt e2 <<< e1); last first. + by left; left; apply/orP; right; rewrite re2a underWC. + have dif2 : (left_pt e2).x != (right_pt e2).x. + by have := edge_cond e2; rewrite lt_neqAle => /andP[]. + have [r [_ [ _ uniq]]] := edge_dir_intersect dif2 le2a' re2u. + move=> /orP[le1u | re1u]. + have [re1u | re1a] := boolP(right_pt e1 <<= e2). + left; left; apply/orP; left; rewrite re1u underW //. + by rewrite strictE. + have le1u' : left_pt e1 <<< e2. + by rewrite strictE. + have [p [pe2 pe1]] := intersection_middle_ua le1u' re1a. + have [q [qe1 qe2]] := intersection_middle_au le2a' re2u. + move: (pe1) (qe2)=> /andP[] /eqP pe1' _ /andP[] /eqP qe2' _. + have rq := uniq _ qe1 qe2'; have rp := uniq _ pe1' pe2. + by right; exists r; rewrite [X in X === e2]rq rp. + have [le1u | le1a] := boolP(left_pt e1 <<= e2). + left; left; apply/orP; left; rewrite le1u underW //. + by rewrite strictE. + have [q [qe1 qe2]] := intersection_middle_au le2a' re2u. + have re1u' : right_pt e1 <<< e2. + by rewrite strictE. + have [p [pe2 pe1]] := intersection_middle_au le1a re1u'. + move: (pe1) (qe2)=> /andP[] /eqP pe1' _ /andP[] /eqP qe2' _. + have rq := uniq _ qe1 qe2'; have rp := uniq _ pe1' pe2. + by right; exists r; rewrite [X in X === e2]rq rp. +have re2a' : right_pt e2 >>> e1. + by rewrite /point_under_edge/generic_trajectories.point_under_edge subrr. +have [ le2u | le2a _] := boolP(left_pt e2 <<< e1); last first. + by left; left; apply/orP; right; rewrite le2a underWC. +have dif2 : (right_pt e2).x != (left_pt e2).x. + by have := edge_cond e2; rewrite lt_neqAle eq_sym => /andP[]. +have [r [_ [ _ uniq]]] := edge_dir_intersect dif2 re2a' le2u. +have transfer a b c : area3 a b c = 0 -> area3 a c b = 0. + by move=> abc; rewrite area3_opposite area3_cycle abc oppr0. +move=> /orP[le1u | re1u]. + have [re1u | re1a] := boolP(right_pt e1 <<= e2). + left; left; apply/orP; left; rewrite re1u underW //. + by rewrite strictE. + have le1u' : left_pt e1 <<< e2. + by rewrite strictE. + have [p [/transfer pe2 pe1]] := intersection_middle_ua le1u' re1a. + have [q [qe1 qe2]] := intersection_middle_ua le2u re2a'. + move: (pe1) (qe2)=> /andP[] /eqP pe1' _ /andP[] /eqP /transfer qe2' _. + have rq := uniq _ qe1 qe2'; have rp := uniq _ pe1' pe2. + by right; exists r; rewrite [X in X === e2]rq rp. +have [le1u | le1a] := boolP(left_pt e1 <<= e2). + left; left; apply/orP; left; rewrite le1u underW //. + by rewrite strictE. +have [q [qe1 qe2]] := intersection_middle_ua le2u re2a'. +have re1u' : right_pt e1 <<< e2. + by rewrite strictE. +have [p [/transfer pe2 pe1]] := intersection_middle_au le1a re1u'. +move: (pe1) (qe2)=> /andP[] /eqP pe1' _ /andP[] /eqP /transfer qe2' _. +have rq := uniq _ qe1 qe2'; have rp := uniq _ pe1' pe2. +by right; exists r; rewrite [X in X === e2]rq rp. +Qed. + +Lemma outgoing_conditions (s oe : seq edge) p he le : + p >>> le -> p <<< he -> le \in s -> he \in s -> + valid_edge le p -> valid_edge he p -> + {subset oe <= s} -> + {in s &, no_crossing} -> + {in oe, forall g, left_pt g == p} -> + [/\ {in oe, forall g, le <| g}, {in oe, forall g, g <| he} & + {in oe &, no_crossing}]. +Proof. +move=> pl ph lein hein vl vh oesub noc lefts; split. ++ move=> g gin; have := noc _ _ (oesub _ gin) lein. + move=>/no_crossingE[]; first by rewrite (eqP (lefts _ _)) // sval. + by rewrite (eqP (lefts _ _)) // => _ /(_ pl). ++ move=> g gin; have := noc _ _ (oesub _ gin) hein. + move=>/no_crossingE[]; first by rewrite (eqP (lefts _ _)) // sval. + by rewrite (eqP (lefts _ _)) // => /(_ ph). +exact: (sub_in2 oesub). +Qed. + +Lemma common_point_edges_y_left r r1 r2 e1 e2 : + valid_edge e1 r -> r.x <= (left_pt e1).x -> + r.x = r1.x -> r.x = r2.x -> left_pt e1 === e2 -> + r1 === e1 -> r2 === e2 -> + r1.y = r2.y. +Proof. +move=> v xl rr1 rr2 e1e2 re1 re2. +have xl': r.x = (left_pt e1).x by apply: le_anti; rewrite xl; case/andP:v. +have:= on_edge_same_point e1e2 re2; rewrite -xl' rr2 => /(_ erefl) <-. +have:= on_edge_same_point (left_on_edge _) re1. +by rewrite -xl' rr1 =>/(_ erefl) <-. +Qed. + +Lemma common_point_edges_y_right r r1 r2 e1 e2 : + valid_edge e1 r -> (right_pt e1).x <= r.x -> + r.x = r1.x -> r.x = r2.x -> right_pt e1 === e2 -> + r1 === e1 -> r2 === e2 -> + r1.y = r2.y. +Proof. +move=> v xl rr1 rr2 e1e2 re1 re2. +have xl': r.x = (right_pt e1).x. + by apply: le_anti; rewrite xl andbC; case/andP:v. +have:= on_edge_same_point e1e2 re2; rewrite -xl' rr2 => /(_ erefl) <-. +have:= on_edge_same_point (right_on_edge _) re1. + by rewrite -xl' rr1 =>/(_ erefl) <-. +Qed. + +Lemma expand_valid p q (pq : p.x < q.x) e r : + valid_edge (Bedge pq) r -> + valid_edge e p -> valid_edge e q -> valid_edge e r. +Proof. +move=>/andP[]pr rq /andP[] lep pre /andP[]leq qre; rewrite /valid_edge. +rewrite /generic_trajectories.valid_edge. +by rewrite (le_trans lep) ?(le_trans rq). +Qed. + +Lemma keep_under (p q : pt) e1 e2 : + inter_at_ext e1 e2 -> + {in [:: p; q] & [:: e1; e2], forall r e, valid_edge e r} -> + p <<< e1 -> ~~ (p <<< e2) -> ~~(q <<< e1) -> ~~(q <<< e2). +Proof. +have left_ext r r1 r2 := @common_point_edges_y_left r r1 r2 e1 e2. +have right_ext r r1 r2 := @common_point_edges_y_right r r1 r2 e1 e2. +move=> noc val pue1 pae2 qae1; apply/negP=> que2; set v := valid_edge. +have : [/\ v e1 p, v e2 p, v e1 q & v e2 q]. + by split; apply: val; rewrite !inE eqxx ?orbT. +have pr e r: valid_edge e r -> + exists r', [/\ valid_edge e r, r' === e & r.x = r'.x]. + move=>/[dup]vr/exists_point_valid[r' /intersection_on_edge [one xx]]. + by exists r'; constructor. +move=>[]/pr[p1 [vp1 pone1 p1p]] /pr[p2 [vp2 pone2 p2p]]. +move=> /pr[q1 [vq1 qone1 q1q]] /pr[q2 [vq2 qone2 q2q]]. +move: vp1 vp2 vq1 vq2 p1p p2p q1q q2q=>vp1 vp2 vq1 vq2 p1p p2p q1q q2q. +move: pone1 pone2 qone1 qone2=>pone1 pone2 qone1 qone2 {pr v val}. +set abbrev := strict_under_edge_lower_y. +have pylt : p.y < p1.y by rewrite -(abbrev _ _ _ _ pone1). +have pyge : p2.y <= p.y by rewrite leNgt -(abbrev _ _ _ _ pone2). +have qyge : q1.y <= q.y by rewrite leNgt -(abbrev _ _ _ _ qone1). +have qylt : q.y < q2.y by rewrite -(abbrev _ _ _ _ qone2). +have yp : p2.y < p1.y by rewrite (le_lt_trans pyge). +have yq : q1.y < q2.y by rewrite (le_lt_trans qyge). +move=> {pyge qyge pylt qylt abbrev}. +have [/[dup]p1p2 + /[dup] q1q2 +] : [/\ p1.x == p2.x & q1.x == q2.x]. + by rewrite -p1p p2p -q1q q2q !eqxx. +move=>/eqP/esym p2p1 /eqP/esym q2q1. +move: (pone1) (pone2) (qone1) (qone2). +move=>/andP[/eqP pl1 _] /andP[/eqP pl2 _] /andP[/eqP ql1 _] /andP[/eqP ql2 _]. +have [pltq | qltp | pq ] := ltrgtP (p.x) (q.x). +- have [p1q1 p2q2] : p1.x < q1.x /\ p2.x < q2.x. + by rewrite -p1p -q1q -p2p -q2q . + set e3 := Bedge p1q1; set e4 := Bedge p2q2. + have l3a : ~~ (left_pt e3 <<= e4). + by move/(@pue_left_edge e4) : p2p1 => -> /=; rewrite subr_ge0 -ltNge. + have r3u : right_pt e3 <<< e4. + by move/(@psue_right_edge e4) : q2q1 => -> /=; rewrite subr_lt0. + have [pi [pi4 /andP[pi3 piint]]] := intersection_middle_au l3a r3u. + have pi1 : pi === e1. + apply/andP; split; last first. + by apply: (expand_valid piint); + rewrite /valid_edge/generic_trajectories.valid_edge -?p1p -?q1q. + rewrite -sgr_eq0 (area3_change_ext _ (edge_cond e1) p1q1) //. + by rewrite (eqP pi3) /sg !eqxx. + have pi2 : pi === e2. + apply/andP; split; last first. + by apply:(expand_valid piint); + rewrite /valid_edge/generic_trajectories.valid_edge -?p1p -?q1q. + rewrite -sgr_eq0 (area3_change_ext _ (edge_cond e2) p2q2) //. + by rewrite pi4 /sg !eqxx. + move: piint; rewrite /valid_edge/generic_trajectories.valid_edge. + rewrite /e3/= -p1p -q1q=> /andP[] ppi piq. + case: noc=> [E | /(_ pi pi1 pi2) piext]; first by move: pae2; rewrite -E pue1. + move: (piext) ppi piq pi1 pi2 { pi3 pi4 }; rewrite !inE. + move => /orP[]/eqP/[dup]pival -> ppi piq pi1 pi2. + have abs := left_ext _ _ _ vp1 ppi p1p p2p pi2 pone1 pone2. + by move: yp; rewrite abs ltxx. + have abs := right_ext _ _ _ vq1 piq q1q q2q pi2 qone1 qone2. + by move: yq; rewrite abs ltxx. +- have [q1p1 q2p2] : q1.x < p1.x /\ q2.x < p2.x. + by rewrite -p1p -q1q -p2p -q2q . + set e3 := Bedge q1p1; set e4 := Bedge q2p2. + have l3u : left_pt e3 <<< e4. + by move/(@psue_left_edge e4):q2q1=> -> /=; rewrite subr_gt0. + have r3a : right_pt e3 >>> e4. + by move/(@pue_right_edge e4):p2p1=> -> /=; rewrite subr_le0 -ltNge. + have [pi [pi4 /andP[pi3 piint]]] := intersection_middle_ua l3u r3a. + have pi1 : pi === e1. + apply/andP; split; last first. + by apply: (expand_valid piint); rewrite /valid_edge + /generic_trajectories.valid_edge -?p1p -?q1q. + rewrite -sgr_eq0 (area3_change_ext _ (edge_cond e1) q1p1) //. + by rewrite (eqP pi3) /sg !eqxx. + have pi2 : pi === e2. + apply/andP; split; last first. + by apply:(expand_valid piint); + rewrite /valid_edge/generic_trajectories.valid_edge -?p1p -?q1q. + rewrite -sgr_eq0 (area3_change_ext _ (edge_cond e2) q2p2) //. + by rewrite pi4 /sg !eqxx. + move: piint; rewrite /valid_edge/generic_trajectories.valid_edge. + rewrite /e3/= -p1p -q1q=> /andP[] qpi pip. + case: noc=> [E | /(_ pi pi1 pi2) piext]; first by move: pae2; rewrite -E pue1. + move: (piext) qpi pip pi1 pi2 { pi3 pi4 }; rewrite !inE. + move => /orP[]/eqP/[dup]pival -> qpi pip pi1 pi2. + have abs := left_ext _ _ _ vq1 qpi q1q q2q pi2 qone1 qone2. + by move: yq; rewrite abs ltxx. + have abs := right_ext _ _ _ vp1 pip p1p p2p pi2 pone1 pone2. + by move: yp; rewrite abs ltxx. +have := conj (on_edge_same_point pone1 qone1) (on_edge_same_point pone2 qone2). +rewrite -p1p -p2p pq q1q (eqP q1q2) => -[]/(_ erefl) p1q1 /(_ erefl) p2q2. +by move: yp; rewrite p1q1 p2q2; rewrite ltNge le_eqVlt yq orbT. +Qed. + +Definition pvert_y (p : pt) (e : edge) := + match vertical_intersection_point p e with + Some p' => p'.y + | None => 0 + end. + +Lemma pvertE p e : valid_edge e p -> + vertical_intersection_point p e = Some (Bpt (p.x) (pvert_y p e)). +Proof. +move=> vep; rewrite /pvert_y. +have [p' p'P] := exists_point_valid vep; rewrite p'P. +have [one pxq] := intersection_on_edge p'P. +by rewrite pxq; case: (p') one. +Qed. + +Lemma pvert_on p e : valid_edge e p -> + Bpt (p.x) (pvert_y p e) === e. +Proof. +move=> vep; rewrite /pvert_y. +have [p' p'P] := exists_point_valid vep; rewrite p'P. +have [one pxq] := intersection_on_edge p'P. +by rewrite pxq; case: (p') one. +Qed. + +Definition on_pvert p e : p === e -> pvert_y p e = p.y. +Proof. +move=> /[dup]/andP[] _ vpe pone. +by rewrite (on_edge_same_point pone (pvert_on vpe)). +Qed. + +Definition cmp_slopes e1 e2 := + sg(((right_pt e2).y - (left_pt e2).y) * + ((right_pt e1).x -(left_pt e1).x) - + ((right_pt e1).y - (left_pt e1).y) * + ((right_pt e2).x - (left_pt e2).x)). + +Definition pedge_below p e1 e2 := + (pvert_y p e1 < pvert_y p e2) || + ((pvert_y p e1 == pvert_y p e2) && (0 <= cmp_slopes e1 e2)). + +Definition pedge_below' p e1 e2 := + (pvert_y p e1 < pvert_y p e2) || + ((pvert_y p e1 == pvert_y p e2) && (cmp_slopes e1 e2 <= 0)). + +Lemma same_left_edge_below_slopes e1 e2 : + left_pt e1 = left_pt e2 -> + e1 <| e2 = (0 <= cmp_slopes e1 e2). +Proof. +move=> sameleft. +rewrite /edge_below !underE [in X in X || _]sameleft. +rewrite (proj1 (area3_two_points _ _)) lexx /=. +rewrite !strictE -[in X in _ || X]sameleft -!leNgt. +rewrite (proj1 (area3_two_points _ _)) lexx /=. +rewrite !area3E !(proj1 (pue_f_eq_slopes _ _ _ _ _ _)). +rewrite /cmp_slopes sameleft -opprB oppr_le0. +rewrite [X in (_ <= X - _) || _]mulrC. +rewrite [X in _ || (_ <= _ - X)]mulrC. +rewrite orbb. +by rewrite sgr_ge0. +Qed. + +Lemma same_right_edge_below_slopes e1 e2 : + right_pt e1 = right_pt e2 -> + e1 <| e2 = (cmp_slopes e1 e2 <= 0). +Proof. +move=> sameright. +rewrite /edge_below !underE [in X in X || _]sameright. +rewrite (proj1 (proj2 (area3_two_points _ _))) lexx /=. +rewrite !strictE -[in X in _ || X]sameright -!leNgt. +rewrite (proj1 (proj2 (area3_two_points _ _))) lexx /= !andbT. +rewrite !area3E !(proj2 (pue_f_eq_slopes _ _ _ _ _ _)). +rewrite /cmp_slopes sameright oppr_le0 opprB. +rewrite !(mulrC ((right_pt e2).y - _)) orbb. +by rewrite sgr_le0 -oppr_ge0 [X in _ = (0 <= X)]opprB. +Qed. + +Definition slope e := + ((right_pt e).y - (left_pt e).y) / ((right_pt e).x - (left_pt e).x). + +Lemma cmp_slopesE e1 e2 : + cmp_slopes e1 e2 = sg(slope e2 - slope e1). +Proof. +have := edge_cond e1. + rewrite -subr_gt0 =>/gtr0_sg den1. +have := edge_cond e2. + rewrite -subr_gt0 =>/gtr0_sg den2. +rewrite -[RHS]mul1r -den1 -[RHS]mul1r -den2 -!sgrM. +rewrite [X in sg( _ * X)]mulrBr /slope. +rewrite [X in sg(X)]mulrBr 2![in X in sg(X - _)]mulrA. +rewrite [X in sg( X * _ * _ - _)]mulrC. +rewrite 2![in X in sg(_ - X)]mulrA. +rewrite /cmp_slopes. +set V := ((right_pt e1).x - _). +set W := ((right_pt e2).x - _). +set U := (_.y - _). +set Z := (_.y - _). +have den20 : W != 0 by rewrite -sgr_eq0 den2 oner_neq0. +have den10 : V != 0 by rewrite -sgr_eq0 den1 oner_neq0. +by rewrite (mulrAC V) mulfK // (mulrAC W) mulfK // (mulrC U) (mulrC Z). +Qed. + +Lemma on_edge_same_slope_right e1 e1' : + left_pt e1' === e1 -> right_pt e1 = right_pt e1' -> + slope e1' = slope e1. +Proof. +move=> /andP[]+ val eqr. +rewrite area3_opposite area3_cycle oppr_eq0. +rewrite area3E (proj1 (pue_f_eq_slopes _ _ _ _ _ _)). +have := edge_cond e1. + rewrite -subr_gt0 => den1. +have := edge_cond e1'. + rewrite -subr_gt0 => den1'. +rewrite subr_eq0. +set W := (_.x - _). +set V := (_.x - _). +have den10 : W != 0. + by rewrite subr_eq0 eq_sym -subr_eq0 lt0r_neq0 // den1. +have den10v : W ^-1 != 0 by rewrite invr_eq0. +have den20 : V != 0. + by rewrite subr_eq0 eq_sym -subr_eq0 lt0r_neq0 // eqr den1'. +have den20v : V ^-1 != 0 by rewrite invr_eq0. +rewrite -(inj_eq (mulIf den10v)) mulfK //. +rewrite -(inj_eq (mulfI den20v)) 2!mulrA 2!(mulrC V ^-1) divff // mul1r. +rewrite -[X in X / V]opprB mulNr -mulrN -invrN /V opprB. +rewrite -[X in X / W]opprB mulNr -mulrN -invrN /V opprB. +by rewrite /slope eqr=> /eqP. +Qed. + +Lemma on_edge_same_slope_left e1 e1' : + right_pt e1' === e1 -> left_pt e1 = left_pt e1' -> + slope e1' = slope e1. +Proof. +move=> /andP[]+ val eqr. +rewrite area3E (proj1 (pue_f_eq_slopes _ _ _ _ _ _)). +have := edge_cond e1. + rewrite -subr_gt0 => den1. +have := edge_cond e1'. + rewrite -subr_gt0 => den1'. +rewrite subr_eq0. +set W := (_.x - _). +set V := (_.x - _). +have den10 : W != 0. + by rewrite subr_eq0 -subr_eq0 lt0r_neq0 // den1. +have den10v : W ^-1 != 0 by rewrite invr_eq0. +have den20 : V != 0. + by rewrite subr_eq0 -subr_eq0 lt0r_neq0 // eqr den1'. +have den20v : V ^-1 != 0 by rewrite invr_eq0. +rewrite -(inj_eq (mulIf den10v)) mulfK //. +rewrite -(inj_eq (mulfI den20v)) 2!mulrA 2!(mulrC V ^-1) divff // mul1r. +by rewrite /slope /W /V eqr=> /eqP. +Qed. + +Lemma cmp_slopesNC e1 e2 : -cmp_slopes e1 e2 = cmp_slopes e2 e1. +Proof. by rewrite /cmp_slopes -sgrN [in LHS]opprB. Qed. + +Lemma contact_left_slope e1 e2 : + left_pt e1 === e2 -> + (right_pt e1 <<= e2) = (0 <= cmp_slopes e1 e2) /\ + (right_pt e1 <<< e2) = (0 < cmp_slopes e1 e2). +Proof. +move=> /[dup] on2 /andP[] form val. +suff area3_eq : + sg (area3 (right_pt e1) (left_pt e2) (right_pt e2)) = + -(cmp_slopes e1 e2). + rewrite !underE !strictE. + rewrite -sgr_le0 area3_eq oppr_le0 sgr_ge0; split;[by [] |]. + by rewrite -sgr_lt0 area3_eq oppr_lt0 sgr_gt0. +move: (val) => /andP[] _; rewrite le_eqVlt=> /orP[/eqP atr | le1ltre2]. + rewrite /cmp_slopes atr. + have eqps : left_pt e1 = right_pt e2. + have := on_edge_same_point (right_on_edge _) on2. + rewrite atr => /(_ erefl); move: (right_pt e2) (left_pt e1) atr. + by move=> [] ? ? [] ? ? /= -> ->. + rewrite area3_opposite area3_cycle. + rewrite sgrN. + rewrite !area3E !(proj1 (pue_f_eq_slopes _ _ _ _ _ _)). + rewrite -eqps -(mulrC (_.y - _)). + rewrite -[X in _ = - sg (X * _ - _)]opprB -[X in _ = - sg (_ - _ * X)]opprB. + by rewrite mulrN mulNr -opprD opprB. +set e2' := Bedge le1ltre2. +have signcond := area3_change_ext (right_pt e1) (edge_cond e2) le1ltre2 + (eqP form) (proj1 (proj2 (area3_two_points _ _))). +rewrite {}signcond. +have on2' : left_pt e2' === e2 by exact: on2. +rewrite cmp_slopesE -(on_edge_same_slope_right on2')// -cmp_slopesE. +rewrite cmp_slopesNC. +rewrite area3E (proj1 (pue_f_eq_slopes _ _ _ _ _ _)) /cmp_slopes. +by rewrite /e2' /= [in LHS](mulrC (_.x - _)). +Qed. + +Lemma contact_right_slope e1 e2 : + right_pt e1 === e2 -> + (left_pt e1 <<= e2) = (cmp_slopes e1 e2 <= 0) /\ + (left_pt e1 <<< e2) = (cmp_slopes e1 e2 < 0). +Proof. +move=> /[dup] on2 /andP[] form val. +suff area3_eq : + sg (area3 (left_pt e1) (left_pt e2) (right_pt e2)) = + cmp_slopes e1 e2. + rewrite !underE !strictE. + rewrite -area3_eq -[X in X = _ /\ _]sgr_le0; split; first by []. + by rewrite -[LHS]sgr_lt0. +move: (val) => /andP[] + _; rewrite le_eqVlt eq_sym=> /orP[/eqP atl | le2ltre1]. + rewrite /cmp_slopes atl. + have eqps : right_pt e1 = left_pt e2. + have := on_edge_same_point (left_on_edge _) on2. + rewrite atl => /(_ erefl); move: (right_pt e1) (left_pt e2) atl. + by move=> [] ? ? [] ? ? /= -> ->. + rewrite !area3E !(proj1 (pue_f_eq_slopes _ _ _ _ _ _)). + rewrite eqps (mulrC (_.x - _)). + rewrite -[X in _ = sg (_ * X - _)]opprB -[X in _ = sg (_ - X * _)]opprB. + by rewrite mulrN mulNr -opprD opprB. +set e2' := Bedge le2ltre1. +have signcond := area3_change_ext (left_pt e1) (edge_cond e2) le2ltre1 + (proj1 (area3_two_points _ _)) (eqP form). +rewrite {}signcond. +have on2' : right_pt e2' === e2 by exact: on2. +rewrite cmp_slopesE -(on_edge_same_slope_left on2')// -cmp_slopesE. +rewrite area3_opposite area3_cycle. +rewrite area3E (proj1 (pue_f_eq_slopes _ _ _ _ _ _)) /cmp_slopes. +rewrite /e2' /= [in LHS](mulrC (_.x - _)) opprB. +by rewrite -4![in LHS](opprB (_ (right_pt e1))) 2!mulrNN. +Qed. + +Lemma sub_edge_right (p : pt) (e : edge) : p === e -> + p.x < (right_pt e).x -> + {e' | [/\ left_pt e' = p, right_pt e' = right_pt e & + forall e2, cmp_slopes e' e2 = cmp_slopes e e2]}. +Proof. +move=>/[dup] one /andP[] aligned val dif; exists (Bedge dif). +split => // e2; rewrite !cmp_slopesE. +by rewrite (@on_edge_same_slope_right e (Bedge dif) one erefl). +Qed. + +Lemma sub_edge_left (p : pt) (e : edge) : p === e -> + (left_pt e).x < p.x -> + {e' | [/\ left_pt e' = left_pt e, right_pt e' = p & + forall e2, cmp_slopes e' e2 = cmp_slopes e e2]}. +Proof. +move=>/[dup] one /andP[] aligned val dif; exists (Bedge dif). +split => // e2; rewrite !cmp_slopesE. +by rewrite (@on_edge_same_slope_left e (Bedge dif) one erefl). +Qed. + +Lemma intersection_imp_crossing e1 e2 p : + p === e1 -> p === e2 -> + (left_pt e1).x < p.x -> p.x < (right_pt e1).x -> + (left_pt e2).x < p.x -> p.x < (right_pt e2).x -> + ~below_alt e1 e2 \/ cmp_slopes e1 e2 == 0. +Proof. +move=> on1 on2 l1ltp pltr1 l2ltp pltr2. +have [e2' [le2' re2' sle2']] := sub_edge_left on2 l2ltp. +have [e2'' [le2'' re2'' sle2'']] := sub_edge_right on2 pltr2. +have [e1' [le1' re1' sle1']] := sub_edge_left on1 l1ltp. +have [e1'' [le1'' re1'' sle1'']] := sub_edge_right on1 pltr1. +have /contact_left_slope/= : left_pt e2'' === e1 by rewrite le2''. +have /contact_right_slope/= : right_pt e2' === e1 by rewrite re2'. +have /contact_left_slope/= : left_pt e1'' === e2 by rewrite le1''. +have /contact_right_slope/= : right_pt e1' === e2 by rewrite re1'. +rewrite le1' le2' re2'' re1'' sle1' sle1'' sle2' sle2'' -(cmp_slopesNC e1). +rewrite !oppr_lte0 !oppr_gte0 => -[]D' D []C' C []B' B []A' A. +rewrite /below_alt/edge_below. +have [ | difslope] := boolP(cmp_slopes e1 e2 == 0); first by right. +left; rewrite D' C' A B A' B' D C -!leNgt orbC=> /orP; rewrite andbC !orbb. +by move/le_anti/esym/eqP; rewrite (negbTE difslope). +Qed. + +Lemma order_below_viz_vertical low_e high_e p pl ph: +valid_edge low_e p -> valid_edge high_e p -> +vertical_intersection_point p low_e = Some pl -> +vertical_intersection_point p high_e = Some ph -> +low_e <| high_e -> +pl.y <= ph.y. +Proof. +move => lowv highv vert_pl vert_ph luh. +have := intersection_on_edge vert_pl => [][] poel lx_eq. +have := intersection_on_edge vert_ph => [][] poeh hx_eq. +have plhv: valid_edge high_e pl. + move : highv. + by rewrite /valid_edge/generic_trajectories.valid_edge -lx_eq. +have pllv: valid_edge low_e pl. + move : lowv. + by rewrite /valid_edge/generic_trajectories.valid_edge -lx_eq. +have := order_edges_viz_point' pllv plhv luh. +rewrite under_onVstrict // poel /= => [] /= plinfh. +have pluh: pl <<= high_e . + by apply plinfh. +have px_eq : pl.x = ph.x. + by rewrite -lx_eq -hx_eq /=. +by rewrite -(under_edge_lower_y px_eq poeh). +Qed. + +Lemma edge_below_equiv p (s : pred edge) : + {in s, forall e, valid_edge e p && (p.x < (right_pt e).x)} -> + {in s &, no_crossing} -> + {in s & , forall e1 e2: edge, (e1 <| e2) = pedge_below p e1 e2}. +Proof. +move=> val noc e1 e2. +move=> /[dup] e1in /val /andP[] /[dup] ve1 /exists_point_valid [p1 p1P] re1. +move: (p1P); rewrite (pvertE ve1) =>/esym[] p1q. +move: (ve1)=> /pvert_on; rewrite -p1q=> on1. +move=> /[dup] e2in /val /andP[] /[dup] ve2 /exists_point_valid [p2 p2P] re2. +move: (p2P); rewrite (pvertE ve2) =>/esym[] p2q. +move: (ve2)=> /pvert_on; rewrite -p2q=> on2; rewrite /pedge_below. +have p1p2 : p1.x = p2.x by rewrite p1q p2q. +have [vylt /= | vylt' /= | vyq] := ltrgtP. +- case: (noc e1 e2 e1in e2in) => // abs. + have := order_below_viz_vertical ve2 ve1 p2P p1P abs; rewrite leNgt. + by rewrite p1q p2q /= vylt. +- have re1' : p1.x < (right_pt e1).x by rewrite p1q. + have p2u : p2 <<< e1. + by rewrite (strict_under_edge_lower_y (esym p1p2)); rewrite // p2q p1q. + have p1a : p1 >>> e2. + by rewrite (under_edge_lower_y p1p2); rewrite // -ltNge p2q p1q. + apply/negP=> /orP[|] /andP[]leftc rightc. + by move: p1a; rewrite (point_on_edge_under _ leftc rightc) // p1q. + move: p2u; rewrite -(negbK (_ <<< _)). + by rewrite (point_on_edge_above _ leftc rightc) // p2q. +have pp : p1 = p2 by rewrite p1q p2q vyq. +move: (ve1) => /andP[] + _; rewrite le_eqVlt=>/orP[/eqP pleft | pmid] /=. + have p1l : p1 = left_pt e1. + apply/esym/eqP; rewrite pt_eqE. + by rewrite (on_edge_same_point (left_on_edge _) on1) pleft p1q// eqxx andbT. + move: ve2 => /andP[] + _; rewrite le_eqVlt=> /orP [/eqP pleft2 | pmid2]. + have p2l : p2 = left_pt e2. + apply/esym/eqP; rewrite pt_eqE. + by rewrite (on_edge_same_point (left_on_edge _) on2) pleft2 p2q// eqxx andbT. + by apply: same_left_edge_below_slopes; rewrite -p1l pp. + have le2ltp2 : (left_pt e2).x < p2.x by rewrite p2q. + have [e2' [le2' re2' sle2']] := sub_edge_left on2 le2ltp2. + have re2'e1 : right_pt e2' === e1 by rewrite re2' -pp. + rewrite /edge_below. + have := (contact_right_slope re2'e1) => /= -[] _; rewrite le2' sle2' => ->. + have p2ltre2 : p2.x < (right_pt e2).x by rewrite p2q. + have [e2'' [le2'' re2'' sle2'']] := sub_edge_right on2 p2ltre2. + have le2''e1 : left_pt e2'' === e1 by rewrite le2'' -pp. + have := (contact_left_slope le2''e1) => -[] _; rewrite re2'' sle2'' => ->. + rewrite -2!leNgt. + set W := (X in _ || X); have [ | difslope] := boolP W. + rewrite {}/W=>/le_anti/esym=>/eqP. + by rewrite -cmp_slopesNC oppr_eq0 orbT=> /eqP->; rewrite lexx. + rewrite orbF -p1l pp {1}underE. + move: (on2); rewrite /point_on_edge. + move=> /andP[] /eqP -> _; rewrite lexx /=. + by move: (on2); rewrite -pp p1l=>/contact_left_slope=>-[]. +have le1ltp1 : (left_pt e1).x < p1.x by rewrite p1q. +have [e1' [le1' re1' sle1']] := sub_edge_left on1 le1ltp1. +have re1'e2 : right_pt e1' === e2 by rewrite re1' pp. +rewrite /edge_below. +set W := (X in X || _); set W' := (X in _ || X). +have := (contact_right_slope re1'e2); rewrite le1' sle1' => /= -[] eq1 _. +have p1ltre1 : p1.x < (right_pt e1).x by rewrite p1q. +have [e1'' [le1'' re1'' sle1'']] := sub_edge_right on1 p1ltre1. +have le1''e2 : left_pt e1'' === e2 by rewrite le1'' pp. +have /= := (contact_left_slope le1''e2); rewrite re1'' sle1'' => - [] /= eq2 _. +have Weq : W = (cmp_slopes e1 e2 == 0). + rewrite /W eq1 eq2; apply/idP/eqP; first by apply/le_anti. + by move=> ->; rewrite lexx. +have [ | difslope /=] := boolP W. + by rewrite /= le_eqVlt Weq => /eqP ->; rewrite eqxx. +rewrite le_eqVlt eq_sym -Weq (negbTE difslope) /=. +move: (ve2) => /andP[] + _; rewrite le_eqVlt => /orP [/eqP l2p | l2ltp]. + have /eqP p2l : left_pt e2 == p1. + rewrite pt_eqE. + rewrite (on_edge_same_point (left_on_edge _) on2 _) -pp l2p p1q //=. + by rewrite !eqxx. + have/contact_left_slope[_ eq3] : left_pt e2 === e1 by rewrite p2l. + move: on1=>/andP[] /eqP + _; rewrite -p2l => eq4. + rewrite /W' eq3 lt_neqAle -cmp_slopesNC eq_sym oppr_eq0 -Weq difslope andTb. + rewrite strictE. + by rewrite -leNgt eq4 lexx -ltNge oppr_lt0. +have xpp1 : p.x = p1.x by rewrite p1q. +move: on2 l2ltp re2; rewrite -pp xpp1 => on2 l2ltp re2. +have := intersection_imp_crossing on1 on2 le1ltp1 p1ltre1 l2ltp re2=> -[[]|abs]. + by apply: noc. +by case/negP: difslope; rewrite Weq. +Qed. + +Lemma edge_below_equiv' p (s : pred edge) : + {in s, forall e, valid_edge e p && ((left_pt e).x < p.x)} -> + {in s &, no_crossing} -> + {in s & , forall e1 e2: edge, (e1 <| e2) = pedge_below' p e1 e2}. +Proof. +move=> val noc e1 e2. +move=> /[dup] e1in /val /andP[] /[dup] ve1 /exists_point_valid [p1 p1P] le1. +move: (p1P); rewrite (pvertE ve1) =>/esym[] p1q. +move: (ve1)=> /pvert_on; rewrite -p1q=> on1. +move=> /[dup] e2in /val /andP[] /[dup] ve2 /exists_point_valid [p2 p2P] le2. +move: (p2P); rewrite (pvertE ve2) =>/esym[] p2q. +move: (ve2)=> /pvert_on; rewrite -p2q=> on2; rewrite /pedge_below'. +have p1p2 : p1.x = p2.x by rewrite p1q p2q. +have [vylt /= | vylt' /= | vyq] := ltrgtP. +- case: (noc e1 e2 e1in e2in) => // abs. + have := order_below_viz_vertical ve2 ve1 p2P p1P abs; rewrite leNgt. + by rewrite p1q p2q /= vylt. +- have le1' : (left_pt e1).x < p1.x by rewrite p1q. + have p2u : p2 <<< e1. + by rewrite (strict_under_edge_lower_y (esym p1p2)); rewrite // p2q p1q. + have p1a : p1 >>> e2. + by rewrite (under_edge_lower_y p1p2); rewrite // -ltNge p2q p1q. + apply/negP=> /orP[|] /andP[]leftc rightc. + by move: p1a; rewrite (point_on_edge_under _ leftc rightc) // p1q. + move: p2u; rewrite -(negbK (_ <<< _)). + by rewrite (point_on_edge_above _ leftc rightc) // p2q. +have pp : p1 = p2 by rewrite p1q p2q vyq. +move: (ve1) => /andP[] _ +; rewrite le_eqVlt=>/orP[/eqP pright | pmid] /=. + have p1r : p1 = right_pt e1. + apply/eqP; rewrite pt_eqE. + by rewrite (on_edge_same_point on1 (right_on_edge _)) -pright p1q// eqxx andbT. + move: ve2 => /andP[] _; rewrite le_eqVlt=> /orP [/eqP pright2 | pmid2]. + have p2l : p2 = right_pt e2. + apply/eqP; rewrite pt_eqE. + by rewrite (on_edge_same_point on2 (right_on_edge _)) -pright2 p2q// eqxx andbT. + by apply: same_right_edge_below_slopes; rewrite -p1r pp. + have p2ltre2 : p2.x < (right_pt e2).x by rewrite p2q. + have [e2' [le2' re2' sle2']] := sub_edge_right on2 p2ltre2. + have le2'e1 : left_pt e2' === e1 by rewrite le2' -pp. + rewrite /edge_below. + have := (contact_left_slope le2'e1) => /= -[] _; rewrite re2' sle2' => ->. + have le2ltp2 : (left_pt e2).x < p2.x by rewrite p2q. + have [e2'' [le2'' re2'' sle2'']] := sub_edge_left on2 le2ltp2. + have re2''e1 : right_pt e2'' === e1 by rewrite re2'' -pp. + have := (contact_right_slope re2''e1) => -[] _; rewrite le2'' sle2'' => ->. + rewrite -2!leNgt. + set W := (X in _ || X); have [ | difslope] := boolP W. + rewrite {}/W=>/le_anti/esym/eqP. + by rewrite -cmp_slopesNC oppr_eq0 orbT=> /eqP->; rewrite lexx. + rewrite orbF -p1r pp [p2 <<= _]underE. + move: (on2); rewrite /point_on_edge. + move=> /andP[] /eqP -> _; rewrite lexx andbT. + by move: (on2); rewrite -pp p1r=>/contact_right_slope=>-[]. +have p1ltre1 : p1.x < (right_pt e1).x by rewrite p1q. +have [e1' [le1' re1' sle1']] := sub_edge_right on1 p1ltre1. +have le1'e2 : left_pt e1' === e2 by rewrite le1' pp. +rewrite /edge_below. +set W := (X in X || _); set W' := (X in _ || X). +have := (contact_left_slope le1'e2); rewrite re1' sle1' => /= -[] eq1 _. +have le1ltp1 : (left_pt e1).x < p1.x by rewrite p1q. +have [e1'' [le1'' re1'' sle1'']] := sub_edge_left on1 le1ltp1. +have re1''e2 : right_pt e1'' === e2 by rewrite re1'' pp. +have /= := (contact_right_slope re1''e2); rewrite le1'' sle1'' => - [] /= eq2 _. +have Weq : W = (cmp_slopes e1 e2 == 0). + rewrite /W eq1 eq2; apply/idP/eqP; first by apply/le_anti. + by move=> ->; rewrite lexx. +have [ | difslope /=] := boolP W. + by rewrite /= le_eqVlt Weq => /eqP ->; rewrite eqxx. +rewrite le_eqVlt -Weq (negbTE difslope) /=. +move: (ve2) => /andP[] _; rewrite le_eqVlt => /orP [/eqP r2p | pltr2]. + have /eqP p2r : right_pt e2 == p1. + rewrite pt_eqE. + rewrite -(on_edge_same_point on2 (right_on_edge _) _) -pp -r2p p1q //=. + by rewrite !eqxx. + have/contact_right_slope[_ eq3] : right_pt e2 === e1 by rewrite p2r. + move: on1=>/andP[] /eqP + _; rewrite -p2r => eq4. + rewrite /W' eq3 lt_neqAle -cmp_slopesNC oppr_eq0 -Weq difslope andTb. + by rewrite /W' strictE + eq4 ltxx andbT -ltNge oppr_gt0. +have xpp1 : p.x = p1.x by rewrite p1q. +move: on2 pltr2 le2; rewrite -pp xpp1 => on2 pltr2 le2. +have := intersection_imp_crossing on1 on2 le1ltp1 p1ltre1 le2 pltr2=> -[[]|abs]. + by apply: noc. +by case/negP: difslope; rewrite Weq. +Qed. + +Lemma pedge_below_trans p: transitive (pedge_below p). +Proof. +move=> e2 e1 e3; rewrite /pedge_below. +move=>/orP[v12 | /andP [y12 s12]] /orP[v23 | /andP[y23 s23]]. +- by rewrite (lt_trans v12 v23). +- by rewrite -(eqP y23) v12. +- by rewrite (eqP y12) v23. +rewrite orbC (eqP y12) y23. +move: s12 s23; rewrite !cmp_slopesE !sgr_ge0 !subr_ge0=> s12 s23. +by rewrite (le_trans s12 s23). +Qed. + +Lemma pedge_below_trans' p: transitive (pedge_below' p). +Proof. +move=> e2 e1 e3; rewrite /pedge_below'. +move=>/orP[v12 | /andP [y12 s12]] /orP[v23 | /andP[y23 s23]]. +- by rewrite (lt_trans v12 v23). +- by rewrite -(eqP y23) v12. +- by rewrite (eqP y12) v23. +rewrite orbC (eqP y12) y23. +move: s12 s23; rewrite !cmp_slopesE !sgr_le0. +rewrite (subr_le0 (slope e1)) (subr_le0 (slope e2)) (subr_le0 (slope e1)). +by move=> s12 s23; rewrite (le_trans s23 s12). +Qed. + +Lemma edge_below_trans p (s : pred edge) : + {in s, forall e, p.x < (right_pt e).x} \/ + {in s, forall e, (left_pt e).x < p.x} -> + {in s, forall e, valid_edge e p} -> {in s &, no_crossing} -> + {in s & & , transitive edge_below}. +Proof. +move=> [rbound | lbound] vals noc e2 e1 e3 e2in e1in e3in. + have valb : {in s, forall e, valid_edge e p && (p.x < (right_pt e).x)}. + by move=> e ein; apply/andP; split;[apply: vals | apply: rbound]. + rewrite (edge_below_equiv valb noc) // (edge_below_equiv valb noc) //. + rewrite (edge_below_equiv valb noc) //. + by apply: pedge_below_trans. +have valb : {in s, forall e, valid_edge e p && ((left_pt e).x < p.x)}. + by move=> e ein; apply/andP; split;[apply: vals | apply: lbound]. +rewrite (edge_below_equiv' valb noc) // (edge_below_equiv' valb noc) //. +rewrite (edge_below_equiv' valb noc) //. +by apply: pedge_below_trans'. +Qed. + +Lemma left_pt_above g : left_pt g >>= g. +Proof. by rewrite strictE (proj1 (area3_two_points _ _)) ltxx. Qed. + +Lemma right_pt_above g : right_pt g >>= g. +Proof. by rewrite strictE (proj1 (proj2 (area3_two_points _ _))) ltxx. Qed. + +Lemma left_pt_below g : left_pt g <<= g. +Proof. by rewrite underE (proj1 (area3_two_points _ _)) lexx. Qed. + +Lemma right_pt_below g : right_pt g <<= g. +Proof. by rewrite underE (proj1 (proj2 (area3_two_points _ _))) lexx. Qed. + +Lemma under_pvert_y (p : pt) (e : edge) : + valid_edge e p -> (p <<= e) = (p.y <= pvert_y p e). +Proof. +move=> val. +have xs : p.x = (Bpt (p.x) (pvert_y p e)).x by []. +have one : Bpt (p.x) (pvert_y p e) === e by apply: pvert_on. +by rewrite (under_edge_lower_y xs one). +Qed. + +Lemma strict_under_pvert_y (p : pt) (e : edge) : + valid_edge e p -> (p <<< e) = (p.y < pvert_y p e). +Proof. +move=> val. +have xs : p.x = (Bpt (p.x) (pvert_y p e)).x by []. +have one : Bpt (p.x) (pvert_y p e) === e by apply: pvert_on. +by rewrite (strict_under_edge_lower_y xs one). +Qed. + +Lemma same_x_valid (p1 p2 : pt) (g : edge) : + p1.x = p2.x -> valid_edge g p1 = valid_edge g p2. +Proof. +by move=> xs; rewrite /valid_edge /generic_trajectories.valid_edge xs. +Qed. + +Lemma same_pvert_y (p1 p2 : pt) (g : edge) : + valid_edge g p1 -> p1.x = p2.x -> pvert_y p1 g = pvert_y p2 g. +Proof. +move=> vg xs. +move: (vg) ; rewrite (same_x_valid _ xs) => vg2. +exact: (on_edge_same_point (pvert_on vg) (pvert_on vg2) xs). +Qed. + +Lemma edge_below_pvert_y g1 g2 p : + valid_edge g1 p -> valid_edge g2 p -> + g1 <| g2 -> pvert_y p g1 <= pvert_y p g2. +Proof. +move=> v1 v2 g1g2. +have := pvert_on v1; set p' := Bpt _ _ => p'on. +have/esym := @same_x_valid p p' g1 erefl; rewrite v1 => v'1. +have/esym := @same_x_valid p p' g2 erefl; rewrite v2 => v'2. +have := order_edges_viz_point' v'1 v'2 g1g2. +rewrite (under_onVstrict v'1) p'on => /(_ isT). +by rewrite under_pvert_y. +Qed. + +Lemma pvert_y_edge_below g1 g2 p : + valid_edge g1 p -> valid_edge g2 p -> + pvert_y p g1 < pvert_y p g2 -> ~~ (g2 <| g1). +Proof. +move=> v1 v2 cmp; apply/negP=> g2g1. +have := edge_below_pvert_y v2 v1 g2g1. +by rewrite leNgt cmp. +Qed. + +Lemma edges_partition_strictly_above p g1 g2 s1 s2: + all (valid_edge^~ p) (s1 ++ g1 :: g2 :: s2) -> + sorted edge_below (s1 ++ g1 :: g2 :: s2) -> + p >>= g1 -> p <<< g2 -> + {in rcons s1 g1 & g2 :: s2, forall g g', ~~ (g' <| g)}. +Proof. +move=> aval pth pg1 pg2. +have vg1 : valid_edge g1 p. + by apply: (allP aval); rewrite !(mem_cat, inE) eqxx ?orbT. +have vg2 : valid_edge g2 p. + by apply: (allP aval); rewrite !(mem_cat, inE) eqxx ?orbT. +have pg1y : pvert_y p g1 <= p.y by rewrite leNgt -strict_under_pvert_y. +have pg2y : p.y < pvert_y p g2 by rewrite -strict_under_pvert_y. +have g1g2 : pvert_y p g1 < pvert_y p g2 by apply: (le_lt_trans pg1y). +have mp : {in s1++ g1 :: g2 :: s2 &, + {homo (pvert_y p) : x y / x <| y >-> x <= y}}. + move=> u v /(allP aval) vu /(allP aval) vv uv. + by apply: edge_below_pvert_y vu vv uv. +have sb2 : {subset [:: g1, g2 & s2] <= (s1 ++ [:: g1, g2 & s2])}. + by move=> u uin; rewrite mem_cat uin orbT. +have g2s2y : {in g2 :: s2, forall g, pvert_y p g1 < pvert_y p g}. + move=> g; rewrite inE => /orP[/eqP -> //| gin]. + have pthy : sorted <=%R [seq pvert_y p h | h <- g2 :: s2]. + apply: (homo_path_in mp); last first. + move: pth. + rewrite (_ : s1 ++ _ = (s1 ++[:: g1]) ++ g2 :: s2); last first. + by rewrite /= -!catA. + by move/sorted_catW=> /andP[]. + apply: (sub_all sb2). + by apply/allP => z; rewrite !(mem_cat, inE) => /orP[] ->; rewrite ?orbT. + have /(allP aval) gin' : g \in (s1 ++ [:: g1, g2 & s2]). + by rewrite mem_cat !inE gin ?orbT. + move: pthy; rewrite /= (path_sortedE le_trans) => /andP[] /allP. + have giny : pvert_y p g \in [seq pvert_y p h | h <- s2] by apply: map_f. + by move=> /(_ _ giny) => /(lt_le_trans g1g2). +have sb1 : {subset rcons s1 g1 <= s1 ++ [:: g1, g2 & s2]}. + by move=> x; rewrite mem_rcons mem_cat !inE => /orP[] ->; rewrite ?orbT. +have s1g1y : {in rcons s1 g1, forall g, pvert_y p g <= pvert_y p g1}. + move=> g; rewrite mem_rcons inE => /orP[/eqP ->| gin]. + apply: le_refl. + case s1eq : s1 gin => [// | init s1']; rewrite -s1eq => gin. + have pthy : sorted <=%R [seq pvert_y p h | h <- rcons s1 g1]. + rewrite s1eq /=; apply: (homo_path_in mp); last first. + move: pth; rewrite s1eq/=. + rewrite (_ : s1' ++ _ = (s1' ++ [:: g1]) ++ g2 :: s2); last first. + by rewrite -catA. + by rewrite cat_path cats1 => /andP[]. + by apply: (sub_all sb1); rewrite s1eq; apply: allss. + have [s' [s'' s'eq]] : exists s' s'', s1 = s' ++ g :: s''. + by move: gin=> /splitPr [s' s'']; exists s', s''. + have dc : rcons (init :: s1') g1 = (s' ++ [:: g]) ++ rcons s'' g1. + by rewrite -s1eq s'eq -!cats1 /= -?catA. + case s'eq2 : s' => [ | init' s'2]. + move: pthy; rewrite s1eq dc s'eq2 /= (path_sortedE le_trans)=> /andP[]. + move=> /allP/(_ (pvert_y p g1)) + _; apply. + by rewrite map_f // mem_rcons inE eqxx. + move: pthy; rewrite s1eq dc s'eq2 /= map_cat cat_path => /andP[] _. + rewrite !map_cat cats1 last_rcons (path_sortedE le_trans) => /andP[] + _. + move=> /allP/(_ (pvert_y p g1)); apply. + by apply: map_f; rewrite mem_rcons inE eqxx. +move=> g g' /[dup]gin /s1g1y giny /[dup] g'in /g2s2y g'iny; apply/negP=> g'g. +have vg : valid_edge g p by apply: (allP aval); apply: sb1. +have vg' : valid_edge g' p. + by apply: (allP aval); apply: sb2; rewrite inE g'in orbT. +have:= edge_below_pvert_y vg' vg g'g; rewrite leNgt. +by rewrite (le_lt_trans _ g'iny). +Qed. + +Lemma edge_below_from_point_above g1 g2 p: + below_alt g1 g2 -> valid_edge g1 p -> valid_edge g2 p -> + p >>= g1 -> p <<< g2 -> g1 <| g2. +Proof. +move=>[] //= g2g1 v1 v2 ab bel. +have := order_edges_strict_viz_point' v2 v1 g2g1 bel. +by rewrite (negbTE ab). +Qed. + +Lemma edge_below_from_point_under g1 g2 p: + below_alt g1 g2 -> valid_edge g1 p -> valid_edge g2 p -> + p <<= g1 -> p >>> g2 -> g2 <| g1. +Proof. +move=>/below_altC[] //=g1g2 v1 v2 bel ab. +have := order_edges_viz_point' v1 v2 g1g2 bel. +by rewrite (negbTE ab). +Qed. + +Lemma transport_below_edge r p e e': + below_alt e e' -> + valid_edge e r -> valid_edge e' r -> + valid_edge e p -> valid_edge e' p -> + pvert_y r e < pvert_y r e' -> + p <<< e -> p <<< e'. +Proof. +move=> noc vr vr' vp vp' cmp pbelow. +have ebe'0 := pvert_y_edge_below vr vr' cmp. +have ebe' : e <| e' by case: noc ebe'0=> [// | -> ]. +by apply:(order_edges_strict_viz_point' vp vp'). +Qed. + +Lemma transport_above_edge r p e e': + below_alt e e' -> + valid_edge e r -> valid_edge e' r -> + valid_edge e p -> valid_edge e' p -> + pvert_y r e < pvert_y r e' -> + p >>> e' -> p >>> e. +Proof. +move=> noc vr vr' vp vp' cmp pabove. +have ebe'0 := pvert_y_edge_below vr vr' cmp. +have ebe' : e <| e' by case: noc ebe'0=> [// | -> ]. +apply/negP=> abs. +by move: pabove; rewrite (order_edges_viz_point' vp vp'). +Qed. + +Lemma path_edge_below_pvert_y bottom s p : + all (valid_edge^~ p) (bottom :: s) -> + path edge_below bottom s -> path <=%R (pvert_y p bottom) + [seq pvert_y p e | e <- s]. +Proof. +move=> aval. +have hp : {in bottom :: s &, + {homo (pvert_y p) : u v / edge_below u v >-> u <= v}}. + move=> u v /(allP aval) vu /(allP aval) vv. + by apply: edge_below_pvert_y vu vv. +by move/(homo_path_in hp)=> /(_ (allss (bottom :: s))). +Qed. + +Lemma edge_below_gap bottom s s' le r p g g' : +{in bottom::rcons s le ++ s' &, no_crossing} -> +all (valid_edge^~ r) (bottom :: rcons s le ++ s') -> +path edge_below bottom (rcons s le ++ s') -> +r >>> le -> r <<= g' -> +g \in rcons s le -> +valid_edge g p -> +p >>> g' -> +g' \in s' -> +valid_edge g' p -> p >>> g. +Proof. +move=> noc aval pth rabove rbelow gin vp pabove g'in vp'. +have gin2 : g \in bottom :: rcons s le ++ s'. + by move: gin; rewrite !(inE, mem_rcons, mem_cat)=>/orP[] ->; rewrite ?orbT. +have g'in2 : g' \in bottom :: rcons s le ++ s'. + by move: g'in; rewrite !(inE, mem_rcons, mem_cat)=> ->; rewrite ?orbT. +have lein : le \in bottom :: rcons s le ++ s'. + by rewrite !(inE, mem_cat, mem_rcons) eqxx ?orbT. +have vl : valid_edge le r by apply: (allP aval). +have vr : valid_edge g r by apply: (allP aval). +have vr' : valid_edge g' r by apply: (allP aval). +have noc' : below_alt g g' by apply: noc. +apply: (transport_above_edge noc' vr) => //. +have aval' : all (valid_edge^~ r) (bottom :: rcons s le). + apply/allP=> u uin; apply: (allP aval). + move: uin; rewrite !(inE, mem_cat, mem_rcons). + by move=> /orP[| /orP[]] ->; rewrite ?orbT. +have aval'' : all (valid_edge^~ r) (le :: s'). + apply/allP=> u uin; apply: (allP aval). + move: uin; rewrite !(inE, mem_cat, mem_rcons). + by move=> /orP[] ->; rewrite ?orbT. +have tr : transitive (relpre (pvert_y r) <=%R). + by move=> y x z; rewrite /=; apply: le_trans. +have le_g' : pvert_y r le < pvert_y r g'. + have le_r : pvert_y r le < r.y by rewrite ltNge -under_pvert_y. + have r_g' : r.y <= pvert_y r g' by rewrite -under_pvert_y. + by apply: lt_le_trans le_r r_g'. +have g_le : pvert_y r g <= pvert_y r le. + move: gin; rewrite mem_rcons inE=> /orP[/eqP -> |gin]; first by rewrite lexx. + have gin' : g \in (bottom :: s) by rewrite inE gin orbT. + move: pth; rewrite cat_path last_rcons => /andP[] + _. + move=> /= /path_edge_below_pvert_y => /(_ _ aval'). + rewrite path_map. + rewrite -[path _ _ _]/(sorted _ (rcons (bottom :: s) le)). + by move=> /(sorted_rconsE tr)/allP/(_ _ gin') /=. +by apply: le_lt_trans le_g'. +Qed. + +Lemma edge_above_gap bottom s s' he r p g g' : +{in bottom::rcons s he ++ s' &, no_crossing} -> +all (valid_edge^~ r) (bottom :: rcons s he ++ s') -> +path edge_below bottom (rcons s he ++ s') -> +r <<< he -> r >>= g -> +g \in rcons s he -> +valid_edge g p -> +p <<< g -> +g' \in s' -> +valid_edge g' p -> p <<< g'. +Proof. +move=> noc aval pth rabove rbelow gin vp pabove g'in vp'. +have gin2 : g \in bottom :: rcons s he ++ s'. + by move: gin; rewrite !(inE, mem_rcons, mem_cat)=>/orP[] ->; rewrite ?orbT. +have g'in2 : g' \in bottom :: rcons s he ++ s'. + by move: g'in; rewrite !(inE, mem_rcons, mem_cat)=> ->; rewrite ?orbT. +have hein : he \in bottom :: rcons s he ++ s'. + by rewrite !(inE, mem_cat, mem_rcons) eqxx ?orbT. +have vl : valid_edge he r by apply: (allP aval). +have vr : valid_edge g r by apply: (allP aval). +have vr' : valid_edge g' r by apply: (allP aval). +have noc' : below_alt g g' by apply: noc. +apply: (transport_below_edge noc' vr) => //. +have aval' : all (valid_edge^~ r) (bottom :: rcons s he). + apply/allP=> u uin; apply: (allP aval). + move: uin; rewrite !(inE, mem_cat, mem_rcons). + by move=> /orP[| /orP[]] ->; rewrite ?orbT. +have aval'' : all (valid_edge^~ r) (he :: s'). + apply/allP=> u uin; apply: (allP aval). + move: uin; rewrite !(inE, mem_cat, mem_rcons). + by move=> /orP[] ->; rewrite ?orbT. +have tr : transitive (relpre (pvert_y r) <=%R). + by move=> y x z; rewrite /=; apply: le_trans. +have g_he : pvert_y r g < pvert_y r he. + have r_he : r.y < pvert_y r he by rewrite -strict_under_pvert_y. + have g_r : pvert_y r g <= r.y by rewrite leNgt -strict_under_pvert_y. + by apply: le_lt_trans g_r r_he. +have he_g' : pvert_y r he <= pvert_y r g'. + move: pth; rewrite cat_path last_rcons => /andP[] _. + move=> /= /path_edge_below_pvert_y => /(_ _ aval''). + rewrite path_map /=. + by rewrite (path_sortedE tr) => /andP[] /allP/(_ _ g'in) /=. +by apply: lt_le_trans he_g'. +Qed. + +Definition non_inner (g : edge) (p : pt) := + p === g -> p = left_pt g \/ p = right_pt g. + +End working_context. + +Notation "p '<<=' e" := (point_under_edge p e)( at level 70, no associativity). +Notation "p '<<<' e" := (point_strictly_under_edge p e)(at level 70, no associativity). + +Notation "p '>>=' e" := (~~(point_strictly_under_edge p e))( at level 70, no associativity). +Notation "p '>>>' e" := (~~(point_under_edge p e))(at level 70, no associativity). +Notation "p '===' e" := (point_on_edge p e)( at level 70, no associativity). +Notation "e1 '<|' e2" := (edge_below e1 e2)( at level 70, no associativity). diff --git a/theories/pol.v b/theories/pol.v index 77adcfa..38d585e 100644 --- a/theories/pol.v +++ b/theories/pol.v @@ -1,15 +1,15 @@ -From mathcomp Require Import all_ssreflect. -From mathcomp Require Import ssralg poly ssrnum ssrint rat polyrcf. +From HB Require Import structures. +From mathcomp Require Import all_ssreflect archimedean. +From mathcomp Require Import ssralg poly ssrnum ssrint rat archimedean polyrcf. From mathcomp Require Import polyorder polydiv. -(** * Descartes. +(** * Descartes. polynomials link with the ssr library *) (* Copyright INRIA (20112012) Marelle Team (Jose Grimm; Yves Bertot; Assia Mahboubi). $Id: pol.v,v 1.35 2012/12/14 11:59:35 grimm Exp $ *) - Set Implicit Arguments. Unset Strict Implicit. Import Prenex Implicits. @@ -68,12 +68,12 @@ Proof. by move=> lta; rewrite mulr_gt0 // invr_gt0 ltr0n. Qed. Lemma half_ltx x: 0 < x -> half x < x. Proof. -by move=>lta; rewrite ltr_pdivr_mulr ?ltr0n // mulr_natr mulr2n ltr_addr. +by move=>lta; rewrite ltr_pdivrMr ?ltr0n // mulr_natr mulr2n ltrDr. Qed. Lemma double_half x : half x + half x = x. Proof. -by rewrite -mulrDl-mulr2n - mulr_natr -mulrA divrr ?two_unit ?mulr1. +by rewrite /half -splitr. Qed. Lemma half_inj (x y : R) : half x = half y -> x = y. @@ -88,35 +88,35 @@ Proof. by rewrite /half mulrBl. Qed. Lemma mid_between (a b: R): a < b -> a < half (a + b) < b. Proof. move => h. rewrite - half_lin - {1} (double_half a) - {3} (double_half b). -by rewrite ltr_add2l ltr_add2r ltr_pmul2r ?h //invr_gt0 ltr0n. +by rewrite ltrD2l ltrD2r ltr_pM2r ?h //invr_gt0 ltr0n. Qed. Lemma maxS (x y: R) (z := (Num.max x y) +1) : (x u < v + 1. - by move=> u v h; rewrite (le_lt_trans h) // ltr_addl ltr01. -by rewrite !p1// ?le_maxr// lexx // orbT. + by move=> u v h; rewrite (le_lt_trans h) // ltrDl ltr01. +by rewrite !p1// ?le_max// lexx // orbT. Qed. Lemma pmul2w1 (a b c d : R) : 0 <= a -> 0 <= d -> a <= b -> c <= d -> a * c <= b * d. Proof. move => a0 d0 ab cd. -apply: (le_trans (ler_wpmul2l a0 cd)). -by apply: (le_trans (ler_wpmul2r d0 ab)). +apply: (le_trans (ler_wpM2l a0 cd)). +by apply: (le_trans (ler_wpM2r d0 ab)). Qed. Lemma inv_comp x y: 0 < x -> 0 < y -> (x < y^-1) = (y < x^-1). Proof. move=> xp yp. -rewrite -(ltr_pmul2r yp) - [y < _](ltr_pmul2l xp). +rewrite -(ltr_pM2r yp) - [y < _](ltr_pM2l xp). by rewrite mulVf ?(gt_eqF yp) // mulfV // (gt_eqF xp). Qed. Lemma inv_compr x y: 0 < x -> 0 < y -> (y^-1 < x) = (x^-1 < y). Proof. move=> xp yp. -rewrite -(ltr_pmul2r yp) - [_ < y](ltr_pmul2l xp). +rewrite -(ltr_pM2r yp) - [_ < y](ltr_pM2l xp). by rewrite mulVf ?(gt_eqF yp) // mulfV // (gt_eqF xp). Qed. @@ -141,7 +141,7 @@ Implicit Types (F: R -> R) (s: seq R) (f g : nat -> R). Lemma bigmaxr_ge0 s F: 0 <= \max_(i <- s) F i. Proof. elim: s; first by rewrite big_nil. -by move=> s IHs Hri0; rewrite big_cons le_maxr Hri0 orbT. +by move=> s IHs Hri0; rewrite big_cons le_max Hri0 orbT. Qed. Lemma bigmaxr_le s F j: @@ -149,16 +149,16 @@ Lemma bigmaxr_le s F j: Proof. elim: s; first by rewrite in_nil. move=> i s IHs Hri0; rewrite big_cons. -case Hi: (j == i); first by rewrite (eqP Hi) le_maxr lexx. +case Hi: (j == i); first by rewrite (eqP Hi) le_max lexx. move: Hri0; rewrite in_cons Hi orFb => ins. -by apply: le_trans (IHs ins) _; rewrite le_maxr lexx orbT. +by apply: le_trans (IHs ins) _; rewrite le_max lexx orbT. Qed. Lemma bigmaxr_le0 s F: \max_(i <- s) F i <= 0 -> forall i, i \in s -> F i <= 0. Proof. elim: s; first by move=> _ i;rewrite in_nil. -move=> k s IHs; rewrite big_cons le_maxl; case /andP => Fk Hr1 i. +move=> k s IHs; rewrite big_cons ge_max; case /andP => Fk Hr1 i. rewrite in_cons; case /orP; [ move /eqP ->; apply: Fk | by apply: IHs]. Qed. @@ -167,8 +167,8 @@ Lemma bigmaxr_gt0 s F: \max_(i <- s) F i > 0 -> { i | i \in s & F i > 0}. Proof. elim :s => [| a l Hrec]; first by rewrite big_nil ltxx. -rewrite big_cons lt_maxr. -case (ltrP 0 (F a)); first by exists a => //; rewrite in_cons eqxx. +rewrite big_cons lt_max. +case (ltrP 0 (F a)); first by exists a => //; rewrite in_cons eqxx. rewrite leNgt => /negbTE ->; rewrite orFb => /Hrec [b bl fp0]. by exists b => //;rewrite in_cons bl orbT. Qed. @@ -196,7 +196,7 @@ Proof. move=> h; apply: (iffP idP) => leFm => [i ir | ]. by apply: le_trans leFm; apply: bigmaxr_le. rewrite big_seq_cond; elim /big_ind:_ => //. - by move=> x y xm ym; rewrite le_maxl; apply /andP. + by move=> x y xm ym; rewrite ge_max; apply /andP. by move=> i; rewrite andbT; apply: leFm. Qed. @@ -226,21 +226,21 @@ Qed. Lemma bigmaxf_ge0 f n: 0 <= \max_(i < n) f i. Proof. elim: n => [| n IHn]; first by rewrite big_ord0. -by rewrite bigmaxf_rec le_maxr IHn orbT. +by rewrite bigmaxf_rec le_max IHn orbT. Qed. Lemma bigmaxf_le f n j: (j < n)%N -> f j <= \max_(i < n) f i. Proof. elim: n => [ //| n IHn]; rewrite bigmaxf_rec. -case Hi: (j == n); first by rewrite (eqP Hi) le_maxr lexx. +case Hi: (j == n); first by rewrite (eqP Hi) le_max lexx. rewrite ltnS leq_eqVlt Hi orFb => aux;apply: (le_trans (IHn aux)). -by rewrite le_maxr lexx orbT. +by rewrite le_max lexx orbT. Qed. Lemma bigmaxf_le0 f n: \max_(i < n) f i <= 0 -> forall i, (i f i <= 0. Proof. -elim: n => [_ i //| n Hr]; rewrite bigmaxf_rec le_maxl; case /andP => Fk H i. +elim: n => [_ i //| n Hr]; rewrite bigmaxf_rec ge_max; case /andP => Fk H i. rewrite ltnS leq_eqVlt; case /orP; [ move /eqP ->; apply: Fk | by apply: Hr]. Qed. @@ -248,7 +248,7 @@ Lemma bigmaxf_gt0 f n: \max_(i < n ) f i > 0 -> { i | (i 0}. Proof. elim :n => [| a IH]; first by rewrite big_ord0 ltxx. case (ltrP 0 (f a)); first by exists a. -rewrite bigmaxf_rec lt_maxr leNgt; move /negbTE => ->; rewrite orFb => aux. +rewrite bigmaxf_rec lt_max leNgt; move /negbTE => ->; rewrite orFb => aux. by move: (IH aux) => [b bl fp0]; exists b => //; apply:ltn_trans (ltnSn a). Qed. @@ -276,7 +276,7 @@ Proof. move=> h; apply: (iffP idP) => leFm => [i ir | ]. by apply: le_trans leFm; apply: bigmaxf_le. rewrite big_seq_cond; elim /big_ind:_ => //. - by move=> x y xm ym; rewrite le_maxl; apply /andP. + by move=> x y xm ym; rewrite ge_max; apply /andP. by move=> [i hi] _; apply: leFm. Qed. @@ -296,7 +296,7 @@ apply: le_trans (_: \sum_(i < n) `| f i * g i| <= _). apply: ler_norm_sum. have ->: \sum_(i < n) `|f i * g i| = \sum_(i < n) `|f i| * `|g i|. by apply: eq_big => // i; rewrite normrM. -rewrite mulr_sumr; apply: ler_sum => i _; apply: ler_wpmul2r. +rewrite mulr_sumr; apply: ler_sum => i _; apply: ler_wpM2r. by rewrite normr_ge0. by apply: (bigmaxf_le (fun i => `|f i|)). Qed. @@ -306,7 +306,7 @@ Lemma normr_sumprod1 f g n b: `| \sum_(i< n) (f i * g i) | <= b * \sum_ (i b0 h; apply: (le_trans (normr_sumprod f g n)). -apply: ler_wpmul2r; first by rewrite sumr_ge0 // => i _; rewrite absr_ge0. +apply: ler_wpM2r; first by rewrite sumr_ge0 // => i _; rewrite absr_ge0. exact /(bigmaxf_lerP (fun z => `|f z|) n b0). Qed. @@ -439,14 +439,19 @@ Lemma shift_poly_is_linear c: linear (shift_poly c). Proof. by move=> a u v; rewrite /shift_poly comp_polyD comp_polyZ. Qed. Lemma shift_poly_multiplicative c: multiplicative (shift_poly c). -Proof. +Proof. split. move=> x y; exact: comp_polyM. by rewrite /shift_poly comp_polyC. Qed. +HB.instance Definition _ (c : R) := GRing.isLinear.Build _ _ _ _ _ (shift_poly_is_linear c). + +HB.instance Definition _ c := GRing.isMultiplicative.Build _ _ _ (shift_poly_multiplicative c). + +(*HB.instance Definition _ c := GRing.isLinear.Build _ _ _ _ _ (shift_poly_is_linear c). + Canonical shift_poly_additive c := Additive (shift_poly_is_linear c). Canonical shift_poly_linear c := Linear (shift_poly_is_linear c). -Canonical shift_poly_rmorphism c := AddRMorphism (shift_poly_multiplicative c). - +Canonical shift_poly_rmorphism c := AddRMorphism (shift_poly_multiplicative c).*) Lemma shift_polyD c1 c2 p: p \shift (c2 + c1) = (p\shift c1) \shift c2. @@ -650,7 +655,7 @@ Qed. Lemma reciprocalM p q : reciprocal_pol (p * q) = reciprocal_pol p * reciprocal_pol q. Proof. -move: (reciprocalC (GRing.zero R)) => aux. +move: (reciprocalC 0) => aux. case (poly0Vpos p); first by move => ->; rewrite mul0r aux mul0r. case (poly0Vpos q); first by move => -> _; rewrite mulr0 aux mulr0. set m:= (size p + size q).-1; move=> pa pb. @@ -727,7 +732,7 @@ Proof. move=> Hp. have H0noroot : ~~(root (p %/ 'X^(\mu_0 p)) 0). rewrite -mu_gt0. - rewrite -eqn0Ngt -(addr0 'X) -(@oppr0 (poly_zmodType R)) -polyC0 mu_div + rewrite -eqn0Ngt -(addr0 'X) -(@oppr0 {poly R}) -polyC0 mu_div ?subn_eq0; by rewrite leqnn. rewrite Pdiv.CommonIdomain.divp_eq0 negb_or Hp /= negb_or. rewrite -size_poly_gt0 {1}size_polyXn /= -leqNgt dvdp_leq //. @@ -824,8 +829,8 @@ Qed. Lemma CauchyBound1 : `| x | <= 1 + \max_(i < n) (`|E i / E n|). Proof. move: (bigmaxf_ge0 (fun i => `|E i / E n|) n) => cp. -case: (lerP `|x| 1)=> cx1; first by rewrite ler_paddr //. -rewrite addrC -ler_subl_addr. +case: (lerP `|x| 1)=> cx1; first by rewrite ler_wpDr //. +rewrite addrC -lerBlDr. move: (normr_sumprod (fun i => E i / E n) (fun i => x ^+ i) n). move: CauchyBound_aux => eq; move: (f_equal (fun z => `| z |) eq). rewrite normrN; move => <-; @@ -837,9 +842,9 @@ move: (sum_powers_of_x (m.+1) `|x|); set aux:= (\sum_(i < m.+1) _) => pa. set c := \max_(i < m.+1) `|E i / E m.+1| => cp r1. have a1p: 0 < `|x| - 1 by rewrite subr_gt0. have r2 : c* aux <= c* ( (`|x| ^+ m.+1) /(`|x| - 1)). - by rewrite (ler_wpmul2l cp) // ler_pdivl_mulr // mulrC pa ger_addl lerN10. -move: (le_trans r1 r2); rewrite mulrA ler_pdivl_mulr // mulrC. -rewrite normrX ler_pmul2r //. + by rewrite (ler_wpM2l cp) // ler_pdivlMr // mulrC pa gerDl lerN10. +move: (le_trans r1 r2); rewrite mulrA ler_pdivlMr // mulrC. +rewrite normrX ler_pM2r //. by apply:(lt_trans ltr01); rewrite exprn_egt1. Qed. @@ -847,7 +852,7 @@ Lemma CauchyBound2 : `| x | <= \sum_(i < n.+1) `|E i / E n|. Proof. case: (lerP `|x| 1)=> cx1. apply: (le_trans cx1). - rewrite big_ord_recr /= divff // normr1 ler_addr. + rewrite big_ord_recr /= divff // normr1 lerDr. rewrite sumr_ge0 // => i _; rewrite absr_ge0 //. move: (CauchyBound_aux). case e: n=> [| m]. @@ -863,7 +868,7 @@ move => h1; have h2 : x = - \sum_(i < m.+1) ( x^-(m - i) *(E i / E m.+1)). expf_eq0 x0 andbF. rewrite (f_equal (fun z => `| z |) h2) normrN. apply: le_trans (_: (\sum_(i < m.+1) `|E i / E m.+1|) <= _); last first. - by rewrite (big_ord_recr m.+1) /= ler_addl normr_ge0. + by rewrite (big_ord_recr m.+1) /= lerDl normr_ge0. have pa: (forall i, (i `| x ^- (m - i) | <= 1). move => i lin. have pa: 0 < `|x ^+ (m - i)| by rewrite normr_gt0 expf_eq0 x0 andbF. @@ -896,14 +901,14 @@ Definition norm_pol (p : {poly R}) := map_poly (fun x => `|x|) p. Lemma pow_monotone n (x y : R) : 0 <= x <= y -> 0 <= x ^+ n <= y ^+ n. Proof. move => /andP [xp xy]. -by rewrite ler_expn2r// ?andbT ?exprn_ge0// nnegrE (le_trans _ xy). +by rewrite lerXn2r// ?andbT ?exprn_ge0// nnegrE (le_trans _ xy). Qed. Lemma diff_xn_ub n (z x y: R): -z <= x -> x <= y -> y <= z -> `| y ^+ n - x ^+ n| <= (z^+(n.-1) *+ n) * (y - x). Proof. move => zx xy yz. -rewrite subrXX mulrC normrM [`|_ - _|]ger0_norm ?ler_wpmul2r // ?subr_ge0 //. +rewrite subrXX mulrC normrM [`|_ - _|]ger0_norm ?ler_wpM2r // ?subr_ge0 //. apply: (le_trans (ler_norm_sum _ _ _)). rewrite - [n in _*+ n] card_ord - sumr_const ler_sum // => [][i lin] _. rewrite normrM !normrX. @@ -911,7 +916,7 @@ have l1: 0<=`|x| <=z by rewrite normr_ge0 /= ler_norml zx /= (le_trans xy yz). have l2: 0<=`|y| <=z by rewrite normr_ge0 /= ler_norml yz /= (le_trans zx xy). have /andP [pa pb] := pow_monotone i l1. have /andP [pc pd] := pow_monotone (n.-1 - i)%N l2. -by move: (ler_pmul pc pa pd pb); rewrite - exprD subnK //; move: lin; case n. +by move: (ler_pM pc pa pd pb); rewrite - exprD subnK //; move: lin; case n. Qed. Lemma pol_lip p (z x y: R): -z <= x -> x <= y -> y <= z -> @@ -928,7 +933,7 @@ have ->: aux = ((\sum_(i s1; rewrite - (prednK s1) size_deriv big_ord_recl mulr0n mulr0 add0r. apply: eq_bigr => i _; rewrite coef_deriv normrMn mulrnAl mulrnAr //. rewrite big_distrl /= ler_sum // => i _;rewrite - mulrBr normrM -mulrA. -apply: (ler_wpmul2l (normr_ge0 p`_i)); exact: (diff_xn_ub i zx xy yz). +apply: (ler_wpM2l (normr_ge0 p`_i)); exact: (diff_xn_ub i zx xy yz). Qed. Lemma pol_ucont (p : {poly R}) a b (c := (norm_pol p^`()).[(Num.max (- a) b)]) : @@ -936,8 +941,8 @@ Lemma pol_ucont (p : {poly R}) a b (c := (norm_pol p^`()).[(Num.max (- a) b)]) : Proof. move => x y ax xy yb. apply: pol_lip => //. -apply: (le_trans _ ax); by rewrite ler_oppl le_maxr lexx. -apply: (le_trans yb); by rewrite le_maxr lexx orbT. +apply: (le_trans _ ax); by rewrite lerNl le_max lexx. +apply: (le_trans yb); by rewrite le_max lexx orbT. Qed. Lemma pol_cont (p : {poly R}) (x eps :R): 0 < eps -> @@ -946,24 +951,24 @@ Lemma pol_cont (p : {poly R}) (x eps :R): 0 < eps -> Proof. move => ep. move: (pol_ucont p (a:= x-1)(b:=x+1)); set c := _ .[_ ] => /= hc. -have pa: x-1 <= x by move: (ler_add2l x (-1) 0); rewrite addr0 lerN10. -have pb: x <= x+1 by move: (ler_add2l x 0 1); rewrite ler01 addr0. +have pa: x-1 <= x by move: (lerD2l x (-1) 0); rewrite addr0 lerN10. +have pb: x <= x+1 by move: (lerD2l x 0 1); rewrite ler01 addr0. have cp: 0<=c. move: (hc _ _ pa pb (lexx (x+1))). by rewrite addrAC addrN add0r mulr1; apply: le_trans; rewrite normr_ge0. exists (Num.min 1 (eps /(c+1))). - rewrite lt_minr ltr01 /= divr_gt0 // ? ep //. - by apply: (lt_le_trans ltr01); move: (ler_add2r 1 0 c); rewrite add0r cp. + rewrite lt_min ltr01 /= divr_gt0 // ? ep //. + by apply: (lt_le_trans ltr01); move: (lerD2r 1 0 c); rewrite add0r cp. move => y. -rewrite lt_minr; case /andP => xy1 xy2. +rewrite lt_min; case /andP => xy1 xy2. apply: (@le_lt_trans _ _ (c * `|(y - x)|)); last first. move: cp; rewrite le0r; case /orP; first by move /eqP => ->; rewrite mul0r. move => cp. - rewrite - (ltr_pmul2l cp) in xy2; apply: (lt_le_trans xy2). - rewrite mulrCA ger_pmulr //. - have c1: c <= c + 1 by move: (ler_add2l c 0 1); rewrite ler01 addr0. + rewrite -(ltr_pM2l cp) in xy2; apply: (lt_le_trans xy2). + rewrite mulrCA ger_pMr //. + have c1: c <= c + 1 by move: (lerD2l c 0 1); rewrite ler01 addr0. have c1p := (lt_le_trans cp c1). - by rewrite -(ler_pmul2r c1p) mulfVK ? (gt_eqF c1p) // mul1r. + by rewrite -(ler_pM2r c1p) mulfVK ? (gt_eqF c1p) // mul1r. move: (ltW xy1); rewrite ler_distl;case /andP => le1 le2. case /orP: (le_total x y) => xy. move: (xy); rewrite - subr_ge0 => xy'. @@ -1035,7 +1040,7 @@ Proof. move=> ab nla plb ep. move: (pol_ucont p (a:=a) (b:= b)); set c1 := _ .[_ ] => /= pc. set c := Num.max 1 c1. -have lc1: 1 <= c by rewrite le_maxr lexx. +have lc1: 1 <= c by rewrite le_max lexx. have cpos:= (lt_le_trans ltr01 lc1). set k := Num.bound ((b - a) * c / eps). move: (upper_nthrootP(leqnn k)) => hh. @@ -1046,21 +1051,21 @@ have c2p: 0 < v-u by rewrite subr_gt0. have hh1: (v-u) * c < eps. rewrite pa;set x := (X in _ / X). have xp: 0 < x by rewrite exprn_gt0 // ltr0n. - rewrite mulrAC -(ltr_pmul2r xp) (mulrVK (unitf_gt0 xp)). + rewrite mulrAC -(ltr_pM2r xp) (mulrVK (unitf_gt0 xp)). move: hh. rewrite -/x. - by rewrite ltr_pdivr_mulr// (mulrC _ x). + by rewrite ltr_pdivrMr// (mulrC _ x). have hh2 : v-u < eps. - by apply: le_lt_trans hh1; rewrite - {1} (mulr1 (v-u)) (ler_pmul2l c2p). + by apply: le_lt_trans hh1; rewrite - {1} (mulr1 (v-u)) (ler_pM2l c2p). have dvp: p.[u] < p.[v] by apply (lt_le_trans pun pvp). have hh5: p.[v] - p.[u] <= eps. move: (pc _ _ ha (ltW hb) hc);rewrite gtr0_norm ? subr_gt0 // mulrC => hh4. apply:(le_trans _ (ltW hh1)); apply: (le_trans hh4). - rewrite (ler_pmul2l c2p) le_maxr lexx orbT //. -rewrite eq1 /pair_in_interval pun pvp dvp (ltW hh2) ler_oppl. + rewrite (ler_pM2l c2p) le_max lexx orbT //. +rewrite eq1 /pair_in_interval pun pvp dvp (ltW hh2) lerNl. rewrite (le_trans _ hh5) ?(le_trans _ hh5) //. - by rewrite -{1} (addr0 p.[v]) ler_add2l oppr_ge0 ltW. -by rewrite -{1} (add0r (- p.[u])) ler_add2r. + by rewrite -{1} (addr0 p.[v]) lerD2l oppr_ge0 ltW. +by rewrite -{1} (add0r (- p.[u])) lerD2r. Qed. Lemma constructive_ivt_bis (p : {poly R})(a b : R) (eps: R): @@ -1084,14 +1089,14 @@ Lemma constructive_ivt_ter (p : {poly R})(a b : R) (eps: R): (p.[xy.2] <= eps) && (a <= xy.1) && (xy.1 < xy.2) && (xy.2 <= b) }. Proof. move=> ab nla plb ep. -have ba' : 0 < b - a by rewrite -(addrN a) ltr_add2r. +have ba' : 0 < b - a by rewrite -(addrN a) ltrD2r. have evalba : 0 < p.[b] - p.[a] by rewrite subr_gt0; exact: lt_le_trans plb. move: (pol_ucont p (a:=a) (b:= b)). set c := _ .[_ ] => /= pc. have cpos : 0 < c. - rewrite - (ltr_pmul2r ba') mul0r. + rewrite - (ltr_pM2r ba') mul0r. by apply: lt_le_trans (pc a b _ _ _) => //; rewrite ? ger0_norm // ltW. -have pdiv : (0 < (b - a) * c / eps) by rewrite ltr_pdivl_mulr // mul0r mulr_gt0. +have pdiv : (0 < (b - a) * c / eps) by rewrite ltr_pdivlMr // mul0r mulr_gt0. move: (archi_boundP (ltW pdiv)); set n := Num.bound _ => qn. have fact1 : (0 : R) < n%:R by exact: lt_trans qn => /=. case: n qn fact1 => [|n]; rewrite ?ltxx // => qn _. @@ -1114,7 +1119,7 @@ move/(@before_find _ 0 (fun x : R => 0 <= p.[x]) sl); move/negbT. rewrite -ltNge => pa'n. move:(ltW ba') => ba'w. have aa' : a <= a'. - rewrite /a'/sl (nth_map 0%N) // ler_addl mulr_ge0 //. + rewrite /a'/sl (nth_map 0%N) // lerDl mulr_ge0 //. by rewrite mulr_ge0 // ?invr_ge0 ?ler0n. have ia'_sharp : (ia' < n.+1)%N. move: ia'iota; rewrite leq_eqVlt; rewrite size_iota; case/orP=> //. @@ -1125,8 +1130,8 @@ have ia'_sharp : (ia' < n.+1)%N. have b'b : b' <= b. rewrite /b'/sl (nth_map 0%N) ?size_iota ?ltnS // nth_iota // add0n. have e : b = a + (b - a) by rewrite addrCA subrr addr0. - rewrite {2}e {e} ler_add2l //= -{2}(mulr1 (b -a)) ler_wpmul2l //. - rewrite ler_pdivr_mulr ?ltr0Sn // mul1r -subr_gte0 /=. + rewrite {2}e {e} lerD2l //= -{2}(mulr1 (b -a)) ler_wpM2l //. + rewrite ler_pdivrMr ?ltr0Sn // mul1r -subr_gte0 /=. have -> : (n.+1 = ia'.+1 + (n.+1 - ia'.+1))%N by rewrite subnKC. by rewrite mulrnDr addrAC subrr add0r subSS ler0n. have b'a'_sub : b' - a' = (b - a) / (n.+1)%:R. @@ -1136,17 +1141,18 @@ have b'a'_sub : b' - a' = (b - a) / (n.+1)%:R. rewrite opprD addrAC addrA subrr add0r addrC -mulrBr. by congr (_ * _); rewrite -mulrBl mulrSr addrAC subrr add0r div1r. have a'b' : a' < b'. - move/eqP: b'a'_sub; rewrite subr_eq; move/eqP->; rewrite ltr_addr. + move/eqP: b'a'_sub; rewrite subr_eq; move/eqP->; rewrite ltrDr. by rewrite mulr_gt0 // invr_gt0 ltr0Sn. rewrite pa'n a'b' b'b aa' pb'p. have : `|p.[b'] - p.[a']| <= eps. have := (pc sl`_ia' sl`_ia'.+1 aa' (ltW a'b') b'b). rewrite b'a'_sub => hpc; apply: le_trans hpc _ => /=. - rewrite mulrA ler_pdivr_mulr ?ltr0Sn // mulrC [eps * _]mulrC. - rewrite -ler_pdivr_mulr //; apply: (ltW qn). + rewrite mulrA ler_pdivrMr ?ltr0Sn // mulrC [eps * _]mulrC. + rewrite -ler_pdivrMr //; apply: (ltW qn). case/ler_normlP => h1 h2. -rewrite ler_oppl -(ler_add2l p.[b']) (le_trans h2) ? ler_addr //. -by rewrite -(ler_add2r (- p.[a'])) (le_trans h2) // ler_addl oppr_gte0 ltW. +rewrite lerNl/= !andbT. +rewrite -[in X in X && _](lerD2l p.[b']) (le_trans h2) ? lerDr //. +by rewrite -(lerD2r (- p.[a'])) (le_trans h2) // lerDl oppr_gte0 ltW. Qed. End PolsOnArchiField. diff --git a/theories/poly_normal.v b/theories/poly_normal.v index 2ca3ff0..92eb380 100644 --- a/theories/poly_normal.v +++ b/theories/poly_normal.v @@ -6,7 +6,7 @@ From mathcomp Require Import polyrcf qe_rcf_th complex. (* This file consists of 3 sections: - introduction of normal polynomials, some lemmas on normal polynomials -- constructions on sequences, such as all_neq0, all_pos, increasing, mid, seqmul, seqn0 +- constructions on sequences, such as all_neq0, all_pos, increasing, mid, seqmul, seqn0 - proof of Proposition 2.44 of [bpr], normal_changes *) (******************************************************************************) @@ -183,8 +183,8 @@ rewrite exprMn_comm; last first. by rewrite -mulNrn mulrC. rewrite sqrrN. rewrite -natrX. -rewrite mulr_natl. -rewrite [_ ^+2 *+ _]mulrS ler_add2l -mulr_natl -andbA /=. +rewrite (mulr_natl _ (2 ^ 2)). +rewrite [_ ^+2 *+ _]mulrS lerD2l -mulr_natl -andbA /=. apply/idP/idP => [/orP [] | H]. rewrite eq_sym paddr_eq0 ?sqr_ge0 //. case/andP => /eqP -> /eqP ->. @@ -195,7 +195,7 @@ case/orP : Hrez => [ | Hrez]. rewrite eq_sym mulf_eq0 oppr_eq0 pnatr_eq0 orFb =>/eqP Hrez. rewrite Hrez expr0n mulr0 exprn_even_le0 //= in H. by rewrite Hrez (eqP H) expr0n add0r eqxx. -rewrite Hrez H ltr_spaddl ?orbT // ?lt_def sqr_ge0 // sqrf_eq0. +rewrite Hrez H ltr_pwDl ?orbT // ?lt_def sqr_ge0 // sqrf_eq0. rewrite lt_def mulf_eq0 oppr_eq0 pnatr_eq0 orFb in Hrez. by case/andP : Hrez => ->. Qed. @@ -350,7 +350,7 @@ case : (leqP k (size p).-1) => Hk2. rewrite coefM (bigD1 ord0) //= subn0 (lt_le_trans (y := (p`_0 * q`_k))) //. rewrite pmulr_lgt0; first by rewrite Hpcoef. by rewrite Hqcoef // (@leq_trans ((size p).-1)). - rewrite ler_addl sumr_ge0 //. + rewrite lerDl sumr_ge0 //. case => /= i Hi Hi2. rewrite pmulr_rge0. case Hki : (k - i <= (size q).-1)%N. @@ -370,7 +370,7 @@ rewrite (bigD1 (Ordinal Hk3)) //= -[size q]prednK ?size_poly_gt0 // addSn addnS -!pred_Sn in Hk. rewrite pmulr_rgt0; first by rewrite Hqcoef. by apply: Hpcoef. -rewrite ler_addl sumr_ge0 //. +rewrite lerDl sumr_ge0 //. case => /= i Hi Hi2. apply: mulr_ge0. case Hi3 : (i <= (size p).-1)%N. @@ -402,7 +402,7 @@ rewrite (big_cat_nat op (n:=n)) // big_nat1 Hn [x in (op _ _ = x)](big_cat_nat op (n:=n)) // big_nat1 big_nat1 (Monoid.mulmA op). congr (op _ _). -rewrite -big_split big_nat [x in (_ = x)]big_nat. +rewrite -[LHS]big_split big_nat [x in (_ = x)]big_nat. apply: eq_bigr => i Hi. rewrite [x in (_ = x)](big_cat_nat op (n:=n)) // ?big_nat1 // ltnW//. by case/andP: Hi=> _ ->. @@ -531,9 +531,9 @@ apply/normalP; split=> [k | |k Hk |i Hpqi j Hij Hj]. \sum_(h.+2 <= j < k.+2) p`_h * q`_(k.-1 - h) * (p`_j * q`_(k.+1 - j)). rewrite big_add1 -pred_Sn -!big_split big_nat [x in (_ = x)]big_nat. apply: eq_bigr => h Hh. - rewrite (big_cat_nat (n:= h.+1) (GRing.add_comoid R) (fun j => true) + rewrite (big_cat_nat (n:= h.+1) GRing.add (fun j => true) (fun j => p`_h * q`_(k.-1 - h) * (p`_j * q`_(k.+1 - j))) ) //. - rewrite (big_cat_nat (n:= h.+2) (m:=h.+1) (GRing.add_comoid R) + rewrite (big_cat_nat (n:= h.+2) (m:=h.+1) GRing.add (fun j => true) (fun j => p`_h * q`_(k.-1 - h) * (p`_j * q`_(k.+1 - j))) ). rewrite big_nat1 -pred_Sn /= -/(nth 0 _ (h.+1)) !addrA. @@ -547,8 +547,8 @@ apply/normalP; split=> [k | |k Hk |i Hpqi j Hij Hj]. rewrite H {H} [x in ((x + _) - _)]addrC -[x in (_ - x)]addrA [x in (_ - (_ + x))]addrC !opprD !addrA addrC -sumrN !addrA -big_split. - have H : \big[GRing.add_comoid R/0]_(1 <= i < k.+1) - (GRing.add_comoid R) + have H : \big[GRing.add/0]_(1 <= i < k.+1) + GRing.add (- (p`_i.-1 * q`_(k - i) * (p`_i * q`_(k.+1 - i)))) (p`_i * q`_(k - i) * (p`_i.-1 * q`_(k - i.-1))) = 0. rewrite big_split sumrN /= addrC. @@ -586,8 +586,8 @@ apply/normalP; split=> [k | |k Hk |i Hpqi j Hij Hj]. by rewrite big_add1 -pred_Sn. rewrite H {H} [x in (_ + (_ + _) - x - _)]xchange -{12}(prednK Hk) [x in (_ + (_ + _) - x - _)]big_nat_recl//. - have H :(\big[GRing.add_comoid R/0]_(0 <= i < k.-1) - \big[GRing.add_comoid R/0]_(i.+1 <= j < k) + have H :(\big[GRing.add/0]_(0 <= i < k.-1) + \big[GRing.add/0]_(i.+1 <= j < k) (p`_j * q`_(k.-1 - j) * (p`_i.+1 * q`_(k.+1 - i.+1))) = \sum_(1 <= h < k) \sum_(h <= j < k) p`_h * q`_(k.+1 - h) * (p`_j * q`_(k.-1 - j))). @@ -602,14 +602,14 @@ apply/normalP; split=> [k | |k Hk |i Hpqi j Hij Hj]. \sum_(1 <= h < k) \sum_(h <= j < k) p`_h.-1 * q`_(k - h) * (p`_j.+1 * q`_(k - j)) + \sum_(1 <= i < k.+1) p`_i.-1 * q`_(k - i) * (p`_k.+1 * q`_0). - rewrite (big_cat_nat (GRing.add_comoid R) (n:= k)) // + rewrite (big_cat_nat GRing.add (n:= k)) // big_nat1 big_nat1 - [x in (_ = _ + x)](big_cat_nat (GRing.add_comoid R) (n:= k)) // + [x in (_ = _ + x)](big_cat_nat GRing.add (n:= k)) // big_nat1 (addnK k 0%N) Monoid.addmA. congr (_ + _). rewrite -big_split big_nat [x in (_ = x)]big_nat. apply: eq_bigr => i Hi. - rewrite (big_cat_nat (GRing.add_comoid R) (n:= k)) //. + rewrite (big_cat_nat GRing.add (n:= k)) //. rewrite big_nat1. by rewrite (addnK k 0%N). apply: ltnW. @@ -620,14 +620,14 @@ apply/normalP; split=> [k | |k Hk |i Hpqi j Hij Hj]. \sum_(1 <= h < k) \sum_(h <= j < k) p`_h * q`_(k - h) * (p`_j * q`_(k - j)) + \sum_(1 <= i < k.+1) p`_i * q`_(k - i) * (p`_k * q`_0). - rewrite (big_cat_nat (GRing.add_comoid R) (n:= k)) // + rewrite (big_cat_nat GRing.add (n:= k)) // big_nat1 big_nat1 - [x in (_ = _ + x)](big_cat_nat (GRing.add_comoid R) (n:= k)) // + [x in (_ = _ + x)](big_cat_nat GRing.add (n:= k)) // big_nat1 (addnK k 0%N) Monoid.addmA. congr (_ + _). rewrite -big_split big_nat [x in (_ = x)]big_nat. apply: eq_bigr => i Hi. - rewrite (big_cat_nat (GRing.add_comoid R) (n:= k)) //. + rewrite (big_cat_nat GRing.add (n:= k)) //. by rewrite big_nat1 (addnK k 0%N). apply: ltnW. by case/andP : Hi. @@ -637,15 +637,15 @@ apply/normalP; split=> [k | |k Hk |i Hpqi j Hij Hj]. [x in (((((_ + x) + _) + _) + _) + _)]addrC !addrA -big_split -addrA [x in (_ + x)]addrC !addrA addrC !addrA -big_split. - have H : \big[GRing.add_comoid R/0]_(1 <= i < k) - (GRing.add_comoid R) - ((GRing.add_comoid R) + have H : \big[GRing.add/0]_(1 <= i < k) + GRing.add + (GRing.add (- (\sum_(i <= j < k) p`_i * q`_(k.+1 - i) * (p`_j * q`_(k.-1 - j)))) (- (\sum_(i <= j < k) p`_i.-1 * q`_(k - i) * (p`_j.+1 * q`_(k - j))))) - ((GRing.add_comoid R) - (\big[GRing.add_comoid R/0]_(i <= j < k) + (GRing.add + (\big[GRing.add/0]_(i <= j < k) (p`_j.+1 * q`_(k - j.+1) * (p`_i.-1 * q`_(k - i.-1)))) (\sum_(i <= j < k) p`_i * q`_(k - i) * (p`_j * q`_(k - j)))) = \sum_(1 <= h < k) \sum_(h <= j < k) (p`_h * p`_j - p`_h.-1 * p`_j.+1) * @@ -848,8 +848,8 @@ Proof. move=> p z Hz Hrootz. have Hrootzbar : root (toC p) z^*. by rewrite -complex_root_conj_polyR. -have Hp := (factor_complex_roots z). -rewrite -(dvdp_map ((ComplexField.real_complex_rmorphism R))) /= Hp. +have /= Hp := (factor_complex_roots z). +rewrite -(dvdp_map (real_complex R)) /= Hp. rewrite Gauss_dvdp. apply/andP; split; by rewrite -root_factor_theorem. apply: Pdiv.ClosedField.root_coprimep => x. @@ -868,7 +868,7 @@ Lemma real_root_div_poly_deg1 (p : {poly R}) (z : C) : Proof. move=>Himz Hroot. rewrite root_factor_theorem (@complexE _ z) Himz mulr0 addr0 in Hroot. -rewrite -(dvdp_map ((ComplexField.real_complex_rmorphism R))) /=. +rewrite -(dvdp_map (real_complex R)) /=. have H : toC ('X - (Re z)%:P) = 'X - ((Re z)%:C)%:P. by rewrite map_poly_is_additive map_polyC map_polyX. by rewrite H. @@ -1579,8 +1579,8 @@ apply/increasingP => k Hk. rewrite spseq_size in Hk. rewrite (@spseq_coef k) //. rewrite (@spseq_coef k.+1) //. - rewrite ler_sub // ler_pdivr_mulr. - rewrite mulrC mulrA ler_pdivl_mulr. + rewrite lerB // ler_pdivrMr. + rewrite mulrC mulrA ler_pdivlMr. by rewrite -expr2 (H3 k.+1). rewrite (normal_0notroot_2 Hpnormal Hp0noroot) //. by rewrite -(@addn2 k) addnC -ltn_subRL p_size subn2. diff --git a/theories/preliminaries.v b/theories/preliminaries.v index 60404a8..1d0f456 100644 --- a/theories/preliminaries.v +++ b/theories/preliminaries.v @@ -1,4 +1,23 @@ +From elpi Require Import elpi. + +#[projections(primitive)] Record r := { fst : nat -> nat; snd : bool }. +Axiom t : r. +Elpi Command test. +Elpi Query lp:{{ + coq.say "quotation for primitive fst t" {{ t.(fst) 3 }}, + coq.say "quotation for compat fst t" {{ fst t 3 }}, + coq.locate "r" (indt I), + coq.env.projections I [some P1,some P2], + coq.say "compatibility constants" P1 P2, + coq.env.primitive-projections I [some (pr Q1 N1), some (pr Q2 N2)], + coq.say "fst primproj" Q1 N1, + coq.say "snd primproj" Q2 N2 +}}. + + + Require Import Reals. +From HB Require Import structures. From mathcomp Require Import all_ssreflect all_algebra vector reals classical_sets Rstruct. From infotheo Require Import convex. @@ -14,15 +33,16 @@ Unset Printing Implicit Defensive. Lemma enum_rank_index {T : finType} i : nat_of_ord (enum_rank i) = index i (enum T). Proof. -rewrite /enum_rank /enum_rank_in /insubd /odflt /oapp insubT//. +rewrite /enum_rank [enum_rank_in]unlock /insubd /odflt /oapp insubT//. by rewrite cardE index_mem mem_enum. Qed. (* TODO: do we keep this as more newcomer friendly than having to look deep into the library ? *) -Lemma enum_prodE {T1 T2 : finType} : - enum [finType of T1 * T2] = prod_enum T1 T2. -Proof. by rewrite enumT Finite.EnumDef.enumDef. Qed. +Lemma enum_prodE {T1 T2 : finType} : enum {: T1 * T2} = prod_enum T1 T2. +Proof. +by rewrite /enum_mem unlock /= /prod_enum -(@eq_filter _ predT) ?filter_predT. +Qed. Lemma index_allpairs {T1 T2: eqType} (s1: seq T1) (s2: seq T2) x1 x2 : x1 \in s1 -> x2 \in s2 -> @@ -30,7 +50,7 @@ Lemma index_allpairs {T1 T2: eqType} (s1: seq T1) (s2: seq T2) x1 x2 : ((index x1 s1) * (size s2) + index x2 s2)%N. Proof. move=>ins1 ins2. -elim: s1 ins1=>//= a s1 IHs1 ins1. +elim: s1 ins1=>//= a s1 IHs1 ins1. (* HERE*) rewrite index_cat. case ax: (a == x1). move: ax=>/eqP ax; subst a; rewrite /muln /muln_rec /addn /addn_rec /=. @@ -43,11 +63,11 @@ case in12: ((x1, x2) \in [seq (a, x0) | x0 <- s2]). by rewrite size_map (IHs1 ins1) addnA. Qed. -Lemma enum_rank_prod {T T': finType} i j : - (nat_of_ord (@enum_rank [finType of T * T'] (i, j)) = (enum_rank i) * #|T'| + enum_rank j)%N. +Lemma enum_rank_prod {T T': finType} (i : T) (j : T') : + (nat_of_ord (enum_rank (i, j)) = (enum_rank i) * #|T'| + enum_rank j)%N. Proof. do 3 rewrite enum_rank_index. -rewrite enumT Finite.EnumDef.enumDef cardE=>/=. +rewrite enum_prodE cardE /=. by apply index_allpairs; rewrite enumT. Qed. @@ -93,10 +113,10 @@ by exists (a' :: s'). Qed. Lemma index_enum_cast_ord n m (e: n = m) : - index_enum [finType of 'I_m] = [seq (cast_ord e i) | i <- index_enum [finType of 'I_n]]. + index_enum 'I_m = [seq (cast_ord e i) | i <- index_enum 'I_n]. Proof. subst m. -rewrite -{1}(map_id (index_enum [finType of 'I_n])). +rewrite -{1}(map_id (index_enum 'I_n)). apply eq_map=>[[x xlt]]. rewrite /cast_ord; congr Ordinal; apply bool_irrelevance. Qed. @@ -178,7 +198,7 @@ Lemma size_index_enum (T: finType): size (index_enum T) = #|T|. Proof. by rewrite cardT enumT. Qed. Lemma map_nth_ord [T : Type] (x: T) (s : seq T) : - [seq nth x s (nat_of_ord i) | i <- index_enum [finType of 'I_(size s)]] = s. + [seq nth x s (nat_of_ord i) | i <- index_enum 'I_(size s)] = s. Proof. rewrite /index_enum; case: index_enum_key=>/=; rewrite -enumT. elim: s=>/= [| a s IHs]. @@ -209,7 +229,7 @@ From infotheo Require Import fdist. Local Open Scope fdist_scope. Lemma Convn_pair [T U : convType] [n : nat] (g : 'I_n -> T * U) (d : {fdist 'I_n}) : - Convn d g = (Convn d (fst \o g), Convn d (snd \o g)). + Convn conv d g = (Convn conv d (Datatypes.fst \o g), Convn conv d (Datatypes.snd \o g)). Proof. elim: n g d => [|n IHn] g d. by have := fdistI0_False d. diff --git a/theories/preliminaries_hull.v b/theories/preliminaries_hull.v index 86607bd..667a501 100644 --- a/theories/preliminaries_hull.v +++ b/theories/preliminaries_hull.v @@ -36,8 +36,8 @@ elim: m n=>[| m IHm] n. rewrite /addn/addn_rec-plus_n_O. move:(size_iota n 0)=>/size0nil->/=; apply/esym/negbTE. rewrite negb_and orbC -implybE; apply/implyP=>/forallP lmono; rewrite -ltnNge. - elim:l a {IHl} lmono=>[| b l IHl] a; first by move=>/(_ 0). - by move=>lmono; apply (ltn_trans (lmono 0)); apply IHl=>i/=; apply (lmono (lift ord0 i)). + elim:l a {IHl} lmono=>[| b l IHl] a; first by move=>/(_ ord0). + by move=>lmono; apply (ltn_trans (lmono ord0)); apply IHl=>i/=; apply (lmono (lift ord0 i)). rewrite/iota-/(iota n.+1 m)/subseq. case: ifP. move=>/eqP an; subst a. @@ -216,18 +216,21 @@ Variable (R : realDomainType). Local Open Scope ereal_scope. (* PRed to MathComp-Analysis: https://github.com/math-comp/analysis/pull/859 *) +(* Definition ereal_blatticeMixin : Order.BLattice.mixin_of (Order.POrder.class (@ereal_porderType R)). exists (-oo); exact leNye. Defined. Canonical ereal_blatticeType := BLatticeType (\bar R) ereal_blatticeMixin. + Definition ereal_tblatticeMixin : Order.TBLattice.mixin_of (Order.POrder.class (ereal_blatticeType)). exists (+oo); exact leey. Defined. Canonical ereal_tblatticeType := TBLatticeType (\bar R) ereal_tblatticeMixin. (* /PRed *) +*) (* Note: Should be generalized to tbLatticeType+orderType, but such a structure is not defined. *) Lemma ereal_joins_lt diff --git a/theories/safe_cells.v b/theories/safe_cells.v new file mode 100644 index 0000000..f3aaf4b --- /dev/null +++ b/theories/safe_cells.v @@ -0,0 +1,751 @@ +From mathcomp Require Import all_ssreflect all_algebra. +Require Export Field. +Require Import generic_trajectories. +Require Import math_comp_complements points_and_edges events cells. +Require Import opening_cells cells_alg. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Require Import NArithRing. +Import Order.TTheory GRing.Theory Num.Theory Num.ExtraDef Num. + +Open Scope ring_scope. + +Section safety_property. + +Variable R : realFieldType. + +Notation pt := (@pt R). +Notation p_x := (p_x R). +Notation p_y := (p_y R). +Notation Bpt := (Bpt R). +Notation edge := (@edge R). +Notation cell := (@cell R edge). +Notation low := (low R edge). +Notation high := (high R edge). +Notation left_pts := (left_pts R edge). +Notation right_pts := (right_pts R edge). +Notation dummy_pt := (dummy_pt R 1). +Notation event := (@event R edge). +Notation point' := (@point R edge). +Notation outgoing := (@point R edge). + +Variables closed : seq cell. +(* The last open cell. We need to prove that that its top edge is top. + Then, coverage will be given for all obstacles by the fact that all + edges in obstacles are different from top. *) +Variables bottom top : edge. +Variable obstacles : seq edge. +Variables points : seq pt. + +Hypothesis obstacles_sub : + {subset [seq low c | c <- closed] ++ + [seq high c | c <- closed] <= bottom :: top :: obstacles}. + +Hypothesis obstacles_point_in : + {subset [seq left_pt g | g <- obstacles] ++ + [seq right_pt g | g <- obstacles] <= points}. + +Hypothesis disj_closed : {in closed &, disjoint_closed_cells R}. +(* +Hypothesis disj_open : {in [:: o_cell] & closed, disjoint_open_closed_cells R}*) + +Hypothesis coverage : {in obstacles, forall g, edge_covered g [::] closed}. +Hypothesis covered_points : + {in points, forall (p : pt), exists2 c, + c \in closed & p \in (right_pts c : seq pt) /\ + (p >>> low c)}. + +Hypothesis non_empty_closed : {in closed, forall c, left_limit c < right_limit c}. +Hypothesis closed_ok : {in closed, forall c, closed_cell_side_limit_ok c}. +Hypothesis noc : {in bottom :: top :: obstacles &, + forall g1 g2, inter_at_ext g1 g2}. +Hypothesis low_high : {in closed, forall c, low c <| high c}. +Hypothesis low_dif_high : {in closed, forall c, low c != high c}. + +Lemma x_left_pts_left_limit (c : cell) (p : pt) : + closed_cell_side_limit_ok c -> + p \in (left_pts c : seq pt) -> p_x p = left_limit c. +Proof. +move=> + pin; move=> /andP[] ln0 /andP[] lsx _. +by rewrite (eqP (allP lsx _ _)). +Qed. + +Lemma x_right_pts_right_limit (c : cell) (p : pt) : + closed_cell_side_limit_ok c -> + p \in (right_pts c : seq pt) -> p_x p = right_limit c. +Proof. +move=> + pin; move=> /andP[] _ /andP[] _ /andP[] _ /andP[] _ /andP[] _. +move=> /andP[] rn0 /andP[] rsx _. +by rewrite (eqP (allP rsx _ _)). +Qed. + +Lemma left_limit_left_pt_high_cl (c : cell) : + closed_cell_side_limit_ok c -> + p_x (left_pt (high c)) <= left_limit c. +Proof. +move=> /andP[] ln0 /andP[] lsx /andP[] _ /andP[] /andP[] _ /andP[] + _ _. +by rewrite (eqP (allP lsx _ (head_in_not_nil _ ln0))). +Qed. + +Lemma right_limit_right_pt_high_cl (c : cell) : + closed_cell_side_limit_ok c -> + right_limit c <= p_x (right_pt (high c)). +Proof. +move=> /andP[] _ /andP[] _ /andP[] _ /andP[] _ /andP[] _. +move=> /andP[] rn0 /andP[] rsx /andP[] _ /andP[] /andP[] _ /andP[] _ + _. +by rewrite (eqP (allP rsx _ (head_in_not_nil _ rn0))). +Qed. + +Lemma left_limit_left_pt_low_cl (c : cell) : + closed_cell_side_limit_ok c -> + p_x (left_pt (low c)) <= left_limit c. +Proof. +move=> /andP[] ln0 /andP[] lsx /andP[] _ /andP[] _ /andP[]. +move=> /andP[] _ /andP[] + _ _. +by rewrite (eqP (allP lsx _ (last_in_not_nil _ ln0))). +Qed. + +Lemma right_limit_right_pt_low_cl (c : cell) : + closed_cell_side_limit_ok c -> + right_limit c <= p_x (right_pt (low c)). +Proof. +move=> /andP[] _ /andP[] _ /andP[] _ /andP[] _ /andP[] _. +move=> /andP[] rn0 /andP[] rsx /andP[] _ /andP[] _ /andP[] _ /andP[] _ +. +by rewrite (eqP (allP rsx _ (last_in_not_nil _ rn0))). +Qed. + +Lemma right_valid : + {in closed, forall c, {in (right_pts c : seq pt), forall p, + valid_edge (low c) p /\ valid_edge (high c) p}}. +Proof. +move=> c cin p pin. +have cok := closed_ok cin. +have lltr : left_limit c < right_limit c. + by apply: non_empty_closed cin. +split. + apply/andP; split; rewrite (x_right_pts_right_limit cok pin). + apply/(le_trans (left_limit_left_pt_low_cl cok)). + by apply/ltW. + by apply: right_limit_right_pt_low_cl. +apply/andP; split; rewrite (x_right_pts_right_limit cok pin). + apply/(le_trans (left_limit_left_pt_high_cl cok)). + by apply/ltW. +by apply: right_limit_right_pt_high_cl. +Qed. + +Lemma closed_cell_in_high_above_low p (c : cell) : + low c != high c -> + low c <| high c -> + inter_at_ext (low c) (high c) -> + closed_cell_side_limit_ok c -> + left_limit c < p_x p < right_limit c -> + p === high c -> p >>> low c. +Proof. +move=> dif bel noclh cok /andP[] midl midr on. +have [vlp vhp] : valid_edge (low c) p /\ valid_edge (high c) p. + move: cok=> /andP[] ln0 /andP[] lsx /andP[]. + move=> _ /andP[] /andP[] _ /andP[] lh _ /andP[] /andP[] _ /andP[] ll _. + move=> /andP[] rn0 /andP[] rsx /andP[]. + move=> _ /andP[] /andP[] _ /andP[] _ rl /andP[] _ /andP[] _ rh. + rewrite (eqP (allP lsx _ (@last_in_not_nil pt dummy_pt _ ln0))) in ll. + rewrite (eqP (allP rsx _ (@head_in_not_nil pt dummy_pt _ rn0))) in rl. + rewrite (eqP (allP lsx _ (@head_in_not_nil pt dummy_pt _ ln0))) in lh. + rewrite (eqP (allP rsx _ (@last_in_not_nil pt dummy_pt _ rn0))) in rh. + split; rewrite /valid_edge/generic_trajectories.valid_edge. + by rewrite (ltW (le_lt_trans ll midl)) (ltW (lt_le_trans midr rh)). + by rewrite (ltW (le_lt_trans lh midl)) (ltW (lt_le_trans midr rl)). +rewrite under_onVstrict // negb_or. +move: noclh=> [abs | noclh]; first by rewrite abs eqxx in dif. +apply/andP; split; last first. + apply/negP=> abs. + have := order_edges_strict_viz_point' vlp vhp bel abs. + by rewrite strict_nonAunder // on. +apply/negP=> abs. +have := noclh _ abs on; rewrite !inE=> /orP[] /eqP {}abs. + move: midl; apply/negP; rewrite -leNgt abs. + by apply: left_limit_left_pt_low_cl. +(* TODO: at this place, the typechecking loops, this warrants a bug report. *) +(*( have := left_limit_max cok. *) +move: midr; apply/negP; rewrite -leNgt abs. +by apply: right_limit_right_pt_low_cl. +Qed. + +(* I don't know yet if this is going to be used. *) +Lemma above_low : + {in closed, forall c p, p === high c -> valid_edge (low c) p -> + p >>= low c}. +Proof. +move=> c cin p /[dup] ponh /andP[] _ vh vl. +apply/negP=> pul. +have lbh : low c <| high c by apply: low_high. +have := order_edges_strict_viz_point' vl vh lbh pul. +by rewrite strict_nonAunder // ponh. +Qed. + +Lemma right_side_under_high (c : cell) (p : pt) : + closed_cell_side_limit_ok c -> + valid_edge (high c) p -> + p \in (right_pts c : seq pt) -> + p <<= high c. +Proof. +move=> cok vph pin. +set p' := Bpt (p_x p) (pvert_y p (high c)). +have sx: p_x p = p_x p' by rewrite /p'. +have p'on : p' === high c by apply: pvert_on vph. +rewrite (under_edge_lower_y sx) //. +have := cok. +do 5 move=> /andP[] _. +move=> /andP[] rn0 /andP[] rsx /andP[] srt /andP[] lon _. +have p'q : p' = head dummy_pt (right_pts c). + have := on_edge_same_point p'on lon. + have /eqP -> := allP rsx _ (head_in_not_nil dummy_pt rn0). + have /eqP -> := allP rsx _ pin=> /(_ erefl) samey. + apply/(@eqP pt). + rewrite pt_eqE samey eqxx andbT. + rewrite (eqP (allP rsx _ pin))/=. + by rewrite (eqP (allP rsx _ (head_in_not_nil dummy_pt rn0))). +move: rn0 p'q pin srt. +elim: (right_pts c) => [| p2 rpts Ih] // rn0 p'1 pin srt. +move: pin; rewrite inE => /orP[/eqP -> | pin]. + by rewrite p'1. +rewrite /= in srt. +(* TODO : use rev_trans here. *) +have gt_trans : transitive (>%R : rel R). + by move=> x y z xy yz ; apply: (lt_trans yz xy). +move: (srt); rewrite (path_sortedE gt_trans)=> /andP[] srt' _. +apply: ltW; rewrite p'1. +by apply: (allP srt'); rewrite map_f. +Qed. + +Lemma in_bound_closed_valid (c : cell) p : + closed_cell_side_limit_ok c -> + left_limit c <= p_x p -> p_x p <= right_limit c -> + valid_edge (low c) p /\ valid_edge (high c) p. +Proof. +move=> cok lp pr. +have llh := left_limit_left_pt_high_cl cok. +have lll := left_limit_left_pt_low_cl cok. +have rrh := right_limit_right_pt_high_cl cok. +have rrl := right_limit_right_pt_low_cl cok. +split; rewrite /valid_edge/generic_trajectories.valid_edge. + by rewrite (le_trans lll lp) (le_trans pr rrl). +by rewrite (le_trans llh lp) (le_trans pr rrh). +Qed. + +Lemma left_side_under_high (c : cell) p : + closed_cell_side_limit_ok c -> + valid_edge (high c) p -> + p \in (left_pts c : seq pt) -> + p <<= high c. +Proof. +move=> cok vph pin. +set p' := Bpt (p_x p) (pvert_y p (high c)). +have sx: p_x p = p_x p' by rewrite /p'. +have p'on : p' === high c by apply: pvert_on vph. +rewrite (under_edge_lower_y sx) //. +have := cok. +move=> /andP[] ln0 /andP[] lsx /andP[] srt /andP[] hon _. +have p'q : p' = head dummy_pt (left_pts c). + have := on_edge_same_point p'on hon. + rewrite (eqP (allP lsx _ pin)). + rewrite (x_left_pts_left_limit cok (head_in_not_nil _ ln0)). + move=> /(_ erefl) samey. + apply/(@eqP pt); rewrite pt_eqE samey eqxx andbT. + rewrite (eqP (allP lsx _ pin)) eq_sym. + by rewrite (allP lsx _ (head_in_not_nil _ ln0)). +move: ln0 p'q pin srt. +case: (left_pts c)=> [| p2 lpts] // _ p'q pin srt. +move: pin; rewrite (@in_cons pt) => /orP[/eqP -> | pin]. + by rewrite p'q. +apply: ltW; rewrite p'q. +move: srt=> /=; rewrite (path_sortedE); last first. + by move=> x y z xy yz; apply: (lt_trans yz xy). +move=> /andP[] /allP/(_ (p_y p)) + _; apply. +by rewrite (@map_f pt). +Qed. + +Lemma safe_cell_interior c p : + c \in closed -> p <<< high c -> p >>> low c -> + left_limit c < p_x p < right_limit c -> + {in obstacles, forall g, ~~ (p === g)}. +Proof. +move=> ccl puh pal /andP[] pright pleft g gin; apply/negP=> pong. +have pinc : inside_closed' p c. + by rewrite inside_closed'E (underW puh) pal pright (ltW pleft). +have [[opc [pccs [pccssub [highs [cpccs [opco lopcq]]]]]] | ] := coverage gin. + by []. +move=> [[ | pc1 pcc] [pccn0 [pcccl [ highs [conn [lpcc rpcc]]]]]]. + by []. +have : left_limit pc1 <= p_x p. + by move:(pong)=> /andP[] _ /andP[]; rewrite lpcc. +rewrite le_eqVlt=> /orP[ /eqP pxq | ]. + have plg : p = left_pt g. + move: lpcc; rewrite /= pxq=> samex. + have := on_edge_same_point pong (left_on_edge _). + rewrite samex=> /(_ erefl) samey. + by apply/(@eqP pt); rewrite pt_eqE samex samey !eqxx. + have pin : p \in points. + apply: obstacles_point_in; rewrite mem_cat; apply/orP; left. + by rewrite plg map_f. + have [c' ccl' [pc'r p'al]] := (covered_points pin). + have := disj_closed ccl ccl'. + move=> [cqc' | ]. + have := non_empty_closed ccl'. + move: pleft; rewrite cqc'. + by rewrite (x_right_pts_right_limit (closed_ok ccl')) // lt_irreflexive. + move=> /(_ p); rewrite pinc=> /negP; apply. + rewrite inside_closed'E p'al. + have c'ok := closed_ok ccl'. + have /andP[_ /andP[_ /andP[_ /andP[_ /andP[_ ]]] ]] := c'ok. + move=> /andP[rn0 /andP[samex /andP[srt /andP[onhigh onlow]]]]. + have prlq : p_x p = right_limit c' by apply/eqP/(allP samex). + rewrite (under_edge_lower_y _ onhigh) /=; last first. + rewrite (eqP (allP samex _ pc'r)). + by rewrite (eqP (allP samex _ (head_in_not_nil dummy_pt rn0))). + have -> /= : p_y p <= p_y (head dummy_pt (right_pts c')). + case psq : (right_pts c') => [ | p1 ps]; first by rewrite psq in rn0. + move: pc'r; rewrite psq inE=> /orP[/eqP -> | pps]; first by []. + apply: ltW. + (* TODO : use rev_trans here. *) + have gt_trans : transitive (>%R : rel R). + by move=> x y z xy yz; apply: (lt_trans yz xy). + move: (srt); rewrite psq /= (path_sortedE gt_trans)=> /andP[] + _. + by move=> /allP /(_ _ (map_f _ pps)). + by rewrite prlq le_refl andbT (non_empty_closed ccl'). +elim: pcc pc1 pcccl highs conn rpcc {lpcc pccn0} => + [ | pc2 pcc Ih] pc1 pcccl highs conn rpcc pc1lp. + have pc1cl : pc1 \in closed by apply: pcccl; rewrite inE eqxx. + have hpc1 : high pc1 = g by apply: (highs _ (mem_head _ _)). + move: rpcc; rewrite /last_cell/= => rpc1. + have vgp : valid_edge g p by move: pong=> /andP[]. + have [pr | pnr ] := eqVneq (p : pt) (right_pt g). + have [c' c'in [prc' pin']] : exists2 c', c' \in closed & + p_x p = right_limit c' /\ inside_closed' p c'. + have pp : p \in points. + by apply/obstacles_point_in; rewrite pr mem_cat map_f // orbT. + have [c' c'in [pr' pal']] := covered_points pp. + exists c'; rewrite // inside_closed'E pal'. + rewrite (x_right_pts_right_limit (closed_ok c'in)) // le_refl. + rewrite (non_empty_closed c'in). + have [vpl' vph'] := right_valid c'in pr'. + by rewrite (right_side_under_high (closed_ok c'in)). + have [cqc' | ] := disj_closed ccl c'in. + by move: pleft; rewrite prc' cqc'; rewrite lt_irreflexive. + by move=> /(_ p); rewrite pin' pinc. + have noc1 : inter_at_ext (low pc1) (high pc1). + by apply/noc; apply: obstacles_sub; rewrite mem_cat map_f //= ?orbT. + have ponh : p === high pc1 by rewrite hpc1. + have pin1 : inside_closed' p pc1. + rewrite inside_closed'E under_onVstrict hpc1 // pong pc1lp /=. + rewrite rpc1; move: vgp=> /andP[] _ ->; rewrite andbT. + have := closed_cell_in_high_above_low (low_dif_high pc1cl) (low_high pc1cl) + noc1 (closed_ok pc1cl) _ ponh; apply. + rewrite pc1lp /= rpc1. + move: (pong)=> /andP[] _ /andP[] _; rewrite le_eqVlt=> /orP[]; last by []. + move=> /eqP abs. + move: pnr=> /negP[]; rewrite pt_eqE abs /=. + rewrite (on_edge_same_point pong (right_on_edge _)) -abs//. + by rewrite !eqxx. + have vph1 : valid_edge (high pc1) p by move: ponh=> /andP[]. + have [cqc' | ] := disj_closed ccl pc1cl. + by move: puh; rewrite strict_nonAunder cqc' // ponh. + by move=> /(_ p); rewrite pin1 pinc. +have pcccl' : {subset pc2 :: pcc <= closed}. + by move=> c' c'in; apply: pcccl; rewrite inE c'in orbT. +have highs' : {in pc2 :: pcc, forall c, high c = g}. + by move=> c' c'in; apply highs; rewrite inE c'in orbT. +have conn' : connect_limits (pc2 :: pcc). + by move: conn; rewrite /= => /andP[]. +have rpcc' : right_limit (last_cell (pc2 :: pcc)) = p_x (right_pt g). + by exact: rpcc. +have [pleft2 | pright2 ] := lerP (p_x p) (left_limit pc2). +(* In this case, p is inside pc1, contradiction with pinc *) + have v1 : valid_edge g p by move: pong=> /andP[]. + have pc1cl : pc1 \in closed by apply: pcccl; rewrite inE eqxx. + suff pin1 : inside_closed' p pc1. + have [cqpc1 | ] := disj_closed ccl pc1cl. + move: puh; rewrite cqpc1 (highs _ (mem_head _ _)) strict_nonAunder //. + by rewrite pong. + by move=> /(_ p); rewrite pin1 pinc. + rewrite inside_closed'E. + have r1l2 : right_limit pc1 = left_limit pc2. + by apply/eqP; move: conn=> /= /andP[]. + move: (conn)=> /= /andP[] /eqP -> _; rewrite pleft2 pc1lp !andbT. + rewrite (highs _ (mem_head _ _)) under_onVstrict // pong /=. + have ponh : p === high pc1 by rewrite (highs _ (mem_head _ _)). + have noc1 : inter_at_ext (low pc1) (high pc1). + by apply/noc; apply: obstacles_sub; rewrite mem_cat map_f //= ?orbT. + move: (pleft2); rewrite le_eqVlt=> /orP[/eqP pat | pltstrict]; last first. + have := closed_cell_in_high_above_low (low_dif_high pc1cl) (low_high pc1cl) + noc1 (closed_ok pc1cl) _ ponh; apply. + move: (conn)=> /= /andP[] /eqP -> _. + by rewrite pltstrict pc1lp. + have sl : p_x (left_pt g) < p_x p. + have llh := left_limit_left_pt_high_cl (closed_ok pc1cl). + by rewrite -(highs _ (mem_head _ _)); apply: (le_lt_trans llh). + have pc2cl : pc2 \in closed by apply: pcccl'; rewrite mem_head. + have sr : p_x p < p_x (right_pt g). + rewrite pat. + rewrite (lt_le_trans (non_empty_closed pc2cl)) //. + have := right_limit_right_pt_high_cl (closed_ok pc2cl). + by rewrite (highs' _ (mem_head _ _)). + have [vl1 vh1] : valid_edge (low pc1) p /\ valid_edge (high pc1) p. + have := in_bound_closed_valid (closed_ok pc1cl) (ltW pc1lp). + by rewrite pat r1l2 le_refl=> /(_ isT). + have := above_low pc1cl ponh vl1. + rewrite strict_nonAunder // negb_and negbK=> /orP[] ponl; last by []. + have lo : low pc1 \in bottom :: top :: obstacles. + by apply: obstacles_sub; rewrite mem_cat map_f. + have ho : high pc1 \in bottom :: top :: obstacles. + by apply: obstacles_sub; rewrite mem_cat map_f ?orbT. + have [lqh | ] := noc ho lo. + by have := low_dif_high pc1cl; rewrite lqh eqxx. + move=> /(_ p ponh ponl); rewrite !inE=> /orP[]/eqP pext. + by move: sl; rewrite pext (highs _ (mem_head _ _)) lt_irreflexive. + by move: sr; rewrite pext (highs _ (mem_head _ _)) lt_irreflexive. +(* In this case, we use the induction hypothesis *) +by have := Ih pc2 pcccl' highs' conn' rpcc' pright2. +Qed. + +End safety_property. + +Lemma last_no_dup_seq {T : eqType} (s : seq T) d: + last d (no_dup_seq s) = last d s. +Proof. +elim: s d => [ | a [ | b s'] Ih] //. +rewrite /=; case: ifP=> [/eqP ab | anb]. + by apply: Ih. +move=> d /=; apply: Ih. +Qed. + +Lemma head_no_dup_seq {T : eqType} (s : seq T) d: + head d (no_dup_seq s) = head d s. +Proof. +elim: s d => [ | a [ | b s'] Ih] //. +rewrite /=; case: ifP=> [/eqP ab | anb]. + by move=> d; rewrite Ih ab. +by []. +Qed. + +Section main_statement. + +Variable R : realFieldType. + +Notation pt := (@pt R). +Notation p_x := (p_x R). +Notation p_y := (p_y R). +Notation Bpt := (Bpt R). +Notation edge := (@edge R). +Notation cell := (@cell R edge). +Notation low := (low R edge). +Notation high := (high R edge). +Notation left_pts := (left_pts R edge). +Notation right_pts := (right_pts R edge). +Notation dummy_pt := (dummy_pt R 1). +Notation event := (@event R edge). +Notation point := (@point R edge). +Notation outgoing := (@outgoing R edge). + +Definition leftmost_points := + leftmost_points R eq_op le +%R (fun x y => x - y) *%R + (fun x y => x / y) edge (@left_pt R) (@right_pt R). + +Arguments pt_eqb : simpl never. + +Lemma start_open_cell_ok (bottom top : edge) p : + {in [:: bottom; top] &, forall g1 g2, inter_at_ext g1 g2} -> + inside_box bottom top p -> + open_cell_side_limit_ok (start_open_cell bottom top). +Proof. +move=> noc0 /andP[] /andP[] pab put /andP[] /andP[] lbp prb /andP[] ltp prt. +have noc : below_alt bottom top. + by apply: (inter_at_ext_no_crossing noc0); rewrite !inE eqxx ?orbT. +have vb : valid_edge bottom p by rewrite /valid_edge/generic_trajectories.valid_edge !ltW. +have vt : valid_edge top p by rewrite /valid_edge/generic_trajectories.valid_edge !ltW. +rewrite /open_cell_side_limit_ok /=. +have ln0 : leftmost_points bottom top != [::] :> seq pt. + rewrite /leftmost_points/generic_trajectories.leftmost_points. + case: ifP=> [lbl | ltl]; rewrite -/(vertical_intersection_point _ _) pvertE //. + rewrite R_ltb_lt in lbl. + rewrite /valid_edge/generic_trajectories.valid_edge. + by rewrite ltW // ?ltW // (lt_trans ltp). + by rewrite /no_dup_seq /=; case: ifP=> _. + move: ltl=> /negbT; rewrite R_ltb_lt -leNgt=> ltl. + by rewrite /valid_edge/generic_trajectories.valid_edge ltl ltW // (lt_trans lbp). +rewrite ln0 /=. +have samex : all (fun p => p_x p == left_limit (start_open_cell bottom top)) + (leftmost_points bottom top). + rewrite /left_limit/generic_trajectories.left_limit. + rewrite /left_pts/generic_trajectories.left_pts /=. + rewrite /leftmost_points/generic_trajectories.leftmost_points. + case: ifP=> [lbl | ltl]. + rewrite R_ltb_lt in lbl. + rewrite -/(vertical_intersection_point _ _). + rewrite pvertE; last first. + by rewrite /valid_edge/generic_trajectories.valid_edge ltW // ltW // (lt_trans ltp). + by rewrite /= !eqxx. + move: ltl=> /negbT; rewrite R_ltb_lt -leNgt=> ltl. + rewrite -/(vertical_intersection_point _ _). + rewrite pvertE; last first. + by rewrite /valid_edge/generic_trajectories.valid_edge ltl ltW // (lt_trans lbp). + set W := (X in no_dup_seq_aux _ X). + have -> : no_dup_seq_aux (pt_eqb R eq_op) W = no_dup_seq (W : seq pt). + by apply/esym/(@no_dup_seq_aux_eq pt). + have := (@eq_all_r pt _ _ (@mem_no_dup_seq pt _)). + move=> ->. + rewrite (@last_no_dup_seq pt). + by rewrite /W /= !eqxx. +rewrite samex /=. +have headin : head dummy_pt (leftmost_points bottom top) === top. + rewrite /leftmost_points/generic_trajectories.leftmost_points. + case: ifP => [lbl | ltl]. + rewrite R_ltb_lt in lbl. + rewrite -/(vertical_intersection_point _ _). + rewrite pvertE; last first. + by rewrite /valid_edge/generic_trajectories.valid_edge ltW // ltW // (lt_trans ltp). + by rewrite /= left_on_edge. + move: ltl=> /negbT; rewrite R_ltb_lt -leNgt=> ltl. + rewrite -/(vertical_intersection_point _ _). + rewrite pvertE; last first. + by rewrite /valid_edge/generic_trajectories.valid_edge ltl ltW // (lt_trans lbp). + set W := (X in no_dup_seq_aux _ X). + have -> : no_dup_seq_aux (pt_eqb R eq_op) W = no_dup_seq (W : seq pt). + by apply/esym/(@no_dup_seq_aux_eq pt). + rewrite (@head_no_dup_seq pt). + rewrite /= pvert_on // /valid_edge/generic_trajectories.valid_edge. + by rewrite ltl ltW // (lt_trans lbp). +have lastin : last dummy_pt (leftmost_points bottom top) === bottom. + rewrite /leftmost_points/generic_trajectories.leftmost_points. + case: ifP => [lbl | ltl]. + rewrite R_ltb_lt in lbl. + rewrite -/(vertical_intersection_point _ _). + rewrite pvertE; last first. + by rewrite /valid_edge/generic_trajectories.valid_edge ltW // ltW // (lt_trans ltp). + by rewrite /= pvert_on // /valid_edge/generic_trajectories.valid_edge ltW // ltW // (lt_trans ltp). + move: ltl=> /negbT; rewrite R_ltb_lt -leNgt=> ltl. + rewrite -/(vertical_intersection_point _ _). + rewrite pvertE; last first. + by rewrite /valid_edge/generic_trajectories.valid_edge ltl ltW // (lt_trans lbp). + set W := (X in no_dup_seq_aux _ X). + have -> : no_dup_seq_aux (pt_eqb R eq_op) W = no_dup_seq (W : seq pt). + by apply/esym/(@no_dup_seq_aux_eq pt). + rewrite (@last_no_dup_seq pt). + by rewrite /= left_on_edge. +rewrite headin lastin !andbT. +have blt : bottom <| top. + by have := edge_below_from_point_above noc vb vt (underWC pab) put. +rewrite /leftmost_points/generic_trajectories.leftmost_points. +case: ifP => [lbl | ltl]. + rewrite R_ltb_lt in lbl. + have vtb : valid_edge bottom (left_pt top). + by rewrite /valid_edge/generic_trajectories.valid_edge ltW // ltW // (lt_trans ltp). + rewrite -/(vertical_intersection_point _ _). + rewrite pvertE //= andbT. + have := order_below_viz_vertical vtb (valid_edge_left top). + rewrite pvertE // => /(_ _ (left_pt top) erefl _ blt) /=. + have -> : vertical_intersection_point (left_pt top) top = Some (left_pt top). + rewrite (pvertE (valid_edge_left _)); congr (Some _); apply/eqP. + by rewrite pt_eqE /= (on_pvert (left_on_edge _)) !eqxx. + move=> /(_ erefl); rewrite le_eqVlt=> /orP[/eqP abs | -> //]. + have := pvert_on vtb; rewrite abs => lton. + have lteq : Bpt (p_x (left_pt top))(p_y (left_pt top)) = + left_pt top. + by apply/(@eqP pt); rewrite pt_eqE /= !eqxx. + rewrite lteq in lton. + have [bqt |]: inter_at_ext bottom top by apply: noc0; rewrite !inE eqxx ?orbT. + by rewrite bqt lt_irreflexive in lbl. + move=> /(_ _ lton (left_on_edge _)); rewrite !inE=> /orP[] /eqP same. + by rewrite same lt_irreflexive in lbl. + by have := lt_trans ltp prb; rewrite same lt_irreflexive. +move: ltl=> /negbT; rewrite R_ltb_lt -leNgt=> ltl. +have vbt : valid_edge top (left_pt bottom). + by rewrite /valid_edge/generic_trajectories.valid_edge ltl ltW // (lt_trans lbp prt). +rewrite -/(vertical_intersection_point _ _). +rewrite pvertE //=. +case: ifP=> [bont | bnont ]. + by []. +have := order_below_viz_vertical (valid_edge_left bottom) vbt. +have -> : vertical_intersection_point (left_pt bottom) bottom = + Some (left_pt bottom). + rewrite (pvertE (valid_edge_left _)); congr (Some _); apply/eqP. + by rewrite pt_eqE /= (on_pvert (left_on_edge _)) !eqxx. +rewrite pvertE // => /(_ (left_pt bottom) _ erefl erefl blt) /=. +rewrite le_eqVlt=> /orP[/eqP abs | -> //]. +have := pvert_on vbt; rewrite abs => lton. +have lteq : Bpt (p_x (left_pt bottom))(p_y (left_pt bottom)) = + left_pt bottom. + by apply/(@eqP pt); rewrite pt_eqE /= !eqxx. +rewrite -abs lteq in lton. +have [bqt |]: inter_at_ext top bottom by apply: noc0; rewrite !inE eqxx ?orbT. + by move: pab; rewrite -bqt under_onVstrict // put orbT. + move=> /(_ _ lton (left_on_edge _)); rewrite !inE=> /orP[] /eqP same. + move: bnont. + rewrite same (on_pvert (left_on_edge top)). + rewrite -[X in X = false]/(_ == _ :> pt). + by rewrite pt_eqE !eqxx. +by have := lt_trans lbp prt; rewrite same lt_irreflexive. +Qed. + +Lemma has_inside_box_bottom_below_top (bottom top : edge) p : + {in [:: bottom; top] &, forall g1 g2, inter_at_ext g1 g2} -> + inside_box bottom top p -> + bottom <| top. +Proof. +move=> noc0. +have : below_alt bottom top. + by apply: (inter_at_ext_no_crossing noc0); rewrite !inE eqxx ?orbT. +move=> [] // abs. +move=> /andP[] /andP[] pab put /andP[] /andP[] vb1 vb2 /andP[] vt1 vt2. +have vb : valid_edge bottom p. + by rewrite /valid_edge/generic_trajectories.valid_edge !ltW. +have vt : valid_edge top p. + by rewrite /valid_edge/generic_trajectories.valid_edge !ltW. +have pub := order_edges_strict_viz_point' vt vb abs put. +by move: pab; rewrite under_onVstrict // pub orbT. +Qed. + +Lemma edges_inside_from_events_inside (bottom top : edge) evs: + all (inside_box bottom top) ([seq point e | e <- evs] : seq pt) -> + {in evs, forall ev, out_left_event ev} -> + close_edges_from_events evs -> + {in events_to_edges evs, + forall g : edge, + inside_box bottom top (left_pt g) && + inside_box bottom top (right_pt g)}. +Proof. +elim: evs => [ | e evs Ih] /=; first by []. +move=> /andP[] inbox_e inbox_es out_es0. +have out_e : out_left_event e by apply: out_es0; rewrite mem_head. +have out_es : {in evs, forall e, out_left_event e}. + by move=> e' e'in; apply: out_es0; rewrite inE e'in orbT. +move=> /andP[] close_e close_es. +move=> g; rewrite events_to_edges_cons mem_cat=> /orP[] gin; last first. + by apply: (Ih inbox_es out_es close_es). +apply/andP; split; first by rewrite (eqP (out_e g gin)). +move: close_e=> /allP /(_ g gin). +move/hasP=> [e2 e2in /eqP ->]. +by apply: (@allP pt _ _ inbox_es); rewrite map_f. +Qed. + +Notation event' := (generic_trajectories.event R edge). +Lemma start_yields_safe_cells evs bottom top (open closed : seq cell): + sorted (fun e1 e2 => p_x (point e1) < p_x (point e2)) evs -> + {in [:: bottom, top & + events_to_edges evs] &, forall e1 e2, inter_at_ext e1 e2} -> + all (inside_box bottom top) [seq point e | e <- evs] -> + {in evs, forall ev : event, out_left_event ev} -> + close_edges_from_events evs -> + {in events_to_edges evs & evs, forall g e, non_inner g (point e)} -> + {in evs, forall e, uniq (outgoing e)} -> + main_process bottom top evs = (open, closed) -> + {in closed & events_to_edges evs, forall c g p, + strict_inside_closed p c -> ~~(p === g)}. +Proof. +set event' := generic_trajectories.event _ _. +set p_x' := generic_trajectories.p_x R. +set point' := generic_trajectories.point R edge. +have [ev0 | evsn0] := eqVneq evs [::]. + rewrite /start /=; rewrite ev0 /=. + by move=> _ _ _ _ _ _ _ [] _ <-. +move=> general_position no_crossing. +move=> all_points_in out_edges_correct. +move=> edges_closed no_event_in_edge outgoing_event_unique start_eq. +have [e0 e0in] : exists e, e \in evs. + by case: (evs) evsn0 => [ | a ?] //; exists a; rewrite mem_head. +have inbox_e : inside_box bottom top (point e0). + by apply: (@allP pt _ _ all_points_in); rewrite map_f. +have noc0 : {in [:: bottom; top] &, forall g1 g2, inter_at_ext g1 g2}. + move=> g1 g2 g1in g2in. + by apply: no_crossing; rewrite -[_ :: _]/([:: _; _] ++ _) mem_cat ?g1in ?g2in. +have startok : open_cell_side_limit_ok (start_open_cell bottom top). + by have := start_open_cell_ok noc0 inbox_e. +have bottom_below_top : bottom <| top. + by have := has_inside_box_bottom_below_top noc0 inbox_e. +have sorted_lex : sorted (@lexPtEv _) evs. + move: general_position; apply: sub_sorted. + by move=> e1 e2; rewrite /lexPtEv/lexPt=> ->. +have all_edges_in : {in events_to_edges evs, forall g, + inside_box bottom top (left_pt g) && + inside_box bottom top (right_pt g)}. + by apply: edges_inside_from_events_inside. +have [closed_has_disjoint_cells no_intersection_closed_open]:= + complete_disjoint_general_position general_position bottom_below_top + startok no_crossing all_edges_in all_points_in sorted_lex (@subset_id _ _) + out_edges_correct edges_closed start_eq. +have [all_edges_covered all_points_covered]:= + start_edge_covered_general_position general_position bottom_below_top + startok no_crossing all_edges_in all_points_in sorted_lex (@subset_id _ _) + out_edges_correct edges_closed no_event_in_edge outgoing_event_unique + start_eq. +have [closed_main_properties [subcl [all_closed_ok last_open_props]]] := + start_safe_sides general_position bottom_below_top startok no_crossing + all_edges_in all_points_in sorted_lex (@subset_id _ _) out_edges_correct + edges_closed no_event_in_edge outgoing_event_unique start_eq. +move=> c g cin gin p pin. +set ref_points := [seq point e | e <- evs]. +(* TODO : decide on moving this to a separate lemma. *) +have sub_ref : {subset [seq left_pt g | g <- events_to_edges evs] ++ + [seq right_pt g | g <- events_to_edges evs] <= + (ref_points : seq pt)}. + rewrite /ref_points. + move: edges_closed out_edges_correct. + elim: (evs) => [ | ev evs' Ih] //= => /andP [cl1 /Ih {}Ih]. + move=> out_evs. + have oute : out_left_event ev by apply: out_evs; rewrite mem_head. + have {}out_evs : {in evs', forall ev, out_left_event ev}. + by move=> e ein; apply: out_evs; rewrite inE ein orbT. + have {}Ih := Ih out_evs. + rewrite events_to_edges_cons. + move=> q; rewrite mem_cat=> /orP[] /mapP[e + ->]. + rewrite mem_cat => /orP[/oute/eqP -> | ein ]; first by rewrite mem_head. + rewrite inE; apply/orP; right; apply: Ih. + by rewrite mem_cat map_f. + rewrite mem_cat=> /orP[/(allP cl1)/hasP[e' e'in /eqP ->] | e'in]. + by rewrite inE map_f ?orbT. + rewrite inE; apply/orP; right; apply: Ih. + by rewrite mem_cat map_f ?orbT. +have covered_closed : + {in events_to_edges evs, forall g, edge_covered g [::] closed}. + move: last_open_props=> [slo [lloq [hloq [ocdis last_open_props]]]]. + case oeq : open slo => [ | lsto [ | ? ?]] // _. + move=> g' g'in. + (* TODO : make a separate lemma. *) + have g'ntop : g' != top. + apply/negP=> /eqP abs. + have := all_edges_in _ g'in => /andP[] /andP[] _ /andP[] _. + by rewrite abs lt_irreflexive. + have := all_edges_covered _ g'in; rewrite oeq. + move=> [ | closed_covered]; last by right; exact: closed_covered. + move=> [opc [pcc [_ [highs [ _ [ opcin _]]]]]]. + move: g'ntop. + rewrite -(highs opc); last by rewrite mem_rcons mem_head. + move: opcin; rewrite inE=> /eqP ->. + by rewrite -hloq oeq /= eqxx. +have non_empty_closed : + {in closed, forall c, left_limit c < right_limit c}. + by move=> c' c'in; have [_ [_ []]]:= closed_main_properties _ c'in. +have rf_cl : {in closed, forall c, low c <| high c}. + by move=> c' c'in; have [it _] := closed_main_properties _ c'in. +have dif_lh_cl : {in closed, forall c, low c != high c}. + by move=> c' c'in; have [_ [it _]] := closed_main_properties _ c'in. +have points_covered' : {in [seq left_pt g0 | g0 <- events_to_edges evs] ++ + [seq right_pt g0 | g0 <- events_to_edges evs], + forall p0 : pt, + exists2 c0 : cell, + c0 \in closed & p0 \in (right_pts c0 : seq pt) /\ p0 >>> low c0}. + by move=> q /sub_ref/mapP[e ein ->]; apply: all_points_covered. +have puh : p <<< high c. + by move: pin; rewrite /strict_inside_closed => /andP[] /andP[]. +have pal : p >>> low c. + by move: pin; rewrite /strict_inside_closed => /andP[] /andP[]. +have p_between : left_limit c < p_x p < right_limit c. + by move: pin; rewrite /strict_inside_closed=> /andP[]. +by have := safe_cell_interior subcl (@subset_id _ _) closed_has_disjoint_cells + covered_closed points_covered' non_empty_closed (allP all_closed_ok) + no_crossing rf_cl dif_lh_cl cin puh pal p_between gin. +Qed. + +End main_statement. diff --git a/theories/shortest_path.v b/theories/shortest_path.v new file mode 100644 index 0000000..3f3f537 --- /dev/null +++ b/theories/shortest_path.v @@ -0,0 +1,148 @@ +From mathcomp Require Import all_ssreflect all_algebra. +Require Import ZArith String OrderedType OrderedTypeEx FMapAVL. + +Notation head := seq.head. +Notation seq := seq.seq. +Notation nth := seq.nth. +Notation sort := path.sort. + +Import Order.POrderTheory Order.TotalTheory. + +Section shortest_path. + +Variable R : Type. +Variable R0 : R. +Variable R_ltb : R -> R -> bool. +Variable R_add : R -> R -> R. + +Variable cell : Type. +Variable node : Type. +Variable node_eqb : node -> node -> bool. +Variable neighbors_of_node : node -> seq (node * R). +Variable source target : node. + +Variable priority_queue : Type. +Variable empty : priority_queue. +Variable gfind : priority_queue -> node -> option (seq node * option R). +Variable update : priority_queue -> node -> seq node -> option R -> + priority_queue. +Variable pop : priority_queue -> + option (node * seq node * option R * priority_queue). + +Definition cmp_option (v v' : option R) := + if v is Some x then + if v' is Some y then + (R_ltb x y)%O + else + true + else + false. + +Definition Dijkstra_step (d : node) (p : seq node) (dist : R) + (q : priority_queue) : priority_queue := + let neighbors := neighbors_of_node d in + foldr (fun '(d', dist') q => + match gfind q d' with + | None => q + | Some (p', o_dist) => + let new_dist_to_d' := Some (R_add dist dist') in + if cmp_option new_dist_to_d' o_dist then + update q d' (d :: p) new_dist_to_d' + else q + end) q neighbors. + +Fixpoint Dijkstra (fuel : nat) (q : priority_queue) := + match fuel with + | 0%nat => None + |S fuel' => + match pop q with + | Some (d, p, Some dist, q') => + if node_eqb d target then Some p else + Dijkstra fuel' (Dijkstra_step d p dist q') + | _ => None + end + end. + +Definition shortest_path (s : seq node) := + Dijkstra (size s) + (update (foldr [fun n q => update q n [::] None] empty s) + source [::] (Some R0)). + +End shortest_path. + +Section shortest_path_proofs. + +Variable R : realDomainType. + +Variable node : eqType. + +Variable neighbors : node -> seq (node * R). + +Variable queue : Type. +Variable empty : queue. +Variable find : queue -> node -> option (seq node * option R). +Variable update : queue -> node -> seq node -> option R -> queue. +Variable pop : queue -> option (node * seq node * option R * queue). + +Hypothesis find_empty : + forall n, find empty n = None. +Hypothesis find_update_eq : forall q n p d p' d', + find q n = Some(p', d') -> cmp_option R <%R d d' -> + find (update q n p d) n = Some(p, d). +Hypothesis find_update_None : forall q n p d, + find q n = None -> find (update q n p d) n = Some(p, d). +Hypothesis find_update_diff : forall q n1 n2 p d, + n1 != n2 -> + find (update q n1 p d) n2 = find q n2. +Hypothesis pop_remove : + forall q n p d q', pop q = Some (n, p, d, q') -> + find q' n = None. +Hypothesis pop_find : + forall q n p d q', pop q = Some (n, p, d, q') -> + find q n = Some(p, d). +Hypothesis pop_diff : + forall q n1 n2 p d q', pop q = Some(n1, p, d, q') -> + n1 != n2 -> + find q' n2 = find q n2. +Hypothesis pop_min : forall q n1 n2 p p' d d' q', + pop q = Some(n1, p, d, q') -> + find q n2 = Some(p', d') -> cmp_option _ <%R d d'. +Hypothesis update_discard : + forall q n p d p' d', + find q n = Some(p, d) -> + ~~ cmp_option _ <%R d' d -> + find (update q n p' d') n = find q n. + +Lemma oltNgt (d1 d2 : option R) : cmp_option _ <%R d1 d2 -> + ~~ cmp_option _ <%R d2 d1. +Proof. +case: d1 => [d1 | ]; case: d2 => [d2 | ] //. +rewrite /cmp_option. +by rewrite -leNgt le_eqVlt orbC => ->. +Qed. + +Lemma update_update q n1 n2 n3 p d p' d' : + find (update (update q n1 p d) n2 p' d') n3 = + find (update (update q n2 p' d') n1 p d) n3. +Proof. +have [n1n3 | n1nn3] := eqVneq n1 n3. + rewrite -n1n3. + have [n1n2 | n1nn2] := eqVneq n1 n2. + rewrite -n1n2. + case n1inq : (find q n1) => [ [p1 d1] | ]. + case cmp1 : (cmp_option _ <%R d d1). + case cmp2 :(cmp_option _ <%R d' d). + have int1 : find (update q n1 p d) n1 = Some(p, d). + by apply: find_update_eq n1inq cmp1. + rewrite (find_update_eq _ _ _ _ _ _ int1 cmp2). + have [cmp3 | cmp3]:= boolP(cmp_option _ <%R d' d1). + have int2 : find (update q n1 p' d') n1 = Some(p', d'). + by apply: find_update_eq n1inq cmp3. + rewrite (update_discard _ _ _ _ _ _ int2); last by apply: oltNgt. + by rewrite int2. + have int3 : find (update q n1 p' d') n1 = Some (p1, d1). + by rewrite (update_discard _ _ _ _ _ _ n1inq). + have : ~~ cmp_option _ <%R d d1. +Admitted. + +End shortest_path_proofs. diff --git a/theories/smooth_trajectories.v b/theories/smooth_trajectories.v index be6af09..50df61f 100644 --- a/theories/smooth_trajectories.v +++ b/theories/smooth_trajectories.v @@ -1,6 +1,7 @@ From mathcomp Require Import all_ssreflect. Require Import ZArith QArith List String OrderedType OrderedTypeEx FMapAVL. Require Import generic_trajectories. +Require Import Qabs. Definition Qlt_bool x y := andb (negb (Qeq_bool x y)) (Qle_bool x y). @@ -27,9 +28,33 @@ Definition scan := complete_process Q Qeq_bool Qle_bool Qplus Qminus Qmult Qdiv 0 edge Bedge left_pt right_pt. +Definition manhattan_distance (p1x p1y p2x p2y : R) := + Qabs (p2x - p1x) + Qabs (p2y - p1y). + +Definition approx_sqrt (x : Q) := + let n := Qnum x in + let d := Qden x in + let safe_n := (1024 * n)%Z in + let safe_d := (1024 * d)%positive in + let n' := Z.sqrt safe_n in + let d' := Pos.sqrt safe_d in + Qred (Qmake n' d'). + +Definition euclidean_distance (p1x p1y p2x p2y : R) := + approx_sqrt ((p2x - p1x) ^ 2 + (p2y - p1y) ^ 2). + +Definition pt_distance := euclidean_distance. + +Definition Qstraight_point_to_point := + point_to_point Q Qeq_bool Qle_bool Qplus Qminus Qmult Qdiv + pt_distance 1 edge Bedge left_pt right_pt. + +Definition Qoptim_three := optim_three Q Qeq_bool Qle_bool Qplus Qminus + Qmult Qdiv 1. + Definition Qsmooth_point_to_point := smooth_point_to_point Q Qeq_bool Qle_bool Qplus Qminus Qmult Qdiv - 1 edge Bedge left_pt right_pt. + pt_distance 1 edge Bedge left_pt right_pt. Definition Qedges_to_cells := edges_to_cells Q Qeq_bool Qle_bool Qplus Qminus Qmult Qdiv 1 @@ -190,7 +215,7 @@ Definition display_smooth_trajectory (tr_x tr_y scale : Q) "stroke"%string :: nil). Definition Qsmooth_from_cells := - smooth_from_cells Q Qeq_bool Qle_bool Qplus Qminus Qmult Qdiv 1 edge + smooth_from_cells Q Qeq_bool Qle_bool Qplus Qminus Qmult Qdiv pt_distance 1 edge Bedge left_pt right_pt. Definition display_full_example tr_x tr_y scale @@ -295,6 +320,7 @@ Definition leftmost_points := that have a vertical left edge have a neighbor on their left that has the same vertical edge on the right. *) +(* Lemma all_cells_have_left_neighbor : forallb (fun edge_list => let cells := Qedges_to_cells example_bottom example_top edge_list in @@ -305,7 +331,8 @@ Lemma all_cells_have_left_neighbor : (existsb (fun c' => lr_connected Q Qeq_bool 1 edge c' c) cells))) cells) example_edge_sets = true. Proof. easy. Qed. - +*) +(* Definition reference_line edge_list p1 p2 := ("[4 4] 0 setdash 3 setlinewidth"%string :: (List.map (fun sg => display_segment 300 400 70 (apt_val (fst sg), apt_val (snd sg))) @@ -315,7 +342,8 @@ Definition reference_line edge_list p1 p2 := Some l => l | None => nil end ++ "stroke %debug"%string :: nil)). - +*) +(* Definition example_test edge_list (p1 p2 : pt) (extra : seq string) := display_full_example 300 400 70 example_bottom example_top edge_list p1 p2 extra. @@ -329,7 +357,7 @@ Definition example_by_index edge_list_index point_pair_index (with_dotted_line : reference_line edge_list (fst pp) (snd pp) else nil). - +*) (* To display a more elaborate example that shows in a curved dash line the result of smoothening the trajectory without repaing, you can execute the following text. @@ -408,3 +436,12 @@ Compute edges_to_events example_edge_list. *) (* Compute example_by_index 0 0 false. *) + +(* Definition approx_sqrt *) + +(* +Definition euclidean_distance (p1 p2 : pt) := + (p_x p2 - p_x p1) ^ 2 + (p_y p2 - p_y p1) ^ 2. + +*) + diff --git a/theories/three_circles.v b/theories/three_circles.v index b0dacba..e782a95 100644 --- a/theories/three_circles.v +++ b/theories/three_circles.v @@ -1,3 +1,4 @@ +From HB Require Import structures. From mathcomp Require Import all_ssreflect. From mathcomp Require Import ssralg poly polydiv polyorder ssrnum zmodp. From mathcomp Require Import polyrcf qe_rcf_th complex. @@ -153,9 +154,11 @@ Proof. split. move=> x y; exact: comp_polyM. by rewrite /scaleX_poly comp_polyC. Qed. -Canonical scaleX_poly_additive (c : R) := Additive (scaleX_poly_is_linear c). -Canonical scaleX_poly_linear c := Linear (scaleX_poly_is_linear c). -Canonical scaleX_poly_rmorphism c := AddRMorphism (scaleX_poly_multiplicative c). +HB.instance Definition _ (c : R) := GRing.isLinear.Build _ _ _ _ _ (scaleX_poly_is_linear c). + +HB.instance Definition _ c := GRing.isMultiplicative.Build _ _ _ (scaleX_poly_multiplicative c). + +(*Canonical scaleX_poly_rmorphism c := AddRMorphism (scaleX_poly_multiplicative c).*) Lemma scaleX_polyC (c a : R) : a%:P \scale c = a%:P. Proof. by rewrite /scaleX_poly comp_polyC. Qed. @@ -302,7 +305,7 @@ Proof. move=> Hp. have H0noroot : ~~(root (p %/ 'X^(\mu_0 p)) 0). rewrite -mu_gt0. - rewrite -eqn0Ngt -(addr0 'X) -(@oppr0 (poly_zmodType R)) -polyC0 mu_div + rewrite -eqn0Ngt -(addr0 'X) -(@oppr0 {poly R}) -polyC0 mu_div ?subn_eq0; by rewrite leqnn. rewrite Pdiv.CommonIdomain.divp_eq0 negb_or Hp /= negb_or. rewrite -size_poly_gt0 {1}size_polyXn /= -leqNgt dvdp_leq //. @@ -583,9 +586,7 @@ rewrite -exprMn -(ler_sqrt (b^+2)). rewrite -(pmulr_lge0 (x:=Num.sqrt 3%:R)); last by rewrite sqrtr_gt0 ltr0n. by rewrite mulrC (@le_trans _ _ `| b |). by rewrite -oppr_ge0 Ha2 /= -(normrN (a-1)) (ger0_norm (x:= -(a-1))). -rewrite exprMn mulr_gt0 // lt_def sqr_ge0. - by rewrite sqrf_eq0 sqrtr_eq0 -ltNge ltr0n. -by rewrite sqrf_eq0 Ha. +by rewrite exprMn mulr_ge0 // ?sqr_ge0//. Qed. Lemma Re_invc (z : C) : Re z^-1 = Re z / ((Re z) ^+ 2 + (Im z) ^+2). diff --git a/html/Makefile b/www/Makefile similarity index 100% rename from html/Makefile rename to www/Makefile diff --git a/www/Makefile.coq.local b/www/Makefile.coq.local new file mode 100644 index 0000000..3465d69 --- /dev/null +++ b/www/Makefile.coq.local @@ -0,0 +1,40 @@ +post-all:: + $(MAKE) -f $(SELF) SmoothTrajectories.mli + +post-all:: + $(MAKE) -f $(SELF) SmoothTrajectories.cmi + +clean:: + rm -f SmoothTrajectories.cmi SmoothTrajectories.cmo jSmoothTrajectories.cmi jSmoothTrajectories.cmo + + +SmoothTrajectories.ml SmoothTrajectories.mli : ../theories/smooth_trajectories.vo + cd ../theories; echo 'Require Import QArith smooth_trajectories. Extraction "SmoothTrajectories.ml" Qsmooth_point_to_point Qstraight_point_to_point Qedges_to_cells Qreduction.Qred.' | coqtop -R . trajectories + cp ../theories/SmoothTrajectories.ml ../theories/SmoothTrajectories.mli . + +SmoothTrajectories.cmi : SmoothTrajectories.mli + ocamlfind ocamlc SmoothTrajectories.mli + +post-all:: + $(MAKE) -f $(SELF) jSmoothTrajectories.cmi +clean:: + rm -f jSmoothTrajectories.cmi + +jSmoothTrajectories.cmi : jSmoothTrajectories.ml + ocamlfind ocamlc jSmoothTrajectories.mli + +post-all:: + $(MAKE) -f $(SELF) SmoothTrajectories.bytes +clean:: + rm -f SmoothTrajectories.bytes + +SmoothTrajectories.bytes : jSmoothTrajectories.cmi jSmoothTrajectories.ml SmoothTrajectories.ml SmoothTrajectories.cmi + ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml-ppx -linkpkg -o SmoothTrajectories.bytes SmoothTrajectories.ml jSmoothTrajectories.ml + +post-all:: + $(MAKE) -f $(SELF) SmoothTrajectories.js +clean:: + rm -f SmoothTrajectories.js + +SmoothTrajectories.js : SmoothTrajectories.bytes + js_of_ocaml --opt=3 SmoothTrajectories.bytes diff --git a/www/add.v b/www/add.v new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/www/add.v @@ -0,0 +1 @@ + diff --git a/html/grid.html b/www/grid.html similarity index 89% rename from html/grid.html rename to www/grid.html index 118df43..d2d69b3 100755 --- a/html/grid.html +++ b/www/grid.html @@ -28,6 +28,13 @@ + + +

+ + +

+

To add an obstacle, click to a first end-point (blue square) then click to the second end-point diff --git a/html/grid.js b/www/grid.js similarity index 65% rename from html/grid.js rename to www/grid.js index 7281805..0762b6d 100644 --- a/html/grid.js +++ b/www/grid.js @@ -256,6 +256,10 @@ function cleanCurve () { } function getCurve() { + console.log("getCurve\n"); + if ((fromValid == false) || (toValid == false)) { + return; + } let val = ""; val += outVal(positions.fX) + outVal(positions.fZ) + outVal(positions.tX) + outVal(positions.tZ); @@ -332,6 +336,105 @@ function getCurve() { } } +/* The straight */ + +var straightFlag = true; + +const straightButtons = + document.querySelectorAll('input[name="Show Straight"]'); + +for (const straightButton of straightButtons) { + straightButton.addEventListener("click", setStraight, false); +} + +function setStraight() { + straightFlag = straightButtons[0].checked; + cleanStraight(); + cleanCurve(); + if (straightFlag) { + getStraight(); + } else { + getCurve(); + } + renderer.render( scene, camera ); +} + + +var straights = []; +const smaterial = new THREE.LineBasicMaterial( { color: 'blue' } ); +setStraight(); + + +function cleanStraight () { + let i = 0; + console.log("straights " + straights); + while (i < straights.length) + for (const straight of straights) { + scene.remove(straight); + i++; + } + renderer.render( scene, camera ); + straights = []; +} + +function getStraight() { + console.log("getStraight\n"); + if ((fromValid == false) || (toValid == false)) { + return; + } + let val = ""; + val += outVal(positions.fX) + outVal(positions.fZ) + + outVal(positions.tX) + outVal(positions.tZ); + if (borders.length != 2) { + return; + } + if (borders[0].fZ <= borders[1].fZ) { + val += outVal(borders[0].fX) + outVal(borders[0].fZ) + + outVal(borders[0].tX) + outVal(borders[0].tZ); + val += outVal(borders[1].fX) + outVal(borders[1].fZ) + + outVal(borders[1].tX) + outVal(borders[1].tZ); + } else { + val += outVal(borders[1].fX) + outVal(borders[1].fZ) + + outVal(borders[1].tX) + outVal(borders[1].tZ); + val += outVal(borders[0].fX) + outVal(borders[0].fZ) + + outVal(borders[0].tX) + outVal(borders[0].tZ); + } + for (const obstacle of obstacles) { + val += outVal(obstacle.fX) + outVal(obstacle.fZ) + + outVal(obstacle.tX) + outVal(obstacle.tZ); + } + console.log("boarders " + borders.length + " obstacles " + obstacles.length); + console.log("val " + val); + let res = ocamlLib.straight(val); + console.log("res " + res); + let res1 = res.split(' ').map(Number); + let i = 0; + while (i < res1.length) { + if (res1[i] == 1) { + /* Straight line */ + let fx = res1[i + 2] / res1 [i + 3] * gSize - 0.5 - gSize/2; + let fy = 0.3; + let fz = res1[i + 4] / res1 [i + 5] * gSize - 0.5 - gSize/2; + let tx = res1[i + 6] / res1 [i + 7] * gSize - 0.5 - gSize/2; + let ty = 0.3; + let tz = res1[i + 8] / res1 [i + 9] * gSize - 0.5 - gSize/2; + console.log("Adding a line" + fx + " " + fz + " " + tx + " " + tz); + let epoints = []; + epoints.push( new THREE.Vector3(fx, fy, fz) ); + epoints.push( new THREE.Vector3(tx, ty, tz)); + let egeometry = new THREE.BufferGeometry().setFromPoints( epoints ); + let sline = new THREE.Line( egeometry, smaterial ); + straights.push(sline); + scene.add( sline ); + renderer.render( scene, camera ); + i += 10; + } else if (res1[i] == 2) { + i += 14; + } else { + i++; + } + } +} /* The modality */ @@ -346,6 +449,7 @@ for (const radioButton of radioButtons) { function setModality() { cleanCurve(); + cleanStraight(); fromValid = false; toValid = false; fromCube.position.y = -0.2; @@ -400,6 +504,7 @@ function onDocumentMouseDown( event ) { fromCube.position.y = -0.2; toCube.position.y = -0.2; cleanCurve(); + cleanStraight(); renderer.render( scene, camera ); } if (fromValid) { @@ -419,6 +524,7 @@ function onDocumentMouseDown( event ) { return; } cleanCurve(); + cleanStraight(); addObstacle(fromX, fromZ, toX, toZ); } if (modality == "positions") { @@ -430,7 +536,12 @@ function onDocumentMouseDown( event ) { renderer.render( scene, camera ); positions = {fX : fromX, fZ : fromZ, tX : toX, tZ : toZ } cleanCurve(); - getCurve(); + cleanStraight(); + if (straightFlag) { + getStraight(); + } else { + getCurve(); + } } } else { fromValid = true; @@ -441,6 +552,102 @@ function onDocumentMouseDown( event ) { fromCube.position.x = fromX; toCube.position.y = -0.2; cleanCurve(); + cleanStraight(); renderer.render( scene, camera ); } } + + +document.getElementById('loadButton').addEventListener('click', function() { + let input = document.createElement('input'); + input.type = 'file'; + input.accept = 'text/*' + input.onchange = _ => { + // you can use this method to get file and perform respective operations + let files = Array.from(input.files); + if (files.length < 1) { + return; + } + let file = files[0]; + var reader = new FileReader(); + reader.onload = function(progressEvent) { + fromValid = false; + toValid = false; + fromCube.position.y = -0.2; + toCube.position.y = -0.2; + for (const obstacle of obstacles) { + scene.remove(obstacle.line); + } + obstacles = []; + renderer.render( scene, camera ); + // Entire file + const text = this.result; + // By lines + var lines = text.split('\n'); + var i = 0; + if (lines[i].indexOf('Obstacles') != -1) { + i++; + while ((i < lines.length) && (lines[i].length != 0) && + (lines[i].indexOf("Positions") == -1)) { + var fX = parseFloat(lines[i]); + var fZ = parseFloat(lines[i+1]); + var tX = parseFloat(lines[i+2]); + var tZ = parseFloat(lines[i+3]); + addObstacle(fX, fZ, tX, tZ); + i += 4; + } + } + if (lines[i].indexOf("Positions") != -1) { + document.getElementById('positions').checked = true; + setModality(); + var fX = parseFloat(lines[i+1]); + var fZ = parseFloat(lines[i+2]); + var tX = parseFloat(lines[i+3]); + var tZ = parseFloat(lines[i+4]); + i += 5; + fromValid = true; + toValid = true; + fromCube.position.z = fZ; + fromCube.position.y = fromY; + fromCube.position.x = fX; + toCube.position.z = tZ; + toCube.position.y = toY; + toCube.position.x = tX; + renderer.render( scene, camera ); + positions = {fX : fX, fZ : fZ, tX : tX, tZ : tZ } + cleanCurve(); + cleanStraight(); + if (straightFlag) { + getStraight(); + } else { + getCurve(); + } + renderer.render( scene, camera ); + } + }; + reader.readAsText(file); + }; + input.click(); +}); + +document.getElementById('saveButton').addEventListener('click', function() { + const link = document.createElement("a"); + let val = ""; + if (obstacles.length != 0) { + val += "Obstacles\n"; + for (const obstacle of obstacles) { + val += obstacle.fX + "\n" + obstacle.fZ + "\n" + + obstacle.tX + "\n" + obstacle.tZ + "\n"; + } + if (positions != null) { + val += "Positions\n"; + val += positions.fX + "\n" + positions.fZ + "\n"; + val += positions.tX + "\n" + positions.tZ + "\n"; + } + } + const file = new Blob([val], { type: 'text/plain' }); + link.href = URL.createObjectURL(file); + link.download = "sample.txt"; + link.click(); + URL.revokeObjectURL(link.href); +}); diff --git a/html/jSmoothTrajectories.ml b/www/jSmoothTrajectories.ml similarity index 91% rename from html/jSmoothTrajectories.ml rename to www/jSmoothTrajectories.ml index 67f8520..cd552f3 100644 --- a/html/jSmoothTrajectories.ml +++ b/www/jSmoothTrajectories.ml @@ -91,7 +91,7 @@ let call_smooth s = l2stringr (curve_elements2n v) -let call_smooth1 s = +let call_straight s = let l = string2ln s in match l with | p1n1 :: p1d1 :: p1n2 :: p1d2 :: p2n1 :: p2d1 :: p2n2 ::p2d2 :: @@ -99,11 +99,13 @@ let call_smooth1 s = e2n1 :: e2d1 :: e2n2 :: e2d2 :: e2n3 :: e2d3 :: e2n4 :: e2d4 :: ls -> let es = list2es ls in - ((n2edge e1n1 e1d1 e1n2 e1d2 e1n3 e1d3 e1n4 e1d4), - (n2edge e2n1 e2d1 e2n2 e2d2 e2n3 e2d3 e2n4 e2d4), - es , - (n2pt p1n1 p1d1 p1n2 p1d2), - (n2pt p2n1 p2d1 p2n2 p2d2)) + let v = qstraight_point_to_point (n2edge e1n1 e1d1 e1n2 e1d2 e1n3 e1d3 e1n4 e1d4) + (n2edge e2n1 e2d1 e2n2 e2d2 e2n3 e2d3 e2n4 e2d4) + es + (n2pt p1n1 p1d1 p1n2 p1d2) + (n2pt p2n1 p2d1 p2n2 p2d2) in + l2stringr (curve_elements2n v) + let rec cells_element2n ce = match ce with @@ -132,6 +134,7 @@ let call_cells s = let _ = Js.export "ocamlLib" (object%js + method straight s = Js.string (call_straight (Js.to_string s)) method smooth s = Js.string (call_smooth (Js.to_string s)) method cells s = Js.string (call_cells (Js.to_string s)) end) diff --git a/html/jSmoothTrajectories.mli b/www/jSmoothTrajectories.mli similarity index 100% rename from html/jSmoothTrajectories.mli rename to www/jSmoothTrajectories.mli