43 #include <ilqgames/dynamics/concatenated_flat_system.h> 44 #include <ilqgames/utils/linear_dynamics_approximation.h> 45 #include <ilqgames/utils/types.h> 47 #include <glog/logging.h> 51 ConcatenatedFlatSystem::ConcatenatedFlatSystem(
52 const FlatSubsystemList& subsystems)
53 : MultiPlayerFlatSystem(std::accumulate(
54 subsystems.begin(), subsystems.end(), 0,
56 const std::shared_ptr<SinglePlayerFlatSystem>& subsystem) {
57 CHECK_NOTNULL(subsystem.get());
58 return total + subsystem->XDim();
60 subsystems_(subsystems) {
62 subsystem_start_dims_.push_back(0);
63 for (
const auto& subsystem : subsystems_) {
64 subsystem_start_dims_.push_back(subsystem_start_dims_.back() +
69 VectorXf ConcatenatedFlatSystem::Evaluate(
70 const VectorXf& x,
const std::vector<VectorXf>& us)
const {
71 CHECK_EQ(us.size(), NumPlayers());
75 Dimension dims_so_far = 0;
76 for (
size_t ii = 0; ii < NumPlayers(); ii++) {
77 const auto& subsystem = subsystems_[ii];
78 xdot.segment(dims_so_far, subsystem->XDim()) =
79 subsystem->Evaluate(x.segment(dims_so_far, subsystem->XDim()), us[ii]);
80 dims_so_far += subsystem->XDim();
86 void ConcatenatedFlatSystem::ComputeLinearizedSystem()
const {
88 LinearDynamicsApproximation linearization(*
this);
90 Dimension dims_so_far = 0;
91 for (
size_t ii = 0; ii < NumPlayers(); ii++) {
92 const auto& subsystem = subsystems_[ii];
93 const Dimension xdim = subsystem->XDim();
94 const Dimension udim = subsystem->UDim();
95 subsystem->LinearizedSystem(
96 linearization.A.block(dims_so_far, dims_so_far, xdim, xdim),
97 linearization.Bs[ii].block(dims_so_far, 0, xdim, udim));
102 discrete_linear_system_.reset(
new LinearDynamicsApproximation(linearization));
105 linearization.A -= MatrixXf::Identity(xdim_, xdim_);
106 linearization.A /= time::kTimeStep;
107 for (
size_t ii = 0; ii < NumPlayers(); ii++)
108 linearization.Bs[ii] /= time::kTimeStep;
109 continuous_linear_system_.reset(
110 new LinearDynamicsApproximation(linearization));
113 MatrixXf ConcatenatedFlatSystem::InverseDecouplingMatrix(
114 const VectorXf& x)
const {
116 MatrixXf M = MatrixXf::Zero(TotalUDim(), TotalUDim());
118 Dimension x_dims_so_far = 0;
119 Dimension u_dims_so_far = 0;
120 for (
size_t ii = 0; ii < NumPlayers(); ii++) {
121 const auto& subsystem = subsystems_[ii];
122 const Dimension xdim = subsystem->XDim();
123 const Dimension udim = subsystem->UDim();
124 M.block(u_dims_so_far, u_dims_so_far, udim, udim) =
125 subsystem->InverseDecouplingMatrix(x.segment(x_dims_so_far, xdim));
127 x_dims_so_far += xdim;
128 u_dims_so_far += udim;
134 VectorXf ConcatenatedFlatSystem::AffineTerm(
const VectorXf& x)
const {
136 VectorXf m(TotalUDim());
138 Dimension x_dims_so_far = 0;
139 Dimension u_dims_so_far = 0;
140 for (
size_t ii = 0; ii < NumPlayers(); ii++) {
141 const auto& subsystem = subsystems_[ii];
142 const Dimension xdim = subsystem->XDim();
143 const Dimension udim = subsystem->UDim();
144 m.segment(u_dims_so_far, udim) =
145 subsystem->AffineTerm(x.segment(x_dims_so_far, xdim));
147 x_dims_so_far += xdim;
148 u_dims_so_far += udim;
154 std::vector<VectorXf> ConcatenatedFlatSystem::LinearizingControls(
155 const VectorXf& x,
const std::vector<VectorXf>& vs)
const {
156 std::vector<VectorXf> us(NumPlayers());
158 Dimension x_dims_so_far = 0;
159 for (
size_t ii = 0; ii < NumPlayers(); ii++) {
160 const auto& subsystem = subsystems_[ii];
161 const Dimension xdim = subsystem->XDim();
163 subsystem->LinearizingControl(x.segment(x_dims_so_far, xdim), vs[ii]);
165 x_dims_so_far += xdim;
171 VectorXf ConcatenatedFlatSystem::LinearizingControl(
const VectorXf& x,
173 PlayerIndex player)
const {
174 return subsystems_[player]->LinearizingControl(
175 x.segment(subsystem_start_dims_[player], SubsystemXDim(player)), v);
178 VectorXf ConcatenatedFlatSystem::ToLinearSystemState(
const VectorXf& x)
const {
181 Dimension x_dims_so_far = 0;
182 for (
size_t ii = 0; ii < NumPlayers(); ii++) {
183 const auto& subsystem = subsystems_[ii];
184 const Dimension xdim = subsystem->XDim();
185 xi.segment(x_dims_so_far, xdim) =
186 subsystem->ToLinearSystemState(x.segment(x_dims_so_far, xdim));
188 x_dims_so_far += xdim;
194 VectorXf ConcatenatedFlatSystem::ToLinearSystemState(
195 const VectorXf& x, PlayerIndex subsystem_idx)
const {
196 CHECK_LT(subsystem_idx, subsystems_.size());
197 return subsystems_[subsystem_idx]->ToLinearSystemState(x.segment(
198 subsystem_start_dims_[subsystem_idx], SubsystemXDim(subsystem_idx)));
201 VectorXf ConcatenatedFlatSystem::FromLinearSystemState(
202 const VectorXf& xi)
const {
205 Dimension x_dims_so_far = 0;
206 for (
size_t ii = 0; ii < NumPlayers(); ii++) {
207 const auto& subsystem = subsystems_[ii];
208 const Dimension xdim = subsystem->XDim();
209 x.segment(x_dims_so_far, xdim) =
210 subsystem->FromLinearSystemState(xi.segment(x_dims_so_far, xdim));
212 x_dims_so_far += xdim;
218 VectorXf ConcatenatedFlatSystem::FromLinearSystemState(
219 const VectorXf& xi, PlayerIndex subsystem_idx)
const {
220 CHECK_LT(subsystem_idx, subsystems_.size());
221 return subsystems_[subsystem_idx]->FromLinearSystemState(xi.segment(
222 subsystem_start_dims_[subsystem_idx], SubsystemXDim(subsystem_idx)));
225 VectorXf ConcatenatedFlatSystem::SubsystemStates(
226 const VectorXf& x, PlayerIndex subsystem_idx)
const {
227 CHECK_LT(subsystem_idx, subsystems_.size());
228 return x.segment(subsystem_start_dims_[subsystem_idx],
229 SubsystemXDim(subsystem_idx));
232 bool ConcatenatedFlatSystem::IsLinearSystemStateSingular(
233 const VectorXf& xi)
const {
234 Dimension x_dims_so_far = 0;
235 for (
size_t ii = 0; ii < NumPlayers(); ii++) {
236 const auto& subsystem = subsystems_[ii];
237 const Dimension xdim = subsystem->XDim();
238 if (subsystem->IsLinearSystemStateSingular(xi.segment(x_dims_so_far, xdim)))
240 x_dims_so_far += xdim;
246 void ConcatenatedFlatSystem::ChangeCostCoordinates(
247 const VectorXf& xi, std::vector<QuadraticCostApproximation>* q)
const {
249 CHECK_EQ(q->size(), NumPlayers());
252 std::vector<std::vector<VectorXf>> first_partials(NumPlayers());
253 std::vector<std::vector<MatrixXf>> second_partials(NumPlayers());
254 Dimension xi_dims_so_far = 0;
255 for (
size_t ii = 0; ii < NumPlayers(); ii++) {
256 const auto& subsystem_ii = subsystems_[ii];
257 const Dimension xdim = subsystem_ii->XDim();
259 first_partials[ii] = std::vector<VectorXf>(xdim, VectorXf::Zero(xdim));
260 second_partials[ii] =
261 std::vector<MatrixXf>(xdim, MatrixXf::Zero(xdim, xdim));
263 DCHECK_LT(xi_dims_so_far + xdim, xi.size());
264 subsystem_ii->Partial(xi.segment(xi_dims_so_far, xdim), &first_partials[ii],
265 &second_partials[ii]);
266 xi_dims_so_far += xdim;
271 std::vector<MatrixXf> hess_xs(NumPlayers(), MatrixXf::Zero(xdim_, xdim_));
272 Dimension rows_so_far = 0;
275 for (PlayerIndex pp = 0; pp < NumPlayers(); pp++) {
277 for (Dimension ii = 0; ii < SubsystemXDim(pp); ii++) {
278 const Dimension ii_rows = ii + rows_so_far;
281 Dimension cols_so_far = rows_so_far;
282 for (PlayerIndex qq = pp; qq < NumPlayers(); qq++) {
284 for (Dimension jj = 0; jj < SubsystemXDim(qq); jj++) {
285 const Dimension jj_cols = jj + cols_so_far;
288 for (PlayerIndex rr = 0; rr < NumPlayers(); rr++) {
289 const MatrixXf& Q = (*q)[rr].state.hess;
290 const VectorXf& l = (*q)[rr].state.grad;
291 MatrixXf& xhess = hess_xs[rr];
292 for (Dimension kk = 0; kk < SubsystemXDim(pp); kk++) {
296 total += l(kk + rows_so_far) * second_partials[pp][kk](ii, jj);
300 for (Dimension ll = 0; ll < SubsystemXDim(qq); ll++) {
301 temp += Q(kk + rows_so_far, ll + cols_so_far) *
302 first_partials[qq][ll](jj);
305 total += temp * first_partials[pp][kk](ii);
307 DCHECK_LT(ii_rows, xdim_);
308 DCHECK_LT(jj_cols, xdim_);
309 xhess(ii_rows, jj_cols) += total;
310 xhess(jj_cols, ii_rows) += total;
316 cols_so_far += SubsystemXDim(qq);
321 rows_so_far += SubsystemXDim(pp);
325 for (PlayerIndex pp = 0; pp < NumPlayers(); pp++) {
333 (*q)[pp].state.hess.swap(hess_xs[pp]);
338 std::vector<VectorXf> grad_xs(NumPlayers(), VectorXf::Zero(xdim_));
342 for (PlayerIndex pp = 0; pp < NumPlayers(); pp++) {
343 const VectorXf& l = (*q)[pp].state.grad;
346 for (Dimension ii = 0; ii < SubsystemXDim(pp); ii++) {
348 for (Dimension jj = 0; jj < SubsystemXDim(pp); jj++) {
349 DCHECK_LT(jj + rows_so_far, l.size());
350 grad_xs[pp](ii + rows_so_far) +=
351 l(jj + rows_so_far) * first_partials[pp][jj](ii);
356 rows_so_far += SubsystemXDim(pp);
360 for (PlayerIndex pp = 0; pp < NumPlayers(); pp++) {
372 (*q)[pp].state.grad.swap(grad_xs[pp]);
377 ChangeControlCostCoordinates(xi, q);
380 void ConcatenatedFlatSystem::ChangeControlCostCoordinates(
381 const VectorXf& xi, std::vector<QuadraticCostApproximation>* q)
const {
385 const VectorXf x = FromLinearSystemState(xi);
386 std::vector<MatrixXf> M_invs(NumPlayers());
388 Dimension x_dims_so_far = 0;
389 for (
size_t ii = 0; ii < NumPlayers(); ii++) {
390 const auto& subsystem_ii = subsystems_[ii];
391 const Dimension xdim = subsystem_ii->XDim();
393 subsystem_ii->InverseDecouplingMatrix(x.segment(x_dims_so_far, xdim));
394 x_dims_so_far += xdim;
398 for (
size_t ii = 0; ii < NumPlayers(); ii++) {
399 for (
auto& element : (*q)[ii].control) {
400 element.second.hess = M_invs[element.first].transpose() *
401 element.second.hess * M_invs[element.first];
406 float ConcatenatedFlatSystem::DistanceBetween(
const VectorXf& x0,
407 const VectorXf& x1)
const {
408 Dimension dims_so_far = 0;
412 for (
const auto& subsystem : subsystems_) {
413 const Dimension xdim = subsystem->XDim();
414 total += subsystem->DistanceBetween(x0.segment(dims_so_far, xdim),
415 x1.segment(dims_so_far, xdim));
423 std::vector<Dimension> ConcatenatedFlatSystem::PositionDimensions()
const {
424 std::vector<Dimension> dims;
426 for (
const auto& s : subsystems_) {
427 const std::vector<Dimension> sub_dims = s->PositionDimensions();
428 dims.insert(dims.end(), sub_dims.begin(), sub_dims.end());