2011-02-05 2 views
1

에서 대체 이런 종류의 작업을 수행하는 방법을, 나는 어떤 evalulation을 대체 할 내 자신의내가 MMA의여 오차 또는 ERF 기능을 사용하지 않을 경우 티카

myErf[x_] := Integrate[Exp[-y^2/2], {y, -Infinity, x}]; 

그리고 내가 원하는 MMA를 정의 할 myErf [x]와 통합 적입니다. 예를 들면 다음과 같습니다.

Integrate[Exp[-y^2+y/2], {y, x, Infinity}] 

이 작업을 수행하는 방법? 또는 일반적으로, mma를 사용하여 표현식을 평가하는 방법은 내가 사용하고 싶은 함수를 사용하는 대신 자체의 함수를 사용하여 표현식을 평가하는 방법입니까? 이 일을하는 방법이 있습니까?

감사합니다. 내 의견에 무엇을 의미

+1

죄송합니다. 귀하가 찾고있는 대체물이 무엇인지 알 수 없습니다. 원하는 결과를 게시 할 수 있습니까? –

+1

필자는 (쉽게) "Integrate"의 동작을 재정의하는 것이 가능하다고 생각하지 않습니다. 내가 생각할 수있는 유일한 두 가지 옵션은 1) 'Erf'형의 integrand를 검색 한 후 나머지를 Integrate로 다시 전달하는 고유 한 통합 함수를 작성합니다. 2) mma의'Integrate'가 마술을 한 후에'Erf' 's를 붙잡고 다시 씁니다. – Simon

+0

@ 사이먼 어쨌든, 내가 생각하는 어떤 접근 방식은 많은 구멍을 가지고 있습니다 ... –

답변

3

순진한

Unprotect[Integrate]; 
Integrate[Exp[-y_^2], {y_, -\[Infinity], x_}] := myErf[x] 

작동하지 않는 일부 Integrate 평가를 차단하려고하는 것입니다.


사실

In[]:= Integrate[Exp[-y^2],{y,-Infinity,z}] 
Out[]= myErf[z] 

(즉 자정에 SO 질문에 대답 나를 가르 칠 것입니다) 작업 않습니다. 그러면 아래 주어진 myIntegrate 함수가 필요하지 않을 수 있습니다.


어쨌든 ... 코멘트에 주어진 두 가지 대안은 다음과 같습니다

1) 당신은 어디 말에

In[1]:= myErf[x_?NumericQ]:=NIntegrate[Exp[-y^2],{y,-\[Infinity],x}] 
(* sames as Erf up to constant and scaling *) 

In[2]:= Clear[myIntegrate] 
     myIntegrate[a_. Exp[b_. y_^2], {y_, -\[Infinity], x_}] /; FreeQ[{a, b}, y] := ConditionalExpression[myErf[x], b < 0] 
     myIntegrate[a_. Exp[b_. y_^2], {y_, xx_, x_}] := myIntegrate[a Exp[b y^2], {y, -\[Infinity], x}] - myIntegrate[a Exp[b y^2], {y, -\[Infinity], xx}] 
     myIntegrate[a_ + b_, lims__] := myIntegrate[a, lims] + myIntegrate[b, lims] (* assuming this is ok *) 
     myIntegrate[expr_, lims__] := Integrate[expr, lims] 

In[8]:= myIntegrate[a Exp[x]+b Exp[-b x^2],{x,2y,z}] 
Out[8]= ConditionalExpression[a (-E^(2 y)+E^z) - myErf[2 y] + myErf[z], b > 0] 

같은 자신의 Erf 통합하여 뭔가를 쓸 수, 나머지 적분 값은 Integrate으로 전달됩니다. 그러나 모든 Erf과 같은 기능을 잡으려면 패턴 매칭 (더 잘 어울리는 중간 단계에서의 변형을 포함)에서 더 똑똑해야합니다. 그들은 내장 루틴을 사용하여 평가하지 않도록

2) 당신은 Erf 타입 기능을 덮어 쓰기 : 분명히, 당신은 myErf 기능에 대한 자신의 규칙을 선택

In[9]:= Clear[myErf]; 
     Unprotect[Erf,Erfc,Erfi]; 
In[10]:= Erf[x__] := myErf[x] 
     Erfc[x__]:= myErfc[x] 
     Erfi[x__]:= myErfi[x] 

In[13]:= {Erf[1], Erfc[2], Erfi[\[Pi]], Integrate[E^-x^2,x]} 
Out[13]= {myErf[1], myErfc[2], myErfi[\[Pi]], 1/2 Sqrt[Pi] myErf[x]} 

.


편집 : 당신이 원하는 일을 간단하고 어쩌면 가장 안전한/부드러운 방법 (레오 니드 덕분에) 단지 Block[{Erf=...},...] 및 매스 매 티카 통합이 모든 작업을 수행하는 것입니다.예를 들어 는 당신 myErf 2

In[2]:= Block[{Erf = (Sqrt[2/Pi]*myErf[Sqrt[2] #] - 1 &)}, 
      Integrate[Exp[-y^2 + y/2], {y, x, Infinity}]] 
Out[2]= (E^(1/16)(Sqrt[\[Pi]] (-1 + 4 x + Sqrt[(-1 + 4 x)^2]) + 
      Sqrt[2] (1 - 4 x) myErf[Sqrt[2] Sqrt[(-(1/4) + x)^2]]) 
     )/(2 Sqrt[(1 - 4 x)^2]) 

편집, 그래서 원래의 게시물에 적분을 해결하기 위해

In[1]:= myErf[x] == Integrate[Exp[-y^2/2], {y, -Infinity, x}] 
Out[1]= myErf[x]==Sqrt[Pi/2] (1+Erf[x/Sqrt[2]]) 

으로 주어졌다 :이 어쩌면 당신은 그냥 번역 할 수 있어야합니다 ~에서 myErf 표현. 이것은 자동이 아니지만 융통성이 있음을 의미합니다. FunctionExpand 명령 1-Erf[x]Erfc[x]을 다시 작성 있다는 것을

In[1]:= toMyErf=(FunctionExpand[#]/.Erf:>(Sqrt[2/Pi]*myErf[Sqrt[2] #]-1&)&); 
     fromMyErf=(#/.myErf:>(Sqrt[Pi/2] (1+Erf[#/Sqrt[2]])&)&); 

In[3]:= Integrate[Exp[-y^2+y/2],{y,x,Infinity}]//toMyErf 
Out[3]= 1/2 E^(1/16) Sqrt[\[Pi]] (2-Sqrt[2/\[Pi]] myErf[Sqrt[2] (-(1/4)+x)]) 
In[4]:= D[x*myErf[x+x^2],x]//fromMyErf//toMyErf 
Out[4]= E^(-(1/2) (x+x^2)^2) x (1+2 x)+myErf[x+x^2] 

참고하십시오. 약간 더 나은 부분을 구현하는 것이 좋습니다.

+0

+1은 자신의 통합 자 정의 방법에 대한 힌트를 보여줍니다. _this_ 특정 사례가 가치가 있는지 확실하지 않습니다. 당신의 잘못이 아닌. –

+0

감사합니다. 그것은 작동합니다. 그러나 어쩌면 나는 너무 많이 요구하고있다. myErf [x]에서 파생물을 얻으려는 다른 요구 사항이있을 경우 (예 : Block [{Erf = (Sqrt [2/Pi] * myErf [Sqrt [2] #] - 1)}, D [x * myErf [x + x^2], x]]가 작동하지 않습니다. –

+0

@ Qiang Li : 새로 추가 된 내용을 확인하십시오. "Erf"와 "myErf"함수를 간단하게 번역 할 수 있다면 가장 좋습니다. – Simon

3

소프 방법은 UpValues을 사용하는 것입니다

ClearAll[withMyErf]; 
SetAttributes[withMyErf, HoldAll]; 
withMyErf[code_] := 
Block[{Exp}, 
Exp /: Integrate[Exp[(a : _ : 1)*x_^2], {x_, t0_, t_}] := 
    ConditionalExpression[(Sqrt[Pi]*(myErf[Sqrt[-a]*t] - myErf[Sqrt[-a]*t0]))/(2*Sqrt[-a]), 
    Re[a] < 0]; 
code] 

예 : 우리의 정의 "동적 범위 지정 구조"의

In[4]:= withMyErf[Integrate[Exp[-3*x^2], {x, -Infinity, t}]] 

Out[4]= 1/2 Sqrt[\[Pi]/3] (myErf[Sqrt[3] t] - myErf[-\[Infinity]]) 

외부는, 모든 것이 평소와 같이 작동합니다. 이 코드를 코드 안에 넣으십시오. 그리고 위험 할 수있는 Integrate의 변경 사항은 없습니다. 우리가 여기서 위험을 감수하는 것은 Exp가 평가하지 않는다는 것입니다. 그러나 그것에 대한 가장 상징적 인 변환 규칙은 어쨌든 로컬 규칙입니다.

편집 : 당신은 표준 방법 티카을 변경하려는 경우

는, 일반적인 질문에 대답하려면 여러 선택이 상황을 평가합니다. 그들 중 일부는 이전 답변에서 언급되었으므로, 좀 더 추상적 인 수준으로 요약하고 싶습니다. 표현식 f[g[something]] 일반적으로 당신이 할 수 감안할 때 : g에 대한

  • 재정의 DownValues ​​- 당신이 원하는 경우이 g를 작동 다른
    f 전에 무언가로 다시 작성하도록하지만, 경우에만 f이 보유하지 않습니다 "인식" g[something]

  • 스탠드 위치에 인수 표현 f[g[_]] 또는 유사에 대하여 더불어, UpValueg에 대한 추가. 이것은 이 부드러운 방식으로 f의 동작을 변경하려는 경우, 즉 UpValue 정의 (이 경우 f[g[_]])와 일치하는 양식의 인수에서만 변경하십시오. 이 작업을 수행하려면 gDownValues (따라서 평가되지 않도록) g[something]이 포함되어서는 안되며, f은 인수를 유지해야합니다. 이것은 f이 시스템 기능이고 g이 사용자 정의 인 일반적인 사용 예입니다. 은 시스템 기능의 동작을 변경하는 가장 간단한 방법입니다. f 은 다르게 작동하지만 규칙은 g에 연결됩니다.

  • DownValuef에 추가하십시오. 이것은 "어려운"방법입니다.f이 인수를 보유하고 있거나 g [무언가]가 그 자체로 다른 것으로 평가되지 않거나 보유 속성을 잠깐 동안 추가해야하는 경우 (더 관입적 인) f에 작동합니다. f이 시스템 기능이면이 메소드가 최후의 수단입니다. 특히 f이 중요하지 않고 자주 사용되는 경우 중요한 내장 기능 인 경우 많은 시스템 기능이 최상위 수준에서 다른 시스템 기능을 사용하는 반면 수정의 모든 결과를 예상하기가 어렵 기 때문에이 문제를 방지하십시오.

  • 평가되지 않은 형식으로 코드를 분석하고 적절한 대체를 수행하는 코드를 평가 한 후 자신의 렉시 컬 범위 지정 구문을 작성한 다음 평가하십시오. 이렇게하려면 코드에서 한 번에 코드에 액세스 할 수 있어야합니다 (즉, 코드는 시작에서 원하는 형식으로 존재해야합니다). 이는 심각한 제한 사항이므로 실제로이 옵션은 대부분의 경우 배제됩니다 . 당신은 당신이 그 (것)들을 적용 할 코드 블록에 동적으로 지역 등의 재정의함으로써 "피해를 지역화"할 수있는 Block 트릭도있다

. 어떤 경우에는 다른 언어 구조로 쉽게 재현 할 수없는 평가 프로세스를 비 국지적으로 제어 할 수있는 방법을 허용하기 때문에 필자는이를 반드시 찾아야합니다.

+0

부드러운 방법은 부드러운 사람들을위한 것입니다! (그리고 코드의 가능한 원하지 않는 부작용에 관심이있는 사람들 ... +1) – Simon

+0

@Simon 나는이 방법을 너무 생각했다. 어느 날까지 나는 알아낼 수일이 걸렸던 버그를 얻었고 소년은 힘들었습니다. 나는 요즘보다 조심 스럽지만 인정할 만하게 더 부드럽습니다. 그래서 여러분은 옳습니다. –

+0

@Leonid : 왜 withMyErf [Exp [-x^2 + x/2], {x , - 무한, t}]] 작동합니까? 조금 설명해 주시겠습니까? 많은 감사. –