Skip to content

Instantly share code, notes, and snippets.

@0
Last active November 27, 2019 17:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0/f52c5ccb159d49bd77a0 to your computer and use it in GitHub Desktop.
Save 0/f52c5ccb159d49bd77a0 to your computer and use it in GitHub Desktop.
Some toys in julialang
# Anaphoric if.
macro aif(ex)
@assert (ex.head == :if) "@aif must be applied to an if expression."
cond = ex.args[1]
ex.args[1] = :(convert(Bool, it))
quote
let it = $cond
$ex
end
end
end
### Examples:
for x in [5, 0]
@aif if x
println("I counted $it things.")
else
println("I didn't find anything.")
end
end
# I counted 5 things.
# I didn't find anything.
# Julia lacks this common conversion, so we add it.
import Base.convert
convert(::Type{Bool}, x::String) = !isempty(x)
for x in ["something", ""]
@aif if x
println("Got $it.")
else
println("There was nothing.")
end
end
# Got something.
# There was nothing.
import Base.in, Base.intersect, Base.push!, Base.show, Base.union
# Bloom filter.
immutable Bloom{k,m}
bits::BitVector
function Bloom(bits::BitVector)
k > 0 || error("Number of hashes must be positive.")
m > 0 || error("Number of bits must be positive.")
length(bits) != m && error("Length mismatch.")
new(bits)
end
end
Bloom(k::Integer, bits::BitVector) = Bloom{k,length(bits)}(bits)
Bloom(k::Integer, m) = Bloom(k, falses(m))
function show{k,m}(io::IO, b::Bloom{k,m})
bitstr = join([x ? "#" : " " for x in b.bits])
size = lpad(dec(sum(b.bits)), ndigits(m), " ")
print(io, "|$bitstr|($size/$m)")
end
function hash_indices{k,m}(b::Bloom{k,m}, x)
[hash(x, convert(Unsigned, i)) % m + 1 for i in 1:k]
end
push!(b::Bloom, x) = (b.bits[hash_indices(b, x)] = true; b)
in(x, b::Bloom) = all(b.bits[hash_indices(b, x)])
union{k,m}(bs::Bloom{k,m}...) = Bloom(k, |([b.bits for b in bs]...))
intersect{k,m}(bs::Bloom{k,m}...) = Bloom(k, (&)([b.bits for b in bs]...))
### Examples:
check(elems, b::Bloom) = filter(x -> x in b, elems)
b = Bloom(4, 16)
elems = {123 5.5 -5 "a"}
println("$b $(check(elems, b))")
for x in elems
push!(b, x)
println("$b $(check(elems, b))")
end
println(check(1:50, b))
# | |( 0/16) {}
# | # ## # |( 4/16) {123}
# | # # ## # |( 5/16) {123,5.5}
# |# # #### ## |( 8/16) {123,5.5,-5}
# |### # #### ## # |(11/16) {123,5.5,-5,"a"}
# [11,15,21,23,33,37,39,42,45]
bs = {Bloom(4, 16) for _ in 1:3}
xss = {[1, 2, 3] [1, 2, 4] [1, 5, 6]}
elems = union(xss...)
for (b, xs) in zip(bs, xss)
for x in xs
push!(b, x)
end
println(" $b $(check(elems, b))")
end
bu = union(bs...)
bi = intersect(bs...)
println("U $bu $(check(elems, bu))")
println("I $bi $(check(elems, bi))")
# | #### # # ## |( 8/16) [1,2,3]
# |# ## # ## ## |( 8/16) [1,2,4]
# | ### ##### #|( 9/16) [1,5,6]
# U |###### # #######|(14/16) [1,2,3,4,5,6]
# I | ## # # |( 4/16) [1]
using DataStructures
# Markov chain text generator.
const start_state = "__START__"
function tokenize(filename)
open(filename) do stream
for line in eachline(stream)
for m in eachmatch(r"\S+", line)
produce(m.match)
end
end
end
end
function expand_state(counts)
values = String[]
for (target, count) in counts
for _ in 1:count
push!(values, target)
end
end
values
end
function build_states(tokens)
counter = DefaultDict(String, DefaultDict, () -> DefaultDict(String, Int, 0))
cur = start_state
for token in tokens
counter[cur][token] += 1
cur = token
end
result = Dict{String,Vector{String}}()
for (state, counts) in counter
result[state] = expand_state(counts)
end
result
end
function walk_states(states)
cur = start_state
while length(states[cur]) > 0
n = states[cur]
r = rand(1:length(n))
cur = n[r]
produce(cur)
end
end
function gen_text(source, lim=100)
tokens = @task tokenize(source)
states = build_states(tokens)
walker = @task walk_states(states)
join([consume(walker) for _ in 1:lim], " ")
end
### Examples:
using TextWrap
# Let's try it on some classics from Project Gutenberg.
println_wrapped(gen_text("alice.txt"))
println()
println_wrapped(gen_text("holmes.txt"))
println()
println_wrapped(gen_text("aesop.txt"))
println()
println_wrapped(gen_text("xmas.txt"))
println()
println_wrapped(gen_text("all.txt"))
# CHAPTER I. Down the evening, beautiful garden--how IS his watch out loud.
# 'Thinking again?' the rest of the Hatter hurriedly left alone. 'I daresay
# it's asleep, I eat cats?' ...
# ADVENTURE III. A clump of the name is infinitely the war he found me for us.
# Well, he remarked, a policeman, or token before three. ...
# The elder woman, ashamed to the theaters without inquiry. I only for
# imaginary schemes perished in the heights of the Stag; and firm even the
# noise, awoke and cried the Amaranth AN EAGLE made a child. ...
# STAVE IV: THE THREE SPIRITS WHEN Scrooge entered poor one away to yield to
# follow it. "Thank'ee," said Scrooge, quickening his daughter laughed
# heartily, and touched a brazier, round and tumult of himself in the growing
# strong in his list. ...
# The Buffoon and ourselves, and his actions were always said to say his den to
# make fine actor, and lost an advance was loose. He slipped behind him. A
# CERTAIN poor ignorant little fancy about a black clay pipe, which it was no
# use without a bad taste. Heavy bands which the saucepan of us all. ...
# Print out all the subtypes of x recursively.
function subtypes_rec(x::DataType; depth=0, seen=Set{DataType}())
indent = " "^2depth
if x in seen
# The type graph is not a tree in Julia, as Any is a subtype of itself,
# so we have to be careful about cycles.
print_with_color(:red, "$indent$x [cycle]\n")
return
end
push!(seen, x)
print_with_color(x.abstract ? :cyan : :bold, "$indent$x\n")
for s in subtypes(x)
subtypes_rec(s, depth=depth+1, seen=seen)
end
nothing
end
### Examples:
# You may need to run Julia with --color to see colored text.
subtypes_rec(Number)
# Number
# Complex{T<:Real}
# Real
# FloatingPoint
# BigFloat
# ...
# Float64
# Integer
# BigInt
# ...
subtypes_rec(Any)
# Any
# AbstractArray{T,N}
# ...
# Any [cycle]
# Associative{K,V}
# Dict{K,V}
# ...
import Base.copy
# Velocity Verlet integrator.
type State{T<:FloatingPoint}
xs::Vector{T}
ps::Vector{T}
end
copy{T}(s::State{T}) = State{T}(copy(s.xs), copy(s.ps))
immutable Universe{T}
masses::Vector{T}
force::Function
state::State{T}
end
Universe(masses, force, xs, ps) = Universe(masses, force, State(xs, ps))
type Integrator
u::Universe
dt
next_force
Integrator(u, dt) = new(u, dt)
end
# Velocity verlet step.
function vvstep(itg::Integrator)
u, s = itg.u, itg.u.state
fs = isdefined(itg, :next_force) ? itg.next_force : u.force(s.xs)
xs_ = s.xs + (itg.dt * s.ps + itg.dt^2 * fs / 2) ./ u.masses
itg.next_force = u.force(xs_)
ps_ = s.ps + itg.dt * (fs .+ itg.next_force) / 2
s.xs, s.ps = xs_, ps_
end
type Trajectory{T}
states::Vector{State{T}}
next_slot
end
Trajectory{T}(u::Universe{T}, n::Integer) = Trajectory(Array(State{T}, n), 1)
isfull(t::Trajectory) = t.next_slot > length(t.states)
function record!(t::Trajectory, s::State)
t.states[t.next_slot] = copy(s)
t.next_slot += 1
end
### Examples:
using Winston
const dt = 0.05
const colors = ["blue", "green"]
# Initial conditions.
const xs0 = [1.0, 0.5]
const ps0 = [0.0, 0.0]
const masses = [2.0, 3.0]
const ks = [1.5, 2.0]
const k_coupling = 4.0
function harmonic_oscillators(xs)
-ks .* xs
end
function harmonic_oscillators_coupled(xs)
-ks .* xs .- k_coupling * [xs[1] - xs[2], xs[2] - xs[1]]
end
const configs = [
(harmonic_oscillators, 10.0, "harmonic oscillators", "normal"),
(harmonic_oscillators_coupled, 100.0, "coupled harmonic oscillators", "coupled"),
]
for (f, time, title, filename) in configs
steps = int(ceil(time / dt))
u = Universe(masses, f, xs0, ps0)
itg = Integrator(u, dt)
t = Trajectory(u, steps)
while !isfull(t)
record!(t, u.state)
vvstep(itg)
end
p = FramedPlot(title="Phase space for $title", xlabel="x", ylabel="p")
for i in 1:2
c = Curve([s.xs[i] for s in t.states], [s.ps[i] for s in t.states], color=colors[i])
add(p, c)
end
file(p, "vv_$filename.pdf")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment