29 static constexpr
const double cd_delta = 1e-9;
38 if (edges->isModified())
41 edges->computeEdgeIndices();
42 edges->reserveEdgeCacheMemory(3, 2);
46 edges->setModified(
false);
55 if (!equality && !inequality && edge->getObjectiveDimension() == 0)
continue;
56 if (!objective && !inequality && edge->getEqualityDimension() == 0)
continue;
57 if (!equality && !objective && edge->getInequalityDimension() == 0)
continue;
65 bool include_nonmixed,
bool include_mixed)
69 for (BaseEdge* edge : vertex->getConnectedObjectiveEdgesRef())
71 edge->computeValuesCached();
73 if (include_lsq_edges)
75 for (
BaseEdge* edge : vertex->getConnectedLsqObjectiveEdgesRef())
77 edge->computeSquaredNormOfValuesCached();
83 for (BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
85 if (edge->getObjectiveDimension() == 0)
continue;
86 if (!include_lsq_edges && edge->isObjectiveLeastSquaresForm())
continue;
90 if (edge->isObjectiveLeastSquaresForm())
91 edge->computeSquaredNormOfObjectiveValuesCached();
93 edge->computeObjectiveValuesCached();
99 bool include_lsq_edges,
bool include_nonmixed,
bool include_mixed,
100 bool precompute_mixed)
102 if (include_nonmixed)
104 for (BaseEdge* edge : vertex->getConnectedObjectiveEdgesRef())
106 Eigen::VectorXd values_minus(edge->getDimension());
107 edge->computeValues(values_minus);
108 gradient_coeff +=
cd_scalar * (edge->getCache().topValues() - values_minus).sum();
109 edge->getCache().popValues();
111 if (include_lsq_edges)
113 for (BaseEdge* edge : vertex->getConnectedLsqObjectiveEdgesRef())
115 gradient_coeff +=
cd_scalar * (edge->getCache().topValues()[0] - edge->computeSquaredNormOfValues());
116 edge->getCache().popValues();
122 for (
BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
124 if (edge->getObjectiveDimension() == 0)
continue;
125 if (!include_lsq_edges && edge->isObjectiveLeastSquaresForm())
continue;
127 if (precompute_mixed) edge->precompute();
129 if (edge->isObjectiveLeastSquaresForm())
131 gradient_coeff +=
cd_scalar * (edge->getObjectiveCache().topValues()[0] - edge->computeSquaredNormOfObjectiveValues());
135 Eigen::VectorXd values_minus(edge->getObjectiveDimension());
136 edge->computeObjectiveValues(values_minus);
137 gradient_coeff +=
cd_scalar * (edge->getObjectiveCache().topValues() - values_minus).sum();
139 edge->getObjectiveCache().popValues();
145 bool include_mixed,
bool precompute_mixed)
147 if (include_nonmixed)
149 for (BaseEdge* edge : vertex->getConnectedLsqObjectiveEdgesRef())
151 edge->computeValuesCached();
156 for (BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
158 if (edge->getObjectiveDimension() == 0)
continue;
159 if (!edge->isObjectiveLeastSquaresForm())
continue;
161 if (precompute_mixed) edge->precompute();
163 edge->computeObjectiveValuesCached();
170 bool include_nonmixed,
bool include_mixed)
172 if (include_nonmixed)
176 Eigen::VectorXd values_minus(edge->getDimension());
177 edge->computeValues(values_minus);
182 jacobian.block(edge->getEdgeIdx(), vtx_idx, edge->getDimension(), 1) =
183 cd_scalar * multipliers_map.cwiseProduct(edge->getCache().topValues() - values_minus);
187 jacobian.block(edge->getEdgeIdx(), vtx_idx, edge->getDimension(), 1) =
cd_scalar * (edge->getCache().topValues() - values_minus);
189 edge->getCache().popValues();
197 if (edge->getObjectiveDimension() == 0)
continue;
198 if (!edge->isObjectiveLeastSquaresForm())
continue;
202 Eigen::VectorXd values_minus(edge->getObjectiveDimension());
203 edge->computeObjectiveValues(values_minus);
207 jacobian.block(edge->getEdgeObjectiveIdx(), vtx_idx, edge->getObjectiveDimension(), 1).noalias() =
208 cd_scalar * multipliers_map.cwiseProduct(edge->getObjectiveCache().topValues() - values_minus);
212 jacobian.block(edge->getEdgeObjectiveIdx(), vtx_idx, edge->getObjectiveDimension(), 1).noalias() =
213 cd_scalar * (edge->getObjectiveCache().topValues() - values_minus);
215 edge->getObjectiveCache().popValues();
225 for (BaseEdge* edge : vertex->getConnectedLsqObjectiveEdgesRef())
227 const int edge_idx = edge->getEdgeIdx() + row_offset;
229 for (
int i = 0; i < edge->getDimension(); ++i)
231 i_row[nnz_idx] = edge_idx + i;
232 j_col[nnz_idx] = vtx_idx;
237 for (BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
239 if (edge->getObjectiveDimension() == 0)
continue;
240 if (!edge->isObjectiveLeastSquaresForm())
continue;
242 const int edge_idx = edge->getEdgeObjectiveIdx() + row_offset;
244 for (
int i = 0; i < edge->getObjectiveDimension(); ++i)
246 i_row[nnz_idx] = edge_idx + i;
247 j_col[nnz_idx] = vtx_idx;
255 const double* multipliers,
bool precompute_mixed)
257 for (BaseEdge* edge : vertex->getConnectedLsqObjectiveEdgesRef())
259 Eigen::VectorXd values_minus(edge->getDimension());
260 edge->computeValues(values_minus);
265 values.segment(nnz_idx, edge->getDimension()) =
cd_scalar * multipliers_map.cwiseProduct(edge->getCache().topValues() - values_minus);
266 nnz_idx += edge->getDimension();
270 values.segment(nnz_idx, edge->getDimension()) =
cd_scalar * (edge->getCache().topValues() - values_minus);
271 nnz_idx += edge->getDimension();
273 edge->getCache().popValues();
276 for (
BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
278 if (edge->getObjectiveDimension() == 0)
continue;
279 if (!edge->isObjectiveLeastSquaresForm())
continue;
281 if (precompute_mixed) edge->precompute();
283 Eigen::VectorXd values_minus(edge->getObjectiveDimension());
284 edge->computeObjectiveValues(values_minus);
288 values.segment(nnz_idx, edge->getObjectiveDimension()).noalias() =
289 cd_scalar * multipliers_map.cwiseProduct(edge->getObjectiveCache().topValues() - values_minus);
290 nnz_idx += edge->getObjectiveDimension();
294 values.segment(nnz_idx, edge->getObjectiveDimension()).noalias() =
cd_scalar * (edge->getObjectiveCache().topValues() - values_minus);
295 nnz_idx += edge->getObjectiveDimension();
297 edge->getObjectiveCache().popValues();
302 bool precompute_mixed)
304 if (include_nonmixed)
306 for (BaseEdge* edge : vertex->getConnectedEqualityEdgesRef())
308 edge->computeValuesCached();
313 for (BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
315 if (edge->getEqualityDimension() == 0)
continue;
317 if (precompute_mixed) edge->precompute();
319 edge->computeEqualityValuesCached();
326 bool include_nonmixed,
bool include_mixed,
bool precompute_mixed)
328 if (include_nonmixed)
332 Eigen::VectorXd values_minus(edge->getDimension());
333 edge->computeValues(values_minus);
338 jacobian.block(edge->getEdgeIdx(), vtx_idx, edge->getDimension(), 1) =
339 cd_scalar * multipliers_map.cwiseProduct(edge->getCache().topValues() - values_minus);
343 jacobian.block(edge->getEdgeIdx(), vtx_idx, edge->getDimension(), 1) =
cd_scalar * (edge->getCache().topValues() - values_minus);
345 edge->getCache().popValues();
353 if (edge->getEqualityDimension() == 0)
continue;
355 if (precompute_mixed) edge->precompute();
357 Eigen::VectorXd values_minus(edge->getEqualityDimension());
358 edge->computeEqualityValues(values_minus);
362 jacobian.block(edge->getEdgeEqualityIdx(), vtx_idx, edge->getEqualityDimension(), 1).noalias() =
363 cd_scalar * multipliers_map.cwiseProduct(edge->getEqualityCache().topValues() - values_minus);
367 jacobian.block(edge->getEdgeEqualityIdx(), vtx_idx, edge->getEqualityDimension(), 1).noalias() =
368 cd_scalar * (edge->getEqualityCache().topValues() - values_minus);
370 edge->getEqualityCache().popValues();
380 for (BaseEdge* edge : vertex->getConnectedEqualityEdgesRef())
382 const int edge_idx = edge->getEdgeIdx() + row_offset;
384 for (
int i = 0; i < edge->getDimension(); ++i)
386 i_row[nnz_idx] = edge_idx + i;
387 j_col[nnz_idx] = vtx_idx;
392 for (BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
394 if (edge->getEqualityDimension() == 0)
continue;
396 const int edge_idx = edge->getEdgeEqualityIdx() + row_offset;
398 for (
int i = 0; i < edge->getEqualityDimension(); ++i)
400 i_row[nnz_idx] = edge_idx + i;
401 j_col[nnz_idx] = vtx_idx;
409 bool precompute_mixed)
411 for (BaseEdge* edge : vertex->getConnectedEqualityEdgesRef())
413 Eigen::VectorXd values_minus(edge->getDimension());
414 edge->computeValues(values_minus);
419 values.segment(nnz_idx, edge->getDimension()) =
cd_scalar * multipliers_map.cwiseProduct(edge->getCache().topValues() - values_minus);
420 nnz_idx += edge->getDimension();
424 values.segment(nnz_idx, edge->getDimension()) =
cd_scalar * (edge->getCache().topValues() - values_minus);
425 nnz_idx += edge->getDimension();
427 edge->getCache().popValues();
430 for (
BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
432 if (edge->getEqualityDimension() == 0)
continue;
434 if (precompute_mixed) edge->precompute();
436 Eigen::VectorXd values_minus(edge->getEqualityDimension());
437 edge->computeEqualityValues(values_minus);
441 values.segment(nnz_idx, edge->getEqualityDimension()).noalias() =
442 cd_scalar * multipliers_map.cwiseProduct(edge->getEqualityCache().topValues() - values_minus);
443 nnz_idx += edge->getEqualityDimension();
447 values.segment(nnz_idx, edge->getEqualityDimension()).noalias() =
cd_scalar * (edge->getEqualityCache().topValues() - values_minus);
448 nnz_idx += edge->getEqualityDimension();
450 edge->getEqualityCache().popValues();
455 bool include_mixed,
bool precompute_mixed)
457 if (include_nonmixed)
459 for (BaseEdge* edge : vertex->getConnectedInequalityEdgesRef())
461 edge->computeValuesCached();
466 for (BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
468 if (edge->getInequalityDimension() == 0)
continue;
470 if (precompute_mixed) edge->precompute();
472 edge->computeInequalityValuesCached();
479 bool include_nonmixed,
bool include_mixed,
bool precompute_mixed)
481 if (include_nonmixed)
485 Eigen::VectorXd values_minus(edge->getDimension());
486 edge->computeValues(values_minus);
491 jacobian.block(edge->getEdgeIdx(), vtx_idx, edge->getDimension(), 1) =
492 cd_scalar * multipliers_map.cwiseProduct(edge->getCache().topValues() - values_minus);
496 jacobian.block(edge->getEdgeIdx(), vtx_idx, edge->getDimension(), 1) =
cd_scalar * (edge->getCache().topValues() - values_minus);
498 edge->getCache().popValues();
506 if (edge->getInequalityDimension() == 0)
continue;
508 if (precompute_mixed) edge->precompute();
510 Eigen::VectorXd values_minus(edge->getInequalityDimension());
511 edge->computeInequalityValues(values_minus);
515 jacobian.block(edge->getEdgeInequalityIdx(), vtx_idx, edge->getInequalityDimension(), 1).noalias() =
516 cd_scalar * multipliers_map.cwiseProduct(edge->getInequalityCache().topValues() - values_minus);
520 jacobian.block(edge->getEdgeInequalityIdx(), vtx_idx, edge->getInequalityDimension(), 1).noalias() =
521 cd_scalar * (edge->getInequalityCache().topValues() - values_minus);
523 edge->getInequalityCache().popValues();
530 bool include_nonmixed,
bool include_mixed)
532 const double weighted_scalar = weight *
cd_scalar;
534 if (include_nonmixed)
536 for (BaseEdge* edge : vertex->getConnectedInequalityEdgesRef())
538 assert(edge->getCache().sizeValues() > 1);
544 Eigen::VectorXd values_minus(edge->getDimension());
545 edge->computeValues(values_minus);
548 for (
int j = 0; j < edge->getDimension(); ++j)
550 if (active[j]) jacobian(edge->getEdgeIdx() + j, vtx_idx) = weighted_scalar * (edge->getCache().topValues()(j) - values_minus(j));
555 edge->getCache().popValues();
556 edge->getCache().popValues();
562 for (BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
564 if (edge->getInequalityDimension() == 0)
continue;
566 assert(edge->getInequalityCache().sizeValues() >
575 Eigen::VectorXd values_minus(edge->getInequalityDimension());
576 edge->computeInequalityValues(values_minus);
579 for (
int j = 0; j < edge->getInequalityDimension(); ++j)
582 jacobian(edge->getEdgeInequalityIdx() + j, vtx_idx) =
583 weighted_scalar * (edge->getInequalityCache().topValues()(j) - values_minus(j));
588 edge->getInequalityCache().popValues();
589 edge->getInequalityCache().popValues();
599 for (BaseEdge* edge : vertex->getConnectedInequalityEdgesRef())
601 const int edge_idx = edge->getEdgeIdx() + row_offset;
603 for (
int i = 0; i < edge->getDimension(); ++i)
605 i_row[nnz_idx] = edge_idx + i;
606 j_col[nnz_idx] = vtx_idx;
611 for (BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
613 if (edge->getInequalityDimension() == 0)
continue;
615 const int edge_idx = edge->getEdgeInequalityIdx() + row_offset;
617 for (
int i = 0; i < edge->getInequalityDimension(); ++i)
619 i_row[nnz_idx] = edge_idx + i;
620 j_col[nnz_idx] = vtx_idx;
628 const double* multipliers,
bool precompute_mixed)
630 for (BaseEdge* edge : vertex->getConnectedInequalityEdgesRef())
632 Eigen::VectorXd values_minus(edge->getDimension());
633 edge->computeValues(values_minus);
638 values.segment(nnz_idx, edge->getDimension()) =
cd_scalar * multipliers_map.cwiseProduct(edge->getCache().topValues() - values_minus);
639 edge->getCache().popValues();
640 nnz_idx += edge->getDimension();
644 values.segment(nnz_idx, edge->getDimension()) =
cd_scalar * (edge->getCache().topValues() - values_minus);
645 edge->getCache().popValues();
646 nnz_idx += edge->getDimension();
650 for (
BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
652 if (edge->getInequalityDimension() == 0)
continue;
654 if (precompute_mixed) edge->precompute();
656 Eigen::VectorXd values_minus(edge->getInequalityDimension());
657 edge->computeInequalityValues(values_minus);
661 values.segment(nnz_idx, edge->getInequalityDimension()).noalias() =
662 cd_scalar * multipliers_map.cwiseProduct(edge->getInequalityCache().topValues() - values_minus);
663 edge->getInequalityCache().popValues();
664 nnz_idx += edge->getInequalityDimension();
668 values.segment(nnz_idx, edge->getInequalityDimension()).noalias() =
cd_scalar * (edge->getInequalityCache().topValues() - values_minus);
669 edge->getInequalityCache().popValues();
670 nnz_idx += edge->getInequalityDimension();
678 const double weighted_scalar = weight *
cd_scalar;
680 for (BaseEdge* edge : vertex->getConnectedInequalityEdgesRef())
682 assert(edge->getCache().sizeValues() > 1);
688 Eigen::VectorXd values_minus(edge->getDimension());
689 edge->computeValues(values_minus);
692 for (
int j = 0; j < edge->getDimension(); ++j)
694 if (active[j]) values(nnz_idx) = weighted_scalar * (edge->getCache().topValues()(j) - values_minus(j));
700 nnz_idx += edge->getDimension();
702 edge->getCache().popValues();
703 edge->getCache().popValues();
706 for (BaseMixedEdge* edge : vertex->getConnectedMixedEdgesRef())
708 if (edge->getInequalityDimension() == 0)
continue;
710 assert(edge->getInequalityCache().sizeValues() > 1);
718 Eigen::VectorXd values_minus(edge->getInequalityDimension());
719 edge->computeInequalityValues(values_minus);
722 for (
int j = 0; j < edge->getInequalityDimension(); ++j)
724 if (active[j]) values(nnz_idx) = weighted_scalar * (edge->getInequalityCache().topValues()(j) - values_minus(j));
730 nnz_idx += edge->getInequalityDimension();
732 edge->getInequalityCache().popValues();
733 edge->getInequalityCache().popValues();
740 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
749 if (vertex->isFixed())
continue;
752 for (
int i = 0; i < vertex->getDimension(); ++i)
754 if (vertex->isFixedComponent(i))
continue;
768 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
774 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
781 if (vertex->isFixed())
continue;
784 for (
int i = 0; i < vertex->getDimension(); ++i)
786 if (vertex->isFixedComponent(i))
continue;
800 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
806 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
817 if (vertex->isFixed())
continue;
820 for (
int i = 0; i < vertex->getDimension(); ++i)
822 if (vertex->isFixedComponent(i))
continue;
836 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
851 for (
int i = 0; i < edge->getNumVertices(); ++i)
853 nnz += edge->getDimension() * edge->getVertexRaw(i)->getDimensionUnfixed();
859 if (edge->getObjectiveDimension() == 0 || !edge->isObjectiveLeastSquaresForm())
continue;
861 for (
int i = 0; i < edge->getNumVertices(); ++i)
863 nnz += edge->getObjectiveDimension() * edge->getVertexRaw(i)->getDimensionUnfixed();
873 assert(j_col.size() == i_row.size());
879 if (vertex->isFixed())
continue;
882 for (
int i = 0; i < vertex->getDimension(); ++i)
884 if (vertex->isFixedComponent(i))
continue;
896 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
905 if (vertex->isFixed())
continue;
908 for (
int i = 0; i < vertex->getDimension(); ++i)
910 if (vertex->isFixedComponent(i))
continue;
924 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
930 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
941 if (vertex->isFixed())
continue;
944 for (
int i = 0; i < vertex->getDimension(); ++i)
946 if (vertex->isFixedComponent(i))
continue;
960 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
975 for (
int i = 0; i < edge->getNumVertices(); ++i)
977 nnz += edge->getDimension() * edge->getVertexRaw(i)->getDimensionUnfixed();
983 if (edge->getEqualityDimension() == 0)
continue;
985 for (
int i = 0; i < edge->getNumVertices(); ++i)
987 nnz += edge->getEqualityDimension() * edge->getVertexRaw(i)->getDimensionUnfixed();
997 assert(j_col.size() == i_row.size());
1003 if (vertex->isFixed())
continue;
1006 for (
int i = 0; i < vertex->getDimension(); ++i)
1008 if (vertex->isFixedComponent(i))
continue;
1020 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1029 if (vertex->isFixed())
continue;
1032 for (
int i = 0; i < vertex->getDimension(); ++i)
1034 if (vertex->isFixedComponent(i))
continue;
1048 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1054 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1065 if (vertex->isFixed())
continue;
1068 for (
int i = 0; i < vertex->getDimension(); ++i)
1070 if (vertex->isFixedComponent(i))
continue;
1084 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1099 for (
int i = 0; i < edge->getNumVertices(); ++i)
1101 nnz += edge->getDimension() * edge->getVertexRaw(i)->getDimensionUnfixed();
1107 if (edge->getInequalityDimension() == 0)
continue;
1109 for (
int i = 0; i < edge->getNumVertices(); ++i)
1111 nnz += edge->getInequalityDimension() * edge->getVertexRaw(i)->getDimensionUnfixed();
1121 assert(j_col.size() == i_row.size());
1127 if (vertex->isFixed())
continue;
1130 for (
int i = 0; i < vertex->getDimension(); ++i)
1132 if (vertex->isFixedComponent(i))
continue;
1145 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1154 if (vertex->isFixed())
continue;
1157 for (
int i = 0; i < vertex->getDimension(); ++i)
1159 if (vertex->isFixedComponent(i))
continue;
1173 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1179 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1190 if (vertex->isFixed())
continue;
1193 for (
int i = 0; i < vertex->getDimension(); ++i)
1195 if (vertex->isFixedComponent(i))
continue;
1211 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1216 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1225 if (vertex->isFixed())
continue;
1228 for (
int i = 0; i < vertex->getDimension(); ++i)
1230 if (vertex->isFixedComponent(i))
continue;
1247 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1260 bool equality,
bool inequality)
1263 assert(j_col.size() == i_row.size());
1272 if (vertex->isFixed())
continue;
1275 for (
int i = 0; i < vertex->getDimension(); ++i)
1277 if (vertex->isFixedComponent(i))
continue;
1290 bool equality,
bool inequality,
const double* multipliers_obj,
1291 const double* multipliers_eq,
const double* multipliers_ineq)
1294 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1303 if (vertex->isFixed())
continue;
1306 for (
int i = 0; i < vertex->getDimension(); ++i)
1308 if (vertex->isFixedComponent(i))
continue;
1331 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1335 bool inequality,
bool finite_combined_bounds,
bool active_ineq,
1336 double weight_eq,
double weight_ineq,
double weight_bounds,
1337 const Eigen::VectorXd* values,
const Eigen::VectorXi* col_nnz)
1341 weight_eq, weight_ineq, weight_bounds, values, col_nnz);
1346 bool equality,
bool inequality,
1347 const double* multipliers_eq,
1348 const double* multipliers_ineq)
1351 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());
1355 jac_values.setZero();
1361 if (vertex->isFixed())
continue;
1364 for (
int i = 0; i < vertex->getDimension(); ++i)
1366 if (vertex->isFixedComponent(i))
continue;
1389 assert(
getGraph().getEdgeSet()->isEdgeCacheEmpty());