{ "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 }