Seven Lines of Julia (examples sought)

Getting a sorted reference list or BibTeX entries from DOIs:

using Downloads
urls = [
    "https://doi.org/10.1137/141000671",
    "https://doi.org/10.1093/comjnl/27.2.97",
]
# replace "text/bibliography; style=apa" by "application/x-bibtex" for bibtex
result = @. String(take!(Downloads.download(urls,IOBuffer(),headers = ["Accept" => "text/bibliography; style=apa"])))

print(join(sort(result),"\n"))

This produces a consistently formatted reference list:

Bezanson, J., Edelman, A., Karpinski, S., & Shah, V. B. (2017). Julia: A Fresh Approach to Numerical Computing. SIAM Review, 59(1), 65–98. https://doi.org/10.1137/141000671

Knuth, D. E. (1984). Literate Programming. The Computer Journal, 27(2), 97–111. https://doi.org/10.1093/comjnl/27.2.97

Also useful with curl in shell:

curl -LH "Accept: text/bibliography; style=apa"  'https://doi.org/10.1137/141000671'
27 Likes

@Niall @greatpet @Henrique_Becker
I feel like nest() & nestlist() are super-useful functions.
They are standard in other packages as Mathematica…
Could there be any value in having something like nest() & nestlist() added to Base?

In Julia v1.8 we’ll have the possibility of type-annotating global variables, to promise their type won’t change:

julia> x::Float64 = 3.14
3.14

julia> x = 2.71
2.71

julia> x = "hello world"
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Float64

Wouldn’t it be nice if we could automatically get the type annotation without having to explicitly type it ourselves? Here be dragons macros (note that the macro definition is exactly 7 lines):

julia> macro stable(ex)
           ex.head !== :(=) && throw(ArgumentError("@stable: `$(ex)` is not an assigment expression."))
           quote
               local x = $(esc(ex.args[2]))
               $(esc(ex.args[1]))::typeof(x) = x
           end
       end
@stable (macro with 1 method)

julia> @stable y = "hello world"
"hello world"

julia> y
"hello world"

julia> y = "foo bar"
"foo bar"

julia> y = 1 + 2
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type String

Thanks @Mason for the tip in Zulip about local and the suggestion for the name of the macro (I initially called it @auto, like the C++ auto keyword).

38 Likes

Simulation of an unstable Kirchhoff vortex using contour dynamics.

using Plots,DifferentialEquations
function myf!(du,u,p,t)
    du[:,:].= 0.0
    for i=1:size(u,1), j=1:size(u,1)-1
        du[i,:].+= (u[j+1,:].-u[j,:]) * log((u[i,1]- 0.5 * (u[j+1,1]+u[j,1]))^2 + (u[i,2]- 0.5 * (u[j+1,2]+u[j,2]))^2)
    end 
end
solu=solve(ODEProblem(myf!,[4.0 * sin.(collect(range(0.0,2.0*pi,length=300))).+0.01*cos.(collect(range(0.0,3.0*pi,length=300))) cos.(collect(range(0.0,2.0*pi,length=300))).+0.01*sin.(collect(range(0.0,3.0*pi,length=300)))],(0.0,4.0)))
anim = @animate for t=0.0:0.01:4.0
        plot(solu(t)[:,1],solu(t)[:,2],xlims = (-7, 7),ylims = (-7, 7),aspect_ratio=1,fill = (0, 0.5, :red)) 
                end
gif(anim, "Kirchhoff vortex.gif", fps = 15)

Kirchhoff vortex

13 Likes

using IterTools
using Statistics
F(x)=[mean(x),prod(x)^(1/length(x)), median(x)]
Fnx(x,n)=nth(iterated(F,x),n)
12 Likes

I get this result and a drawing that looks like the city of Tokyo seen from above.

Where am I wrong?

julia> using WordCloud

julia> using HTTP

julia> url = "https://discourse.julialang.org/t/seven-lines-of-julia-examples-sought/50416"
"https://discourse.julialang.org/t/seven-lines-of-julia-examples-sought/50416"

julia> wc = url |> HTTP.get |> HTTP.body |> String |> html2text   |> wordcloud |> generate!
Total words: 2537. Unique words: 917. After filtration: 797.
The top 500 words are kept.
color scheme: :Derain, random size: 7
angles = [0, 45, 90]
shape(squircle, 778, 778, rt=0.676, color=(0.995, 0.972, 0.977), padding=73)
fonts = "serif Medium"
mask size: 924×924, content area: 729² (33²/word)
set fontsize ∈ [8.0, 924]
set density = 0.5
⋯scale=36.4378580599903, density=1.1556920617525943     ↑
⋯scale=23.967171129908238, density=0.6062046331392033   ↑
⋯scale=20.708195992075236, density=0.5404095939083428   ↑
⋯scale=18.423033876602776, density=0.5081258437883059   ↑
fontsize ∈ [8.0, 47.19357688711178]
407 words(81%) are limited to the minimum font size.
┌ Warning: It seems too crowded. Word size may be seriously distorted. You need to reduce the number of words or set a larger mask.
└ @ WordCloud C:\Users\sprmn\.julia\packages\WordCloud\kNUgd\src\wc-method.jl:60
▸1. scale = 17.801707615058803
[ Info: nepoch: 1000, patient: 10
[ Info: @epoch 89(+21) Ρ -> 0.177 (current 448 collisions, best 390 collisions)

Very nice! You can use two of your remaining three lines for

using Plots
plotF(x, N) = plot(hcat(first(iterated(F, x), N+1)[begin+1:end]); seriestype=:scatter)

to see the convergence.

convergence

2 Likes

Nice idea.
I tried, as an exercise, to make a graph myself.
Maybe @rafael.guerra can make it dynamic.

PS
but couldn’t plot work with iterators and thus build the graph dynamically?

using IterTools, Statistics, Plots

F(x)=[mean(x),prod(x)^(1/length(x)), median(x)]

F1nx(x,n)= last(firstrest(takestrict(iterated(F,x),n)))

plotF(x, N) = plot(collect.(zip(F1nx(x,N)...)),title= "fixed point", label=["arith" "geom" "median"])

plotF([10,-20,300,1,-50],10)

fixed point of the averages

@rocco_sprmnt21, as you asked, I felt obliged. See a simple code below, FWIW:

using IterTools, Statistics, Plots; gr(size=(800,600), dpi=600)

F(x) = [mean(x),prod(x)^(1/length(x)), median(x)]
F1nx(x,n) = last(firstrest(takestrict(iterated(F,x),n)))

function plotF(x,N)
    plot((1:3)', [NaN, NaN, NaN], title= "fixed point", xlabel="N", xlims=(0,N), c=[:red :blue :green], label=["mean" "geom" "median"])
    yn = collect.(zip(F1nx(x,N)...))
    for n in 2:N
        display(plot!(2:n, getindex.(yn, (1:n-1,)), msw=0,ms=5,m=:o,c=[:red :blue :green]))
        sleep(0.4)
    end
end

plotF([10,-20,300,1,-50], 10)
2 Likes

I show the following seven lines, just to show if I understand how you make “dynamic” graphs

using IterTools, Statistics, Plots
Fnx(x,n)=nth(iterated(x->[mean(x),prod(x)^(1/length(x)), median(x)],x),n)
plot(title= "fixed point", xlabel="N iteration", xlims=(1,11))
for n in (2:10)
    display(plot!(n:n, (x->[x]).(Fnx([10,-20,300,1,-50],n)), msw=0,ms=5,m=:>,
            c=[:red :blue :green], label=(n>2) ? nothing : ["mean" "geom" "median"]));
    sleep(0.5) 
end
1 Like

Slightly longer, but still in the spirit of this thread; here’s a simple discrete paper-scissors-rock reaction-diffusion simulation in a dozen lines:

using CircularArrays # convenient for periodic boundary conditions
using Images

neighbor_offsets = [CartesianIndex(i, j) for i ∈ -1:1, j ∈ -1:1 if !(i == j == 0)]

function step(grid)
    newgrid = copy(grid)
    for I in eachindex(grid)
        neighbors = [grid[I + Δ] for Δ in neighbor_offsets]
        dominant = mod1(grid[I] + 1, 3) # 3 beats 2, 2 beats 1 and 1 beats 3
        newgrid[I] = count(==(dominant), neighbors) >= 3 ? dominant : grid[I]
    end
    newgrid
end

grid = CircularArray(rand(1:3, 100, 100))
animation = foldl((steps, _) -> [steps..., step(steps[end])], 1:100; init=[grid])
save("animation.gif", rand(RGB, 3)[cat(animation...; dims=3)])

animation.gif:
animation

24 Likes

I didn’t see anything wrong. Where is your Tokyo drawing?

3 Likes

Pango’s font rendering issue again. I guess you use windows. You can try ] pin Pango_jll@1.42.4 to solve it. It does look like a city seen from above. Haha.

2 Likes

Much better. Now you can also read the names of the streets :grin:

3 Likes

This is a cool thread! I think some gratuitous giff-ery would be acceptable here:

liquidlatex

using Luxor, MathTeXEngine
a = Movie(800, 300, "liquidlatex")
animate(a, Scene(a, (s, f) -> begin
    background("black"); sethue("turquoise"); fontsize(150)
    text(L"e^{iπ} + 1 = 0", O, halign=:center, valign=:middle, paths=true)
    e = storepath()
    drawpath(e, f/150, :stroke)
   end, 1:150), creategif=true)
59 Likes

anyone have any idea what i miss to admire this beautiful animation on my pc?

ulia> using Luxor, MathTeXEngine
julia> a = Movie(800, 300, "liquidlatex")
Movie(800.0, 300.0, "liquidlatex", 1:250)

julia> animate(a, Scene(a, (s, f) -> begin
           background("black"); sethue("turquoise"); fontsize(150)
           text(L"e^{iπ} + 1 = 0", O, halign=:center, valign=:middle, paths=true)
           e = storepath()
           drawpath(e, f/150, :stroke)
          end, 1:150), creategif=true)
ERROR: LoadError: UndefVarError: @L_str not defined
in expression starting at c:\Users\sprmn\.julia\environments\v1.7\animate gif1.jl:5

L"" is in LaTeXStrings.jl but that should be re-exported by MathTeXEngine.

What version are you running?

 pkg> st
      Status `C:\Users\stephan\AppData\Local\Temp\jl_2EoXW3\Project.toml`
  [ae8d54c2] Luxor v3.3.0
  [0a4f8689] MathTeXEngine v0.4.1

It really is a beautiful animation :slight_smile:

this is part of my status

[b964fa9f] LaTeXStrings v1.3.0
  [23fbe1c1] Latexify v0.15.13
  [50d2b5c4] Lazy v0.15.1
  [16fef848] LiveServer v0.7.4
  [bdcacae8] LoopVectorization v0.12.103
  [ae8d54c2] Luxor v3.3.0
  [1914dd2f] MacroTools v0.5.9
  [ee78f7c6] Makie v0.15.1
  [945b72a4] MarketData v0.13.9
  [0a4f8689] MathTeXEngine v0.1.2

but I have just installed, for the occasion, the packages indicated.

euler formula
is it for this reason that I don’t have the right font?

1 Like

Your MathTeXEngine is quite old. I wonder what’s holding it back. Try ]add MathTeXEngine@0.4 and see what’s conflicting.

Yep, you need Computer Modern as a system font. See Add text ¡ Luxor