Monday, January 16, 2012

My experience with airBaltic

UPD: Please read the entire post. I will not remove the story line written originally, because this is exactly what has happened. However airBaltic contacted me on the phone themselves and told about positive resolution of the case. Please read on.

Original story:
-----
First of all, I would like to assure you that I'm not the best at blaming, meaning I simply don't like doing it publicly. It's probably unfair to only publicly blame an air operator and never praise them. But that's how it works. A happy customer doesn't compile an entire blog post about how cool it was to fly with a certain operator. "If I'm happy, I stay silent" principle. But believe me, if the case I'll tell you here about would resolve positively, I wouldn't hesitate to blog about it.

Here is the case. We planned a 3 days trip to Moscow from Helsinki and back together with my wife. Using skyscanner we've found the cheapest option: fly with airBaltic via Riga. Quick friend survey, all's good, settled. I went online and started my ticket search last Saturday. The cheapest option was to depart on 16:25. Chosen that, prepared to pay. After double-checking dates and times it struck me: nope, no good, departure set to 8:25. Cancelled search, started all over. First question here: is it bad luck or bad system? You choose.
Re-ran my search, all is good, paid 531 euros. But when I printed the travel receipt, this time it REALLY struck me: the return flight date was set to one month later! Another bad luck or system fault? This time I'm inclined to choose the second option. No problems, calling to the Finnish office. "On the weekends office is closed". I decided to call first thing next Monday morning. This is my first mistake and I admit it: should have called to Latvia and pay some euro and a half a minute to change the date.

Calling first thing Monday morning: young lady's voice, I described her the problem. She refused to change the date without an additional fee. I have asked her to connect me to her manager. After a couple of minutes (yeah-yeah, customer is on the first place), manager's voice: teaching and preaching me how I should have used their system. "On every page of multi-page ticket booking process, you can look on your right and check the departure and return flight dates and times." All right, thanks! But look, attempted I to explain the system fault: "Unless you really travel back in one month,there is no way to choose that different month without extra movements. No does the system suggest you the best return flights from in a month period!" This was simply noise for her and she continued teaching me how to use the system. I asked her to give me her manager / director. Guess what was the answer: "This is not possible". "Why?". "I'm sorry, but this is not possible." Being a customer, I'm pretty sure, I can talk to almost any worker of the company, who stays in the customer relations line. This time it is your fault, airBaltic.

"I would like to change the return flight date back to what it should be". But the lady tought me another time: "This is only possible if you pay 150 euros. You should have called us on Saturday and explained the problem." Which I did! And the Finnish office was closed. Is this really my problem now? I doubt it. Because, it is YOUR REPRESENTATIVE, airBaltic! What if I wouldn't have an opportunity to call abroad (yes, Riga is abroad to me) and pay for an international call? And if it didn't work, make sure to take my call on Monday morning seriously, attend to it and make an exception or a good men deal. What on Earth does this rule "if you called after two days, it cannot be changed without a fee" policy mean? Do you want to keep a customer or loose it? What do you loose by changing the month standing away date? Afraid not to find any cusomer during an entire month?

"And if I cancel the entire trip, what sum can be refunded?" "You get 76 euros back". Excellent.

Without further ramblings, I would like to publicly thank airBaltic for 531 euros worth "stay at home and don't travel with us" service. It has really taught me not to use your services. Ever.
Everything seems to be mortal in this wolrd, and airBaltic's serivce will die as well. But by making this type of "friendly" customer service and policies you only bring the end faster.

Good luck and enjoy 531-76 euros for not taking us where we wanted.
-----

UPDATE to the story: airBaltic continues working on the case, here is what they posted on twitter: @DmitryKan Dmitry, your case is not closed. Please give us a bit more time and colleagues will come back to you.

UPDATE 2: The case has been resolved. I have received a call from airBaltic, where they said that the return flight date was changed without an extra fee. I don't know was it a result of my social media activity since yesterday evening, but airBaltic service was extremely fast and accurate this time. Since all the posts I have done on the Internet about airBaltic link here, the landed people will read these updates as well. Thank you, airBaltic.

Wednesday, November 9, 2011

axis2: serialization and deserialization of wsdl2java generated objects

Using axis2's wsdl2java tool and a third-party wsdl I have generated service stub and supporting classes (data holders). Since there was a need to do post-processing of loaded data from a service, there was a need to serialize one of the data holder objects.

Questions that I had and posted on stackoverflow.com were:

1) is there a standard axis2 tool / approach that can be used for the purpose?

2) since the data holder class does not implement Serializable interface what would be the easiest way of serializing the object into xml format with the ability to restore the original object?

Data binding option was used (-d jaxbri) and each field of the class in question is annotated with @XmlElement tag, e.g.:

@XmlElement(name = "ID", required = true)
protected String id;



Here is how I solved it:

1. axis2 generated java classes set (client side) had an object called ObjectFactory. Majority of its methods create JAXBElement objects with values of fields of the class holder
2. I had to implement a serializable wrapper class ASerializable for the class holder, such that it uses the ObjectFactory to create the JAXBElement objects for all the fields.
3. some external code uses the wrapper class to create an serializable object and writes it to the output stream.
4. on the receiving end:

ASerializable aSerializable;
        A a;
        aSerializable= (ASerializable)in.readObject();
        a.setID((String)aSerializable.getID().getValue());

It still looks like extra work for the pre-annotated class serialization, but better than serializing into some text format and manual type checking during deserialization.
Some good intro into serialization with java can be found here.

Saturday, October 1, 2011

First international publication

Celebration!



Had my first international publication shown on the DBLP. Somehow it was something I wanted to achieve as an intermediate goal in the academic career. In a way this gives some visibility to what I have been doing for around 4 years. I mean NLP (Natural Language Processing) and Machine Translation more precisely. Before going international, I've had 5 publications in the Russian scientific journals and conferences.

On the same ICSOFT'11 conference where this publication has been presented in a form of poster, I had an honor to serve as knowledge-based systems track chair. Both presenting my work and leading the session were exciting. I wanted also to say thanks to the ICSOFT's organizing committee for giving me the participant's grant, that made my participation possible. Special thanks to Sergio Brissos.


ICSOFT 2011 Conference


ICSOFT is strictly not an NLP conference. However, it has a knowledge-based track, where rather relevant NLP related topics are listed:

Ontology Engineering
Decision Support Systems
Intelligent Problem Solving
Expert Systems
Reasoning Techniques
Knowledge Acquisition
Knowledge Mining
Machine Learning
Natural Language Processing
Human-Machine Cooperation

Two publications I remembered



From these, ontology engineering articles were strong. One of them (Barbara Furletti, Franco Turini: Mining Influence Rules out of Ontologies, see here) was about mining ontology and reasoning rules from the oldest Italian bank's data. This sounds exceptional to me, when some (even old) commercial data is given away to researchers.

Another, non-directly related to NLP, article I remembered was by Manolya Kavakli et al (Manolya Kavakli, Tarashankar Rudra, Manning Li: An Embodied Conversational Agent for Counselling Aborigines - Mr. Warnanggal.), where one of the challenges is providing health assistance to the Australlian aborigines via a computer based system, not very motivated people, poor, stealing food and other things. Another challenge is dealing with about 500 languages, that these aborigines speak. Here is a potential for interesting NLP problems.

Why would I recommend going to a conference not directly related to your research topic?


As a pre-word, I should mention, that in a way whatever we do in the NLP is materialized in the form of programming code. Therefore our work qualifies to a software engineering conference as well as to an NLP one.

Going to a strictly SW conference can give you the following benefits:
* concrete questions of you work in the light of software development practices. Some NLP researchers may think it is not very important to make their SW configurable, re-usable or performant. In the end of the day, this matters a lot, especially if you plan to implement you work into industrial level solution

* if you do a poster presentation, people can give you good insights into the quality of your poster and what can be improved. There were two extreme cases on the conference: one with the entire article text being pasted into the poster and another one with a couple of boxes and an arrow between them. The audience has reacted in an expected way: the first poster did not draw almost any attention, while the second had gathered the majority of the audience.

* you can pause and reflect a little bit: are you doing something valuable? Do you like what you do?


A couple of words about Spain, where ICSOFT'11 happened. +45 is something I have experienced for the first time; visiting royal palace Alcázar of Seville was extremely interesting and of course partying with conference peers over Spanish wine and tapas made the event memorable.

Enjoy you research life and publish your work as soon as possible.

Saturday, August 27, 2011

Оценка системы машинного перевода

Есть система машинного перевода с русского на английский.
Нужно сделать ручную оценку работы системы.

Целевая аудитория: все, кто хочет сделать машинные переводчики лучше (примеры: translate.google.com, translate.ru) и люди, интересующиеся прикладной лингвистикой (Natural Language Processing). Умение программировать НЕ требуется.

Связь: dmitry.kan[+AT+]gmail.com, twitter: DmitryKan

Задача: получить у меня пакет предложений (объём: сколько возьмётесь).

В пакете: предложения на русском языке и их переводы экспертом на английский язык.

Прогнать предложения на русском через систему. Просмотреть вручную их переводы на английский язык.

Составить список слов, которые не были найдены (это просто: не найденные слова будут выведены на русском). Послать мне список слов, я добавлю их в систему машинного перевода.

На выходе от вас три группы предложений из пакета:
1. хорошо перевелись
2. приемлемо перевелись (понятно по английской фразе, что было в русской)
3. плохо перевелись (непонятно по английской фразе, что было в русской)

Работа волонтёрская. Начальный бонус: статья со мной в соавторстве на конференции либо в журнале, если вам это интересно. Если нет -- всяческий пиар вам.

Дальше: если сработаемся, предложу Вам работу в лингвистических проектах (умение программировать обязательно).

Ссылки для интересующихся
[1] http://www.slideshare.net/dmitrykan/icsoft-2011-51cr
[2] http://www.slideshare.net/dmitrykan/automatic-build-of-semantic-translational-dictionary
[3] http://ufal.mff.cuni.cz/umc/

interested in rule based machine translation (rbmt)? / Интересуетесь машинным переводом на правилах?

I'm looking for students and activists of rule-based machine translation to help me in the evaluation of my machine translation system from Russian into English. Details in the e-mail: dmitry.kan[+AT+]gmail.com (substitute characters from [ fro ] with @).

Я ищу студентов и активистов машинного перевода на правилах для оценки моей системы машинного перевода с русского на английский. Детали по почте: dmitry.kan[+AT+]gmail.com (замените символы с [ по ] знаком @).

Thursday, July 14, 2011

Interested in machine translation between Russian and English?

Then mark August 15-19 2011 in your calendars. Web of Data'11 has accepted my poster on machine translation with semantic features, the full paper title is:

Semantic Feature Machine Translation System for Information Retrieval

Some details on the work from another poster, accepted to ICSOFT'11 can be checked here:

Sunday, July 10, 2011

Пример кода, интегрирующего AOT морфологический лемматайзер в C#

АОТ предлагает свой лемматайзер для русского и английского языка на сайте www.aot.ru. Если Вам нужно интегрировать их COM внутри проекта на C#, читайте ниже.

После установки библиотеки при помощи Setup.exe, загрузите Lemmatizer.dll в C# проект. Скопируйте следующий метод или его тело, например, в main-class:


private static void initAOTMorphoanalyzer()
{
LEMMATIZERLib.ILemmatizer lemmatizerRu = new LEMMATIZERLib.LemmatizerRussian();
lemmatizerRu.LoadDictionariesRegistry();
LEMMATIZERLib.IParadigmCollection piParadigmCollection = lemmatizerRu.CreateParadigmCollectionFromForm("мыла", 0, 0);

Console.Out.WriteLine(piParadigmCollection.Count);

for (int j=0; j < piParadigmCollection.Count; j++)
{
object[] args = { j };

Type paradigmCollectionType = piParadigmCollection.GetType();

if (paradigmCollectionType != null)
{
object Item = paradigmCollectionType.InvokeMember("Item", BindingFlags.GetProperty, null, piParadigmCollection, args);
Type itemType = Item.GetType();
if (itemType != null)
{
object Norm = itemType.InvokeMember("Norm", BindingFlags.GetProperty, null, Item, null);
Console.Out.WriteLine(Norm);
}
else
Console.Out.WriteLine("itemType is null");
}
else
Console.Out.WriteLine("paradigmCollectionType is null");
}
}



Результат:
2
МЫЛО
МЫТЬ

COM test example for C#: AOT lemmatizer

I will post this both in English and Russian for more people's benefit.

There is a Russian / English lemmatizer from AOT (www.aot.ru). If you need to use the COM that AOT provides inside C#, read on. Load the lemmatizer.dll inside your C# project. Insert the following method or its body inside your code, for example main class:


private static void initAOTMorphoanalyzer()
{
LEMMATIZERLib.ILemmatizer lemmatizerRu = new LEMMATIZERLib.LemmatizerRussian();
lemmatizerRu.LoadDictionariesRegistry();
LEMMATIZERLib.IParadigmCollection piParadigmCollection = lemmatizerRu.CreateParadigmCollectionFromForm("мыла", 0, 0);

Console.Out.WriteLine(piParadigmCollection.Count);

for (int j=0; j < piParadigmCollection.Count; j++)
{
object[] args = { j };

Type paradigmCollectionType = piParadigmCollection.GetType();

if (paradigmCollectionType != null)
{
object Item = paradigmCollectionType.InvokeMember("Item", BindingFlags.GetProperty, null, piParadigmCollection, args);
Type itemType = Item.GetType();
if (itemType != null)
{
object Norm = itemType.InvokeMember("Norm", BindingFlags.GetProperty, null, Item, null);
Console.Out.WriteLine(Norm);
}
else
Console.Out.WriteLine("itemType is null");
}
else
Console.Out.WriteLine("paradigmCollectionType is null");
}
}



Output:
2
МЫЛО
МЫТЬ

Wednesday, June 8, 2011

Amazed by Scala #1: objects and compilation

7 minutes and here is an object, that can be compiled into java classes:



import scala.actors._
import Actor._

object TopStock {
val symbols = List( "AAPL", "GOOG", "IBM", "MSFT")
val receiver = self
val year = 2008

def main(args: Array[String]) = {
symbols.foreach { symbol =>
actor { receiver ! getYearEndClosing(symbol, year) }
}

val (topStock, highestPrice) = getTopStock(symbols.length)
printf("Top stock of %d is %s closing at price %f\n", year, topStock, highestPrice)
}

def getYearEndClosing(symbol : String, year : Int) = {
val url = "http://ichart.finance.yahoo.com/table.csv?s="+
symbol + "&a=11&b=01&c=" + year + "&d=11&e=31&f=" + year+
"&g=m"

val data = io.Source.fromURL(url).mkString
val price = data.split("\n")(1).split(",")(4).toDouble
(symbol, price)
}

def getTopStock(count : Int) : (String, Double) = {
(1 to count).foldLeft("", 0.0) { (previousHigh, index) =>
receiveWithin(10000) {
case (symbol : String, price : Double) =>
if (price > previousHigh._2) (symbol, price) else previousHigh
}
}
}
}


Saved in TopStock.scala. Compiled with

> scalac TopStock.scala

ran with

> scala TopStock

Top stock of 2008 is GOOG closing at price 307,650000

Amazed by Scala

Top stock of 2008 is GOOG closing at price 307,650000 among (AAPL, GOOG, IBM, MSFT). Amazed by simplicity, clarity and beauty of the following code in Scala from this book.



import scala.actors._
import Actor._

val symbols = List( "AAPL", "GOOG", "IBM", "MSFT")
val receiver = self
val year = 2008

symbols.foreach { symbol =>
actor { receiver ! getYearEndClosing(symbol, year) }
}

val (topStock, highestPrice) = getTopStock(symbols.length)

printf("Top stock of %d is %s closing at price %f\n", year,
topStock, highestPrice)

def getYearEndClosing(symbol : String, year : Int) = {
val url = "http://ichart.finance.yahoo.com/table.csv?s="+
symbol + "&a=11&b=01&c=" + year + "&d=11&e=31&f=" + year+
"&g=m"

val data = io.Source.fromURL(url).mkString
val price = data.split("\n")(1).split(",")(4).toDouble
(symbol, price)
}

def getTopStock(count : Int) : (String, Double) = {
(1 to count).foldLeft("", 0.0) { (previousHigh, index) =>
receiveWithin(10000) {
case (symbol : String, price : Double) =>
if (price > previousHigh._2) (symbol, price) else
previousHigh
}
}
}