Theory ISQ_Proof

section ‹ Proof Support for Quantities ›

theory ISQ_Proof
  imports ISQ_Quantities
begin

named_theorems si_transfer

definition magQ :: "'a['u::dim_type, 's::unit_system]  'a" (_Q) where
[si_def]: "magQ x = mag (fromQ x)"

definition dimQ :: "'a['u::dim_type, 's::unit_system]  Dimension" where
[si_def]: "dimQ x = dim (fromQ x)"

lemma quant_eq_iff_mag_eq [si_eq]:
  "x = y  xQ = yQ"
  by (auto simp add: magQ_def, transfer, simp add: eq_unit)

lemma quant_eqI [si_transfer]:
  "xQ = yQ  x = y"
  by (simp add: quant_eq_iff_mag_eq)

lemma quant_equiv_iff [si_eq]:
  fixes x :: "'a['u1::dim_type, 's::unit_system]" and y :: "'a['u2::dim_type, 's::unit_system]"
  shows "x Q y  xQ = yQ  QD('u1) = QD('u2)"
proof -
  have "t ta. (ta::'a['u2, 's]) = t  mag (fromQ ta)  mag (fromQ t)"
    by (simp add: magQ_def quant_eq_iff_mag_eq)
  then show ?thesis
    by (metis (full_types) qequiv.rep_eq coerceQuant_eq_iff2 qeq magQ_def)
qed

lemma quant_equivI [si_transfer]:
  fixes x :: "'a['u1::dim_type, 's::unit_system]" and y :: "'a['u2::dim_type, 's::unit_system]"
  assumes "QD('u1) = QD('u2)" "QD('u1) = QD('u2)  xQ = yQ"
  shows "x Q y"
  using assms quant_equiv_iff by blast
  
lemma quant_le_iff_magn_le [si_eq]:
  "x  y  xQ  yQ"
  by (auto simp add: magQ_def; (transfer, simp))

lemma quant_leI [si_transfer]:
  "xQ  yQ  x  y"
  by (simp add: quant_le_iff_magn_le)

lemma quant_less_iff_magn_less [si_eq]:
  "x < y  xQ < yQ"
  by (auto simp add: magQ_def; (transfer, simp))

lemma quant_lessI [si_transfer]:
  "xQ < yQ  x < y"
  by (simp add: quant_less_iff_magn_less)

lemma magQ_zero [si_eq]: "0Q = 0"
  by (simp add: magQ_def, transfer, simp)

lemma magQ_one [si_eq]: "1Q = 1"
  by (simp add: magQ_def, transfer, simp)

lemma magQ_plus [si_eq]: "x + yQ = xQ + yQ"
  by (simp add: magQ_def, transfer, simp)

lemma magQ_minus [si_eq]: "x - yQ = xQ - yQ"
  by (simp add: magQ_def, transfer, simp)

lemma magQ_uminus [si_eq]: "- xQ = - xQ"
  by (simp add: magQ_def, transfer, simp)

lemma magQ_scaleQ [si_eq]: "x *Q yQ = x * yQ"
  by (simp add: magQ_def, transfer, simp)

lemma magQ_qtimes [si_eq]: "x  yQ = xQ  yQ"
  by (simp add: magQ_def, transfer, simp)

lemma magQ_qinverse [si_eq]: "x-𝟭Q = inverse xQ"
  by (simp add: magQ_def, transfer, simp)

lemma magQ_qdivivide [si_eq]: "(x::('a::field)[_,_]) / yQ = xQ / yQ"
  by (simp add: magQ_def, transfer, simp add: field_class.field_divide_inverse)

lemma magQ_numeral [si_eq]: "numeral nQ = numeral n"
  apply (induct n, simp_all add: si_def)
  apply (metis magQ_def magQ_one)
  apply (metis magQ_def magQ_plus numeral_code(2))
  apply (metis magQ_def magQ_one magQ_plus numeral_code(3))
  done

lemma magQ_coerce [si_eq]: 
  fixes q :: "'a['d1::dim_type, 's::unit_system]" and t :: "'d2::dim_type itself"
  assumes "QD('d1) = QD('d2)"
  shows "coerceQuantT t qQ = qQ"
  by (simp add: coerceQuantT_def magQ_def assms, metis assms qequiv.rep_eq updown_eq_iff)

lemma dimQ [simp]: "dimQ(x :: 'a['d::dim_type, 's::unit_system]) = QD('d)"
  by (simp add: dimQ_def, transfer, simp)

text ‹ The following tactic breaks an SI conjecture down to numeric and unit properties ›

method si_simp uses add =
  (rule_tac si_transfer; simp add: add si_eq field_simps)

text ‹ The next tactic additionally compiles the semantics of the underlying units ›

method si_calc uses add = 
  (si_simp add: add; simp add: si_def add)

lemma "QD(N  Θ  N) = QD(Θ  N2)" by (simp add: si_eq si_def)
  
end