Regression support added
authorTasuku Suzuki <stasuku@gmail.com>
Mon, 27 Jan 2014 00:41:22 +0000 (09:41 +0900)
committerTasuku Suzuki <stasuku@gmail.com>
Mon, 27 Jan 2014 01:58:57 +0000 (10:58 +0900)
Change-Id: Iee2969247520c65f3c69e309f6db411149cb92da
Reviewed-on: http://cr.qtquick.me/799
Reviewed-by: Tasuku Suzuki <stasuku@gmail.com>
Tested-by: Tasuku Suzuki <stasuku@gmail.com>
30 files changed:
examples/cpp/cpp.pro
examples/cpp/recommender/npb_similar_player/npb_similar_player.pro
examples/cpp/regression/regression.pro [new file with mode: 0644]
examples/cpp/regression/rent_data/dialog.cpp [new file with mode: 0644]
examples/cpp/regression/rent_data/dialog.h [new file with mode: 0644]
examples/cpp/regression/rent_data/dialog.ui [new file with mode: 0644]
examples/cpp/regression/rent_data/main.cpp [new file with mode: 0644]
examples/cpp/regression/rent_data/rent-data.csv [new file with mode: 0644]
examples/cpp/regression/rent_data/rent_data.json [new file with mode: 0644]
examples/cpp/regression/rent_data/rent_data.pro [new file with mode: 0644]
examples/cpp/regression/rent_data/rent_data.qrc [new file with mode: 0644]
examples/qml/qml.pro
examples/qml/regression/iris/iris.json [new file with mode: 0644]
examples/qml/regression/iris/iris.pro [new file with mode: 0644]
examples/qml/regression/iris/main.cpp [new file with mode: 0644]
examples/qml/regression/iris/qml/iris/iris.data [new file with mode: 0644]
examples/qml/regression/iris/qml/iris/iris.qml [new file with mode: 0644]
examples/qml/regression/iris/qtquick2controlsapplicationviewer/qtquick2controlsapplicationviewer.cpp [new file with mode: 0644]
examples/qml/regression/iris/qtquick2controlsapplicationviewer/qtquick2controlsapplicationviewer.h [new file with mode: 0644]
examples/qml/regression/iris/qtquick2controlsapplicationviewer/qtquick2controlsapplicationviewer.pri [new file with mode: 0644]
examples/qml/regression/regression.pro [new file with mode: 0644]
src/imports/jubatus/jubatus.pro
src/imports/jubatus/main.cpp
src/imports/jubatus/qmljubatusregression.cpp [new file with mode: 0644]
src/imports/jubatus/qmljubatusregression.h [new file with mode: 0644]
src/jubatus/client/qjubatusclient.h
src/jubatus/jubatus.pro
src/jubatus/regression/qjubatusregression.cpp [new file with mode: 0644]
src/jubatus/regression/qjubatusregression.h [new file with mode: 0644]
src/jubatus/regression/regression.pri [new file with mode: 0644]

index ceee12f..f941325 100644 (file)
@@ -1,2 +1,2 @@
 TEMPLATE = subdirs
-SUBDIRS += anomaly classifier recommender
+SUBDIRS += anomaly classifier recommender regression
index 569aa12..e1cc284 100644 (file)
@@ -5,7 +5,7 @@ CONFIG += c++11
 SOURCES = main.cpp \
     dialog.cpp
 
-OTHER_FILES += npb_similar_player
+OTHER_FILES += npb_similar_player.json
 
 RESOURCES += \
     npb_similar_player.qrc
diff --git a/examples/cpp/regression/regression.pro b/examples/cpp/regression/regression.pro
new file mode 100644 (file)
index 0000000..61a77ce
--- /dev/null
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS += rent_data
diff --git a/examples/cpp/regression/rent_data/dialog.cpp b/examples/cpp/regression/rent_data/dialog.cpp
new file mode 100644 (file)
index 0000000..0625bc1
--- /dev/null
@@ -0,0 +1,72 @@
+#include "dialog.h"
+#include "ui_dialog.h"
+
+#include <QtCore>
+#include <QtWidgets>
+#include <QtJubatus>
+
+class Dialog::Private
+{
+public:
+    Private(Dialog *parent);
+
+private:
+    Dialog *q;
+    Ui::Dialog ui;
+    QJubatusRegression regression;
+};
+
+Dialog::Private::Private(Dialog *parent)
+    : q(parent)
+{
+    ui.setupUi(q);
+
+    regression.setName("rent_data");
+    regression.setTimeout(10);
+    connect(&regression, &QJubatusRegression::error, [this](const QString &message) {
+        QMessageBox::warning(q, tr("Error"), message);
+        QMetaObject::invokeMethod(q, "close", Qt::QueuedConnection);
+    });
+
+    QFile file(":/rent-data.csv");
+    file.open(QFile::ReadOnly | QFile::Text);
+    QTextStream stream(&file);
+    QList<QJubatusRegression::ScoredDatum> scoredData;
+    while (!stream.atEnd()) {
+        QStringList list = stream.readLine().split(",");
+        if (list.size() != 6)
+            continue;
+        QVariantMap data;
+        float rent = list.takeFirst().toFloat();
+        data.insert(QStringLiteral("distance"), list.takeFirst().toFloat());
+        data.insert(QStringLiteral("size"), list.takeFirst().toFloat());
+        data.insert(QStringLiteral("age"), list.takeFirst().toFloat());
+        data.insert(QStringLiteral("floor"), list.takeFirst().toFloat());
+        data.insert(QStringLiteral("direction"), list.takeFirst());
+        QJubatusRegression::ScoredDatum scoredDatum;
+        scoredDatum.score = rent;
+        scoredDatum.data = data;
+        scoredData.append(scoredDatum);
+    }
+    file.close();
+    regression.train(scoredData);
+
+    connect(ui.buttonBox, &QDialogButtonBox::rejected, q, &QDialog::close);
+    connect(ui.estimate, &QPushButton::clicked, [this]() {
+        QVariantMap data;
+        data.insert(QStringLiteral("distance"), ui.distance->value());
+        data.insert(QStringLiteral("size"), ui.size->value());
+        data.insert(QStringLiteral("age"), ui.age->value());
+        data.insert(QStringLiteral("floor"), ui.floor->value());
+        data.insert(QStringLiteral("direction"), ui.direction->currentText());
+        QList<float> ret = regression.estimate(QList<QVariantMap>() << data);
+        QMessageBox::information(q, tr("estimated rent"), tr("%1 JPY/Month").arg(ret.first() * 10000));
+    });
+}
+
+Dialog::Dialog(QWidget *parent)
+    : QDialog(parent)
+    , d(new Private(this))
+{
+    connect(this, &QObject::destroyed, [this]() { delete d; });
+}
diff --git a/examples/cpp/regression/rent_data/dialog.h b/examples/cpp/regression/rent_data/dialog.h
new file mode 100644 (file)
index 0000000..2bb6c7c
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef DIALOG_H
+#define DIALOG_H
+
+#include <QDialog>
+
+class Dialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit Dialog(QWidget *parent = 0);
+
+private:
+    class Private;
+    Private *d;
+};
+
+#endif // DIALOG_H
diff --git a/examples/cpp/regression/rent_data/dialog.ui b/examples/cpp/regression/rent_data/dialog.ui
new file mode 100644 (file)
index 0000000..f286114
--- /dev/null
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>297</width>
+    <height>239</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>rent</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Parameters</string>
+     </property>
+     <layout class="QFormLayout" name="formLayout">
+      <property name="fieldGrowthPolicy">
+       <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+      </property>
+      <item row="0" column="0">
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>&amp;Distance:</string>
+        </property>
+        <property name="buddy">
+         <cstring>distance</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QSpinBox" name="distance">
+        <property name="suffix">
+         <string> mins</string>
+        </property>
+        <property name="minimum">
+         <number>0</number>
+        </property>
+        <property name="maximum">
+         <number>20</number>
+        </property>
+        <property name="value">
+         <number>10</number>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>&amp;Size:</string>
+        </property>
+        <property name="buddy">
+         <cstring>size</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QSpinBox" name="size">
+        <property name="suffix">
+         <string> m2</string>
+        </property>
+        <property name="value">
+         <number>30</number>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QLabel" name="label_3">
+        <property name="text">
+         <string>&amp;Age:</string>
+        </property>
+        <property name="buddy">
+         <cstring>age</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QSpinBox" name="age">
+        <property name="suffix">
+         <string> yrs</string>
+        </property>
+        <property name="maximum">
+         <number>50</number>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="0">
+       <widget class="QLabel" name="label_4">
+        <property name="text">
+         <string>&amp;Floor:</string>
+        </property>
+        <property name="buddy">
+         <cstring>floor</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <widget class="QSpinBox" name="floor">
+        <property name="suffix">
+         <string>F</string>
+        </property>
+        <property name="minimum">
+         <number>1</number>
+        </property>
+        <property name="maximum">
+         <number>30</number>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="0">
+       <widget class="QLabel" name="label_5">
+        <property name="text">
+         <string>&amp;Direction:</string>
+        </property>
+        <property name="buddy">
+         <cstring>direction</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="4" column="1">
+       <widget class="QComboBox" name="direction">
+        <item>
+         <property name="text">
+          <string>N</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>NE</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>E</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>SE</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>S</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>SW</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>W</string>
+         </property>
+        </item>
+        <item>
+         <property name="text">
+          <string>NW</string>
+         </property>
+        </item>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <layout class="QVBoxLayout" name="verticalLayout">
+     <item>
+      <widget class="QPushButton" name="estimate">
+       <property name="text">
+        <string>Estimate</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="verticalSpacer">
+       <property name="orientation">
+        <enum>Qt::Vertical</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>40</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QDialogButtonBox" name="buttonBox">
+       <property name="standardButtons">
+        <set>QDialogButtonBox::Close</set>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/cpp/regression/rent_data/main.cpp b/examples/cpp/regression/rent_data/main.cpp
new file mode 100644 (file)
index 0000000..27efccc
--- /dev/null
@@ -0,0 +1,13 @@
+#include <QtWidgets>
+
+#include "dialog.h"
+
+int main(int argc, char **argv)
+{
+    QApplication app(argc, argv);
+
+    Dialog dialog;
+    dialog.show();
+
+    return app.exec();
+}
diff --git a/examples/cpp/regression/rent_data/rent-data.csv b/examples/cpp/regression/rent_data/rent-data.csv
new file mode 100644 (file)
index 0000000..e1346cd
--- /dev/null
@@ -0,0 +1,150 @@
+#
+# S町の1Rマンションの賃貸情報
+#
+# 家賃(万円), 駅からの徒歩時間 (分), 専有面積 (m*m), 築年数 (年), 階数, 向き [ N / NE / E / SE / S / SW / W / NW ]
+#
+7.1, 10, 22.34, 6, 2, E
+8, 10, 38.29, 45, 4, SE
+4.5, 26, 18.23, 24, 2, W
+4.75, 7, 15, 24, 3, SW
+7.3, 15, 20.13, 14, 8, S
+8.6, 22, 36.54, 9, 2, E
+6.3, 11, 20.1, 30, 7, SE
+9.6, 10, 30.03, 0, 5, SW
+9, 10, 30.03, 0, 2, SE
+9, 10, 30.03, 0, 2, SE
+8.4, 16, 30.91, 9, 9, SE
+9.2, 12, 30.03, 0, 2, SE
+9.2, 12, 30.03, 0, 2, SE
+9.2, 12, 30.03, 0, 2, SE
+9.2, 12, 30.03, 0, 2, SE
+8.8, 10, 30.03, 0, 1, W
+5.05, 7, 15, 24, 10, E
+5.05, 7, 15, 24, 10, E
+5.05, 7, 15, 24, 10, E
+5.05, 7, 15, 24, 10, E
+6, 15, 29.48, 24, 4, NW
+9.7, 3, 36.94, 11, 5, NW
+9.22, 10, 30.03, 0, 2, SE
+4.7, 9, 14.62, 28, 5, E
+6.6, 5, 22.26, 22, 5, E
+5.9, 8, 21.56, 23, 4, NE
+5.9, 8, 21.56, 23, 4, NE
+4.7, 9, 14.62, 28, 5, NE
+12.3, 8, 40.12, 9, 7, SE
+4.5, 20, 16.25, 23, 3, SW
+9.2, 10, 30.03, 0, 4, SE
+6.9, 7, 22.83, 25, 4, SW
+5.8, 2, 17.24, 29, 9, E
+6.1, 5, 20.43, 22, 3, SE
+9.6, 35, 35.39, 6, 2, SW
+9.6, 10, 30.03, 0, 5, SE
+9.5, 6, 31.1, 7, 8, SW
+7.8, 15, 23.37, 5, 10, NW
+6.3, 7, 24.39, 25, 7, SE
+4.7, 1, 16.35, 21, 4, SE
+9.4, 12, 30.03, 0, 4, SE
+9.4, 10, 30.03, 0, 4, SE
+9.3, 10, 30.03, 0, 3, SE
+9.3, 10, 30.03, 0, 3, SE
+9.3, 10, 30.03, 0, 3, SE
+9.3, 10, 30.03, 0, 3, SE
+9.3, 10, 30.03, 0, 3, SE
+9.3, 10, 30.03, 0, 3, SE
+9.3, 10, 30.03, 0, 3, SE
+9.3, 10, 30.03, 0, 3, SE
+9.3, 10, 30.03, 0, 3, SE
+9.3, 10, 30.03, 0, 3, SE
+5.8, 1, 17.16, 29, 9, E
+4.85, 7, 15, 24, 8, E
+4.85, 7, 15, 24, 8, E
+4.85, 7, 15, 24, 8, E
+4.85, 7, 15, 24, 8, E
+4.85, 7, 15, 24, 8, E
+6.4, 9, 28.3, 28, 6, E
+7.3, 15, 20.13, 14, 8, SE
+7.8, 5, 25.03, 6, 2, SW
+7.8, 5, 25.03, 6, 2, SW
+7.2, 25, 25.33, 23, 3, SE
+7.67, 7, 30, 24, 9, E
+7.67, 7, 30, 24, 9, E
+7.67, 7, 30, 24, 9, E
+6.5, 7, 24.39, 25, 7, SE
+4.75, 7, 15, 24, 3, W
+7.5, 25, 22.82, 23, 4, SE
+7.5, 25, 22.82, 23, 4, SE
+5.3, 7, 18.07, 25, 06, SE
+9, 11, 31.8, 12, 3, SE
+7.3, 12, 23.09, 12, 3, S
+5.5, 1, 17.59, 29, 8, S
+9.2, 10, 30.03, 0, 2, SW
+9.2, 10, 30.03, 0, 2, SW
+6.3, 8, 21.56, 23, 2, N
+8.8, 10, 30.03, 0, 1, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+9.2, 10, 30.03, 0, 2, SE
+7.7, 10, 21.02, 5, 1, E
+7.2, 10, 18.75, 5, 1, SW
+7.2, 10, 18.75, 5, 1, SW
+7.2, 10, 18.75, 5, 1, SW
+7.7, 10, 18.75, 5, 1, W
+4.75, 7, 15, 24, 3, E
+4.75, 7, 15, 24, 3, E
+4.75, 7, 15, 24, 3, E
+4.75, 7, 15, 24, 3, E
+4.75, 7, 15, 24, 3, E
+5.6, 20, 21.14, 7, 3, SW
+12, 10, 40.12, 9, 7, SE
+10.6, 3, 37.18, 11, 9, NW
+4.95, 7, 15, 24, 10, E
+4.85, 7, 15, 24, 10, E
+4.85, 7, 15, 24, 10, E
+4.85, 7, 15, 24, 10, E
+5.05, 7, 15, 24, 10, SW
+9.5, 5, 30, 13, 8, NE
+7.7, 10, 18.75, 5, 1, SW
+9.3, 12, 30.03, 0, 3, SE
+9.3, 12, 30.03, 0, 3, SE
+9.3, 12, 30.03, 0, 3, SE
+9.3, 12, 30.03, 0, 3, SE
+9.3, 12, 30.03, 0, 3, SE
+4.7, 10, 14.62, 28, 5, E
+9, 10, 30.03, 0, 1, S
+9, 10, 30.03, 0, 1, S
+8.2, 10, 23.56, 6, 3, E
+7.2, 4, 16, 5, 2, S
+7.2, 4, 16, 5, 2, S
+4.85, 7, 15, 24, 9, SE
+6.6, 5, 22.26, 22, 5, SE
+9, 10, 30.03, 0, 1, SE
+9, 10, 30.03, 0, 1, SE
+9, 10, 30.03, 0, 1, SE
+9, 10, 30.03, 0, 1, SE
+9, 10, 30.03, 0, 1, SE
+8.3, 9, 32.18, 24, 3, S
+7.8, 10, 21.02, 5, 4, W
+6.8, 25, 25.33, 23, 3, SE
+9.1, 10, 30.03, 0, 3, SE
+9.1, 10, 30.03, 0, 3, SE
+7.5, 10, 21.02, 5, 4, SW
+8.3, 9, 32.18, 24, 3, E
+10.3, 3, 36.94, 11, 7, SE
+4.3, 15, 16.25, 23, 1, SW
+25, 15, 74.96, 10, 15, E
+4.6, 17, 16.32, 18, 4, SE
+4.2, 15, 16.94, 26, 4, SW
+6.5, 5, 22.83, 25, 4, NE
+5.9, 8, 21.56, 23, 4, SW
diff --git a/examples/cpp/regression/rent_data/rent_data.json b/examples/cpp/regression/rent_data/rent_data.json
new file mode 100644 (file)
index 0000000..94e039e
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "method": "PA",
+  "converter": {
+    "num_filter_types": {},
+    "num_filter_rules": [],
+    "string_filter_types": {},
+    "string_filter_rules": [],
+    "num_types": {},
+    "num_rules": [
+      { "key": "*", "type": "num" }
+    ],
+    "string_types": {},
+    "string_rules": [
+      { "key": "direction", "type": "str", "sample_weight": "bin", "global_weight": "bin" }
+    ]
+  },
+  "parameter": {
+    "sensitivity": 0.1,
+    "regularization_weight": 3.402823e+38
+  }
+}
diff --git a/examples/cpp/regression/rent_data/rent_data.pro b/examples/cpp/regression/rent_data/rent_data.pro
new file mode 100644 (file)
index 0000000..f954ae8
--- /dev/null
@@ -0,0 +1,17 @@
+TEMPLATE = app
+TARGET = jubatus-rent-data
+QT = core network gui widgets jubatus
+CONFIG += c++11
+SOURCES = main.cpp \
+    dialog.cpp
+
+OTHER_FILES += rent_data.json
+
+RESOURCES += \
+    rent_data.qrc
+
+FORMS += \
+    dialog.ui
+
+HEADERS += \
+    dialog.h
diff --git a/examples/cpp/regression/rent_data/rent_data.qrc b/examples/cpp/regression/rent_data/rent_data.qrc
new file mode 100644 (file)
index 0000000..6f910f7
--- /dev/null
@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/">
+        <file>rent-data.csv</file>
+    </qresource>
+</RCC>
index a2832bd..cf7b980 100644 (file)
@@ -1,3 +1,3 @@
 TEMPLATE = subdirs
-SUBDIRS += classifier recommender
+SUBDIRS += classifier recommender regression
 
diff --git a/examples/qml/regression/iris/iris.json b/examples/qml/regression/iris/iris.json
new file mode 100644 (file)
index 0000000..bfe9b12
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "method": "PA",
+  "converter": {
+    "num_filter_types": {},
+    "num_filter_rules": [],
+    "string_filter_types": {},
+    "string_filter_rules": [],
+    "num_types": {},
+    "num_rules": [
+      { "key": "*", "type": "num"}
+    ],
+    "string_types": {},
+    "string_rules": [
+      { "key": "*", "type": "str", "sample_weight": "bin", "global_weight": "bin" }
+    ]
+  },
+  "parameter": {
+    "sensitivity": 0.1,
+    "regularization_weight": 3.402823e+38
+  }
+}
diff --git a/examples/qml/regression/iris/iris.pro b/examples/qml/regression/iris/iris.pro
new file mode 100644 (file)
index 0000000..d3cec94
--- /dev/null
@@ -0,0 +1,19 @@
+# Add more folders to ship with the application, here
+folder_01.source = qml/iris
+folder_01.target = qml
+DEPLOYMENTFOLDERS = folder_01
+
+# Additional import path used to resolve QML modules in Creator's code model
+QML_IMPORT_PATH =
+
+# The .cpp file which was generated for your project. Feel free to hack it.
+SOURCES += main.cpp
+
+# Installation path
+# target.path =
+
+# Please do not modify the following two lines. Required for deployment.
+include(qtquick2controlsapplicationviewer/qtquick2controlsapplicationviewer.pri)
+qtcAddDeployment()
+
+OTHER_FILES += iris.json
diff --git a/examples/qml/regression/iris/main.cpp b/examples/qml/regression/iris/main.cpp
new file mode 100644 (file)
index 0000000..7d30384
--- /dev/null
@@ -0,0 +1,12 @@
+#include "qtquick2controlsapplicationviewer.h"
+
+int main(int argc, char *argv[])
+{
+    Application app(argc, argv);
+
+    QtQuick2ControlsApplicationViewer viewer;
+    viewer.setMainQmlFile(QStringLiteral("qml/iris/iris.qml"));
+    viewer.show();
+
+    return app.exec();
+}
diff --git a/examples/qml/regression/iris/qml/iris/iris.data b/examples/qml/regression/iris/qml/iris/iris.data
new file mode 100644 (file)
index 0000000..5c4316c
--- /dev/null
@@ -0,0 +1,151 @@
+5.1,3.5,1.4,0.2,Iris-setosa
+4.9,3.0,1.4,0.2,Iris-setosa
+4.7,3.2,1.3,0.2,Iris-setosa
+4.6,3.1,1.5,0.2,Iris-setosa
+5.0,3.6,1.4,0.2,Iris-setosa
+5.4,3.9,1.7,0.4,Iris-setosa
+4.6,3.4,1.4,0.3,Iris-setosa
+5.0,3.4,1.5,0.2,Iris-setosa
+4.4,2.9,1.4,0.2,Iris-setosa
+4.9,3.1,1.5,0.1,Iris-setosa
+5.4,3.7,1.5,0.2,Iris-setosa
+4.8,3.4,1.6,0.2,Iris-setosa
+4.8,3.0,1.4,0.1,Iris-setosa
+4.3,3.0,1.1,0.1,Iris-setosa
+5.8,4.0,1.2,0.2,Iris-setosa
+5.7,4.4,1.5,0.4,Iris-setosa
+5.4,3.9,1.3,0.4,Iris-setosa
+5.1,3.5,1.4,0.3,Iris-setosa
+5.7,3.8,1.7,0.3,Iris-setosa
+5.1,3.8,1.5,0.3,Iris-setosa
+5.4,3.4,1.7,0.2,Iris-setosa
+5.1,3.7,1.5,0.4,Iris-setosa
+4.6,3.6,1.0,0.2,Iris-setosa
+5.1,3.3,1.7,0.5,Iris-setosa
+4.8,3.4,1.9,0.2,Iris-setosa
+5.0,3.0,1.6,0.2,Iris-setosa
+5.0,3.4,1.6,0.4,Iris-setosa
+5.2,3.5,1.5,0.2,Iris-setosa
+5.2,3.4,1.4,0.2,Iris-setosa
+4.7,3.2,1.6,0.2,Iris-setosa
+4.8,3.1,1.6,0.2,Iris-setosa
+5.4,3.4,1.5,0.4,Iris-setosa
+5.2,4.1,1.5,0.1,Iris-setosa
+5.5,4.2,1.4,0.2,Iris-setosa
+4.9,3.1,1.5,0.1,Iris-setosa
+5.0,3.2,1.2,0.2,Iris-setosa
+5.5,3.5,1.3,0.2,Iris-setosa
+4.9,3.1,1.5,0.1,Iris-setosa
+4.4,3.0,1.3,0.2,Iris-setosa
+5.1,3.4,1.5,0.2,Iris-setosa
+5.0,3.5,1.3,0.3,Iris-setosa
+4.5,2.3,1.3,0.3,Iris-setosa
+4.4,3.2,1.3,0.2,Iris-setosa
+5.0,3.5,1.6,0.6,Iris-setosa
+5.1,3.8,1.9,0.4,Iris-setosa
+4.8,3.0,1.4,0.3,Iris-setosa
+5.1,3.8,1.6,0.2,Iris-setosa
+4.6,3.2,1.4,0.2,Iris-setosa
+5.3,3.7,1.5,0.2,Iris-setosa
+5.0,3.3,1.4,0.2,Iris-setosa
+7.0,3.2,4.7,1.4,Iris-versicolor
+6.4,3.2,4.5,1.5,Iris-versicolor
+6.9,3.1,4.9,1.5,Iris-versicolor
+5.5,2.3,4.0,1.3,Iris-versicolor
+6.5,2.8,4.6,1.5,Iris-versicolor
+5.7,2.8,4.5,1.3,Iris-versicolor
+6.3,3.3,4.7,1.6,Iris-versicolor
+4.9,2.4,3.3,1.0,Iris-versicolor
+6.6,2.9,4.6,1.3,Iris-versicolor
+5.2,2.7,3.9,1.4,Iris-versicolor
+5.0,2.0,3.5,1.0,Iris-versicolor
+5.9,3.0,4.2,1.5,Iris-versicolor
+6.0,2.2,4.0,1.0,Iris-versicolor
+6.1,2.9,4.7,1.4,Iris-versicolor
+5.6,2.9,3.6,1.3,Iris-versicolor
+6.7,3.1,4.4,1.4,Iris-versicolor
+5.6,3.0,4.5,1.5,Iris-versicolor
+5.8,2.7,4.1,1.0,Iris-versicolor
+6.2,2.2,4.5,1.5,Iris-versicolor
+5.6,2.5,3.9,1.1,Iris-versicolor
+5.9,3.2,4.8,1.8,Iris-versicolor
+6.1,2.8,4.0,1.3,Iris-versicolor
+6.3,2.5,4.9,1.5,Iris-versicolor
+6.1,2.8,4.7,1.2,Iris-versicolor
+6.4,2.9,4.3,1.3,Iris-versicolor
+6.6,3.0,4.4,1.4,Iris-versicolor
+6.8,2.8,4.8,1.4,Iris-versicolor
+6.7,3.0,5.0,1.7,Iris-versicolor
+6.0,2.9,4.5,1.5,Iris-versicolor
+5.7,2.6,3.5,1.0,Iris-versicolor
+5.5,2.4,3.8,1.1,Iris-versicolor
+5.5,2.4,3.7,1.0,Iris-versicolor
+5.8,2.7,3.9,1.2,Iris-versicolor
+6.0,2.7,5.1,1.6,Iris-versicolor
+5.4,3.0,4.5,1.5,Iris-versicolor
+6.0,3.4,4.5,1.6,Iris-versicolor
+6.7,3.1,4.7,1.5,Iris-versicolor
+6.3,2.3,4.4,1.3,Iris-versicolor
+5.6,3.0,4.1,1.3,Iris-versicolor
+5.5,2.5,4.0,1.3,Iris-versicolor
+5.5,2.6,4.4,1.2,Iris-versicolor
+6.1,3.0,4.6,1.4,Iris-versicolor
+5.8,2.6,4.0,1.2,Iris-versicolor
+5.0,2.3,3.3,1.0,Iris-versicolor
+5.6,2.7,4.2,1.3,Iris-versicolor
+5.7,3.0,4.2,1.2,Iris-versicolor
+5.7,2.9,4.2,1.3,Iris-versicolor
+6.2,2.9,4.3,1.3,Iris-versicolor
+5.1,2.5,3.0,1.1,Iris-versicolor
+5.7,2.8,4.1,1.3,Iris-versicolor
+6.3,3.3,6.0,2.5,Iris-virginica
+5.8,2.7,5.1,1.9,Iris-virginica
+7.1,3.0,5.9,2.1,Iris-virginica
+6.3,2.9,5.6,1.8,Iris-virginica
+6.5,3.0,5.8,2.2,Iris-virginica
+7.6,3.0,6.6,2.1,Iris-virginica
+4.9,2.5,4.5,1.7,Iris-virginica
+7.3,2.9,6.3,1.8,Iris-virginica
+6.7,2.5,5.8,1.8,Iris-virginica
+7.2,3.6,6.1,2.5,Iris-virginica
+6.5,3.2,5.1,2.0,Iris-virginica
+6.4,2.7,5.3,1.9,Iris-virginica
+6.8,3.0,5.5,2.1,Iris-virginica
+5.7,2.5,5.0,2.0,Iris-virginica
+5.8,2.8,5.1,2.4,Iris-virginica
+6.4,3.2,5.3,2.3,Iris-virginica
+6.5,3.0,5.5,1.8,Iris-virginica
+7.7,3.8,6.7,2.2,Iris-virginica
+7.7,2.6,6.9,2.3,Iris-virginica
+6.0,2.2,5.0,1.5,Iris-virginica
+6.9,3.2,5.7,2.3,Iris-virginica
+5.6,2.8,4.9,2.0,Iris-virginica
+7.7,2.8,6.7,2.0,Iris-virginica
+6.3,2.7,4.9,1.8,Iris-virginica
+6.7,3.3,5.7,2.1,Iris-virginica
+7.2,3.2,6.0,1.8,Iris-virginica
+6.2,2.8,4.8,1.8,Iris-virginica
+6.1,3.0,4.9,1.8,Iris-virginica
+6.4,2.8,5.6,2.1,Iris-virginica
+7.2,3.0,5.8,1.6,Iris-virginica
+7.4,2.8,6.1,1.9,Iris-virginica
+7.9,3.8,6.4,2.0,Iris-virginica
+6.4,2.8,5.6,2.2,Iris-virginica
+6.3,2.8,5.1,1.5,Iris-virginica
+6.1,2.6,5.6,1.4,Iris-virginica
+7.7,3.0,6.1,2.3,Iris-virginica
+6.3,3.4,5.6,2.4,Iris-virginica
+6.4,3.1,5.5,1.8,Iris-virginica
+6.0,3.0,4.8,1.8,Iris-virginica
+6.9,3.1,5.4,2.1,Iris-virginica
+6.7,3.1,5.6,2.4,Iris-virginica
+6.9,3.1,5.1,2.3,Iris-virginica
+5.8,2.7,5.1,1.9,Iris-virginica
+6.8,3.2,5.9,2.3,Iris-virginica
+6.7,3.3,5.7,2.5,Iris-virginica
+6.7,3.0,5.2,2.3,Iris-virginica
+6.3,2.5,5.0,1.9,Iris-virginica
+6.5,3.0,5.2,2.0,Iris-virginica
+6.2,3.4,5.4,2.3,Iris-virginica
+5.9,3.0,5.1,1.8,Iris-virginica
+
diff --git a/examples/qml/regression/iris/qml/iris/iris.qml b/examples/qml/regression/iris/qml/iris/iris.qml
new file mode 100644 (file)
index 0000000..d7113c1
--- /dev/null
@@ -0,0 +1,94 @@
+import QtQuick 2.2
+import QtQuick.Controls 1.1
+import QtQuick.Layouts 1.1
+import QtJubatus 0.1 as Jubatus
+
+ApplicationWindow {
+    title: qsTr("Iris")
+    width: 300
+    height: 200
+
+    Jubatus.Regression {
+        id: regression
+        name: 'iris'
+        timeout: 10
+        property bool hasError: false
+        onError: {
+            console.debug(message)
+            hasError = true
+        }
+    }
+
+    Component.onCompleted: {
+        var request = new XMLHttpRequest
+        request.onreadystatechange = function() {
+            switch (request.readyState) {
+            case XMLHttpRequest.DONE:
+                var lines = request.responseText.split('\n')
+                for (var i in lines) {
+                    if (lines[i] === '') continue
+                    var columns = lines[i].split(',')
+                    var data = new Object
+                    data.petal_width = parseFloat(columns[2])
+                    data.class = columns[4]
+                    regression.train(data, parseFloat(columns[3]))
+                    patalLength.update()
+                }
+                break
+            }
+        }
+
+        request.open("GET", "./iris.data")
+        request.send()
+    }
+
+    menuBar: MenuBar {
+        Menu {
+            title: qsTr("File")
+            MenuItem {
+                text: qsTr("Exit")
+                onTriggered: Qt.quit();
+            }
+        }
+    }
+
+    GridLayout {
+        anchors.fill: parent
+        columns: 2
+        Label {
+            text: 'Petal Width:'
+        }
+        SpinBox {
+            id: petalWidth
+            Layout.fillWidth: true
+            decimals: 1
+            minimumValue: 0.0
+            maximumValue: 6.0
+            value: 2.0
+            onValueChanged: patalLength.update()
+        }
+        Label {
+            text: 'Class:'
+        }
+        ComboBox {
+            id: irisClass
+            Layout.fillWidth: true
+            model: ['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']
+            onCurrentIndexChanged: patalLength.update()
+        }
+        Label {
+            text: 'Petal Length:'
+        }
+        Label {
+            id: patalLength
+            Layout.fillWidth: true
+            function update() {
+                var data = new Object
+                data.petal_width = petalWidth.value
+                data.class = irisClass.currentText
+                var score = regression.estimate(data)
+                patalLength.text = score
+            }
+        }
+    }
+}
diff --git a/examples/qml/regression/iris/qtquick2controlsapplicationviewer/qtquick2controlsapplicationviewer.cpp b/examples/qml/regression/iris/qtquick2controlsapplicationviewer/qtquick2controlsapplicationviewer.cpp
new file mode 100644 (file)
index 0000000..8c453b2
--- /dev/null
@@ -0,0 +1,102 @@
+// checksum 0x7cc2 version 0x90001
+/*
+  This file was generated by the Qt Quick 2 Application wizard of Qt Creator.
+  QtQuick2ControlsApplicationViewer is a convenience class.
+  QML paths are handled here.
+  It is recommended not to modify this file, since newer versions of Qt Creator
+  may offer an updated version of it.
+*/
+#include "qtquick2controlsapplicationviewer.h"
+
+#include <QCoreApplication>
+#include <QDir>
+#include <QQmlComponent>
+#include <QQmlEngine>
+#include <QQuickView>
+
+class QtQuick2ApplicationViewerPrivate
+{
+    QString mainQmlFile;
+    QQmlEngine engine;
+    QQuickWindow *window;
+
+    QtQuick2ApplicationViewerPrivate() : window(0)
+    {}
+
+    ~QtQuick2ApplicationViewerPrivate()
+    {
+        delete window;
+    }
+
+    static QString adjustPath(const QString &path);
+
+    friend class QtQuick2ControlsApplicationViewer;
+};
+
+QString QtQuick2ApplicationViewerPrivate::adjustPath(const QString &path)
+{
+#if defined(Q_OS_MAC)
+    if (!QDir::isAbsolutePath(path))
+        return QStringLiteral("%1/../Resources/%2")
+                .arg(QCoreApplication::applicationDirPath(), path);
+#elif defined(Q_OS_BLACKBERRY)
+    if (!QDir::isAbsolutePath(path))
+        return QStringLiteral("app/native/%1").arg(path);
+#elif !defined(Q_OS_ANDROID)
+    QString pathInInstallDir =
+            QStringLiteral("%1/../%2").arg(QCoreApplication::applicationDirPath(), path);
+    if (QFileInfo(pathInInstallDir).exists())
+        return pathInInstallDir;
+    pathInInstallDir =
+            QStringLiteral("%1/%2").arg(QCoreApplication::applicationDirPath(), path);
+    if (QFileInfo(pathInInstallDir).exists())
+        return pathInInstallDir;
+#endif
+    return path;
+}
+
+QtQuick2ControlsApplicationViewer::QtQuick2ControlsApplicationViewer()
+    : d(new QtQuick2ApplicationViewerPrivate())
+{
+
+}
+
+QtQuick2ControlsApplicationViewer::~QtQuick2ControlsApplicationViewer()
+{
+    delete d;
+}
+
+void QtQuick2ControlsApplicationViewer::setMainQmlFile(const QString &file)
+{
+    d->mainQmlFile = QtQuick2ApplicationViewerPrivate::adjustPath(file);
+
+    QQmlComponent component(&d->engine);
+
+    QObject::connect(&d->engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));
+
+#ifdef Q_OS_ANDROID
+    component.loadUrl(QUrl(QStringLiteral("assets:/")+d->mainQmlFile));
+#else
+    component.loadUrl(QUrl::fromLocalFile(d->mainQmlFile));
+#endif
+
+    if (!component.isReady())
+        qWarning("%s", qPrintable(component.errorString()));
+
+    d->window = qobject_cast<QQuickWindow *>(component.create());
+    if (!d->window)
+        qFatal("Error: Your root item has to be a Window.");
+
+    d->engine.setIncubationController(d->window->incubationController());
+}
+
+void QtQuick2ControlsApplicationViewer::addImportPath(const QString &path)
+{
+    d->engine.addImportPath(QtQuick2ApplicationViewerPrivate::adjustPath(path));
+}
+
+void QtQuick2ControlsApplicationViewer::show()
+{
+    if (d->window)
+        d->window->show();
+}
diff --git a/examples/qml/regression/iris/qtquick2controlsapplicationviewer/qtquick2controlsapplicationviewer.h b/examples/qml/regression/iris/qtquick2controlsapplicationviewer/qtquick2controlsapplicationviewer.h
new file mode 100644 (file)
index 0000000..e585554
--- /dev/null
@@ -0,0 +1,42 @@
+// checksum 0xad2d version 0x90001
+/*
+  This file was generated by the Qt Quick 2 Application wizard of Qt Creator.
+  QtQuick2ControlsApplicationViewer is a convenience class.
+  QML paths are handled here.
+  It is recommended not to modify this file, since newer versions of Qt Creator
+  may offer an updated version of it.
+*/
+#ifndef QTQUICK2APPLICATIONVIEWER_H
+#define QTQUICK2APPLICATIONVIEWER_H
+
+#ifndef QT_NO_WIDGETS
+#include <QApplication>
+#else
+#include <QGuiApplication>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_WIDGETS
+#define Application QApplication
+#else
+#define Application QGuiApplication
+#endif
+
+QT_END_NAMESPACE
+
+class QtQuick2ControlsApplicationViewer
+{
+public:
+    explicit QtQuick2ControlsApplicationViewer();
+    virtual ~QtQuick2ControlsApplicationViewer();
+
+    void setMainQmlFile(const QString &file);
+    void addImportPath(const QString &path);
+    void show();
+
+private:
+    class QtQuick2ApplicationViewerPrivate *d;
+};
+
+#endif // QTQUICK2APPLICATIONVIEWER_H
diff --git a/examples/qml/regression/iris/qtquick2controlsapplicationviewer/qtquick2controlsapplicationviewer.pri b/examples/qml/regression/iris/qtquick2controlsapplicationviewer/qtquick2controlsapplicationviewer.pri
new file mode 100644 (file)
index 0000000..784d7fb
--- /dev/null
@@ -0,0 +1,202 @@
+# checksum 0x84e4 version 0x90001
+# This file was generated by the Qt Quick 2 Controls Application wizard of Qt Creator.
+# The code below adds the QtQuick2ApplicationViewer to the project and handles
+# the activation of QML debugging.
+# It is recommended not to modify this file, since newer versions of Qt Creator
+# may offer an updated version of it.
+
+QT += qml quick widgets
+
+SOURCES += $$PWD/qtquick2controlsapplicationviewer.cpp
+HEADERS += $$PWD/qtquick2controlsapplicationviewer.h
+INCLUDEPATH += $$PWD
+# This file was generated by an application wizard of Qt Creator.
+# The code below handles deployment to Android and Maemo, aswell as copying
+# of the application data to shadow build directories on desktop.
+# It is recommended not to modify this file, since newer versions of Qt Creator
+# may offer an updated version of it.
+
+defineTest(qtcAddDeployment) {
+for(deploymentfolder, DEPLOYMENTFOLDERS) {
+    item = item$${deploymentfolder}
+    greaterThan(QT_MAJOR_VERSION, 4) {
+        itemsources = $${item}.files
+    } else {
+        itemsources = $${item}.sources
+    }
+    $$itemsources = $$eval($${deploymentfolder}.source)
+    itempath = $${item}.path
+    $$itempath= $$eval($${deploymentfolder}.target)
+    export($$itemsources)
+    export($$itempath)
+    DEPLOYMENT += $$item
+}
+
+MAINPROFILEPWD = $$PWD
+
+android-no-sdk {
+    for(deploymentfolder, DEPLOYMENTFOLDERS) {
+        item = item$${deploymentfolder}
+        itemfiles = $${item}.files
+        $$itemfiles = $$eval($${deploymentfolder}.source)
+        itempath = $${item}.path
+        $$itempath = /data/user/qt/$$eval($${deploymentfolder}.target)
+        export($$itemfiles)
+        export($$itempath)
+        INSTALLS += $$item
+    }
+
+    target.path = /data/user/qt
+
+    export(target.path)
+    INSTALLS += target
+} else:android {
+    for(deploymentfolder, DEPLOYMENTFOLDERS) {
+        item = item$${deploymentfolder}
+        itemfiles = $${item}.files
+        $$itemfiles = $$eval($${deploymentfolder}.source)
+        itempath = $${item}.path
+        $$itempath = /assets/$$eval($${deploymentfolder}.target)
+        export($$itemfiles)
+        export($$itempath)
+        INSTALLS += $$item
+    }
+
+    x86 {
+        target.path = /libs/x86
+    } else: armeabi-v7a {
+        target.path = /libs/armeabi-v7a
+    } else {
+        target.path = /libs/armeabi
+    }
+
+    export(target.path)
+    INSTALLS += target
+} else:win32 {
+    copyCommand =
+    for(deploymentfolder, DEPLOYMENTFOLDERS) {
+        source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
+        source = $$replace(source, /, \\)
+        sourcePathSegments = $$split(source, \\)
+        target = $$OUT_PWD/$$eval($${deploymentfolder}.target)/$$last(sourcePathSegments)
+        target = $$replace(target, /, \\)
+        target ~= s,\\\\\\.?\\\\,\\,
+        !isEqual(source,$$target) {
+            !isEmpty(copyCommand):copyCommand += &&
+            isEqual(QMAKE_DIR_SEP, \\) {
+                copyCommand += $(COPY_DIR) \"$$source\" \"$$target\"
+            } else {
+                source = $$replace(source, \\\\, /)
+                target = $$OUT_PWD/$$eval($${deploymentfolder}.target)
+                target = $$replace(target, \\\\, /)
+                copyCommand += test -d \"$$target\" || mkdir -p \"$$target\" && cp -r \"$$source\" \"$$target\"
+            }
+        }
+    }
+    !isEmpty(copyCommand) {
+        copyCommand = @echo Copying application data... && $$copyCommand
+        copydeploymentfolders.commands = $$copyCommand
+        first.depends = $(first) copydeploymentfolders
+        export(first.depends)
+        export(copydeploymentfolders.commands)
+        QMAKE_EXTRA_TARGETS += first copydeploymentfolders
+    }
+} else:ios {
+    copyCommand =
+    for(deploymentfolder, DEPLOYMENTFOLDERS) {
+        source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
+        source = $$replace(source, \\\\, /)
+        target = $CODESIGNING_FOLDER_PATH/$$eval($${deploymentfolder}.target)
+        target = $$replace(target, \\\\, /)
+        sourcePathSegments = $$split(source, /)
+        targetFullPath = $$target/$$last(sourcePathSegments)
+        targetFullPath ~= s,/\\.?/,/,
+        !isEqual(source,$$targetFullPath) {
+            !isEmpty(copyCommand):copyCommand += &&
+            copyCommand += mkdir -p \"$$target\"
+            copyCommand += && cp -r \"$$source\" \"$$target\"
+        }
+    }
+    !isEmpty(copyCommand) {
+        copyCommand = echo Copying application data... && $$copyCommand
+        !isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK += ";"
+        QMAKE_POST_LINK += "$$copyCommand"
+        export(QMAKE_POST_LINK)
+    }
+} else:unix {
+    maemo5 {
+        desktopfile.files = $${TARGET}.desktop
+        desktopfile.path = /usr/share/applications/hildon
+        icon.files = $${TARGET}64.png
+        icon.path = /usr/share/icons/hicolor/64x64/apps
+    } else:!isEmpty(MEEGO_VERSION_MAJOR) {
+        desktopfile.files = $${TARGET}_harmattan.desktop
+        desktopfile.path = /usr/share/applications
+        icon.files = $${TARGET}80.png
+        icon.path = /usr/share/icons/hicolor/80x80/apps
+    } else { # Assumed to be a Desktop Unix
+        copyCommand =
+        for(deploymentfolder, DEPLOYMENTFOLDERS) {
+            source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source)
+            source = $$replace(source, \\\\, /)
+            macx {
+                target = $$OUT_PWD/$${TARGET}.app/Contents/Resources/$$eval($${deploymentfolder}.target)
+            } else {
+                target = $$OUT_PWD/$$eval($${deploymentfolder}.target)
+            }
+            target = $$replace(target, \\\\, /)
+            sourcePathSegments = $$split(source, /)
+            targetFullPath = $$target/$$last(sourcePathSegments)
+            targetFullPath ~= s,/\\.?/,/,
+            !isEqual(source,$$targetFullPath) {
+                !isEmpty(copyCommand):copyCommand += &&
+                copyCommand += $(MKDIR) \"$$target\"
+                copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\"
+            }
+        }
+        !isEmpty(copyCommand) {
+            copyCommand = @echo Copying application data... && $$copyCommand
+            copydeploymentfolders.commands = $$copyCommand
+            first.depends = $(first) copydeploymentfolders
+            export(first.depends)
+            export(copydeploymentfolders.commands)
+            QMAKE_EXTRA_TARGETS += first copydeploymentfolders
+        }
+    }
+    !isEmpty(target.path) {
+        installPrefix = $${target.path}
+    } else {
+        installPrefix = /opt/$${TARGET}
+    }
+    for(deploymentfolder, DEPLOYMENTFOLDERS) {
+        item = item$${deploymentfolder}
+        itemfiles = $${item}.files
+        $$itemfiles = $$eval($${deploymentfolder}.source)
+        itempath = $${item}.path
+        $$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target)
+        export($$itemfiles)
+        export($$itempath)
+        INSTALLS += $$item
+    }
+
+    !isEmpty(desktopfile.path) {
+        export(icon.files)
+        export(icon.path)
+        export(desktopfile.files)
+        export(desktopfile.path)
+        INSTALLS += icon desktopfile
+    }
+
+    isEmpty(target.path) {
+        target.path = $${installPrefix}/bin
+        export(target.path)
+    }
+    INSTALLS += target
+}
+
+export (ICON)
+export (INSTALLS)
+export (DEPLOYMENT)
+export (LIBS)
+export (QMAKE_EXTRA_TARGETS)
+}
diff --git a/examples/qml/regression/regression.pro b/examples/qml/regression/regression.pro
new file mode 100644 (file)
index 0000000..a204c27
--- /dev/null
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS += iris
+
index 4142ce5..46b17c4 100644 (file)
@@ -7,7 +7,8 @@ CONFIG += exceptions
 
 SOURCES += main.cpp \
     qmljubatusclassifier.cpp \
-    qmljubatusrecommender.cpp
+    qmljubatusrecommender.cpp \
+    qmljubatusregression.cpp
 
 load(qml_plugin)
 
@@ -15,4 +16,5 @@ OTHER_FILES = plugins.qmltypes qmldir
 
 HEADERS += \
     qmljubatusclassifier.h \
-    qmljubatusrecommender.h
+    qmljubatusrecommender.h \
+    qmljubatusregression.h
index 688df7c..f02e288 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "qmljubatusclassifier.h"
 #include "qmljubatusrecommender.h"
+#include "qmljubatusregression.h"
 
 class QmlJubatusPlugin : public QQmlExtensionPlugin
 {
@@ -42,6 +43,7 @@ public:
         // @uri QtJubatus
         qmlRegisterType<QmlJubatusClassifier>(uri, 0, 1, "Classifier");
         qmlRegisterType<QmlJubatusRecommender>(uri, 0, 1, "Recommender");
+        qmlRegisterType<QmlJubatusRegression>(uri, 0, 1, "Regression");
     }
 };
 
diff --git a/src/imports/jubatus/qmljubatusregression.cpp b/src/imports/jubatus/qmljubatusregression.cpp
new file mode 100644 (file)
index 0000000..9c0f44e
--- /dev/null
@@ -0,0 +1,23 @@
+#include "qmljubatusregression.h"
+
+QmlJubatusRegression::QmlJubatusRegression(QObject *parent) :
+    QJubatusRegression(parent)
+{
+}
+bool QmlJubatusRegression::train(const QVariantMap &data, float score)
+{
+    QJubatusRegression::ScoredDatum datum;
+    datum.data = data;
+    datum.score = score;
+    return QJubatusRegression::train(QList<ScoredDatum>() << datum) == 1;
+}
+
+float QmlJubatusRegression::estimate(const QVariantMap &data)
+{
+    float ret = 0.0;
+    QList<float> results = QJubatusRegression::estimate(QList<QVariantMap>() << data);
+    if (!results.isEmpty()) {
+        ret = results.first();
+    }
+    return ret;
+}
diff --git a/src/imports/jubatus/qmljubatusregression.h b/src/imports/jubatus/qmljubatusregression.h
new file mode 100644 (file)
index 0000000..f67b4e8
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef QMLJUBATUSREGRESSION_H
+#define QMLJUBATUSREGRESSION_H
+
+#include <QtJubatus/QJubatusRegression>
+
+class QmlJubatusRegression : public QJubatusRegression
+{
+    Q_OBJECT
+public:
+    explicit QmlJubatusRegression(QObject *parent = 0);
+
+    Q_INVOKABLE bool train(const QVariantMap &data, float score);
+    Q_INVOKABLE float estimate(const QVariantMap &data);
+};
+
+#endif // QMLJUBATUSREGRESSION_H
index eb069da..2cb63ce 100644 (file)
@@ -97,9 +97,11 @@ private:
 
 #define EXEC_JUBATUS_COMMAND(COMMAND) \
     try { \
+        bool done = false; \
         for (int i = 0; i < 3; i++) { \
             try { \
                 COMMAND; \
+                done = true; \
                 break; \
             } catch (msgpack::rpc::connection_closed_error &e) { \
                 client()->get_client().close(); \
@@ -110,6 +112,9 @@ private:
             } \
             ::sleep(1); \
         } \
+        if (!done) { \
+            COMMAND; \
+        } \
     } catch(msgpack::rpc::rpc_error &e) { \
         emit error(QString::fromUtf8(e.what())); \
     }
index ebf0d0a..188ae60 100644 (file)
@@ -17,3 +17,4 @@ include(./client/client.pri)
 include(./anomaly/anomaly.pri)
 include(./classifier/classifier.pri)
 include(./recommender/recommender.pri)
+include(./regression/regression.pri)
diff --git a/src/jubatus/regression/qjubatusregression.cpp b/src/jubatus/regression/qjubatusregression.cpp
new file mode 100644 (file)
index 0000000..111be24
--- /dev/null
@@ -0,0 +1,80 @@
+/* Copyright (c) 2012 Silk Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Silk nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL SILK BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qjubatusregression.h"
+
+#include <QtCore/QDebug>
+
+#include <jubatus/client/regression_client.hpp>
+
+QJubatusRegression::QJubatusRegression(QObject *parent)
+    : QJubatusClient(parent)
+{
+}
+
+int QJubatusRegression::train(const QList<ScoredDatum> &data)
+{
+    int ret = 0;
+    EXEC_JUBATUS_COMMAND( ret = client()->train(convert(data)); )
+    return ret;
+}
+
+QList<float> QJubatusRegression::estimate(const QList<QVariantMap> &data)
+{
+    QList<float> ret;
+    EXEC_JUBATUS_COMMAND( ret = convert(client()->estimate(convert(data))); )
+    return ret;
+}
+
+jubatus::regression::scored_datum QJubatusRegression::convert(const QJubatusRegression::ScoredDatum &data) const
+{
+    jubatus::regression::scored_datum ret;
+    ret.score = data.score;
+    ret.data = convert(data.data);
+    return ret;
+}
+
+std::vector<jubatus::regression::scored_datum> QJubatusRegression::convert(const QList<QJubatusRegression::ScoredDatum> &data) const
+{
+    std::vector<jubatus::regression::scored_datum> ret;
+    foreach (const QJubatusRegression::ScoredDatum &datum, data) {
+        ret.push_back(convert(datum));
+    }
+    return ret;
+}
+
+QList<float> QJubatusRegression::convert(const std::vector<float> &data) const
+{
+    QList<float> ret;
+    for (auto it = data.begin(); it != data.end(); ++it) {
+        ret.append(*it);
+    }
+    return ret;
+}
+
+jubatus::regression::client::regression *QJubatusRegression::client() {
+    return QJubatusClient::client<jubatus::regression::client::regression>();
+}
diff --git a/src/jubatus/regression/qjubatusregression.h b/src/jubatus/regression/qjubatusregression.h
new file mode 100644 (file)
index 0000000..7dcbe26
--- /dev/null
@@ -0,0 +1,68 @@
+/* Copyright (c) 2012 Silk Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Silk nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL SILK BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef QJUBATUSREGRESSION_H
+#define QJUBATUSREGRESSION_H
+
+#include "jubatus_global.h"
+#include "qjubatusclient.h"
+
+#include <QtCore/QVariant>
+
+namespace jubatus {
+    namespace regression {
+        struct scored_datum;
+        namespace client {
+            class regression;
+        }
+    }
+}
+
+class JUBATUS_EXPORT QJubatusRegression : public QJubatusClient
+{
+    Q_OBJECT
+public:
+    explicit QJubatusRegression(QObject *parent = 0);
+
+    struct ScoredDatum {
+        float score;
+        QVariantMap data;
+    };
+
+    Q_INVOKABLE int train(const QList<ScoredDatum> &data);
+    Q_INVOKABLE QList<float> estimate(const QList<QVariantMap> &data);
+
+protected:
+    using QJubatusClient::convert;
+    jubatus::regression::scored_datum convert(const ScoredDatum &data) const;
+    std::vector<jubatus::regression::scored_datum> convert(const QList<ScoredDatum> &data) const;
+    QList<float> convert(const std::vector<float> &data) const;
+
+private:
+    jubatus::regression::client::regression *client();
+};
+
+#endif // QJUBATUSREGRESSION_H
diff --git a/src/jubatus/regression/regression.pri b/src/jubatus/regression/regression.pri
new file mode 100644 (file)
index 0000000..b80e341
--- /dev/null
@@ -0,0 +1,6 @@
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+PUBLIC_HEADERS += $$PWD/qjubatusregression.h
+HEADERS += $$PUBLIC_HEADERS
+SOURCES += $$PWD/qjubatusregression.cpp