2011-12-28 30 views
19

¿Cómo podemos evaluar un cuaderno de Mathematica desde la línea de comandos (es decir, cuando se ejecuta el kernel en el modo de línea de comandos)?¿Cómo evaluar un cuaderno desde la línea de comando?

Supongamos que estamos trabajando en una máquina remota. Sé que es posible convertir el portátil en un archivo m, y evaluar eso, pero tengo curiosidad si es posible hacerlo directamente con el portátil.


Esto es lo que tengo hasta ahora:

En primer lugar, we need to start a headless X server en el equipo Linux remoto, por lo que la parte delantera se puede ejecutar allí (y abrir el bloc de notas). Omita este paso si está trabajando en una máquina local.

Xvfb :1 & 
export DISPLAY=:1 

Después de esto comenzó un núcleo de Mathematica (math) e hizo lo siguiente.

Es necesario usar UsingFrontEnd porque la apertura de la computadora portátil requiere una interfaz. test.nb tiene una sola celda de entrada que contiene a=1.

In[1]:= [email protected]["test.nb"] 

Out[1]= -NotebookObject- 

Después de tratar de evaluar el bloc de notas, al parecer consigo un dialog, y necesito utilizar Return[] volver. No estoy seguro de por qué la línea de entrada comienza a contar de nuevo desde 1 (¿se inició un kernel nuevo en el extremo frontal?) Tenga en cuenta que a no obtuvo un valor.

In[2]:= [email protected][nb] 

In[1]:= a 

Out[1]= a 

In[2]:= Return[] 

Out[2]= a 

Después de regresar del diálogo, a todavía no tiene un valor.

In[3]:= a 

Out[3]= a 
+0

parece que estamos trabajando de una manera similar y son igualmente vago! – acl

+1

+1 ¡Me encantaría saber esto también! Me encantaría evaluar mis cuadernos en un sistema remoto en nuestro HPC. –

Respuesta

10

Esto es en Windows, usando Arnouds buen trabajo y sólo añadir a secas MathLink (bastante lento por cierto ...):

link = LinkCreate["8000", LinkProtocol -> "TCPIP"]; 
UsingFrontEnd[ 
NotebookPauseForEvaluation[nb_] := Module[{}, 
While[ NotebookEvaluatingQ[nb], Pause[.25] ] ]; 
NotebookEvaluatingQ[nb_]:=Module[{}, 
SelectionMove[nb,All,Notebook]; 
[email protected]@Map["Evaluating"/.#&,Developer`CellInformation[nb]] 
]; 
nb = NotebookOpen["G:\\mma\\test.nb"]; 
SelectionMove[nb, Before, Notebook]; 
NotebookWrite[nb, Cell["Link = LinkConnect[\"8000\", LinkProtocol -> \"TCPIP\"]", "Input"]]; 
SelectionMove[nb, After, Notebook]; 
NotebookWrite[nb, Cell["LinkWrite[Link, a]", "Input"]]; 
SelectionMove[nb, All, Notebook]; 
SelectionEvaluate[nb]; 
a = LinkRead[link]; 
Print["a = ",a]; 
] 
+0

¡Gracias! ¿Realmente necesitamos 'LinkProtocol ->" TCPIP "' aquí o podemos usar el predeterminado más eficiente? (Creo que por defecto usa archivos mapeados de memoria para la conmutación entre procesos) – Szabolcs

+0

Probablemente. Al menos no puedo hacer que funcione con LinkProtocol -> "SharedMemory" –

+0

BTW: ¿Por qué realmente necesitas esto? ¿No es más fácil guardar tus resultados con DumpSave o algo así? –

11

Esta es una respuesta parcial a su pregunta. El siguiente código abre un cuaderno, le asigna un kernel de "Prueba" , evalúa el cuaderno en ese núcleo, espera a que finalice la evaluación y guarda el cuaderno evaluado. No se causa que a se definan en el núcleo de la línea de comandos local.

Esta espera para las evaluaciones del kernel para terminar en el cuaderno:

NotebookPauseForEvaluation[nb_] := Module[{}, 
While[ NotebookEvaluatingQ[nb], Pause[.25] ] ] 

Esto comprueba si cualquier célula en el ordenador portátil se encuentra todavía en proceso de evaluación:

NotebookEvaluatingQ[nb_]:=Module[{}, 
SelectionMove[nb,All,Notebook]; 
[email protected]@Map["Evaluating"/.#&,Developer`CellInformation[nb]] 
] 

Esto es sólo un mensaje de diagnóstico, cuando usted está tratando de redefinir un núcleo, como "prueba":

AddTestEvaluator::exists = "Evaluator `1` is already defined, but has a definition that is `2` and not the expected `3`."; 

Este es el código t o añadir un evaluador, como "prueba" de la interfaz:

AddTestEvaluator[evaluator_String] := Module[ 
{evaluatornames, testevaluator}, 
evaluatornames = EvaluatorNames /. Options[$FrontEnd, EvaluatorNames]; 
testevaluator = evaluator -> {"AutoStartOnLaunch" -> False}; 
Which[ 
    MemberQ[evaluatornames, evaluator -> {"AutoStartOnLaunch" -> False}], 
    Null, 
    MemberQ[evaluatornames, evaluator -> _], 
    Message[AddTestEvaluator::exists, 
    evaluator, 
    evaluator /. (EvaluatorNames /. Options[$FrontEnd, EvaluatorNames]), 
    {"AutoStartOnLaunch" -> False} 
], 
True, 
AppendTo[evaluatornames, testevaluator]; 
SetOptions[$FrontEnd, EvaluatorNames -> evaluatornames] 
] 
] 

Por último, este es el código para evaluar un cuaderno bajo un kernel "Test" y guardar el kernel evaluado:

UsingFrontEnd[  
    AddTestEvaluator["Test"]; 
    nb = NotebookOpen["test.nb"]; 
    SetOptions[nb,Evaluator->"Test"]; 
    SelectionMove[nb,All,Notebook]; 
    SelectionEvaluate[nb]; 
    NotebookPauseForEvaluation[nb]; 
    NotebookSave[nb] 
] 

I Todavía estoy buscando una solución para su problema completo (que tiene a definido en el comando local kernel de línea).

+1

¡Esto ya es muy útil! ¿Sabes si hay una forma * fácil * de transferir definiciones asociadas con un símbolo entre kernels? Esto es exactamente lo que sucede durante los cálculos paralelos, y lo que hace 'DistributeDefinitions'. Así que supongo que esto ya está implementado. Pero, ¿son las funciones que hacen que este usuario sea accesible? – Szabolcs

Cuestiones relacionadas