I would like to put titles to my graph with the PLplot bindings in OCaml. So far, my code looks like this:
let simple_example g filename =
let p =
P.init (0.0, -2.0) (10.0, 2.0) `greedy (`svg `core) ~filename:filename
in
P.plot ~stream:p [P.func `blue g (0.0, 10.0) ~step:0.001];
P.finish ~stream:p ();
;;
I had a look at the plplot.mli file and tried to use the text an text_outside functions, unsuccessfully. I know there is the Quick_plot module, which enables me to write titles easily, but I would like to avoid it as I lose a lot of other options with it.
Edit.
I had a look at the "canonical" examples, without success (here : http://plplot.sourceforge.net/docbook-manual/plplot-html-5.11.1/ocaml_howto.html)
The function P.label should do what you want:
https://github.com/hcarty/ocaml-plplot/blob/d261e5ec21274ca1a7065e16ab57e87617f8dfcb/src/plplot.mli#L284
This function is the Plot module's equivalent to pllab.
You can get help from PLplot web site which provides example using ocaml among other languages.
I managed to display a label to the parabol drawing :
let simple_example () =
let xs = Array.init 21 (fun xi -> float xi -. 10.0) in
let ys = Array.map (fun x -> x**2.0) xs in
plinit ();
plenv (-10.0) 10.0 0.0 100.0 0 0;
plline xs ys;
pllab "(x)" "(y)" "#frPLplot Example 1 - y=x#u2";
plend();
();;
And if you want to use the Plot module from Plplot, you just have to add this into the list you give to P.plot like below :
let simple_example g filename =
let p =
P.init (0.0, -2.0) (10.0, 2.0) `greedy (`svg `core) ~filename:filename
in
P.plot ~stream:p [P.func `blue g (0.0, 10.0) ~step:0.001; P.text `blue 0. 0. "function"];
P.finish ~stream:p ();
;;
Related
I've written a generic except function for Maps that, given a source map and an other map, returns only the items of the source map without corresponding keys in the other map.
module MapExt =
let getKeys<'k,'v when 'k : comparison> : Map<'k,'v> -> 'k[] =
Map.toArray >> Array.map fst
let except<'k,'v when 'k : comparison>(other:Map<'k,'v>) (source:Map<'k,'v>) : ('k * 'v)[] =
source |> getKeys
|> Array.except (other |> getKeys)
|> Array.map(fun k -> (k, source.[k]))
Now, I've seen in the second part of this answer, that an optimized version of the map's keys is obtained via a Map.fold.
Therefore, can I do a similar optimization of my original MapExt module in the following way?
module MapExtOpt =
let getKeys<'k,'v when 'k : comparison> (m : Map<'k,'v>) : 'k list =
Map.fold (fun keys key _ -> key::keys) [] m
let except<'k,'v when 'k : comparison>
(other : Map<'k,'v>) (source : Map<'k,'v>) : ('k * 'v) list =
source
|> Map.fold (fun s k v ->
if (other.ContainsKey k) then
s
else
(k,v) :: s
) []
Or am I reinventing some already existing (and optimized) functions?
I don't think there is a built in function, but this is a simpler way of doing what you are trying to do. It only goes over the 'to be removed' map once, so its much more efficient.
let except toRemove source =
Map.fold (fun m k _ -> if Map.containsKey k m then Map.remove k m else m) source toRemove
Finally,
thanks to Loïc Denuzière for his comment on Slack:
The if is not necessary: if m doesn't contain k, Map.remove k m just returns m anyway
I think I can also apply a double eta reduction by considering that it makes sense to speak about the keys to remove (not about a map whose values are ignored), so I would simply redefine it as
let except<'k,'v when 'k : comparison> = List.foldBack Map.remove<'k,'v>
I'm new to Julia and I have some difficulties with the programming with types approach.
I wanted to load a 3D mesh from a file to practice and I have made some custom types to store it.
Here are my types:
struct Vertex
x::Number
y::Number
z::Number
Vertex(x::Number, y::Number, z::Number) = new(x, y, z)
Vertex(t::Tuple{Number, Number, Number}) = new(t[1], t[2], t[3])
Vertex(x::Number, y::Number) = new(x, y, 0)
Vertex(t::Tuple{Number, Number}) = new(t[1], t[2], 0)
Vertex(x::Number) = new(x, 0, 0)
Vertex(t::Tuple{Number}) = new(t[1], 0, 0)
Vertex() = new(0, 0, 0)
Vertex(t::Tuple{}) = new(0, 0, 0)
end
struct Mesh
t::Vector{Vertex} # List of triangles
f::Vector{Vertex} # List of faces
n::Vector{Vertex} # List of normals
Mesh(t::Vertex, f::Vertex) = new([t], [f], [])
Mesh(t::Vector{Vertex}, f::Vector{Vertex}, n::Vector{Vertex}) = new(t, f, n)
Mesh(t::Vector{Vertex}, f::Vector{Vertex}, n::Vector) = new(t, f, n)
Mesh(t::Vector, f::Vector, n::Vector) = new(t, f, n)
#Mesh(t::Triangle) = new([t], [])
#Mesh(t::Vector{Triangle}) = new(t, [])
end
I can effectively load a mesh in my Mesh type.
Now, I would like to plot it using the method plot_trisurf from PyPlot. However, this method expect an array of arrays and I'm not sure my way of doing it is the right way:
function plotMesh(M)
Xv = map(e -> e.x, M.t[:])
Yv = map(e -> e.x, M.t[:])
Zv = map(e -> e.x, M.t[:])
Fv = map(e -> (e.x, e.y, e.z), M.f[:])
plot_trisurf(Xv, Yv, Zv, triangles=Fv, alpha=1)
gca()[:projection] = "3d"
end
Q:
The Xv, Yv, Zv doesn't feel right at the moment,
and the Fv do not work at all. [Corrected -> see Edit]
What it the best way of doing this?
Is my type design correct? or should I change it to something more suitable?
Thanks
[edit]
After some more tests I finally managed to make it work, however I'm still not sure if it is the best way to do things in Julia nor if my type system is a good one.
function plotMesh(M::Mesh)
Xv = map(e -> e.x, M.t[:])
Yv = map(e -> e.y, M.t[:])
Zv = map(e -> e.z, M.t[:])
Fv = map(e -> [Int(e.x)-1, Int(e.y)-1, Int(e.z)-1], M.f[:])
print(size(Xv))
print(size(Fv))
plot_trisurf(Xv, Yv, Zv, triangles=Fv)
gca()[:projection] = "3d"
end
First 3D plot in Julia
[edit]
The vertices and normals are (in general) floats and the faces are integers.
The object I'm using is bunny.obj
and my code for loading the object in the structures is:
function read_obj(filename::String)
v = []
f = []
n = []
tof(x) = parse(Float64, x)
open(filename) do file
for line in eachline(file)
l = split(line, ' ')
if l[1] ∈ ["v", "f", "n"]
values = (tof(l[2]), tof(l[3]), tof(l[4]))
if l[1] == "v"
push!(v, Vertex(values))
elseif l[1] == "f"
faces = (Int(values[1]), Int(values[2]), Int(values[3]))
push!(f, Vertex(faces))
elseif l[1] == "n"
push!(n, Vertex(values))
end
end
end
end
return Mesh(v, f, n)
end
My way of loading the object is surely not the best way of doing it. If you have any material to improve my skills feel free to share :)
First I would change the definition of Vertex like this (it seems below you require entries to be integers, if not, you can change Integer to Number)
struct Vertex{T<:Integer}
x::T
y::T
z::T
end
Vertex(x::T=0, y::T=zero(T)) where {T<:Integer} = Vertex(x,y,zero(T))
Vertex(t::Tuple) = Vertex(t...)
Next in Mesh you can use StructArrays.jl package like this (this way you can easily access fields of Vertex as vectors):
using StructArrays
struct Mesh{S<:StructArray, T}
t::S
f::S
n::S
function Mesh(t::Vector{T}, f::Vector{T}, n::Vector{T}) where {T<:Vertex}
st, sf, sn = StructArray(t), StructArray(f), StructArray(n)
new{typeof(st), T}(st, sf, sn)
end
end
Mesh(t::T, f::T) where {T<:Vertex} = Mesh([t], [f], T[])
now you can define the plotting function for example as:
function plotMesh(M::Mesh{S, T}) where {S,T}
Fv = eachrow([M.f.x M.f.y M.f.z] .- one(T))
print(size(M.t.x))
print(size(Fv))
plot_trisurf(M.t.x, M.t.y, M.t.z, triangles=Fv)
gca()[:projection] = "3d"
end
Note 1: All codes make sure that all the structures operate on concrete types so that the code will be faster than using abstract types (like Number). Also I make sure that all entries have the same type.
Note 2: I have written this from my head as you did not provide data to test the code against (so please let me know if anything fails in this code). Strictly speaking you do not have to use StructArrays.jl to achieve the goal, but I hope that you will agree that using them gives you a more readable code.
I need a type of tree and a map on those, so I do this:
type 'a grouping =
G of ('a * 'a grouping) list
with
member g.map f =
let (G gs) = g
gs |> List.map (fun (s, g) -> f s, g.map f) |> G
But this makes me wonder:
The map member is boilerplate. In Haskell, GHC would implement fmap for me (... deriving (Functor)). I know F# doesn't have typeclasses, but is there some other way I can avoid writing map myself in F#?
Can I somehow avoid the line let (G gs) = g?
Is this whole construction somehow non-idiomatic? It looks weird to me, but maybe that's just because putting members on sum types is new to me.
I don't think there is a way to derive automatically map, however there's a way to emulate type classes in F#, your code can be written like this:
#r #"FsControl.Core.dll"
#r #"FSharpPlus.dll"
open FSharpPlus
open FsControl.Core.TypeMethods
type 'a grouping =
G of ('a * 'a grouping) list
with
// Add an instance for Functor
static member instance (_:Functor.Map, G gs, _) = fun (f:'b->'c) ->
map (fun (s, g) -> f s, map f g) gs |> G
// TEST
let a = G [(1, G [2, G[]] )]
let b = map ((+) 10) a // G [(11, G [12, G[]] )]
Note that map is really overloaded, the first application you see calls the instance for List<'a> and the second one the instance for grouping<'a>. So it behaves like fmap in Haskell.
Also note this way you can decompose G gs without creating the let (G gs) = g
Now regarding what is idiomatic I think many people would agree your solution is more F# idiomatic, but to me new idioms should also be developed in order to get more features and overcome current language limitations, that's why I consider using a library which define clear conventions also idiomatic.
Anyway I agree with #kvb in that it's slightly more idiomatic to define map into a module, in F#+ that convention is also used, so you have the generic map and the specific ModuleX.map
I'm studying OCaml these days and came across this:
OCaml has limits on what it can put on the righthand side of a let rec. Like this one
let memo_rec f_norec =
let rec f = memoize (fun x -> f_norec f x) in
f;;
Error: This kind of expression is not allowed as right-hand side of `let rec'
in which, the memoize is a function that take a function and turns it into a memorized version with Hashtable. It's apparent that OCaml has some restriction on the use of constructs at the right-hand side of 'let rec', but I don't really get it, could anyone explain a bit more on this?
The kind of expressions that are allowed to be bound by let rec are described in section 8.1 of the manual. Specifically, function applications involving the let rec defined names are not allowed.
A rough summary (taken from that very link):
Informally, the class of accepted definitions consists of those definitions where the defined names occur only inside function bodies or as argument to a data constructor.
You can use tying-the-knot techniques to define memoizing fixpoints. See for example those two equivalent definitions:
let fix_memo f =
let rec g = {contents = fixpoint}
and fixpoint x = f !g x in
g := memoize !g;
!g
let fix_memo f =
let g = ref (fun _ -> assert false) in
g := memoize (fun x -> f !g x);
!g
Or using lazy as reminded by Alain:
let fix_memo f =
let rec fix = lazy (memoize (fun x -> f (Lazy.force fix) x)) in
Lazy.force fix
I am using Map to implement pure functional DFS and BFS for graph.
here is my code:
module IntMap = Map.Make(struct type t = int let compare = compare end);;
module IntSet = Set.Make(struct type t = int let compare = compare end);;
type digraph = int list IntMap.t;;
exception CantAddEdge;;
let create v =
let rec fill i acc =
if i < v then
fill (i+1) (IntMap.add i [] acc)
else
acc
in
fill 0 IntMap.empty;;
let num_vertices g = IntMap.cardinal g;;
let add_edge u v g =
if IntMap.mem u g && IntMap.mem v g then
let add u v g =
let l = IntMap.find u g in
if List.mem v l then g
else IntMap.add u (v::l) g
in
add u v (add v u g)
else
raise CantAddEdge;;
let dfs_path u g =
let rec dfs current visited path =
let dfs_child current (visited, path) c =
if not (IntSet.mem c visited) then
dfs c (IntSet.add c visited) (IntMap.add c current path)
else
(visited, path)
in
List.fold_left (dfs_child current) (visited, path) (IntMap.find current g)
in
let (v, p) = dfs u (IntSet.singleton u) IntMap.empty
in
p;;
let bfs_path u g =
let rec bfs current_list v p n =
let bfs_current (v,p,n) current =
let bfs_child current (v, p, n) c =
if not (IntSet.mem c v) then begin
print_int c;
((IntSet.add c v), (IntMap.add c current p), (c::n))
end
else
(v, p, n)
in
List.fold_left (bfs_child current) (v, p, n) (IntMap.find current g)
in
let (v,p,n) = List.fold_left bfs_current (v,p,n) current_list
in
if n = [] then p
else bfs n v p []
in
bfs [u] (IntSet.singleton u) IntMap.empty [];;
I know the code is quite long, but I really do wish for some suggestions:
Is it worthy to really implement a pure functional set of graph algorithm? I do this because I am getting used to functional and hate imperative now.
Is my implementation too complicated in some parts or all?
Although I like functional, personally I think the implementation I make seems more complicated than the imperative array-everywhere version. Is my feeling correct?
Edit
Added Bipartite code
(* basically, we have two sets, one for red node and the other for black node*)
(* we keep marking color to nodes via DFS and different level of nodes go to coresponding color set*)
(* unless a node is meant to be one color but already in the set of the other color*)
type colorType = Red | Black;;
let dfs_bipartite u g =
let rec dfs current color red black block =
if block then (red, black, block)
else
let dfs_child current color (red, black, block) c =
if block then (red, black, block)
else
let c_red = IntSet.mem c red and c_black = IntSet.mem c black in
if (not c_red) && (not c_black) then
if color = Red then
dfs c Black (IntSet.add c red) black false
else
dfs c Red red (IntSet.add c black) false
else if (c_red && color = Black) || (c_black && color = Red) then (red, black, true)
else (red, black, block)
in
List.fold_left (dfs_child current color) (red, black, block) (IntMap.find current g)
in
let (r, b, block) = dfs u Black (IntSet.singleton u) IntSet.empty false
in
not block;;
Edit 2
DFS with list based path
let dfs_path u g =
let rec dfs current visited path =
let dfs_child (visited, path) c =
if not (IntSet.mem c visited) then begin
print_int c;
dfs c (IntSet.add c visited) (c::path)
end
else (visited, path)
in
List.fold_left dfs_child (visited, path) (IntMap.find current g)
in
let (v, p) = dfs u (IntSet.singleton u) [u]
in
p;;
I'm not sure what you mean by worthy. It's worthy to set yourself this task as a learning exercise. It's also worthy to use immutable data to solve actual real world graph problems. It doesn't seem to me that graph processing is an area of application where pure functional code costs more than one is generally willing to pay for the benefits.
You're representing a path as a map from each node to the next. This is nice because you can start up the path in the middle. But a list is a simpler and more natural representation of a path for a lot of applications. At any rate, yours is a pretty heavyweight representation and so it makes your code a little heavier than I would have expected. (BTW it was hard to figure this out--some comments would help.)
I don't personally think this code is more complicated than imperative could would be. I also think that arrays make a poor representation for graphs when viewed as linked structures. So I don't believe an "arrays everywhere" solution is what you want to compare against. I'd compare against a malloc()/struct based (a la C) or against an object-based solution, personally.
When representing graphs as adjacency matrices, I'd say the array representation is more competitive. If your graph changes size a lot, or if you want to access nodes by keys other than integers, maps still have many advantages.
It is worthy to do that if you cannot find good codes in open source community. Do not reinvent wheels.
There is another post has an extensive explanation on DFS algorithm by OCaml, Topological sort in OCaml
What I suggest is to try write bfs, bfs_current and bfs_child into a single function.