summaryrefslogtreecommitdiffstats
path: root/nlpsolver/src/com/sun/star/comp/Calc/NLPSolver/BaseNLPSolver.java
diff options
context:
space:
mode:
Diffstat (limited to 'nlpsolver/src/com/sun/star/comp/Calc/NLPSolver/BaseNLPSolver.java')
-rw-r--r--nlpsolver/src/com/sun/star/comp/Calc/NLPSolver/BaseNLPSolver.java551
1 files changed, 551 insertions, 0 deletions
diff --git a/nlpsolver/src/com/sun/star/comp/Calc/NLPSolver/BaseNLPSolver.java b/nlpsolver/src/com/sun/star/comp/Calc/NLPSolver/BaseNLPSolver.java
new file mode 100644
index 000000000..d425e2a4c
--- /dev/null
+++ b/nlpsolver/src/com/sun/star/comp/Calc/NLPSolver/BaseNLPSolver.java
@@ -0,0 +1,551 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2009 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package com.sun.star.comp.Calc.NLPSolver;
+
+import com.sun.star.awt.XReschedule;
+import com.sun.star.beans.Property;
+import com.sun.star.beans.PropertyVetoException;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.XPropertyChangeListener;
+import com.sun.star.beans.XPropertySetInfo;
+import com.sun.star.beans.XVetoableChangeListener;
+import com.sun.star.chart.XChartDataArray;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.document.XEmbeddedObjectSupplier;
+import com.sun.star.frame.XModel;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.IndexOutOfBoundsException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.lang.XMultiComponentFactory;
+import com.sun.star.lib.uno.helper.WeakBase;
+import com.sun.star.sheet.SolverConstraint;
+import com.sun.star.sheet.SolverConstraintOperator;
+import com.sun.star.sheet.XSpreadsheet;
+import com.sun.star.sheet.XSpreadsheetDocument;
+import com.sun.star.sheet.XSpreadsheets;
+import com.sun.star.table.CellAddress;
+import com.sun.star.table.CellContentType;
+import com.sun.star.table.CellRangeAddress;
+import com.sun.star.table.XCell;
+import com.sun.star.table.XTableChartsSupplier;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public abstract class BaseNLPSolver extends WeakBase
+ implements com.sun.star.lang.XLocalizable,
+ com.sun.star.sheet.XSolver,
+ com.sun.star.sheet.XSolverDescription,
+ com.sun.star.beans.XPropertySet,
+ com.sun.star.beans.XPropertySetInfo
+{
+
+ protected final XComponentContext m_xContext;
+ private final String m_name;
+
+ private final ArrayList<PropertyInfo> m_properties = new ArrayList<PropertyInfo>();
+ private final HashMap<String, PropertyInfo> m_propertyMap = new HashMap<String, PropertyInfo>();
+
+ private com.sun.star.lang.Locale m_locale = new com.sun.star.lang.Locale();
+ private final ResourceManager resourceManager;
+
+ private CellAddress m_objective;
+ protected CellAddress[] m_variables;
+ protected SolverConstraint[] m_constraints;
+
+ public BaseNLPSolver(XComponentContext xContext, String name) {
+ m_xContext = xContext;
+ m_name = name;
+ // init members exposed as XSolver properties through uno bridge
+ m_objective = new CellAddress();
+ m_variables = new CellAddress[0];
+ m_constraints = new SolverConstraint[0];
+
+ XMultiComponentFactory componentFactory = xContext.getServiceManager();
+ try {
+ Object toolkit = componentFactory.createInstanceWithContext("com.sun.star.awt.Toolkit", xContext);
+ m_xReschedule = UnoRuntime.queryInterface(XReschedule.class, toolkit);
+ } catch (Exception ex) {
+ Logger.getLogger(BaseNLPSolver.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ resourceManager = new ResourceManager(xContext, "com.sun.star.comp.Calc.NLPSolver", "/locale", "NLPSolverCommon");
+
+ registerProperty(m_assumeNonNegative);
+ }
+
+ protected void registerProperty(PropertyInfo property) {
+ m_properties.add(property);
+ m_propertyMap.put(property.getProperty().Name, property);
+ property.localize(resourceManager);
+ }
+
+ // com.sun.star.lang.XLocalizable:
+ public void setLocale(com.sun.star.lang.Locale eLocale)
+ {
+ m_locale = eLocale;
+ }
+
+ public com.sun.star.lang.Locale getLocale()
+ {
+ return m_locale;
+ }
+
+ // com.sun.star.sheet.XSolver:
+
+ private XSpreadsheetDocument m_document;
+ private XModel m_xModel;
+ protected XReschedule m_xReschedule;
+ protected ExtSolverConstraint[] m_extConstraints;
+ protected boolean m_maximize;
+
+ protected int m_variableCount;
+ protected int m_constraintCount;
+ protected int m_cellRangeCount;
+ protected XCell m_objectiveCell;
+ protected XCell[] m_variableCells;
+ protected XChartDataArray[] m_cellRangeData;
+ protected CellMap[] m_variableMap;
+ protected double[][][] m_variableData;
+
+ protected double m_functionValue;
+ protected double[] m_currentParameters;
+ protected boolean m_success = false;
+
+ public XSpreadsheetDocument getDocument() {
+ return m_document;
+ }
+
+ public void setDocument(XSpreadsheetDocument document) {
+ m_document = document;
+ m_xModel = UnoRuntime.queryInterface(XModel.class, m_document);
+ }
+
+ public CellAddress getObjective() {
+ return m_objective;
+ }
+
+ public void setObjective(CellAddress objective) {
+ m_objective = objective;
+ m_objectiveCell = getCell(objective);
+ }
+
+ public CellAddress[] getVariables() {
+ return m_variables;
+ }
+
+ private static class RowInfo {
+ private short Sheet;
+ private int Row;
+ private int StartCol;
+ private int EndCol;
+
+ private RowInfo(short sheet, int row) {
+ Sheet = sheet;
+ Row = row;
+ }
+
+ private CellRangeAddress getCellRangeAddress(int lastRow) {
+ CellRangeAddress result = new CellRangeAddress();
+ result.Sheet = Sheet;
+ result.StartColumn = StartCol;
+ result.StartRow = Row;
+ result.EndColumn = EndCol;
+ result.EndRow = lastRow;
+ return result;
+ }
+ }
+
+ protected static class CellMap {
+ protected int Range;
+ protected int Col;
+ protected int Row;
+ }
+
+ protected class ExtSolverConstraint {
+
+ public XCell Left;
+ public SolverConstraintOperator Operator;
+ public XCell Right;
+ public double Data;
+
+ private ExtSolverConstraint(XCell left, SolverConstraintOperator operator, Object right) {
+ this.Left = left;
+ this.Operator = operator;
+ this.Right = null;
+ if (right instanceof Number) {
+ this.Data = ((Number)right).doubleValue();
+ } else if (right instanceof CellAddress) {
+ XCell cell = getCell((CellAddress)right);
+ if (cell.getType() == CellContentType.VALUE) {
+ this.Data = cell.getValue();
+ } else {
+ this.Right = cell;
+ this.Data = 0.0;
+ }
+ }
+ }
+
+ public double getLeftValue() {
+ if (this.Right == null) {
+ return this.Left.getValue();
+ } else {
+ return this.Left.getValue() - this.Right.getValue();
+ }
+ }
+
+ }
+
+ public void setVariables(CellAddress[] variables) {
+ m_variables = variables;
+ m_variableCount = variables.length;
+
+ //update cell references
+ m_variableCells = new XCell[m_variableCount];
+ m_currentParameters = new double[m_variableCount];
+ for (int i = 0; i < m_variableCount; i++) {
+ m_variableCells[i] = getCell(variables[i]);
+ m_currentParameters[i] = m_variableCells[i].getValue();
+ }
+
+ //parse for cell ranges (under the assumption, that the cells are ordered
+ //left to right, top to bottom for each cell range
+ m_variableMap = new CellMap[m_variableCount];
+ m_variableData = new double[m_variableCount][][];
+
+ ArrayList<RowInfo> rows = new ArrayList<RowInfo>();
+ RowInfo currentRow = null;
+ int lastSheet = -1, lastRow = -1;
+ for (int i = 0; i < m_variableCount; i++) {
+ boolean match = lastSheet == m_variables[i].Sheet &&
+ lastRow == m_variables[i].Row;
+ assert !match || currentRow != null;
+ if (match && currentRow.EndCol == m_variables[i].Column - 1)
+ currentRow.EndCol++;
+ else {
+ currentRow = new RowInfo(m_variables[i].Sheet, m_variables[i].Row);
+ currentRow.StartCol = m_variables[i].Column;
+ currentRow.EndCol = m_variables[i].Column;
+ rows.add(currentRow);
+ lastSheet = currentRow.Sheet;
+ lastRow = currentRow.Row;
+ }
+ }
+
+ ArrayList<CellRangeAddress> cellRangeAddresses = new ArrayList<CellRangeAddress>();
+ if (rows.size() > 0) {
+ RowInfo firstRow = rows.get(0);
+ int offset = 0;
+ for (int i = 1; i < rows.size(); i++) {
+ currentRow = rows.get(i);
+ if (currentRow.Sheet != firstRow.Sheet ||
+ currentRow.Row != firstRow.Row + offset + 1 ||
+ currentRow.StartCol != firstRow.StartCol ||
+ currentRow.EndCol != firstRow.EndCol) {
+ cellRangeAddresses.add(firstRow.getCellRangeAddress(firstRow.Row + offset));
+ firstRow = currentRow;
+ offset = 0;
+ } else {
+ offset++;
+ }
+ }
+ cellRangeAddresses.add(firstRow.getCellRangeAddress(firstRow.Row + offset));
+ }
+
+ m_cellRangeCount = cellRangeAddresses.size();
+ m_cellRangeData = new XChartDataArray[m_cellRangeCount];
+ int varID = 0;
+ //get cell range data and map the variables to their new location
+ for (int i = 0; i < m_cellRangeCount; i++) {
+ for (int y = 0; y <= cellRangeAddresses.get(i).EndRow - cellRangeAddresses.get(i).StartRow; y++)
+ for (int x = 0; x <= cellRangeAddresses.get(i).EndColumn - cellRangeAddresses.get(i).StartColumn; x++) {
+ CellMap map = new CellMap();
+ m_variableMap[varID++] = map;
+ map.Range = i;
+ map.Col = x;
+ map.Row = y;
+ }
+ m_cellRangeData[i] = getChartDataArray(cellRangeAddresses.get(i));
+ m_variableData[i] = m_cellRangeData[i].getData();
+ }
+ }
+
+ public SolverConstraint[] getConstraints() {
+ return m_constraints;
+ }
+
+ public void setConstraints(SolverConstraint[] constraints) {
+ m_constraints = constraints;
+ m_constraintCount = constraints.length;
+
+ //update cell references
+ m_extConstraints = new ExtSolverConstraint[m_constraintCount];
+ for (int i = 0; i < m_constraintCount; i++) {
+ m_extConstraints[i] = new ExtSolverConstraint(
+ getCell(constraints[i].Left),
+ constraints[i].Operator,
+ constraints[i].Right);
+ }
+ }
+
+ public boolean getMaximize() {
+ return m_maximize;
+ }
+
+ public void setMaximize(boolean maximize) {
+ m_maximize = maximize;
+ }
+
+ public boolean getSuccess() {
+ return m_success;
+ }
+
+ public double getResultValue() {
+ return m_functionValue;
+ }
+
+ public double[] getSolution() {
+ return m_currentParameters;
+ }
+
+ private XCell getCell(CellAddress cellAddress) {
+ return getCell(cellAddress.Column, cellAddress.Row, cellAddress.Sheet);
+ }
+
+ private XCell getCell(int col, int row, int sheet) {
+ try {
+ XSpreadsheets xSpreadsheets = m_document.getSheets();
+ XIndexAccess xSheetIndex = UnoRuntime.queryInterface(XIndexAccess.class, xSpreadsheets);
+ XSpreadsheet xSpreadsheet = UnoRuntime.queryInterface(XSpreadsheet.class, xSheetIndex.getByIndex(sheet));
+ return xSpreadsheet.getCellByPosition(col, row);
+ } catch (IndexOutOfBoundsException ex) {
+ Logger.getLogger(BaseNLPSolver.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (WrappedTargetException ex) {
+ Logger.getLogger(BaseNLPSolver.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ return null;
+ }
+
+
+
+ private XChartDataArray getChartDataArray(CellRangeAddress cellRangeAddress) {
+ return getChartDataArray(cellRangeAddress.Sheet, cellRangeAddress.StartColumn,
+ cellRangeAddress.StartRow, cellRangeAddress.EndColumn, cellRangeAddress.EndRow);
+ }
+
+ private XChartDataArray getChartDataArray(int sheet, int startCol, int startRow, int endCol, int endRow) {
+ try {
+ XSpreadsheets xSpreadsheets = m_document.getSheets();
+ XIndexAccess xSheetIndex = UnoRuntime.queryInterface(XIndexAccess.class, xSpreadsheets);
+ XSpreadsheet xSpreadsheet = UnoRuntime.queryInterface(XSpreadsheet.class, xSheetIndex.getByIndex(sheet));
+ return UnoRuntime.queryInterface(XChartDataArray.class, xSpreadsheet.getCellRangeByPosition(startCol, startRow, endCol, endRow));
+ } catch (IndexOutOfBoundsException ex) {
+ Logger.getLogger(BaseNLPSolver.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (WrappedTargetException ex) {
+ Logger.getLogger(BaseNLPSolver.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ return null;
+ }
+
+ protected PropertyInfo<Boolean> m_assumeNonNegative = new PropertyInfo<Boolean>("AssumeNonNegative", false, "Assume Non-Negative Variables");
+
+ protected void initializeSolve() {
+ lockDocument();
+ }
+
+ protected void finalizeSolve() {
+ unlockDocument();
+ }
+
+ public String getComponentDescription() {
+ return m_name;
+ }
+
+ public String getStatusDescription() {
+ return "";
+ }
+
+ public String getPropertyDescription(String property) {
+ PropertyInfo propertyInfo = m_propertyMap.get(property);
+ if (propertyInfo != null)
+ return propertyInfo.getDescription();
+ else
+ return "";
+ }
+
+ // com.sun.star.beans.XPropertySet:
+
+ public XPropertySetInfo getPropertySetInfo() {
+ return this;
+ }
+
+ public void setPropertyValue(String property, Object value) throws UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException {
+ PropertyInfo propertyInfo = m_propertyMap.get(property);
+ if (propertyInfo != null)
+ propertyInfo.setValue(value);
+ else
+ throw new UnknownPropertyException();
+ }
+
+ public Object getPropertyValue(String property) throws UnknownPropertyException, WrappedTargetException {
+ PropertyInfo propertyInfo = m_propertyMap.get(property);
+ if (propertyInfo != null)
+ return propertyInfo.getValue();
+ else
+ throw new UnknownPropertyException();
+ }
+
+ public void addPropertyChangeListener(String property, XPropertyChangeListener listener) throws UnknownPropertyException, WrappedTargetException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void removePropertyChangeListener(String property, XPropertyChangeListener listener) throws UnknownPropertyException, WrappedTargetException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void addVetoableChangeListener(String property, XVetoableChangeListener listener) throws UnknownPropertyException, WrappedTargetException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public void removeVetoableChangeListener(String property, XVetoableChangeListener listener) throws UnknownPropertyException, WrappedTargetException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ // com.sun.star.beans.XPropertySetInfo:
+
+ public Property[] getProperties() {
+ int propertyCount = m_properties.size();
+ Property[] properties = new Property[propertyCount];
+ for (int i = 0; i < propertyCount; i++)
+ properties[i] = m_properties.get(i).getProperty();
+ return properties;
+ }
+
+ public Property getPropertyByName(String property) throws UnknownPropertyException {
+ PropertyInfo propertyInfo = m_propertyMap.get(property);
+ if (propertyInfo != null)
+ return propertyInfo.getProperty();
+ else
+ throw new UnknownPropertyException();
+ }
+
+ public boolean hasPropertyByName(String property) {
+ return m_propertyMap.containsKey(property);
+ }
+
+ // Helper functions
+ private void lockDocument(boolean lock) {
+ if (lock)
+ m_xModel.lockControllers();
+ else
+ m_xModel.unlockControllers();
+
+ try {
+ XIndexAccess xSpreadsheets = UnoRuntime.queryInterface(XIndexAccess.class, m_document.getSheets());
+ int sheets = xSpreadsheets.getCount();
+ for (int i = 0; i < sheets; i++) {
+ Object sheet = xSpreadsheets.getByIndex(i);
+ XTableChartsSupplier xTableChartsSupplier = UnoRuntime.queryInterface(XTableChartsSupplier.class, sheet);
+ XIndexAccess xCharts = UnoRuntime.queryInterface(XIndexAccess.class, xTableChartsSupplier.getCharts());
+ int charts = xCharts.getCount();
+ for (int j = 0; j < charts; j++) {
+ Object chart = xCharts.getByIndex(j);
+ XEmbeddedObjectSupplier xChartObjects = UnoRuntime.queryInterface(XEmbeddedObjectSupplier.class, chart);
+ XModel xChartModel = UnoRuntime.queryInterface(XModel.class, xChartObjects.getEmbeddedObject());
+ if (lock)
+ xChartModel.lockControllers();
+ else
+ xChartModel.unlockControllers();
+ }
+ }
+ } catch (Exception ex) {
+ Logger.getLogger(BaseNLPSolver.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ protected void lockDocument() {
+ lockDocument(true);
+ }
+
+ protected void unlockDocument() {
+ lockDocument(false);
+ }
+
+ public static String nanoTimeToString(ResourceManager resourceManager, long nanoseconds) {
+ if (nanoseconds < 0) return null; // shouldn't happen... but if it does, throw an error!
+
+ if (nanoseconds == 0) return "0";
+
+ if (nanoseconds < 1000)
+ return nanoseconds + " " + resourceManager.getLocalizedString("Time.Nanoseconds", "Nanoseconds");
+
+ double microseconds = (double) nanoseconds / 1000;
+ if (microseconds < 1000)
+ return String.format("%.2f %s", microseconds, resourceManager.getLocalizedString("Time.Microseconds", "Microseconds"));
+
+ double milliseconds = microseconds / 1000;
+ if (milliseconds < 1000)
+ return String.format("%.2f %s", milliseconds, resourceManager.getLocalizedString("Time.Milliseconds", "Milliseconds"));
+
+ double seconds = milliseconds / 1000;
+ if (seconds < 90)
+ return String.format("%.2f %s", seconds, resourceManager.getLocalizedString("Time.Seconds", "Seconds"));
+
+ long minutes = (long) seconds / 60;
+ seconds -= minutes * 60;
+ long hours = minutes / 60;
+ minutes -= hours * 60;
+ long days = hours / 24;
+ hours -= days * 24;
+
+ if (days > 0)
+ return String.format("%d %s, %d %s",
+ days, resourceManager.getLocalizedString(String.format("Time.Day%s", days == 1 ? "" : "s"), "Days"),
+ hours, resourceManager.getLocalizedString(String.format("Time.Hour%s", hours == 1 ? "" : "s"), "Hours"));
+
+ if (hours > 0)
+ return String.format("%d %s, %d %s",
+ hours, resourceManager.getLocalizedString(String.format("Time.Hour%s", hours == 1 ? "" : "s"), "Hours"),
+ minutes, resourceManager.getLocalizedString(String.format("Time.Minute%s", minutes == 1 ? "" : "s"), "Minutes"));
+
+ if (minutes > 0)
+ return String.format("%d %s, %.0f %s",
+ minutes, resourceManager.getLocalizedString(String.format("Time.Minute%s", minutes == 1 ? "" : "s"), "Minutes"),
+ Math.floor(seconds), resourceManager.getLocalizedString(String.format("Time.Second%s", Math.floor(seconds) == 1 ? "" : "s"), "Seconds"));
+
+ return String.format("%.2f %s", seconds, resourceManager.getLocalizedString("Time.Seconds", "Seconds"));
+ }
+ // </editor-fold>
+
+}