/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributor(s): - * */ package org.la4j.linear; import org.la4j.LinearAlgebra; import org.la4j.decomposition.MatrixDecompositor; import org.la4j.Matrix; import org.la4j.Vector; import org.la4j.Vectors; public class ForwardBackSubstitutionSolver extends AbstractSolver implements LinearSystemSolver { private static final long serialVersionUID = 4071505L; // Matrices from RAW_LU decomposition private final Matrix lu; private final Matrix p; public ForwardBackSubstitutionSolver(Matrix a) { super(a); // we use Raw LU for this MatrixDecompositor decompositor = a.withDecompositor(LinearAlgebra.RAW_LU); Matrix[] lup = decompositor.decompose(); // TODO: it doesn't look safe. this.lu = lup[0]; this.p = lup[1]; } @Override public Vector solve(Vector b) { ensureRHSIsCorrect(b); int n = unknowns(); // checks whether the lu matrix is singular or not for (int i = 0; i < n; i++) { if (lu.get(i, i) == 0.0) { fail("This system can not be solved: coefficient matrix is singular."); } } Vector x = b.blankOfLength(n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (p.get(i, j) != 0.0) { x.set(i, b.get(j)); break; } } } for (int j = 0; j < n; j++) { for (int i = j + 1; i < n; i++) { x.updateAt(i, Vectors.asMinusFunction(x.get(j) * lu.get(i, j))); } } for (int j = n - 1; j >= 0; j--) { x.updateAt(j, Vectors.asDivFunction(lu.get(j, j))); for (int i = 0; i < j; i++) { x.updateAt(i, Vectors.asMinusFunction(x.get(j) * lu.get(i, j))); } } return x; } @Override public boolean applicableTo(Matrix matrix) { return matrix.rows() == matrix.columns(); } }