2011-02-23 68 views
20

Soy un mal cacher: A veces, cuando nadie está mirando, guardo los resultados sin incluir el contexto completo como el siguiente:Mathematica: Cómo borrar el caché de un símbolo, es decir, Unset sin patrones DownValues ​​

f[x_]:=f[x]=x+a; 
a=2; f[1]; 
DownValues[f] 

Out[2]= {HoldPattern[f[1]]:>3,HoldPattern[f[x_]]:>(f[x]=x+a)} 

Esto conduce a errores terriblemente sutiles, y, más importante aún, a la necesidad de borrar el caché cuando cambio el contexto. Una forma de borrar el caché es completamente el símbolo Clear y repetir las definiciones, pero esto no es realmente una solución.

Lo que realmente me gustaría es un método para borrar todos los DownValues ​​sin patrón asociados con un símbolo.
Para mayor claridad, voy a incluir mi solución presente como una respuesta, pero si falla por dos razones

  • Sólo se borra DownValues ​​con todos los argumentos numéricos
  • Por razones estéticas, me gustaría evitar usando Block para agarrar los DownValues.

¿Alguna idea sobre cómo mejorar ClearCache?

Respuesta

22

he hecho funciones similares en el pasado (pero no puedo recordar dónde).

¿El siguiente código hace todo lo que necesita?

ClearCache[f_] := DownValues[f] = DeleteCases[DownValues[f], 
               _?(FreeQ[First[#], Pattern] &)] 

Esto tal vez debería extenderse a UpValues y SubValues. Y el Head de f restringido a Symbol.

+2

_? (FreeQ [#, Pattern] &) ... wow! –

+0

@belisarius: Tu comentario sin un voto explícito me vuelve paranoico porque he hecho algo estúpido ... Una solución simple no significa que soy un simplón, ¿o sí? – Simon

+0

@Simon Me acabo de olvidar. ¡Me avergüenza! Ese patrón es brillante. –

3

Esta es mi solución actual al problema, pero como se menciona en la pregunta no se busca estrictamente DownValues sin patrón, ni es muy elegante.
tienda del DownValues para f

In[6]:= dv = DownValues[f] 

Out[6]= {HoldPattern[f[1]] :> 3, HoldPattern[f[x_]] :> (f[x] = x + a)} 

Encuentra la DownValues para limpiar el interior de un Block para evitar la evaluación inmediata

In[7]:= dv2clear = Block[{f}, 
    [email protected]@Cases[dv, 
     HoldPattern[f[args__ /; Apply[And, NumericQ /@ Flatten[{args}]]]], {3}]] 

Out[7]= Hold[{f[1]}] 

Aplicar Unset a la DownValues objetivo dentro de la lista que mantendrá y luego liberar

In[8]:= Map[Unset, dv2clear, {2}] 
[email protected]% 

Out[8]= Hold[{(f[1]) =.}] 

Esto funciona bien

In[10]:= DownValues[f] 

Out[10]= {HoldPattern[f[x_]] :> (f[x] = x + a)} 

Y puede ser envuelto de esta manera:

ClearCache[f_] := Module[{dv, dv2clear}, 
    (* Cache downvalues for use inside block *) 
    dv = DownValues[f]; 
    (* Find the downvalues to clear in Block to avoid immediate evaluation *) 
    dv2clear = Block[{f},[email protected]@Cases[dv,HoldPattern[ 
     f[args__ /; Apply[And, NumericQ /@ Flatten[{args}]]]], {3}]]; 
    (* Apply Unset to the terms inside the held list and then release *) 
    [email protected][Unset, dv2clear, {2}];] 
8

Simplemente para complementar la otra excelente solución: si tiene una lista muy grande de DownValues y tiene estrictos requisitos de eficiencia para ClearCache, puede acelerar significativamente el proceso borrando todas las definiciones y luego reconstruyendo solo aquellas con patrones.Aquí está un ejemplo:

In[1]:= 
ClearCache[f_] := 
    DownValues[f] = DeleteCases[DownValues[f], _?(FreeQ[First[#], Pattern] &)]; 

In[2]:= Clear[f]; 
f[x_] := f[x] = x; 

In[4]:= f /@ Range[1000000]; 

In[5]:= ClearCache[f]; // Timing 

Out[5]= {7.765, Null} 

In[6]:= 
ClearAll[createDefs]; 
SetAttributes[createDefs, HoldRest]; 
createDefs[f_, defs_: Automatic] := 
     (createDefs[f] := (Clear[f]; defs); createDefs[f]); 

In[9]:= Clear[f]; 
createDefs[f, f[x_] := f[x] = x] 

In[11]:= f /@ Range[1000000]; 

In[12]:= Length[DownValues[f]] 

Out[12]= 1000001 

In[13]:= createDefs[f]; // Timing 

Out[13]= {1.079, Null} 

In[14]:= DownValues[f] 

Out[14]= {HoldPattern[f[x_]] :> (f[x] = x)} 

en cuenta que sólo tiene que llamar al createDefs una vez con el código que crea las definiciones basadas en patrones de la función. El resto del tiempo lo llama como createDefs[f], ya que memoriza el código necesario para volver a crear las definiciones en la primera llamada.

También es posible que no desee generar grandes cachés, pero esto está fuera de su control en el enfoque simple f[x_]:=f[x]=rhs. En otras palabras, la memoria caché puede contener muchas cosas viejas innecesarias, pero en este enfoque no se puede decir definiciones antiguas (ya no se usan) de las nuevas. Parcialmente me dirigí a este problema con un paquete que llamé Caché, que se puede encontrar en here junto con el cuaderno que ilustra su uso. Le da más control sobre el tamaño de la memoria caché. Tiene sus problemas, pero ocasionalmente puede ser útil.

+0

Gracias, Leonid. También es bueno tener este enfoque en la lista aquí. Lo he usado ocasionalmente (es decir, antes de compilar 'ClearCache') pero realmente no me gusta cómo interfiere con el proceso de implementación. Para mis usos particulares, los resultados que guardo en la memoria caché son tan caros que podría borrar la memoria caché de un año en un abrir y cerrar de ojos :) – Janus

6

Una vez que implementé un esquema para limit the number of memoized values (y conservar la memoria). Busque la memorización en esa página. Esto también podría ser útil aquí (especialmente considerando algunas de las preguntas marcadas como duplicadas de esta).

El código

SetAttributes[memo, HoldAll] 
SetAttributes[memoStore, HoldFirst] 
SetAttributes[memoVals, HoldFirst] 

memoVals[_] = {}; 

memoStore[f_, x_] := 
With[{vals = memoVals[f]}, 
    If[Length[vals] > 200, 
    f /: memoStore[f, First[vals]] =.; 
    memoVals[f] ^= Append[Rest[memoVals[f]], x], 
    memoVals[f] ^= Append[memoVals[f], x]]; 
    f /: memoStore[f, x] = f[x]] 

memo[f_Symbol][x_?NumericQ] := memoStore[f, x] 

memoClearCache[f_Symbol] := 
(Scan[(f /: memoStore[f, #] =.) &, memoVals[f]]; 
    f /: memoVals[f] =.) 

uso y la descripción

Esta versión funciona con funciones que toman un solo argumento numérico. Llame al memo[f][x] en lugar de f[x] para usar una versión memorada. Los valores en caché todavía están asociados con f, por lo que cuando se borra f, desaparecen. El número de valores almacenados en caché está limitado a 200 por defecto. Use memoClearCache[f] para borrar todos los valores memorizados.

Cuestiones relacionadas