User:Mafs/Computer algebra: Difference between revisions
No edit summary |
No edit summary |
||
Line 76: | Line 76: | ||
replacing the parse() function by the explicit <nowiki><math></nowiki> parsing. |
replacing the parse() function by the explicit <nowiki><math></nowiki> parsing. |
||
;Patch correcting the error return if multiple Algebra environments exist on the same page. |
|||
Since the variable <nowiki>$maxima_session_result </nowiki> is global, its value is kept within different Algebra blocks in the same page. If must be rest to false for each block. Change |
|||
$maxima_input = implode(" ", $list); |
|||
$maxima_response = maxima_process($maxima_input); |
|||
by |
|||
$maxima_input = implode(" ", $list); |
|||
$maxima_session_result=false; |
|||
$maxima_response = maxima_process($maxima_input); |
|||
'''Attention:''' For copying click on '''edit''' and copy from the source text. |
'''Attention:''' For copying click on '''edit''' and copy from the source text. |
Revision as of 16:29, 22 November 2006
Installation
- enable math in mediawiki
- get a copy of the maxima software from http://maxima.sourceforge.net
- put the php script as Maxima.php into the extension directory
- within the scipt adapt the path to the maxima executable
- add the line
require_once("extension/Maxima.php");
- to your LocalSettings.php
- The script is not well tested. It is **not** recommended to use the script on a public site.
- A quote from the maxima mailing list:
I'd be careful about using this script, or scripts like it. In particular the variable $maxima_blacklist does not appear to contain the Maxima "system" command. It appears that an arbitrary user would be able to execute a system command, which (at a very quick first read through) represents a rather large security hole.
- So, although "system" has been added to the list, do only use the script for experiments on localhost! Mafs 20:30, 1 March 2006 (UTC)
Syntax
<Algebra> </Algebra> defines a maxima session. Any line terminating with a semicolon is passed to maxima for evaluation. For all other lines the wiki syntax applies.
The maxima syntax is described on http://maxima.sourceforge.net/docs.shtml.
If the maxima session terminates with an error or a question, the raw output of maxima will be displayed. For details how to avoid such questions see the maxima documentation.
Example
<Algebra> Equation 1 eq1: x^2 + 3*x*y + y^2 = 0; Equation 2 eq2: 3*x + y = 1; Solution solve([eq1, eq2]); ---- Integration f(x) := exp( sin(x)); integrate(f(x), x , 0, %pi); </Algebra>
Screen shoot
PHP Script
- Patch avoiding the use of $wgOut->parse() that spoils other math tags that may exist on the same page.
Since the parse() function can not be invoked twice on the same page, change on the code bellow
$tex_math = "$indent<math>".$m[1]."</math>\n"
by
$tex_math = $indent.MathRenderer::renderMath($m[1])."\n";
and remove
$text = $wgOut->parse($text);
replacing the parse() function by the explicit <math> parsing.
- Patch correcting the error return if multiple Algebra environments exist on the same page.
Since the variable $maxima_session_result is global, its value is kept within different Algebra blocks in the same page. If must be rest to false for each block. Change
$maxima_input = implode(" ", $list); $maxima_response = maxima_process($maxima_input);
by
$maxima_input = implode(" ", $list); $maxima_session_result=false; $maxima_response = maxima_process($maxima_input);
Attention: For copying click on edit and copy from the source text.
<nowiki> <?php /* Computer Algebra - Maxima - Mediawiki M. Arndt <chmarndt at medemsand.de> (February 2006) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ if( !defined( 'MEDIAWIKI' ) ) { die(); } $wgExtensionCredits['other'][] = array( 'name' => 'Algebra extension', 'author' => 'Markus Arndt', 'version' => 'February 2006', 'url' => 'http://meta.wikimedia.org/wiki/User:Mafs/Computer_algebra', 'description' => 'using http://maxima.sourceforge.net algebraic expressions are evaluated and displayed' ); $wgExtensionFunctions[] = "wfAlgebraExtension"; function wfAlgebraExtension() { global $wgParser; $wgParser->setHook( "Algebra", "renderAlgebra" ); } function renderAlgebra( $text ){ global $wgMathPath, $wgOut, $wgUploadDirectory, $maxima_session_result; $list = array(); // Extract the maxima expressions and replace them by placehoders. $i = 0; while(preg_match("|^(.*?;)\s*$|m", $text, $t)) { $list[] = $t[1]." tex(%);"; $text = str_replace($t[0], "algebra_".md5($i), $text); $i++; } $maxima_input = implode(" ", $list); $maxima_response = maxima_process($maxima_input); if ($maxima_session_result) { $maxima_response = str_replace("$$", "--n9853g204zh--", $maxima_response); $maxima_response = str_replace("|\n", "--n9853g204zh--", $maxima_response); // Replace the placeholders by maximas tex expressions, add math-tags $i = 0; while(preg_match("/--n9853g204zh--(.*?)--n9853g204zh--/is", $maxima_response, $m)) { $tex_math = "$indent<math>".$m[1]."</math>\n"; $maxima_response = substr($maxima_response, 0, strpos($maxima_response, $m[0])).substr($maxima_response, strpos($maxima_response, $m[0])+strlen($m[0])); $text = str_replace("algebra_".md5($i), $tex_math, $text); $i++; } $text = $wgOut->parse($text); } else { $text = "<h2><Algebra></h2><h3>Maximas error message or question:</h3><pre>$maxima_response
</Algebra>
";
}
return $text; }
function maxima_process($text) {
global $maxima_process_message, $maxima_ex_time, $maxima_session_result;
// Some Settings $maxima_path = "/usr/local/bin/maxima"; $temp_path = "/tmp/maxima/"; $max_execution_time = 5; // in seconds
// As a simplistic security measure, all lines containing one of these expressions // are not passed to maxima. $maxima_blacklist = array("save", "load", "plot", "lisp", "includ", "compil", "file", "batch", "stringout", "translat", "stout", "stin", "block", "system");
$maxima_question = false; $max_execution_time_exceeded = false; $unique_md5 = md5 (uniqid (rand())); $maxima_input = $text; $maxima_process_message = "";
if ( ! is_dir( $temp_path ) ) { mkdir( $temp_path, 0777 ); }
$maxima_input = str_replace("\n", "", $maxima_input);
$lines = explode(";", $maxima_input);
foreach($lines as $line) {
$delete = False;
foreach($maxima_blacklist as $d) {
if (eregi($d, $line, $a)) {
$delete = True;
$maxima_process_message .= "The expression \"".trim($line).";\" has not been passed to maxima.
";
break;
}
}
if (!$delete) $newline[] = $line;
}
$maxima_input = implode(";", $newline);
$maxima_input = $maxima_input . " maxima_session_".$unique_md5.";"; $out_file = $temp_path."maxima_$unique_md5.out"; $in_file = $temp_path."maxima_$unique_md5.in"; $pid_file = $temp_path."maxima_$unique_md5.pid";
$fp = fopen($in_file, "w"); fwrite($fp, $maxima_input); fclose($fp);
$cmd = "env MAXIMA_USERDIR=$temp_path $maxima_path --batch=\"$in_file\" > $out_file &\njobs -l > $pid_file";
// For checking the environment: // $cmd = "/usr/local/bin/maxima -d"; // return $cmd;
$start_time = time() + microtime();
passthru($cmd, $ret);
// Process Control *****************************************************************
$pf = file_get_contents($pid_file); preg_match("/^.*? ([0-9]+) .*/", $pf, $p); $pid = trim($p[1]);
if ($pid > 0 and is_numeric($pid)) { while( true ) {
$delta_time = time() + microtime() - $start_time; if ($delta_time > $max_execution_time) $max_execution_time_exceeded = true;
shell_exec("kill -s stop $pid"); $l = shell_exec("wc -l $out_file"); $m = shell_exec("head -n $l $out_file"); shell_exec("kill -s cont $pid");
if (preg_match("/.*\?$/s", trim($m), $a)) $maxima_question = true;
$s = shell_exec("ps -o pid,args -p $pid | grep maxima"); //return $s; if (!strstr($s, $pid)) break;
if ($max_execution_time_exceeded or $maxima_question) break; }
$s = shell_exec("ps -o pid,args -p $pid | grep maxima"); if (strstr($s, $pid)) shell_exec("kill $pid");
// Process Control *****************************************************************
$end_time = time() + microtime(); $maxima_ex_time = ($end_time - $start_time);
if (file_exists($out_file) ) $maxima_response = file_get_contents($out_file); else {
$maxima_process_message .= "Maxima did not run properly (1).
";
}
// remove repeated questions if ($maxima_question) { preg_match("/.*(\n[^\n]*?\?)$/s", trim($m), $a); $maxima_response = str_replace($a[1], "", $maxima_response); $maxima_response = trim($maxima_response)."\n\n".trim($a[1]); }
if (strstr($maxima_response, "maxima_session_".$unique_md5)) $maxima_session_result = true;
// remove headings, tail if (strstr($maxima_response, $unique_md5)) { $maxima_response = preg_replace("|.*$unique_md5.in\s*\n(.*?)|s", "\\1", $maxima_response); $maxima_response = preg_replace("|(.*?)\n[^\n]*?maxima_session_$unique_md5.*|s", "\\1", $maxima_response); }
if ($max_execution_time_exceeded) $maxima_process_message .= "The maximal allowed execution time has been exceeded.
";
} else {
$maxima_process_message .= "Maxima did not run properly (2).
";
}
$s = shell_exec("rm ".$temp_path."maxima_".$unique_md5."*");
return $maxima_response; } ?>
</nowiki>