2011-10-16 2 views
8

Tôi muốn nội suy một hàm trong mathematica.Tránh lặp lại các cuộc gọi đến Nội suy

Chức năng phụ thuộc vào một tham số a, trên thực tế nó là nghịch đảo của một hàm F đó cũng phụ thuộc vào a, vì vậy tôi xây dựng xấp xỉ của tôi như sau,

approx = Interpolation[Table[{F[0.1 n, a], 0.1 n}, {n, -100, 100}]] 

bây giờ tôi chỉ có thể gọi approx[x] để đánh giá hàm nghịch đảo tại một điểm.

Thay vào đó tôi muốn làm một cái gì đó như thế này: Xác định một chức năng mà phải mất một tham số,

G[x_,a_] = "construct the interpolating function, 
      and return the value of the function at x" 

Sau đó viết G [x, a] để đánh giá chức năng. Nếu không, tôi sẽ phải lặp lại nội suy cho tất cả các tham số mà tôi quan tâm và có rất nhiều biến nằm xung quanh. Tôi đã thử đặt nội suy [] gọi bên trong một mô-đun nhưng chỉ xây dựng nội suy mỗi khi tôi gọi G [x, a]! Làm cách nào để tránh điều này?

Cảm ơn bạn đã đọc.

Trả lời

6

Hãy thử một cái gì đó dọc theo những dòng:

G[a_]:=G[a]=Interpolation[Table[{F[0.1 n, a], 0.1 n}, {n, -100, 100}]] 

G[0.2] (* particular value of G[a] *) 

G[0.2][0.3] (* the value you want *) 

Bạn sẽ chỉ đánh giá G lần đầu tiên bạn gọi cho mỗi giá trị cụ thể là a.

+0

Cách tiếp cận này có vẻ là phương pháp đơn giản nhất so với các phương pháp khác được cung cấp. Có thể có một rút lại cho lược đồ này qua bộ nhớ đệm rõ ràng như được mô tả trong các câu trả lời khác. Nhưng tôi không đủ chuyên gia để biết sự khác biệt. – mark

+3

Các câu trả lời khác đối phó với cách phát hành bộ nhớ được lưu trữ trong biểu tượng bộ nhớ cache khi nó phát triển quá lớn. Ý tưởng bộ nhớ đệm của chúng giống như trong câu trả lời này. Nếu mã của bạn không phải là quá nhiều bộ nhớ, bạn có thể không quan tâm đến việc giải phóng bộ nhớ của phiên hiện tại, nhưng nó có thể hữu ích nếu bạn tính toán lớn. – faysou

+0

@Faysal Aberkane ... Cảm ơn – mark

12

Bước đầu tiên là để parameterize approx với a:

approx[a_] := Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]] 

Với định nghĩa này, G sau đó có thể được định nghĩa như sau:

G[x_, a_] := approx[a][x] 

Nhưng, như quan sát thấy trong câu hỏi, điều này kết thúc xây dựng lại nội suy mỗi khi G được gọi. Một cách để tránh điều này là để xác định lại approx sử dụng memoization:

m: approx[a_] := m = Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]] 

Bây giờ, approx sẽ tiết kiệm được các chức năng nội suy cho bất kỳ a nhất định, tránh tái thiết trong các cuộc gọi tiếp theo với cùng a. Tất nhiên, điều này sử dụng hết bộ nhớ vì vậy nếu có một số lượng lớn các giá trị khác biệt của a thì bộ nhớ có thể chạy ngắn. Có thể bản địa hoá bộ nhớ cache được sử dụng bởi approx bằng cách kết hợp các giá trị lưu với một biểu tượng (cache trong trường hợp này):

approx[a_] := cache[a] /. 
    _cache :> (cache[a] = Interpolation[Table[{F[0.1` n,a],0.1` n},{n,-100,100}]]) 

Với phiên bản này của approx, cache có thể được định vị sử dụng Block, ví dụ:

Block[{cache} 
, Table[G[x, a], {x, 0, 5}, {a, 0, 1, 0.1}] 
] 

Chức năng nội suy vẫn được lưu trữ tạm thời cho mỗi giá trị riêng biệt a, nhưng bây giờ các định nghĩa đã lưu đó được giải phóng sau khi thoát khỏi Block.

Để biết thêm thông tin về chức năng với bộ nhớ trong Mathematica, xem các câu hỏi SO:

The best way to construct a function with memory

Dynamic Programming in Mathematica: how to automatically localize and/or clear memoized function's definitions

+0

Cảm ơn bạn đã trả lời của bạn, nó đã thúc đẩy tôi đi học Mathematica nhiều hơn nữa! – mark

6

Bạn có thể sử dụng định nghĩa của CacheIndex Tôi đã đăng trong What is in your Mathematica tool bag?. Một điều tốt về việc sử dụng hàm này là bạn có thể lưu các giá trị hoặc các phần mã mà không cần phải định nghĩa một hàm mới (mặc dù chúng ta làm ở đây để phù hợp với ví dụ).

G[x_,a_] := 
    CacheIndex[a, 
     Pause[3]; 
     Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]] 
    ][x]; 

Tôi đã thêm Pause [3] để làm rõ rằng định nghĩa của Nội suy được lưu trong bộ nhớ cache cho mỗi sau khi tính được một lần.

Sau đó, bạn có thể xóa các giá trị nội suy cache trong CacheIndex sử dụng

DeleteCachedValues[CacheIndex] (*or*) 
DeleteCachedValues[CacheIndex,1]. 

tôi thích nghi chức năng Cache và CacheIndex của tôi để cho phù hợp với ý tưởng của WReach của việc sử dụng một biểu tượng riêng biệt định nghĩa trong một khối. Một điều không thực tế ở đây là bạn phải định nghĩa các thuộc tính Giữ cho biểu tượng được sử dụng làm bộ nhớ đệm, nhưng ý tưởng vẫn thú vị.

Dưới đây là định nghĩa của CacheSymbol

SetAttributes[CacheSymbol,HoldAll]; 
CacheSymbol[cacheSymbol_,expr_]:=cacheSymbol[expr]/.(_cacheSymbol:>(cacheSymbol[expr]=expr)); 

Bạn có thể kiểm tra điều này thực hiện bằng cách sử dụng hướng dẫn sau đây, trong một ví dụ bộ nhớ cache sản sẽ được định nghĩa trong một khối.

ClearAll[cache] 
SetAttributes[cache,HoldFirst] 
CacheSymbol[cache,Pause[3];2+2] 
?cache 
CacheSymbol[cache,Pause[3];2+2] 

Dưới đây là định nghĩa của CacheSymbolIndex

SetAttributes[CacheIndexSymbol,HoldAll]; 
CacheIndexSymbol[cacheSymbol_,index_,expr_]:=cacheSymbol[index,expr]/.(_cacheSymbol:>(cacheSymbol[index,expr]=expr)); 

Bạn có thể kiểm tra điều này thực hiện bằng cách sử dụng hướng dẫn sau đây, trong một ví dụ bộ nhớ cache sản sẽ được định nghĩa trong một khối.

ClearAll[cache] 
SetAttributes[cache,HoldRest] 
CacheIndexSymbol[cache,2+2,Pause[3];2+2] 
?cache 
CacheIndexSymbol[cache,2+2,Pause[3];2+2] 

và tương tự như ví dụ của WReach chúng ta sẽ phải

G[x_,a_] := 
    CacheIndexSymbol[cache,a, 
     Print["Caching"]; 
     Interpolation[Table[{F[0.1 n,a],0.1 n},{n,-100,100}]] 
    ][x] 

Block[{cache}, 
    SetAttributes[cache,HoldRest]; 
    Table[G[x, a], {x, 0, 5}, {a, 0, 1, 0.1}] 
]