Creating a custom TreeModel using Gtk.jl - julia

Background: I am trying to build a mini spreadsheet application in Julia that could hold potentially thousands of columns/rows. I found that GTK seems to be fairly mature graphics library to this task (though no spreadsheet application that I know of exists in Julia). GTK's default TreeModel/ListStore works but writing data to it would almost certaintly be a huge pain and very slow as it requires tuples to pass each row to it...
My attempt based on the documentation from Gtk.jl (does not work as intended, I also created the various methods I want to override):
mutable struct CustomTreeModel <: ListStore
handle::Ptr{Gtk.GObject}
_num_rows::Int
_n_columns::Int
cell_matrix::Matrix{Cell}
function CustomTreeModel(cell_matrix)
ls = ListStore(String)
tm_handle = Base.unsafe_convert(Ptr{Gtk.GObject}, ls)
new_obj = new(tm_handle, size(cell_matrix, 1), size(cell_matrix, 2), cell_matrix)
return gobject_move_ref(new_obj, ls)
end
#Methods to override
get_value(self::CustomTreeModel, iter_, column) = string(self.cell_matrix[iter_.user_data][column])
get_n_columns(self::CustomTreeModel) = self._n_columns
get_column_type(self::CustomTreeModel, column) = String
get_flags(self::CustomTreeModel) = Gtk.GtkTreeModelFlags.GTK_TREE_MODEL_ITERS_PERSIST
...
#I want to override the tree model though
tv = GtkTreeView(GtkTreeModel(CustomTreeModel(cells)))
Based on the GTK documentation, it appears I have two choices: override the TreeModel class's virtual methods (cant from Julia) or register the type. Unfortunately I have no idea how to do the latter.
Any thoughts on how to implement a custom model using Gtk.jl?

Related

Updater does not work with dictionary of optimizers

I have been trying to modify the cifer example code of Chainer so that it works with multiple optimizers.
As written in page 946 of Chainer Documentation (Release 7.0.0b3), I thought that the function, training.updaters.ParallelUpdater, can take not only an optimizer object but also a dictionary that maps strings to optimizers.
So, I put three optimizer objects in a dictionary, setup them with a model, and put the dictionary into the ParallelUpdate function as an argument. (see the code below)
optimizers = {}
optimizers['SGD'] = chainer.optimizers.SGD(args.learnrate)
optimizers['Adam'] = chainer.optimizers.Adam()
optimizers['RMSProp'] = chainer.optimizers.RMSprop()
.
.
for key in optimizers.keys() :
optimizers[key].setup(model)
.
.
updater = training.updaters.ParallelUpdater(
train_iter, optimizer=optimizers, devices = devices
)
However, the program gives an error message as follows.
File "C:\WPy64-3720\python-3.7.2.amd64\lib\site-packages\chainer\training\updaters\parallel_updater.py", line 82, in __init__
models = {'main': optimizer.target}
AttributeError: 'dict' object has no attribute 'target'
I understand that 'dict' object is not an optimizer object, but I thought that the description in the document implies that the optimizers are automatically exracted from the dictionary.
Does anybody know what is wrong with my code or how to make the updater work with multiple optimizers?
To use multiple optimizers, you need to override the update_core method and provide custom logic to update with these optimizers. The feature of accepting a dict of optimizers is designed for optimizing multiple different objectives with separate optimizers (e.g. GANs) rather than applying different update rules for parameters of a single objective.
Note that it means you eventually need to implement the parallel update by yourself because ParallelUpdater.update_core, which you need to override, actually implement parallelization. I strongly recommend ChainerMN, which cleanly decouple the optimization logic and parallel training.

How do I declare a map type in Reason ML?

One advantage of Reason ML over JavaScript is that it provides a Map type that uses structural equality rather than reference equality.
However, I cannot find usage examples of this.
For example, how would I declare a type scores that is a map of strings to integers?
/* Something like this */
type scores = Map<string, int>;
And how would I construct an instance?
/* Something like this */
let myMap = scores();
let myMap2 = myMap.set('x', 100);
The standard library Map is actually quite unique in the programming language world in that it is a module functor which you must use to construct a map module for your specific key type (and the API reference documentation is therefore found under Map.Make):
module StringMap = Map.Make({
type t = string;
let compare = compare
});
type scores = StringMap.t(int);
let myMap = StringMap.empty;
let myMap2 = StringMap.add("x", 100, myMap);
There are other data structures you can use to construct map-like functionality, particularly if you need a string key specifically. There's a comparison of different methods in the BuckleScript Cookbook. All except Js.Dict are available outside BuckleScript. BuckleScript also ships with a new Map data structure in its beta standard library which I haven't tried yet.
If you're just dealing with a Map<string, int>, Belt's Map.String would do the trick.
module MS = Belt.Map.String;
let foo: MS.t(int) = [|("a", 1), ("b", 2), ("c", 3)|]->MS.fromArray;
The ergonomics around the Belt version are a little less painful, and they're immutable maps to boot! There's also Map.Int within Belt. For other key types, you'll have to define your own comparator. Which is back to something similar to the two step process #glennsl detailed above.

What does the "Base" keyword mean in Julia?

I saw this example in the Julia language documentation. It uses something called Base. What is this Base?
immutable Squares
count::Int
end
Base.start(::Squares) = 1
Base.next(S::Squares, state) = (state*state, state+1)
Base.done(S::Squares, s) = s > S.count;
Base.eltype(::Type{Squares}) = Int # Note that this is defined for the type
Base.length(S::Squares) = S.count;
Base is a module which defines many of the functions, types and macros used in the Julia language. You can view the files for everything it contains here or call whos(Base) to print a list.
In fact, these functions and types (which include things like sum and Int) are so fundamental to the language that they are included in Julia's top-level scope by default.
This means that we can just use sum instead of Base.sum every time we want to use that particular function. Both names refer to the same thing:
Julia> sum === Base.sum
true
Julia> #which sum # show where the name is defined
Base
So why, you might ask, is it necessary is write things like Base.start instead of simply start?
The point is that start is just a name. We are free to rebind names in the top-level scope to anything we like. For instance start = 0 will rebind the name 'start' to the integer 0 (so that it no longer refers to Base.start).
Concentrating now on the specific example in docs, if we simply wrote start(::Squares) = 1, then we find that we have created a new function with 1 method:
Julia> start
start (generic function with 1 method)
But Julia's iterator interface (invoked using the for loop) requires us to add the new method to Base.start! We haven't done this and so we get an error if we try to iterate:
julia> for i in Squares(7)
println(i)
end
ERROR: MethodError: no method matching start(::Squares)
By updating the Base.start function instead by writing Base.start(::Squares) = 1, the iterator interface can use the method for the Squares type and iteration will work as we expect (as long as Base.done and Base.next are also extended for this type).
I'll grant that for something so fundamental, the explanation is buried a bit far down in the documentation, but http://docs.julialang.org/en/release-0.4/manual/modules/#standard-modules describes this:
There are three important standard modules: Main, Core, and Base.
Base is the standard library (the contents of base/). All modules
implicitly contain using Base, since this is needed in the vast
majority of cases.

Does R support collections in S4?

I have created an S4 class ("card") that resembles a record with several fields. Now I want to define a collection class ("cat") to hold many "card" objects. The cat class will include methods for searching, editing, and adding cards.
Here is a simplified version of what I'm trying to create:
Card <- setClass("Card",
representation(dsOwner = "character", dsFile = "character", dsUrl = "character"))
Cat <- setClass("Cat", representation(cardlist = "list"))
setGeneric("addcard",
function(catObj, owner, file, url)
standardGeneric("addcard"))
setMethod("addcard",
signature(catObj = "Cat"),
function(catObj, owner, file, url){
index <- length(catObj) + 1
catObj[[index]] <- new("Card",
dsOwner = owner,
dsFile = file,
dsUrl = url)
return(index)
})
catalog <- new("Cat")
addcard(catalog, owner = "some online resource", file = "some file name", url = "http://some.url")
Unfortunately, executing the addcard method throws an error I don't understand:
Error in '[[<-'('*tmp*`, index, value = <S4 object of class "Card">) :
[[<- defined for objects of type "S4" only for subclasses of environment'.
Did I not define the cat class correctly?
R does not have a coherent java/C++-like container support to handle arrays, lists, sets, maps, etc (in OOP sense.)
R vectors/lists are in many ways similar to java lists/c++ arrays. I don't know much about speed and efficiency though, I suspect R does many more copies unlike java/c++
Simple set functions with vectors can be done by union, setdiff, unique etc functions. There is also library "sets" that handled very well the simple objects I throw to it.
named vectors (including named lists) are in many ways like a maps. The key is the name, and with some tricks you can make a string key out of any type of object. I suspect though these are not hashed, and the performance seems not to be good. You can also implement maps via environment (see Natural way to represent hash tables/dictionaries/maps in R) and data.table (Dictionaries and pairs in R)
Usually you get pretty far by using these simple measures but I would love to see a more rigorous and efficient implementation. I would happy to be wrong though :-)

How to create a collection in Julia?

This seems like a really basic question, but can't find the answer. How do I create a collection in Julia? For example, I want to open a text file and parse each line to create an (iterable or otherwise) collection. Obviously I don't know how many elements there are in advance.
I can iterate through the lines like this
I = each_line(open(fileName,"r"))
state = start(I)
while !done(I, state)
(i, state) = next(I, state)
println(i)
end
But I don't know how to put each i into an array or other collection. I tried
map( i -> println(i), each_line(open(fileName,"r") ) )
But got the error
no method map(Function,EachLine)
You could do this:
lines = String[]
for line in each_line(open(fileName))
push!(lines, line)
end
And then lines contains the list of lines. You need the String in the first line to make the array extensible.
Standard collections and supported operations are mainly covered in the standard library documentation.
Specifically, the Deques section covers all of the operations supported by the 1d Array type (vector), including push! and pop! as well as insertion, resizing, etc.
Omar's answer is correct, and I will just add a small qualification: String[] creates a 1d array of Strings. The same constructor syntax may be used for example to create Int[], Float[], or even Any[] vectors. The latter type may hold objects of any type.
Depending on your Julia version, you may also be able to write collect(eachline(open("LICENSE.md"))) or [eachline(open("LICENSE.md"))...]. I think these won't work in 0.1.x versions but will working in newer 0.2 development versions (which are recommended at this point – 0.2 is on its way soon).

Resources