Showing posts with label technical. Show all posts
Showing posts with label technical. Show all posts

Saturday, August 08, 2009

Client/Server: technical view

As told in the previous article, I'm changing Matrex from a pure standalone desktop application to an application that allows to work standalone or in a client/server architecture.
To support the client/server architecture I use the RMI protocol.

This means that the calculation engine, the one that calculates the functions and therefore generates the content of matrices, presentations, charts, will be both in the desktop application and in the server.
For this reason, the GUI has to use in the same way the objects involved in the calculation (projects, matrices, functions...) , whether they are on the client side or on the server side.
To do this, the original calculation objects (projects, matrices functions,...) are wrapped in two different new categories of objects: Local (client) and Server:



Both the wrappers, share the same remote interface (which extends the RMI's Remote interface).

The reasons I use wrappers instead of the original objectts is because all the methods of a RMI business object must throw the RemoteException exception.
RemoteException is needed to understand when the server is down or there are problems of connection, so I would never do without it.
On the other side, it becomes annoying to catch it every time some code calls a method of a business object, so I want to do it only when it is strictly needed.
So I use the wrappers only in the GUI, where it is needed. Instead the calculation engine uses the original objects.

Now, why Local and Server wrappers? Why not use only Server wrappers, both on the server and on the client side?
There are several reasons:
  • Server machines and projects have slight different interfaces when they are on the client and on the server side, mainly because projects on the server side can only be saved in a specific directory, projects on the client side can be saved in any directory of the disk.
  • The server wrappers extends the UnicastRemoteObject, local wrappers don't. I don't really understand completely how the Java compiler and RMI compiler handle these objects, so I cannot be sure that they don't have some effects on the application's performance. If these performance effects are needed with the server business objects, I don't want them on the local objects.
And why I did not use the original classes instead of the Local wrappers? Because I needed a special wrapper for the Matrix class when it is used in the GUI, and only when used in the GUI, called SafeMatrix, which makes the Matrix methods thread safe.
But this means that all the other calculation classes need to have parameters of type SafeMatrix when called by the GUI, and instead use parameters of type Matrix when called by the calculation engine. And this means that I need special wrappers that use SafeMatrex parameters, the Local wrappers.


So, now I'm working on it. I will take some time, because in the GUI all the references to the original objects must be changed to the new remote interfaces.
Which means:
  • remote exceptions to handle.
  • utility functions to convert the original classes to the wrappers.
  • some code duplication.
  • many wrappers to write, expecially for the charts, for which there is one class for each chart type.
Also, I expect to reduce the number of methods in the calculation classes to reduce the number of remote calls.

When I have something that more or less works I'll publish it as an alpha version.

Thursday, February 26, 2009

ToolBarWithMenu component

The SWT ToolBar component has a minor problem: when there is no space enough to show all the buttons contained in the ToolBar, it just shows the first ones.
It is true that the SWT.WRAP property partially fixes the problem wrapping the buttons in two or more lines, but this does not work in some platforms (e.g. Linux) in which the property is ignored.
This can be a problem, because the user of the application can be completely unaware of the buttons that are not displayed.
I have seen other graphical libraries solve this problem adding an additional button at the end of the toolbar. This button when clicked shows a menu with the missing buttons.
So I adopted the same logic in SWT: I made a class called ToolBarWithMenu
, which adds a button at the start of the toolbar. The button has a menu showing the buttons that are not displayed in the toolbar because there is no space. Here is an example in Matrex:


Clicking on one of the menu items has the same effect as clicking on the related toolbar button.
It works as expected also for a button with an attached menu, if the button's selection listener that shows the menu implements the IHasMenu interface.

Friday, August 29, 2008

Callbacks

A Matrex project consists in a network of matrices and functions (let's forget about charts, presentations and timers).
They are connected together by the relations:
  • The matrix Mi is input parameter of the function Fj
  • The matrix Mi is output (result) of the function Fj
When a matrix changes its content, it fires the functions of which is input, which recalculate their output matrices, which in turn fires the functions of which are input and so on.

One peculiar property of this network is that it does not have loops. In mathematics it is representable as a simple graph.
This means that a matrix cannot be, directly or through other functions and matrices, input and output of the same function.

This is a good property, because it guarantees that, if the calculation of each single function terminates in a finite time, the calculation of the whole project terminates in a finite time.
In other words, the calculation of the project cannot contain an infinite loop.

In the upcoming version 1.3 I made an exception to this property, to solve the following problem:
I added a new solver function template to Matrex, that finds the minima of functions.
To use a solver, you need to pass to it the function you want to minimize.
In a programming language, you pass the function to mimimize to the solver function as a callback function (or a closure).

But how I did this in Matrex?
In Matrex, a programming language's function is equivalent to a network of functions and matrices, which, seen as a black box, has input and output matrices:



This block of functions and matrices can be equivalent to a callback function, with a trick:
  • the output of the callback block and the input of the caller must have one matrix in common
  • the output of the caller and the input of the callback block must have one matrix in common
The output matrix of the caller that is input matrix of the callback block is called callback matrix.

Here is a picture showing the concept:



In this way the caller, by
changing the content of one of its input matrices recalculates the callback block.
When the callback block executes, it updates the content of its output matrices. But one of those is a input matrix of the caller, therefore the caller is recalculated.

Caller and callback block execute each other until the caller decides to stop and does not change the content of the output matrix that it has in common with the callback block.

But when does the caller decide to stop? This depends by the caller code.

The solver I added In Matrex is Nelder Mead (sys.mathstat.optimization.neldermead), an implementation of the direct search algorithm, a simplex optimization algorithm (it uses the Apache Commons Math library).
At each step of the solving process the solver needs to call a function to calculate the cost of the current solution. The cost calculation function is our callback function.
The following picture shows the solver, the cost calculation function and their input and output matrices:



x is the callback matrix of the solver. It is both output matrix of the solver and input matrix of the cost calculation function.
When the content of x is changed, the cost calculation function is fired and it calculates the cost matrix, which is input of the solver.
The solver is executed and produces a new content for the x matrix, therefore firing the cost calculation function, until the cost is good enough to stop. At this point it stops changing the content of x and writes the final solution in the result matrix.

What I learned writing the Nelder Mead solver template is that one has to write the caller code carefully m
aking always sure that the mutual execution of caller and callback function stops at a certain point, in a way or the other. For example a solver must stop after a certain number of iterations, even if it does not converge.

Adding callbacks in Matrex required some changes in the code:
  • The callback matrix is special: adding a function that has a callback output matrix requires that this matrix is already in the project (it is the input matrix for the callback block).
  • Functions that have callback output matrices are not calculated when the project is loaded.
    Calculating them only once would leave them incomplete (for a solver this means to calculate only one step).
    Calculate them until they stop would be a risk. Better to leave to the user the responsability to calculate them.
Because of the complexity of this new feature, I introduce it in Matrex as experimental.

Wednesday, March 21, 2007

SWT: cell selection in Table

The SWT Table allows only to select rows, not the cells in the rows.
This is a strong limitation for applications that use tables to do something more complex than showing the content of database tables.

In Matrex I needed to import xls (Excel) files and select from them rectangles of cells to add as matrices.
So, I built the TableWithCellSelection class, which allows the user to select rectangles of cells in the table.



It works listening the mouseMove, mouseDown and mouseUp events to keep track of the mouse movements and to change the background of the cells when they are selected.
The class works only for tables that are created with the SWT.FULL_SELECTION and SWT.VIRTUAL styles, which means that the table must be virtual.

Features: Clicking SHIFT together with the left mouse button the selection process restarts from a previously selected cells rectangle.

Limitations: It is not possible to scroll the table during the selection. To be able to select big rectangles you can use the SHIFT key.