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, POW_1_FN} from "./polynomial"; import {compositeFn, 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)) }); console.log('reducing system:'); this.polynomials.forEach(p => console.log(p.toString())); 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.linearParam, m2.linearParam, constant]); this.substitutedParams.push([m1.linearParam, new Polynomial().monomial(constant).term(m2.linearParam, POW_1_FN)]); } 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 (linearSub.length) { while (linearSub.length) { const [param, toParam, k, b] = linearSub.pop(); let transaction = compositeFn(); for (let polynomial of this.polynomials) { if (polynomial) { const polyTransaction = polynomial.linearSubstitution(param, toParam, k, b); if (!polyTransaction) { transaction = null; break; } transaction.push(polyTransaction); transaction.push(() => this.substitutedParams.push(param, new Polynomial(b).monomial(k).term(toParam, POW_1_FN))); } } if (transaction) { requirePass = true; transaction(); } } } if (requirePass) { this.polynomials.forEach(polynomial => polynomial && polynomial.compact()); } } this.polynomials = this.polynomials.filter(p => p); } prepare() { this.reset(); this.evaluatePolynomials(); console.log('solving system:'); this.polynomials.forEach(p => console.log(p.toString())); console.log('with respect to:'); this.substitutedParams.forEach(([x, expr]) => console.log('X' + x.id + ' = ' + expr.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; } }