{
"cells": [
{
"cell_type": "markdown",
"id": "190210bc",
"metadata": {},
"source": [
"# Using Wolfram Engine in Raku\n",
"\n",
"Anton Antonov \n",
"[RakuForPrediction at WordPress](https://rakuforprediction.wordpress.com) \n",
"December 2022"
]
},
{
"cell_type": "markdown",
"id": "bdff6cce",
"metadata": {},
"source": [
"## Introduction\n",
"\n",
"In this notebook we are going to demonstrate how to connect to [Wolfram Engine (WE)](https://www.wolfram.com/engine/) using [ZMQ](https://zeromq.org/).\n",
"\n",
"See the related package [\"Proc::ZMQed\"](https://raku.land/zef:antononcube/Proc::ZMQed), blog post [\"Proc::ZMQed\"](https://rakuforprediction.wordpress.com/2022/11/29/proczmqed/).\n",
"\n",
"**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."
]
},
{
"cell_type": "markdown",
"id": "142b07a1",
"metadata": {},
"source": [
"--------\n",
"\n",
"## Estalishing ZMQ connection\n",
"\n",
"First we have to establish the a connection between WE and our Raku session. We use [\"Proc::ZMQed\"](https://raku.land/zef:antononcube/Proc::ZMQed)."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "706e9f41",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"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)"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"use Proc::ZMQed::Mathematica;\n",
"my Proc::ZMQed::Mathematica $wlProc .= new(url => 'tcp://127.0.0.1', port => '5550');"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "dafedb76",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"()"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"$wlProc.start-proc():!proclaim;"
]
},
{
"cell_type": "markdown",
"id": "f836019d",
"metadata": {},
"source": [
"Here is a simple symobolic expansion command (a non-trivial computation to convince ourselves that the connection with WE is working):"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "c299d50d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Sent : Expand[(x+y)^4]\n",
"Got :\n",
" 4 3 2 2 3 4\n",
"x + 4 x y + 6 x y + 4 x y + y\n"
]
}
],
"source": [
"my $cmd = 'Expand[(x+y)^4]';\n",
"my $wlRes = $wlProc.evaluate($cmd);\n",
"say \"Sent : $cmd\";\n",
"say \"Got :\\n $wlRes\";"
]
},
{
"cell_type": "markdown",
"id": "bb8b9c7a",
"metadata": {},
"source": [
"The result is pretty formated text. Let us get an expression that we can use in Raku:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "4352fd00",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Sent : FortranForm[Expand[($x+$y)^4]]\n",
"Got : $x**4 + 4*$x**3*$y + 6*$x**2*$y**2 + 4*$x*$y**3 + $y**4\n"
]
}
],
"source": [
"$cmd = 'FortranForm[Expand[($x+$y)^4]]';\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"say \"Sent : $cmd\";\n",
"say \"Got : $wlRes\";"
]
},
{
"cell_type": "markdown",
"id": "2c8d8689",
"metadata": {},
"source": [
"Her we assign values to the variables in the expression above and evaluate the string with `EVAL`:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "92047fba",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Using : {:x(5), :y(3)}\n",
"EVAL($wlRes) : 4096\n"
]
}
],
"source": [
"my $x = 5;\n",
"my $y = 3;\n",
"\n",
"use MONKEY-SEE-NO-EVAL;\n",
"say \"Using : {{:$x, :$y}.raku}\";\n",
"say 'EVAL($wlRes) : ', EVAL($wlRes);"
]
},
{
"cell_type": "markdown",
"id": "10df4d5f",
"metadata": {},
"source": [
"Here is a diagram that summarizes the computations in this section:\n",
"\n",
"![WEandRaku](https://rakuforprediction.files.wordpress.com/2022/11/mermaid-diagram-2022-12-06-092042.png?w=600)"
]
},
{
"cell_type": "markdown",
"id": "50d7edbe",
"metadata": {},
"source": [
"-------\n",
"\n",
"## More advanced computations\n",
"\n",
"Let us look into more advanced computations.\n",
"\n",
"Here we differentiate an expression:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "1c712e0d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Sent : D[(x+y)^3, x]\n",
"Got :\n",
" 2\n",
"3 (x + y)\n"
]
}
],
"source": [
"$cmd = 'D[(x+y)^3, x]';\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"say \"Sent : $cmd\";\n",
"say \"Got :\\n $wlRes\";"
]
},
{
"cell_type": "markdown",
"id": "931c7bca",
"metadata": {},
"source": [
"Here we find the solutions of a differential equation -- note that we have escape `'` when specifying the derivatives:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "77a3ef0c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Sent : sol = DSolve[{y'[x] == -3 y[x]^2, y[1] == 2}, y[x], x]\n",
"Got :\n",
" 2\n",
"{{y[x] -> --------}}\n",
" -5 + 6 x\n"
]
}
],
"source": [
"$cmd = 'sol = DSolve[{y\\'[x] == -3 y[x]^2, y[1] == 2}, y[x], x]';\n",
"\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"say \"Sent : $cmd\";\n",
"say \"Got :\\n {$wlRes}\";"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "1c9b9756",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"/tmp/wlimg.txt"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"$cmd='p=Plot[y[x] /. sol, {x, 1, 4}]; ps=ExportString[p,{\"Base64\",\"PNG\"}]; Export[\"/tmp/wlimg.txt\",ps]';\n",
"$wlRes = $wlProc.evaluate($cmd);"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "9d6628c5",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"use Text::Plot;\n",
"my $timg=slurp('/tmp/wlimg.txt');\n",
"from-base64($timg)"
]
},
{
"cell_type": "markdown",
"id": "138f402d",
"metadata": {},
"source": [
"----------\n",
"\n",
"## Clock face"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "e956c2d0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2022-12-24T19:54:19\n"
]
},
{
"data": {
"text/html": [
""
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"my $dt = now.DateTime.Str.substr(0,19);\n",
"say $dt;\n",
"$cmd = '\n",
"p=ClockGauge[\"' ~ $dt ~ '\"];\n",
"ps=ExportString[p,{\"Base64\",\"PNG\"}]; \n",
"Export[\"/tmp/wlimg.txt\",ps]';\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"my $timg=slurp('/tmp/wlimg.txt');\n",
"from-base64($timg)"
]
},
{
"cell_type": "markdown",
"id": "03b81441",
"metadata": {},
"source": [
"-------\n",
"\n",
"## Geo computations"
]
},
{
"cell_type": "markdown",
"id": "bc68b6ed",
"metadata": {},
"source": [
"Here we find the nearest ocean to our current location:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "9a89b6de",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Sent : GeoNearest[\"Ocean\", Here]\n",
"Got :\n",
" \"\\{Entity[Ocean, AtlanticOcean]}\"\n"
]
}
],
"source": [
"$cmd = 'GeoNearest[\"Ocean\", Here]';\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"say \"Sent : $cmd\";\n",
"say \"Got :\\n {$wlRes.raku}\";"
]
},
{
"cell_type": "markdown",
"id": "3cab07fd",
"metadata": {},
"source": [
"Here we find the Geo-coordinates of Miami, FL, USA and assign the results to the WL variable `loc`:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "c915ca06",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Sent : loc = FindGeoLocation[\"Miami, FL\"]\n",
"Got :\n",
" \"GeoPosition[\\{25.7743, -80.1937}]\"\n"
]
}
],
"source": [
"$cmd = 'loc = FindGeoLocation[\"Miami, FL\"]';\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"say \"Sent : $cmd\";\n",
"say \"Got :\\n {$wlRes.raku}\";"
]
},
{
"cell_type": "markdown",
"id": "49c3df00",
"metadata": {},
"source": [
"Here we find the cities with 30 miles of the location found above and convert the corresponding distance into kilometers:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "4cf29cd0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Sent : res = GeoNearest[\"City\", loc, {7, Quantity[30, \"Miles\"]}]; res2 = Map[{#[\"Name\"], QuantityMagnitude@UnitConvert[GeoDistance[loc, #],\"Kilometers\"]}&, res]\n",
"Got :\n",
" \"\\{\\{Miami, 0.}, \\{Miami Beach, 2.52844}, \\{Fisher Island, 4.61465}, \\{Brownsville, 5.43461}, \\{Coral Gables, 6.07561}, \\{Gladeview, 7.10614}, \\{Miami Springs, 7.38113}}\"\n"
]
}
],
"source": [
"$cmd = 'res = GeoNearest[\"City\", loc, {7, Quantity[30, \"Miles\"]}]; res2 = Map[{#[\"Name\"], QuantityMagnitude@UnitConvert[GeoDistance[loc, #],\"Kilometers\"]}&, res]';\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"say \"Sent : $cmd\";\n",
"say \"Got :\\n {$wlRes.raku}\";"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "3cfbc82c",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"$cmd = 'p=GeoGraphics[GeoMarker/@GeoNearest[\"City\", loc, {7, Quantity[30, \"Miles\"]}]];ps=ExportString[p,{\"Base64\",\"PNG\"}]; Export[\"/tmp/wlimg.txt\",ps]';\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"my $timg=slurp('/tmp/wlimg.txt');\n",
"from-base64($timg)"
]
},
{
"cell_type": "markdown",
"id": "1e416fb5",
"metadata": {},
"source": [
"-------\n",
"\n",
"## Using Wolfram|Alpha"
]
},
{
"cell_type": "markdown",
"id": "caccac91",
"metadata": {},
"source": [
"Here we use [Wolfram|Alpha](https://www.wolframalpha.com) to find the distance from Earth to Sun:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "ea5e9882",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Sent : WolframAlpha[\"Earth distance from Sun\", \"Result\"]\n",
"Got :\n",
" \"0.983621 astronomical units\"\n"
]
}
],
"source": [
"$cmd = 'WolframAlpha[\"Earth distance from Sun\", \"Result\"]';\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"say \"Sent : $cmd\";\n",
"say \"Got :\\n {$wlRes.raku}\";"
]
},
{
"cell_type": "markdown",
"id": "7f48034d",
"metadata": {},
"source": [
"Here we find the dietary [callories in 20 servings of potato salad](https://www.wolframalpha.com/input?i=calories+in+20+servings+of+potato+salad):"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "f60b5ac9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Sent : WolframAlpha[\"calories in 20 servings of ice cream\", \"Result\"]\n",
"Got :\n",
" \"3200. dietary Calories\"\n"
]
}
],
"source": [
"$cmd = 'WolframAlpha[\"calories in 20 servings of ice cream\", \"Result\"]';\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"say \"Sent : $cmd\";\n",
"say \"Got :\\n {$wlRes.raku}\";"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "ffc56072",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"$cmd = 'p=WolframAlpha[\"calories in 20 servings of potato salad\", {{\"NutritionLabelSingle:ExpandedFoodData\", 1}, \"Image\"}]; ps=ExportString[p,{\"Base64\",\"PNG\"}]; Export[\"/tmp/wlimg.txt\",ps]';\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"$timg=slurp('/tmp/wlimg.txt');\n",
"from-base64($timg)"
]
},
{
"cell_type": "markdown",
"id": "de28c964",
"metadata": {},
"source": [
"------\n",
"\n",
"## Using repostiory functions"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "c93cd12e",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"$cmd = '\n",
"p=ResourceFunction[\"RandomMondrian\"][];\n",
"ps=ExportString[p,{\"Base64\",\"PNG\"}]; \n",
"Export[\"/tmp/wlimg.txt\",ps]';\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"my $timg=slurp('/tmp/wlimg.txt');\n",
"from-base64($timg)"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "43fff313",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
""
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"$cmd = '\n",
"p=ResourceFunction[\"RandomMandala\"][\"Radius\"->{10,8,4},\"ConnectingFunction\"->FilledCurve@*BezierCurve,ColorFunction -> \"Rainbow\",Background->Automatic];\n",
"ps=ExportString[p,{\"Base64\",\"PNG\"}]; \n",
"Export[\"/tmp/wlimg.txt\",ps]';\n",
"$wlRes = $wlProc.evaluate($cmd);\n",
"my $timg=slurp('/tmp/wlimg.txt');\n",
"from-base64($timg)"
]
},
{
"cell_type": "markdown",
"id": "8f0695a0",
"metadata": {},
"source": [
"-----\n",
"\n",
"## Epilog"
]
},
{
"cell_type": "markdown",
"id": "2317bffb",
"metadata": {},
"source": [
"Here we close the ZMQ connection:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9a8034d3",
"metadata": {},
"outputs": [],
"source": [
"#$wlProc.terminate"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Raku",
"language": "raku",
"name": "raku"
},
"language_info": {
"file_extension": ".raku",
"mimetype": "text/plain",
"name": "raku",
"version": "6.d"
}
},
"nbformat": 4,
"nbformat_minor": 5
}