Anton Antonov
RakuForPrediction at WordPress
December 2022
In this notebook we are going to demonstrate how to connect to Wolfram Engine (WE) using ZMQ.
See the related package "Proc::ZMQed", blog post "Proc::ZMQed".
Remark: WE uses Wolfam Language (WL). We can say that WE and WL are part of Mathematica. Mathematica and WL are used as synonyms in this notebook.
First we have to establish the a connection between WE and our Raku session. We use "Proc::ZMQed".
use Proc::ZMQed::Mathematica;
my Proc::ZMQed::Mathematica $wlProc .= new(url => 'tcp://127.0.0.1', port => '5550');
Proc::ZMQed::Mathematica.new(cli-name => "wolframscript", code-option => "-code", url => "tcp://127.0.0.1", port => "5550", proc => Any, context => Net::ZMQ4::Context, receiver => Net::ZMQ4::Socket)
$wlProc.start-proc():!proclaim;
()
Here is a simple symobolic expansion command (a non-trivial computation to convince ourselves that the connection with WE is working):
my $cmd = 'Expand[(x+y)^4]';
my $wlRes = $wlProc.evaluate($cmd);
say "Sent : $cmd";
say "Got :\n $wlRes";
Sent : Expand[(x+y)^4] Got : 4 3 2 2 3 4 x + 4 x y + 6 x y + 4 x y + y
The result is pretty formated text. Let us get an expression that we can use in Raku:
$cmd = 'FortranForm[Expand[($x+$y)^4]]';
$wlRes = $wlProc.evaluate($cmd);
say "Sent : $cmd";
say "Got : $wlRes";
Sent : FortranForm[Expand[($x+$y)^4]] Got : $x**4 + 4*$x**3*$y + 6*$x**2*$y**2 + 4*$x*$y**3 + $y**4
Her we assign values to the variables in the expression above and evaluate the string with EVAL
:
my $x = 5;
my $y = 3;
use MONKEY-SEE-NO-EVAL;
say "Using : {{:$x, :$y}.raku}";
say 'EVAL($wlRes) : ', EVAL($wlRes);
Using : {:x(5), :y(3)} EVAL($wlRes) : 4096
Here is a diagram that summarizes the computations in this section:
Let us look into more advanced computations.
Here we differentiate an expression:
$cmd = 'D[(x+y)^3, x]';
$wlRes = $wlProc.evaluate($cmd);
say "Sent : $cmd";
say "Got :\n $wlRes";
Sent : D[(x+y)^3, x] Got : 2 3 (x + y)
Here we find the solutions of a differential equation -- note that we have escape '
when specifying the derivatives:
$cmd = 'sol = DSolve[{y\'[x] == -3 y[x]^2, y[1] == 2}, y[x], x]';
$wlRes = $wlProc.evaluate($cmd);
say "Sent : $cmd";
say "Got :\n {$wlRes}";
Sent : sol = DSolve[{y'[x] == -3 y[x]^2, y[1] == 2}, y[x], x] Got : 2 {{y[x] -> --------}} -5 + 6 x
$cmd='p=Plot[y[x] /. sol, {x, 1, 4}]; ps=ExportString[p,{"Base64","PNG"}]; Export["/tmp/wlimg.txt",ps]';
$wlRes = $wlProc.evaluate($cmd);
/tmp/wlimg.txt
use Text::Plot;
my $timg=slurp('/tmp/wlimg.txt');
from-base64($timg)
my $dt = now.DateTime.Str.substr(0,19);
say $dt;
$cmd = '
p=ClockGauge["' ~ $dt ~ '"];
ps=ExportString[p,{"Base64","PNG"}];
Export["/tmp/wlimg.txt",ps]';
$wlRes = $wlProc.evaluate($cmd);
my $timg=slurp('/tmp/wlimg.txt');
from-base64($timg)
2022-12-24T19:54:19
Here we find the nearest ocean to our current location:
$cmd = 'GeoNearest["Ocean", Here]';
$wlRes = $wlProc.evaluate($cmd);
say "Sent : $cmd";
say "Got :\n {$wlRes.raku}";
Sent : GeoNearest["Ocean", Here] Got : "\{Entity[Ocean, AtlanticOcean]}"
Here we find the Geo-coordinates of Miami, FL, USA and assign the results to the WL variable loc
:
$cmd = 'loc = FindGeoLocation["Miami, FL"]';
$wlRes = $wlProc.evaluate($cmd);
say "Sent : $cmd";
say "Got :\n {$wlRes.raku}";
Sent : loc = FindGeoLocation["Miami, FL"] Got : "GeoPosition[\{25.7743, -80.1937}]"
Here we find the cities with 30 miles of the location found above and convert the corresponding distance into kilometers:
$cmd = 'res = GeoNearest["City", loc, {7, Quantity[30, "Miles"]}]; res2 = Map[{#["Name"], QuantityMagnitude@UnitConvert[GeoDistance[loc, #],"Kilometers"]}&, res]';
$wlRes = $wlProc.evaluate($cmd);
say "Sent : $cmd";
say "Got :\n {$wlRes.raku}";
Sent : res = GeoNearest["City", loc, {7, Quantity[30, "Miles"]}]; res2 = Map[{#["Name"], QuantityMagnitude@UnitConvert[GeoDistance[loc, #],"Kilometers"]}&, res] Got : "\{\{Miami, 0.}, \{Miami Beach, 2.52844}, \{Fisher Island, 4.61465}, \{Brownsville, 5.43461}, \{Coral Gables, 6.07561}, \{Gladeview, 7.10614}, \{Miami Springs, 7.38113}}"
$cmd = 'p=GeoGraphics[GeoMarker/@GeoNearest["City", loc, {7, Quantity[30, "Miles"]}]];ps=ExportString[p,{"Base64","PNG"}]; Export["/tmp/wlimg.txt",ps]';
$wlRes = $wlProc.evaluate($cmd);
my $timg=slurp('/tmp/wlimg.txt');
from-base64($timg)
Here we use Wolfram|Alpha to find the distance from Earth to Sun:
$cmd = 'WolframAlpha["Earth distance from Sun", "Result"]';
$wlRes = $wlProc.evaluate($cmd);
say "Sent : $cmd";
say "Got :\n {$wlRes.raku}";
Sent : WolframAlpha["Earth distance from Sun", "Result"] Got : "0.983621 astronomical units"
Here we find the dietary callories in 20 servings of potato salad:
$cmd = 'WolframAlpha["calories in 20 servings of ice cream", "Result"]';
$wlRes = $wlProc.evaluate($cmd);
say "Sent : $cmd";
say "Got :\n {$wlRes.raku}";
Sent : WolframAlpha["calories in 20 servings of ice cream", "Result"] Got : "3200. dietary Calories"
$cmd = 'p=WolframAlpha["calories in 20 servings of potato salad", {{"NutritionLabelSingle:ExpandedFoodData", 1}, "Image"}]; ps=ExportString[p,{"Base64","PNG"}]; Export["/tmp/wlimg.txt",ps]';
$wlRes = $wlProc.evaluate($cmd);
$timg=slurp('/tmp/wlimg.txt');
from-base64($timg)
$cmd = '
p=ResourceFunction["RandomMondrian"][];
ps=ExportString[p,{"Base64","PNG"}];
Export["/tmp/wlimg.txt",ps]';
$wlRes = $wlProc.evaluate($cmd);
my $timg=slurp('/tmp/wlimg.txt');
from-base64($timg)
$cmd = '
p=ResourceFunction["RandomMandala"]["Radius"->{10,8,4},"ConnectingFunction"->FilledCurve@*BezierCurve,ColorFunction -> "Rainbow",Background->Automatic];
ps=ExportString[p,{"Base64","PNG"}];
Export["/tmp/wlimg.txt",ps]';
$wlRes = $wlProc.evaluate($cmd);
my $timg=slurp('/tmp/wlimg.txt');
from-base64($timg)
Here we close the ZMQ connection:
#$wlProc.terminate