(* This program is free software; you can redistribute it and/or      *)
(* modify it under the terms of the GNU Lesser General Public License *)
(* as published by the Free Software Foundation; either version 2.1   *)
(* of the License, or (at your option) any later version.             *)
(*                                                                    *)
(* This program is distributed in the hope that it will be useful,    *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of     *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *)
(* GNU General Public License for more details.                       *)
(*                                                                    *)
(* You should have received a copy of the GNU Lesser General Public   *)
(* License along with this program; if not, write to the Free         *)
(* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *)
(* 02110-1301 USA                                                     *)
Require Export DistributedReferenceCounting.machine3.invariant0.
Require Export DistributedReferenceCounting.machine3.invariant1.
Require Export DistributedReferenceCounting.machine3.invariant2.
Require Export DistributedReferenceCounting.machine3.invariant3.
Unset Standard Proposition Elimination Names.
(* Where send_table on the owner is defined in terms of the other components *)
(* Proofs are indentical to the ones for machine1. The only differnce is that aux1, add_reduce, and invariant4 have an explicit -1 *)
Section INVARIANT4.
Definition new_inc_count (m : Message) :=
match m with
| inc_dec s => 1%Z
| _ => 0%Z
end.
(* Below five remarks aux1, aux2, aux3, aux4, aux5 ... followed by the real meat the invariant 4. *)
Remark aux1 :
forall c : Config,
legal c ->
st c owner =
(sigma_receive_table (rt c) + sigma_weight (bm c) -
sigma_table_but_owner Z (fun (_ : Site) (x : Z) => x) (st c) - 1)%Z.
Remark aux2 :
forall c : Config,
legal c ->
sigma_table_but_owner Z (fun (_ : Site) (x : Z) => x) (st c) =
sigma_but Site owner eq_site_dec LS (fun s : Site => sigma_rooted s (bm c)).
Remark aux3 :
forall (s1 s2 : Site) (q : queue Message),
(cardinal q -
sigma_but Site owner eq_site_dec LS (fun s : Site => rooted s s1 s2 q))%Z =
reduce Message
(fun a : Message =>
(cardinal_count a -
sigma_but Site owner eq_site_dec LS
(fun s : Site => rooted_fun s s1 s2 a))%Z) q.
Remark aux4 :
forall t : Site -> Site -> queue Message,
sigma2_table Site LS LS (queue Message)
(fun (s1 s2 : Site) (q : queue Message) =>
(cardinal q -
sigma_but Site owner eq_site_dec LS (fun s : Site => rooted s s1 s2 q))%Z)
t =
sigma2_table Site LS LS (queue Message)
(fun (s1 s2 : Site) (q : queue Message) =>
reduce Message
(fun a : Message =>
(cardinal_count a -
sigma_but Site owner eq_site_dec LS
(fun s : Site => rooted_fun s s1 s2 a))%Z) q) t.
Remark aux5 :
forall c : Config,
legal c ->
sigma2_table Site LS LS (queue Message)
(fun (s1 s2 : Site) (q : queue Message) =>
reduce Message
(fun a : Message =>
(cardinal_count a -
sigma_but Site owner eq_site_dec LS
(fun s : Site => rooted_fun s s1 s2 a))%Z) q)
(bm c) =
(sigma2_table Site LS LS (queue Message)
(fun (s1 s2 : Site) (q : queue Message) =>
if eq_site_dec s2 owner
then reduce Message dec_count q
else 0) (bm c) +
sigma2_table Site LS LS (queue Message)
(fun (s1 s2 : Site) (q : queue Message) =>
if eq_site_dec s1 owner
then reduce Message copy_count q
else 0) (bm c) -
sigma2_table Site LS LS (queue Message)
(fun (s1 s2 : Site) (q : queue Message) => reduce Message new_inc_count q)
(bm c))%Z.

Lemma simpl_copy_sum :
forall c : Config,
legal c ->
sigma2_table Site LS LS (queue Message)
(fun (s1 _ : Site) (q : queue Message) =>
match eq_site_dec s1 owner with
| left _ => reduce Message copy_count q
| right _ => 0%Z
end) (bm c) =
sigma_table Site LS Z (Z_id Site)
(fun s2 : Site => reduce Message copy_count (bm c owner s2)).