jsketcher/web/app/sketcher/constr/AlgNumSystem.js
Val Erastov (xibyte) 2fafec904c polynomial analysis
2020-01-07 00:17:20 -08:00

237 lines
5.8 KiB
JavaScript

import {createByConstraintName} from "./solverConstraints";
import {Param, prepare} from "./solver";
import {findConstructionCluster} from "./constructions";
import {GCCircle, GCPoint} from "./constractibles";
import {eqEps, eqTol} from "../../brep/geom/tolerance";
import {Polynomial} from "./polynomial";
import {NOOP} from "../../../../modules/gems/func";
export class AlgNumSubSystem {
generator = NOOP;//new BoundaryObjectsGenerator();
constraints = [];
ownParams = new Set();
readOnlyParams = new Set();
generatedParams = new Set();
beingSolvedParams = new Set();
// generators = [];
subSystems = []; //subsystems are generated by generators only
polynomials = [];
substitutedParams = [];
polyToConstr = new Map();
conflicting = new Set();
redundant = new Set();
SubSystem(generator) {
this.generator = generator;
}
addConstraint(constraint, _ancestorParams) {
if (this.canBeAdded(constraint.params)) {
// this.constraints.push(constraint);
// this.constraints
}
this.constraints.push(constraint);
}
reset() {
this.polynomials = [];
this.substitutedParams = [];
this.polyToConstr.clear();
this.conflicting.clear();
this.redundant.clear();
this.beingSolvedParams.clear();
}
evaluatePolynomials() {
this.constraints.forEach(c => {
c.collectPolynomials(this.polynomials);
this.polynomials.forEach(p => this.polyToConstr.set(p, c))
});
const toEliminate = Array.from(this.readOnlyParams);
const toSubstitute = [];
const linearSub = [];
let requirePass = true;
while (requirePass) {
requirePass = false;
for (let i = 0; i < this.polynomials.length; ++i) {
const polynomial = this.polynomials[i];
if (!polynomial) {
continue;
}
if (polynomial.monomials.length === 0) {
if (!eqEps(polynomial.constant, 0)) {
this.conflicting.add(this.polyToConstr.get(polynomial));
}
this.polynomials[i] = null;
} else if (polynomial.monomials.length === 1) {
const monomial = polynomial.monomials[0];
const terms = monomial.terms;
if (terms.length === 1) {
const term = terms[0];
if (term.fn.degree === 1) {
term.param.set(- polynomial.constant / monomial.constant);
toEliminate.push(term.param);
}
}
this.polynomials[i] = null;
} else if (polynomial.monomials.length === 2 && polynomial.isLinear) {
const [m1, m2] = polynomial.monomials;
const constant = - m2.constant / m1.constant;
if (!eqEps(polynomial.constant, 0)) {
toSubstitute.push([m1.param, m2.param, constant]);
this.substitutedParams.push([m1.param, new Polynomial().monomial(constant).addParam(m2.param)]);
} else {
// linearSub.push([m1.param, m2.param, constant, - polynomial.constant / m1.constant]);
}
this.polynomials[i] = null;
}
}
while (toEliminate.length) {
requirePass = true;
const param = toEliminate.pop();
for (let polynomial of this.polynomials) {
if (polynomial) {
polynomial.eliminate(param, param.get());
}
}
}
while (toSubstitute.length) {
requirePass = true;
const [param, toParam, dotConstant] = toSubstitute.pop();
for (let polynomial of this.polynomials) {
if (polynomial) {
polynomial.substitute(param, toParam, dotConstant);
}
}
}
if (requirePass) {
this.polynomials.forEach(polynomial => polynomial && polynomial.compact());
}
}
while (toEliminate.length || toSubstitute.length) {
// while (linearSub.length) {
// const [param, toParam, b, c] = linearSub.pop();
// for (let polynomial of polynomials) {
// if (polynomial) {
// polynomial.linerSub(param, toParam, b, c);
// }
// }
// }
}
this.polynomials = this.polynomials.filter(p => p);
}
prepare() {
this.reset();
this.evaluatePolynomials();
console.log('solving system:');
this.polynomials.forEach(p => console.log(p.toString()));
const residuals = [];
this.polynomials.forEach(p => residuals.push(p.asResidual()));
for (let residual of residuals) {
residual.params.forEach(solverParam => {
if (!this.beingSolvedParams.has(solverParam)) {
solverParam.reset(solverParam.objectParam.get());
this.beingSolvedParams.add(solverParam);
}
});
}
this.numericalSolver = prepare(residuals);
}
solve(rough) {
this.generator();
this.beingSolvedParams.forEach(solverParam => {
solverParam.set(solverParam.objectParam.get());
});
this.numericalSolver.solveSystem(rough);
this.beingSolvedParams.forEach(solverParam => {
solverParam.objectParam.set(solverParam.get());
});
for (let i = this.substitutedParams.length - 1; i >= 0; i--) {
let [param, expression] = this.substitutedParams[i];
param.set(expression.value);
}
}
canBeAdded(subjectParams, ancestorParams) {
for (let p of subjectParams) {
if (!this.ownParams.has(p) && (!ancestorParams || !ancestorParams.has(p))) {
return false;
}
}
return true;
}
}
export class AlgNumSystem {
constraints = [];
generators = [];
locked = new Set();
constantParams = new Set();
constructor(visitAllObjects) {
this.visitAllObjects = visitAllObjects;
}
addConstraint(constraint) {
this.constraints.push(constraint);
if (constraint.schema.generator) {
}
}
startTransaction(interactiveLock = []) {
this.systemTransaction.prepare(interactiveLock);
return this.systemTransaction;
}
}