src/HOL/Real_Asymp/real_asymp_diag.ML
changeset 69597 ff784d5a5bfb
parent 68828 7030922e91a1
child 70308 7f568724d67e
equal deleted inserted replaced
69596:c8a2755bf220 69597:ff784d5a5bfb
    17 structure Real_Asymp_Diag : REAL_ASYMP_DIAG = struct
    17 structure Real_Asymp_Diag : REAL_ASYMP_DIAG = struct
    18 
    18 
    19 open Lazy_Eval
    19 open Lazy_Eval
    20 open Multiseries_Expansion
    20 open Multiseries_Expansion
    21 
    21 
    22 fun pretty_limit _ (Const (@{const_name "at_top"}, _)) = Pretty.str "\<infinity>"
    22 fun pretty_limit _ (Const (\<^const_name>\<open>at_top\<close>, _)) = Pretty.str "\<infinity>"
    23   | pretty_limit _ (Const (@{const_name "at_bot"}, _)) = Pretty.str "-\<infinity>"
    23   | pretty_limit _ (Const (\<^const_name>\<open>at_bot\<close>, _)) = Pretty.str "-\<infinity>"
    24   | pretty_limit _ (Const (@{const_name "at_infinity"}, _)) = Pretty.str "\<plusminus>\<infinity>"
    24   | pretty_limit _ (Const (\<^const_name>\<open>at_infinity\<close>, _)) = Pretty.str "\<plusminus>\<infinity>"
    25   | pretty_limit ctxt (Const (@{const_name "at_within"}, _) $ c $ 
    25   | pretty_limit ctxt (Const (\<^const_name>\<open>at_within\<close>, _) $ c $ 
    26         (Const (@{const_name "greaterThan"}, _) $ _)) = 
    26         (Const (\<^const_name>\<open>greaterThan\<close>, _) $ _)) = 
    27       Pretty.block [Syntax.pretty_term ctxt c, Pretty.str "\<^sup>+"]
    27       Pretty.block [Syntax.pretty_term ctxt c, Pretty.str "\<^sup>+"]
    28   | pretty_limit ctxt (Const (@{const_name "at_within"}, _) $ c $ 
    28   | pretty_limit ctxt (Const (\<^const_name>\<open>at_within\<close>, _) $ c $ 
    29         (Const (@{const_name "lessThan"}, _) $ _)) = 
    29         (Const (\<^const_name>\<open>lessThan\<close>, _) $ _)) = 
    30       Pretty.block [Syntax.pretty_term ctxt c, Pretty.str "\<^sup>-"]
    30       Pretty.block [Syntax.pretty_term ctxt c, Pretty.str "\<^sup>-"]
    31   | pretty_limit ctxt (Const (@{const_name "at_within"}, _) $ c $ Const ("UNIV", _)) = 
    31   | pretty_limit ctxt (Const (\<^const_name>\<open>at_within\<close>, _) $ c $ Const ("UNIV", _)) = 
    32       Syntax.pretty_term ctxt c
    32       Syntax.pretty_term ctxt c
    33   | pretty_limit ctxt (Const (@{const_name "nhds"}, _) $ c) =
    33   | pretty_limit ctxt (Const (\<^const_name>\<open>nhds\<close>, _) $ c) =
    34       Syntax.pretty_term ctxt c
    34       Syntax.pretty_term ctxt c
    35   | pretty_limit _ t = raise TERM ("pretty_limit", [t])
    35   | pretty_limit _ t = raise TERM ("pretty_limit", [t])
    36 
    36 
    37 fun reduce_to_at_top flt t = Envir.beta_eta_contract (
    37 fun reduce_to_at_top flt t = Envir.beta_eta_contract (
    38     case flt of
    38     case flt of
    39       @{term "at_top :: real filter"} => t
    39       \<^term>\<open>at_top :: real filter\<close> => t
    40     | @{term "at_bot :: real filter"} =>
    40     | \<^term>\<open>at_bot :: real filter\<close> =>
    41         Term.betapply (@{term "%(f::real\<Rightarrow>real) x. f (-x)"}, t)
    41         Term.betapply (\<^term>\<open>%(f::real\<Rightarrow>real) x. f (-x)\<close>, t)
    42     | @{term "at_left 0 :: real filter"} =>
    42     | \<^term>\<open>at_left 0 :: real filter\<close> =>
    43         Term.betapply (@{term "%(f::real\<Rightarrow>real) x. f (-inverse x)"}, t)
    43         Term.betapply (\<^term>\<open>%(f::real\<Rightarrow>real) x. f (-inverse x)\<close>, t)
    44     | @{term "at_right 0 :: real filter"} =>
    44     | \<^term>\<open>at_right 0 :: real filter\<close> =>
    45         Term.betapply (@{term "%(f::real\<Rightarrow>real) x. f (inverse x)"}, t)
    45         Term.betapply (\<^term>\<open>%(f::real\<Rightarrow>real) x. f (inverse x)\<close>, t)
    46     | @{term "at_within :: real => _"} $ c $ (@{term "greaterThan :: real \<Rightarrow> _"} $ c') =>
    46     | \<^term>\<open>at_within :: real => _\<close> $ c $ (\<^term>\<open>greaterThan :: real \<Rightarrow> _\<close> $ c') =>
    47         if c aconv c' then
    47         if c aconv c' then
    48           Term.betapply (Term.betapply (@{term "%(f::real\<Rightarrow>real) c x. f (c + inverse x)"}, t), c)
    48           Term.betapply (Term.betapply (\<^term>\<open>%(f::real\<Rightarrow>real) c x. f (c + inverse x)\<close>, t), c)
    49         else
    49         else
    50           raise TERM ("Unsupported filter for real_limit", [flt])
    50           raise TERM ("Unsupported filter for real_limit", [flt])
    51     | @{term "at_within :: real => _"} $ c $ (@{term "lessThan :: real \<Rightarrow> _"} $ c') =>
    51     | \<^term>\<open>at_within :: real => _\<close> $ c $ (\<^term>\<open>lessThan :: real \<Rightarrow> _\<close> $ c') =>
    52         if c aconv c' then
    52         if c aconv c' then
    53           Term.betapply (Term.betapply (@{term "%(f::real\<Rightarrow>real) c x. f (c - inverse x)"}, t), c)
    53           Term.betapply (Term.betapply (\<^term>\<open>%(f::real\<Rightarrow>real) c x. f (c - inverse x)\<close>, t), c)
    54         else
    54         else
    55           raise TERM ("Unsupported filter for real_limit", [flt])
    55           raise TERM ("Unsupported filter for real_limit", [flt])
    56     | _ =>
    56     | _ =>
    57         raise TERM ("Unsupported filter for real_limit", [flt]))
    57         raise TERM ("Unsupported filter for real_limit", [flt]))
    58 
    58 
    59 fun mk_uminus (@{term "uminus :: real => real"} $ c) = c
    59 fun mk_uminus (\<^term>\<open>uminus :: real => real\<close> $ c) = c
    60   | mk_uminus c = Term.betapply (@{term "uminus :: real => real"}, c)
    60   | mk_uminus c = Term.betapply (\<^term>\<open>uminus :: real => real\<close>, c)
    61 
    61 
    62 fun transfer_expansion_from_at_top' flt t = Envir.beta_eta_contract (
    62 fun transfer_expansion_from_at_top' flt t = Envir.beta_eta_contract (
    63     case flt of
    63     case flt of
    64       @{term "at_top :: real filter"} => t
    64       \<^term>\<open>at_top :: real filter\<close> => t
    65     | @{term "at_bot :: real filter"} =>
    65     | \<^term>\<open>at_bot :: real filter\<close> =>
    66         Term.betapply (@{term "%(f::real\<Rightarrow>real) x. f (-x)"}, t)
    66         Term.betapply (\<^term>\<open>%(f::real\<Rightarrow>real) x. f (-x)\<close>, t)
    67     | @{term "at_left 0 :: real filter"} =>
    67     | \<^term>\<open>at_left 0 :: real filter\<close> =>
    68         Term.betapply (@{term "%(f::real\<Rightarrow>real) x. f (-inverse x)"}, t)
    68         Term.betapply (\<^term>\<open>%(f::real\<Rightarrow>real) x. f (-inverse x)\<close>, t)
    69     | @{term "at_right 0 :: real filter"} =>
    69     | \<^term>\<open>at_right 0 :: real filter\<close> =>
    70         Term.betapply (@{term "%(f::real\<Rightarrow>real) x. f (inverse x)"}, t)
    70         Term.betapply (\<^term>\<open>%(f::real\<Rightarrow>real) x. f (inverse x)\<close>, t)
    71     | @{term "at_within :: real => _"} $ c $ (@{term "greaterThan :: real \<Rightarrow> _"} $ c') =>
    71     | \<^term>\<open>at_within :: real => _\<close> $ c $ (\<^term>\<open>greaterThan :: real \<Rightarrow> _\<close> $ c') =>
    72         if c aconv c' then
    72         if c aconv c' then
    73           Term.betapply (Term.betapply (@{term "%(f::real\<Rightarrow>real) c x. f (inverse (x - c))"}, t), c)
    73           Term.betapply (Term.betapply (\<^term>\<open>%(f::real\<Rightarrow>real) c x. f (inverse (x - c))\<close>, t), c)
    74         else
    74         else
    75           raise TERM ("Unsupported filter for real_limit", [flt])
    75           raise TERM ("Unsupported filter for real_limit", [flt])
    76     | @{term "at_within :: real => _"} $ c $ (@{term "lessThan :: real \<Rightarrow> _"} $ c') =>
    76     | \<^term>\<open>at_within :: real => _\<close> $ c $ (\<^term>\<open>lessThan :: real \<Rightarrow> _\<close> $ c') =>
    77         if c aconv c' then
    77         if c aconv c' then
    78           Term.betapply (Term.betapply (@{term "%(f::real\<Rightarrow>real) c x. f (inverse (c - x))"}, t), c)
    78           Term.betapply (Term.betapply (\<^term>\<open>%(f::real\<Rightarrow>real) c x. f (inverse (c - x))\<close>, t), c)
    79         else
    79         else
    80           raise TERM ("Unsupported filter for real_limit", [flt])
    80           raise TERM ("Unsupported filter for real_limit", [flt])
    81     | _ =>
    81     | _ =>
    82         raise TERM ("Unsupported filter for real_limit", [flt]))
    82         raise TERM ("Unsupported filter for real_limit", [flt]))
    83 
    83 
    84 
    84 
    85 fun transfer_expansion_from_at_top flt =
    85 fun transfer_expansion_from_at_top flt =
    86   let
    86   let
    87     fun go idx (t as (@{term "(powr) :: real => _"} $ 
    87     fun go idx (t as (\<^term>\<open>(powr) :: real => _\<close> $ 
    88                  (@{term "inverse :: real \<Rightarrow> _"} $ Bound n) $ e)) =
    88                  (\<^term>\<open>inverse :: real \<Rightarrow> _\<close> $ Bound n) $ e)) =
    89           if n = idx then
    89           if n = idx then
    90             Envir.beta_eta_contract (@{term "(powr) :: real => _"} $ Bound n $ mk_uminus e)
    90             Envir.beta_eta_contract (\<^term>\<open>(powr) :: real => _\<close> $ Bound n $ mk_uminus e)
    91           else
    91           else
    92             t
    92             t
    93       | go idx (t as (@{term "(powr) :: real => _"} $ (@{term "uminus :: real \<Rightarrow> real"} $
    93       | go idx (t as (\<^term>\<open>(powr) :: real => _\<close> $ (\<^term>\<open>uminus :: real \<Rightarrow> real\<close> $
    94               (@{term "inverse :: real \<Rightarrow> _"} $ Bound n)) $ e)) =
    94               (\<^term>\<open>inverse :: real \<Rightarrow> _\<close> $ Bound n)) $ e)) =
    95           if n = idx then
    95           if n = idx then
    96             Envir.beta_eta_contract (@{term "(powr) :: real => _"} $
    96             Envir.beta_eta_contract (\<^term>\<open>(powr) :: real => _\<close> $
    97               (mk_uminus (Bound n)) $ mk_uminus e)
    97               (mk_uminus (Bound n)) $ mk_uminus e)
    98           else
    98           else
    99             t
    99             t
   100       | go idx (t as (@{term "(powr) :: real => _"} $ (@{term "inverse :: real \<Rightarrow> _"} $ 
   100       | go idx (t as (\<^term>\<open>(powr) :: real => _\<close> $ (\<^term>\<open>inverse :: real \<Rightarrow> _\<close> $ 
   101               (@{term "(-) :: real \<Rightarrow> _"} $ Bound n $ c)) $ e)) =
   101               (\<^term>\<open>(-) :: real \<Rightarrow> _\<close> $ Bound n $ c)) $ e)) =
   102           if n = idx then
   102           if n = idx then
   103             Envir.beta_eta_contract (@{term "(powr) :: real => _"} $
   103             Envir.beta_eta_contract (\<^term>\<open>(powr) :: real => _\<close> $
   104               (@{term "(-) :: real => _"} $ Bound n $ c) $ mk_uminus e)
   104               (\<^term>\<open>(-) :: real => _\<close> $ Bound n $ c) $ mk_uminus e)
   105           else
   105           else
   106             t
   106             t
   107       | go idx (t as (@{term "(powr) :: real => _"} $ (@{term "inverse :: real \<Rightarrow> _"} $ 
   107       | go idx (t as (\<^term>\<open>(powr) :: real => _\<close> $ (\<^term>\<open>inverse :: real \<Rightarrow> _\<close> $ 
   108               (@{term "(-) :: real \<Rightarrow> _"} $ c $ Bound n)) $ e)) =
   108               (\<^term>\<open>(-) :: real \<Rightarrow> _\<close> $ c $ Bound n)) $ e)) =
   109           if n = idx then
   109           if n = idx then
   110             Envir.beta_eta_contract (@{term "(powr) :: real => _"} $
   110             Envir.beta_eta_contract (\<^term>\<open>(powr) :: real => _\<close> $
   111               (@{term "(-) :: real => _"} $ c $ Bound n) $ mk_uminus e)
   111               (\<^term>\<open>(-) :: real => _\<close> $ c $ Bound n) $ mk_uminus e)
   112           else
   112           else
   113             t
   113             t
   114       | go idx (s $ t) = go idx s $ go idx t
   114       | go idx (s $ t) = go idx s $ go idx t
   115       | go idx (Abs (x, T, t)) = Abs (x, T, go (idx + 1) t)
   115       | go idx (Abs (x, T, t)) = Abs (x, T, go (idx + 1) t)
   116       | go _ t = t
   116       | go _ t = t
   143 
   143 
   144 val limit_cmd =
   144 val limit_cmd =
   145   gen_limit 
   145   gen_limit 
   146     (fn ctxt => 
   146     (fn ctxt => 
   147       Syntax.parse_term ctxt 
   147       Syntax.parse_term ctxt 
   148       #> Type.constraint @{typ "real => real"} 
   148       #> Type.constraint \<^typ>\<open>real => real\<close> 
   149       #> Syntax.check_term ctxt)
   149       #> Syntax.check_term ctxt)
   150     (fn ctxt => fn flt =>
   150     (fn ctxt => fn flt =>
   151         case flt of
   151         case flt of
   152           NONE => @{term "at_top :: real filter"}
   152           NONE => \<^term>\<open>at_top :: real filter\<close>
   153         | SOME flt =>
   153         | SOME flt =>
   154             flt
   154             flt
   155             |> Syntax.parse_term ctxt
   155             |> Syntax.parse_term ctxt
   156             |> Type.constraint @{typ "real filter"}
   156             |> Type.constraint \<^typ>\<open>real filter\<close>
   157             |> Syntax.check_term ctxt)
   157             |> Syntax.check_term ctxt)
   158     (fn ctxt => flat o flat o map (map (Proof_Context.get_fact ctxt o fst)))
   158     (fn ctxt => flat o flat o map (map (Proof_Context.get_fact ctxt o fst)))
   159     (fn ctxt => pretty_limit_result ctxt #> Pretty.writeln)
   159     (fn ctxt => pretty_limit_result ctxt #> Pretty.writeln)
   160 
   160 
   161 val limit = gen_limit Syntax.check_term Syntax.check_term (K I) (K I)
   161 val limit = gen_limit Syntax.check_term Syntax.check_term (K I) (K I)
   179       | _ => error
   179       | _ => error
   180     val t =
   180     val t =
   181       case error of
   181       case error of
   182         NONE => exp
   182         NONE => exp
   183       | SOME err =>
   183       | SOME err =>
   184           Term.betapply (Term.betapply (@{term "expansion_with_remainder_term"}, exp), err)
   184           Term.betapply (Term.betapply (\<^term>\<open>expansion_with_remainder_term\<close>, exp), err)
   185   in
   185   in
   186     res ctxt (t, basis)
   186     res ctxt (t, basis)
   187   end
   187   end
   188 
   188 
   189 fun print_basis_elem ctxt t =
   189 fun print_basis_elem ctxt t =
   192 
   192 
   193 val expansion_cmd =
   193 val expansion_cmd =
   194   gen_expansion
   194   gen_expansion
   195     (fn ctxt => 
   195     (fn ctxt => 
   196       Syntax.parse_term ctxt 
   196       Syntax.parse_term ctxt 
   197       #> Type.constraint @{typ "real => real"} 
   197       #> Type.constraint \<^typ>\<open>real => real\<close> 
   198       #> Syntax.check_term ctxt)
   198       #> Syntax.check_term ctxt)
   199     (fn ctxt => fn flt =>
   199     (fn ctxt => fn flt =>
   200         case flt of
   200         case flt of
   201           NONE => @{term "at_top :: real filter"}
   201           NONE => \<^term>\<open>at_top :: real filter\<close>
   202         | SOME flt =>
   202         | SOME flt =>
   203             flt
   203             flt
   204             |> Syntax.parse_term ctxt
   204             |> Syntax.parse_term ctxt
   205             |> Type.constraint @{typ "real filter"}
   205             |> Type.constraint \<^typ>\<open>real filter\<close>
   206             |> Syntax.check_term ctxt)
   206             |> Syntax.check_term ctxt)
   207     (fn ctxt => flat o flat o map (map (Proof_Context.get_fact ctxt o fst)))
   207     (fn ctxt => flat o flat o map (map (Proof_Context.get_fact ctxt o fst)))
   208     (fn ctxt => fn (exp, basis) =>
   208     (fn ctxt => fn (exp, basis) =>
   209        Pretty.writeln (Pretty.chunks (
   209        Pretty.writeln (Pretty.chunks (
   210          [Pretty.str "Expansion:",
   210          [Pretty.str "Expansion:",
   244 val dflt_expansion_opts = {limit = NONE, facts = [], terms = (3, false)}
   244 val dflt_expansion_opts = {limit = NONE, facts = [], terms = (3, false)}
   245 
   245 
   246 in
   246 in
   247 
   247 
   248 val _ =
   248 val _ =
   249   Outer_Syntax.command @{command_keyword real_limit}
   249   Outer_Syntax.command \<^command_keyword>\<open>real_limit\<close>
   250     "semi-automatically compute limits of real functions"
   250     "semi-automatically compute limits of real functions"
   251     ((Parse.term -- parse_opts limit_opts dflt_limit_opts) >>
   251     ((Parse.term -- parse_opts limit_opts dflt_limit_opts) >>
   252     (fn (t, {limit = flt, facts = thms}) => 
   252     (fn (t, {limit = flt, facts = thms}) => 
   253       (Toplevel.keep (fn state => 
   253       (Toplevel.keep (fn state => 
   254         Real_Asymp_Diag.limit_cmd (Toplevel.context_of state) thms t flt))))
   254         Real_Asymp_Diag.limit_cmd (Toplevel.context_of state) thms t flt))))
   255 
   255 
   256 val _ =
   256 val _ =
   257   Outer_Syntax.command @{command_keyword real_expansion}
   257   Outer_Syntax.command \<^command_keyword>\<open>real_expansion\<close>
   258     "semi-automatically compute expansions of real functions"
   258     "semi-automatically compute expansions of real functions"
   259     (Parse.term -- parse_opts expansion_opts dflt_expansion_opts >> 
   259     (Parse.term -- parse_opts expansion_opts dflt_expansion_opts >> 
   260     (fn (t, {limit = flt, terms = n_strict, facts = thms}) => 
   260     (fn (t, {limit = flt, terms = n_strict, facts = thms}) => 
   261       (Toplevel.keep (fn state => 
   261       (Toplevel.keep (fn state => 
   262         Real_Asymp_Diag.expansion_cmd (Toplevel.context_of state) thms (swap n_strict) t flt))))
   262         Real_Asymp_Diag.expansion_cmd (Toplevel.context_of state) thms (swap n_strict) t flt))))