Theory Polynomial_Instantiation

(*******************************************************************************

  Project: Sumcheck Protocol

  Authors: Azucena Garvia Bosshard <zucegb@gmail.com>
           Christoph Sprenger, ETH Zurich <sprenger@inf.ethz.ch>
           Jonathan Bootle, IBM Research Europe <jbt@zurich.ibm.com>

*******************************************************************************)

section ‹Instantiation for Multivariate Polynomials›

theory Polynomial_Instantiation
  imports 
    "Polynomials.More_MPoly_Type"
begin

text ‹
\textbf{NOTE:} if considered to be useful enough, the definitions and lemmas in this theory could 
be moved to the theory @{theory "Polynomials.More_MPoly_Type"}.
›

text ‹Define instantiation of mpoly's. The conditions @{term "(≠) 1"} and @{term "(≠) 0"} in 
the sets being multiplied or added over are needed to prove the correspondence with evaluation: 
a full instance corresponds to an evaluation (see lemma below).›

subsection ‹Instantiation of monomials›

type_synonym ('a, 'b) subst = "'a ⇀ 'b"

lift_definition 
  inst_monom_coeff :: ‹(nat ⇒0 nat) ⇒ (nat, 'a) subst ⇒ 'a::comm_semiring_1› 
  is ‹λm σ. (∏v | v ∈ dom σ ∧ the (σ v) ^ m v ≠ 1. the (σ v) ^ m v)› .

lift_definition 
  inst_monom_resid :: ‹(nat ⇒0 nat) ⇒ (nat, 'a) subst ⇒ (nat ⇒0 nat)›  
  is ‹(λm σ v. m v when v ∉ dom σ)›
  by (metis (mono_tags, lifting) finite_subset mem_Collect_eq subsetI zero_when) 

lemmas inst_monom_defs = inst_monom_coeff_def inst_monom_resid_def

lemma lookup_inst_monom_resid:
  shows ‹lookup (inst_monom_resid m σ) v = (if v ∈ dom σ then 0 else lookup m v)›
  by transfer simp


subsection ‹Instantiation of polynomials›

definition 
  inst_fun :: ‹((nat ⇒0 nat) ⇒ 'a) ⇒ (nat, 'a) subst ⇒ (nat ⇒0 nat) ⇒ 'a::comm_semiring_1› where
  ‹inst_fun p σ = (λm. (∑m' | inst_monom_resid m' σ = m ∧ p m' * inst_monom_coeff m' σ ≠ 0.
                               p m' * inst_monom_coeff m' σ))›

lemma finite_inst_fun_keys: 
  assumes ‹finite {m. p m ≠ 0}›
  shows ‹finite {m. (∑m' | inst_monom_resid m' σ = m ∧ p m' ≠ 0 ∧ inst_monom_coeff m' σ ≠ 0.
                               p m' * inst_monom_coeff m' σ) ≠ 0}›
proof -
  from ‹finite {m. p m ≠ 0}›
  have ‹finite ((λm'. inst_monom_resid m' σ)`{x. p x ≠ 0})› by auto
  moreover 
  have ‹{m. (∑m' | inst_monom_resid m' σ = m ∧ p m' ≠ 0 ∧ inst_monom_coeff m' σ ≠ 0. 
                         p m' * inst_monom_coeff m' σ) ≠ 0}
            ⊆ (λm'. inst_monom_resid m' σ)`{m. p m ≠ 0}›
    by (auto elim: sum.not_neutral_contains_not_neutral)
  ultimately show ?thesis
    by (auto elim: finite_subset)
qed

lemma finite_inst_fun_keys_ext:
  assumes ‹finite {m. p m ≠ 0}›
  shows  "finite {a. (∑m' | inst_monom_resid m' σ = a ∧ p m' ≠ 0 ∧ inst_monom_coeff m' σ ≠ 0.
        p m' * inst_monom_coeff m' σ * (∏aa. the (ρ aa) ^ lookup (inst_monom_resid m' σ) aa)) ≠ 0}"
proof -
  from ‹finite {m. p m ≠ 0}›
  have ‹finite ((λm'. inst_monom_resid m' σ)`{x. p x ≠ 0})› by auto
  moreover 
  have ‹{m. (∑m' | inst_monom_resid m' σ = m ∧ p m' ≠ 0 ∧ inst_monom_coeff m' σ ≠ 0. 
                         p m' * inst_monom_coeff m' σ * 
                         (∏aa. the (ρ aa) ^ lookup (inst_monom_resid m' σ) aa)) ≠ 0}
            ⊆ (λm'. inst_monom_resid m' σ)`{m. p m ≠ 0}›
    by (auto elim: sum.not_neutral_contains_not_neutral)
  ultimately show ?thesis
    by (auto elim: finite_subset)
qed

lift_definition 
  inst_aux :: ‹((nat ⇒0 nat) ⇒0 'a) ⇒ (nat, 'a) subst ⇒ (nat ⇒0 nat) ⇒0 'a::semidom› 
  is inst_fun 
  by (auto simp add: inst_fun_def intro: finite_inst_fun_keys)

lift_definition inst :: ‹'a mpoly ⇒ (nat, 'a::semidom) subst ⇒ 'a mpoly› 
  is inst_aux .

lemmas inst_defs = inst_def inst_aux_def inst_fun_def


subsection ‹Full instantiation corresponds to evaluation›

lemma dom_Some: ‹dom (Some o f) = UNIV›
  by (simp add: dom_def)

lemma inst_full_eq_insertion:      
  fixes p :: ‹('a::semidom) mpoly› and σ :: ‹nat ⇒ 'a› 
  shows ‹inst p (Some o σ) = Const (insertion σ p)›
proof transfer
  fix p :: ‹(nat ⇒0 nat) ⇒0 'a› and σ :: ‹nat ⇒ 'a› 
  show ‹inst_aux p (Some o σ) = Const0 (insertion_aux σ p)›
    unfolding poly_mapping_eq_iff
    apply (simp add: Const0_def inst_aux.rep_eq inst_fun_def inst_monom_defs
                     Poly_Mapping.single.rep_eq insertion_aux.rep_eq insertion_fun_def)
    apply (rule ext)
    subgoal for m
      by (cases "m = 0") 
         (simp_all add: Sum_any.expand_set Prod_any.expand_set dom_Some)
    done
qed


end