package no.birkett.kiwi; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * Created by alex on 30/01/15. */ public class Row { private double constant; private Map cells = new HashMap(); public Row() { this(0); } public Row(double constant) { this.constant = constant; } public Row(Row other) { this.cells = other.cells; this.constant = other.constant; } public double getConstant() { return constant; } public void setConstant(double constant) { this.constant = constant; } public Map getCells() { return cells; } public void setCells(Map cells) { this.cells = cells; } /** * Add a constant value to the row constant. * * @return The new value of the constant */ double add(double value) { return this.constant += value; } /** * Insert a symbol into the row with a given coefficient. *

* If the symbol already exists in the row, the coefficient will be * added to the existing coefficient. If the resulting coefficient * is zero, the symbol will be removed from the row */ void insert(Symbol symbol, double coefficient) { Double existingCoefficient = cells.get(symbol); if (existingCoefficient != null) { coefficient = existingCoefficient; } if (Util.nearZero(coefficient)) { cells.remove(symbol); } else { cells.put(symbol, Double.valueOf(coefficient)); } } /** * Insert a symbol into the row with a given coefficient. *

* If the symbol already exists in the row, the coefficient will be * added to the existing coefficient. If the resulting coefficient * is zero, the symbol will be removed from the row */ void insert(Symbol symbol) { insert(symbol, 1.0); } /** * Insert a row into this row with a given coefficient. * The constant and the cells of the other row will be multiplied by * the coefficient and added to this row. Any cell with a resulting * coefficient of zero will be removed from the row. * * @param other * @param coefficient */ void insert(Row other, double coefficient) { this.constant += other.constant * coefficient; Set> map = other.getCells().entrySet(); for (Map.Entry entry : map) { double coeff = entry.getValue() * coefficient; insert(entry.getKey(), coeff); } } /** * Insert a row into this row with a given coefficient. * The constant and the cells of the other row will be multiplied by * the coefficient and added to this row. Any cell with a resulting * coefficient of zero will be removed from the row. * * @param other */ void insert(Row other) { insert(other, 0); } /** * Remove the given symbol from the row. */ void remove(Symbol symbol) { cells.remove(symbol); // not sure what this does, can the symbol be added more than once? /*CellMap::iterator it = m_cells.find( symbol ); if( it != m_cells.end() ) m_cells.erase( it );*/ } /** * Reverse the sign of the constant and all cells in the row. */ void reverseSign() { this.constant = -this.constant; Set> map = getCells().entrySet(); for (Map.Entry entry : map) { entry.setValue(-entry.getValue()); } } /** * Solve the row for the given symbol. *

* This method assumes the row is of the form a * x + b * y + c = 0 * and (assuming solve for x) will modify the row to represent the * right hand side of x = -b/a * y - c / a. The target symbol will * be removed from the row, and the constant and other cells will * be multiplied by the negative inverse of the target coefficient. * The given symbol *must* exist in the row. * * @param symbol */ void solveFor(Symbol symbol) { double coeff = -1.0 / cells.get(symbol); cells.remove(symbol); this.constant *= coeff; Set> map = getCells().entrySet(); for (Map.Entry entry : map) { entry.setValue(entry.getValue() * coeff); } } /** * Solve the row for the given symbols. *

* This method assumes the row is of the form x = b * y + c and will * solve the row such that y = x / b - c / b. The rhs symbol will be * removed from the row, the lhs added, and the result divided by the * negative inverse of the rhs coefficient. * The lhs symbol *must not* exist in the row, and the rhs symbol * must* exist in the row. * * @param lhs * @param rhs */ void solveFor(Symbol lhs, Symbol rhs) { insert(lhs, -1.0); solveFor(rhs); } /** * Get the coefficient for the given symbol. *

* If the symbol does not exist in the row, zero will be returned. * * @return */ double coefficientFor(Symbol symbol) { if (this.cells.containsKey(symbol)) { return this.cells.get(symbol); } else { return 0.0; } } /** * Substitute a symbol with the data from another row. *

* Given a row of the form a * x + b and a substitution of the * form x = 3 * y + c the row will be updated to reflect the * expression 3 * a * y + a * c + b. * If the symbol does not exist in the row, this is a no-op. */ void substitute(Symbol symbol, Row row) { if (cells.containsKey(symbol)) { double coefficient = cells.get(symbol); cells.remove(symbol); insert(row, coefficient); } } }