【问题标题】:Trying to get Mathematica to approximate an integral试图让 Mathematica 逼近一个积分
【发布时间】:2011-11-09 18:58:36
【问题描述】:

我试图让 Mathematica 逼近一个积分,它是各种参数的函数。我不需要它非常精确 - 答案将是一个分数,5 位数会很好,但我会满足于少至 2。
问题是主积分中隐藏了一个符号积分,我不能在它上面使用 NIntegrate 因为它是符号的。

    F[x_, c_] := (1 - (1 - x)^c)^c;
    a[n_, c_, x_] := F[a[n - 1, c, x], c];
    a[0, c_, x_] = x;

    MyIntegral[n_,c_] := 
      NIntegrate[Integrate[(D[a[n,c,y],y]*y)/(1-a[n,c,x]),{y,x,1}],{x,0,1}]

n 大于 2 且 c 大于 3 左右时,Mathematica 开始挂起(通常因为 nc 都高一点)。

是否有任何技巧可以重写此表达式以便更容易地对其进行评估?我在外部NIntegrate 上使用了不同的WorkingPrecisionAccuracyGoalPrecisionGoal 选项,但是这些都没有帮助内部积分,这就是问题所在。事实上,对于nc 的较高值,我什至无法让 Mathematica 展开内导数,即

Expand[D[a[4,6,y],y]] 

挂起。

我正在使用 Mathematica 8 for Students。

如果有人对我如何让 M. 近似此有任何提示,我将不胜感激。

【问题讨论】:

  • 对于投票结束的个人,这是一个关于 Mathematica 编程语言和环境的有效问题。因此,它不是 stackoverflow 的主题。
  • 如果单独进行内积分,会不会有时序问题?另外,nc 应该是整数吗?如果是这样,请考虑将a 的定义更改为a[n_Integer, c_Integer, x_],因为它会阻止无限递归。
  • @rcollyer:如果您的计时问题是指积分需要很长时间或有效挂起,那么可以。事实上,现在想想,我可能会把内积分放在这个问题上。或者你问的时间有什么更具体的吗? (我非常缺乏经验......谢谢你的耐心。)我正在尝试整数的东西..似乎没有解决问题,但仍在试验(这是一个很好的提示)。
  • 我没想到“整数的东西”能解决这个问题,只是让代码更可靠一点。至于NIntegrate挂起,我认为这里可能有两个问题:1.内部积分需要很长时间来评估(你现在已经说过),2.NIntegrate可能正在重新评估内部x 的每个值的积分。怀疑是问题(2),我想知道首先象征性地评估内部是否会有所帮助。但是,我想不会。回到绘图板。
  • Memoization 对计时有一点帮助,但对于大型 nc 需要很长时间,我并不感到惊讶。里面有很多嵌套的((((()^c)^c)^c...)^c)...

标签: wolfram-mathematica


【解决方案1】:

由于您只想要一个数字输出(或者这就是您将得到的),您可以使用 NIntegrate 将符号积分转换为数字积分,如下所示:

Clear[a,myIntegral]
a[n_Integer?Positive, c_Integer?Positive, x_] := 
  a[n, c, x] = (1 - (1 - a[n - 1, c, x])^c)^c;
a[0, c_Integer, x_] = x;

myIntegral[n_, c_] := 
 NIntegrate[D[a[n, c, y], y]*y/(1 - a[n, c, x]), {x, 0, 1}, {y, x, 1},
   WorkingPrecision -> 200, PrecisionGoal -> 5]

这比以符号方式执行集成要快得多。这是一个比较:

尤达:

myIntegral[2,2]//Timing
Out[1]= {0.088441, 0.647376595...}

myIntegral[5,2]//Timing
Out[2]= {1.10486, 0.587502888...}

rcollyer:

MyIntegral[2,2]//Timing
Out[3]= {1.0029, 0.647376}

MyIntegral[5,2]//Timing 
Out[4]= {27.1697, 0.587503006...}
(* Obtained with WorkingPrecision->500, PrecisionGoal->5, MaxRecursion->20 *)

Jand 的功能与 rcollyer 的功能类似。当然,当您增加n 时,您必须将您的WorkingPrecision 增加得比这更高,如you've experienced in your previous question。既然你说你只需要大约 5 位的精度,我已经明确地将 PrecisionGoal 设置为 5。你可以根据需要进行更改。

【讨论】:

  • 我不知道为什么我没有想到,这应该是第一件事。我会投票给你,但我没有选票,我会进一步为你的压倒性领先做出贡献。 :P
  • @rcollyer:你怎么会没票?他们有限制吗? (或者你在开玩笑?)
  • @Jand 是的,投票限制为每天最多 30 个。在这 30 个问题中,如果您对超过 10 个问题进行投票,那么您将获得额外的 10 个,当天最多 40 个。根据您投票的问题数量,您的上限可以在 30 到 40 之间。
  • @rcollyer 我会等你赶上来之后我拿到银牌 :D
  • @Jand,不是在开玩笑。问题和答案的投票限制为 30 票,仅问题的投票限制为 10。
【解决方案2】:

为了对 cme​​ts 进行编码,我会尝试以下方法。首先,为了消除关于变量n 的无限递归,我会将您的函数重写为

F[x_, c_] := (1 - (1-x)^c)^c;
(* see note below *)
a[n_Integer?Positive, c_, x_] := F[a[n - 1, c, x], c];  
a[0, c_, x_] = x;

那样n==0实际上将成为一个停止点。 ?Positive 表单是PatternTest,可用于将附加条件应用于参数。我怀疑问题是NIntegrate 正在为x 的每个值重新评估内部Integrate,所以我会取消评估,比如

MyIntegral[n_,c_] := 
  With[{ int = Integrate[(D[a[n,c,y],y]*y)/(1-a[n,c,x]),{y,x,1}] },
    NIntegrate[int,{x,0,1}]
  ]

其中With 是几个专门用于创建局部常量的范围构造之一。

您的 cmets 表明内部积分需要很长时间,您是否尝试过简化被积函数,因为它是 a 的导数乘以 a 的函数?对我来说,这似乎是链式规则扩展的结果。

注意:根据 Yoda 在 cmets 中的建议,您可以向 a 添加缓存或记忆机制。将其定义更改为

d:a[n_Integer?Positive, c_, x_] := d = F[a[n - 1, c, x], c];

这里的诀窍是,在d:a[ ... ] 中,d 是一个命名模式,在 d = F[...] 中再次使用它来缓存 a 的值以用于那些特定的参数值。

【讨论】:

  • 如果我不允许问,请忽略此问题,但为什么我的评论中的格式不起作用?我从问题上留下的 cmets 复制了语法......我不知道我做错了什么。
  • @Jand,对不起。我正在尝试更改系统上的变量,但它悄悄进入了我的答案。现在修好了。顺便说一句,要将某些内容标记为内联代码,请将其包装在严重标记中,`.
  • 啊,我看到它在我发布第一条评论之前就已经修复了。所以我删除了它。感谢您的格式提示,我现在将对其进行测试Does this look like code?
  • @Jand,“添加评论”按钮下方还有一个帮助链接,其中详细说明了标记。
  • 虽然我接受了 yoda 的回答,但我还是从你的回答中学到了很多普遍有用的信息。所以,非常感谢您抽出宝贵的时间来输入它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-10
  • 2021-02-22
  • 1970-01-01
  • 2011-11-15
  • 1970-01-01
相关资源
最近更新 更多