1 /* Siconos is a program dedicated to modeling, simulation and control
2 * of non smooth dynamical systems.
3 *
4 * Copyright 2021 INRIA.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include <assert.h> // for assert
20 #include <stdio.h> // for printf
21 #include <stdlib.h> // for exit
22 #include "FischerBurmeister.h" // for phi_Mixed_FB
23 #include "MLCP_Solvers.h" // for mlcp_compute_error
24 #include "MixedLinearComplementarityProblem.h" // for MixedLinearComplement...
25 #include "Newton_methods.h" // for functions_LSA, init_l...
26 #include "NumericsFwd.h" // for MixedLinearComplement...
27 #include "NumericsMatrix.h" // for NumericsMatrix
28 #include "SiconosBlas.h" // for cblas_dgemv, cblas_dcopy
29
30 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
31
FB_compute_F_mlcp(void * data_opaque,double * z,double * w)32 static void FB_compute_F_mlcp(void* data_opaque, double* z, double* w)
33 {
34 // Computation of the new value w = F(z) = Mz + q
35 // q --> w
36 MixedLinearComplementarityProblem* problem = (MixedLinearComplementarityProblem *)data_opaque;
37 assert(problem->M);
38 assert(problem->M->matrix0);
39 unsigned int n = problem->n;
40 unsigned int m = problem->m;
41 /* Problem in the form (M,q) */
42 if(problem->isStorageType1)
43 {
44 cblas_dcopy(n, problem->q, 1, w, 1);
45 // Mz+q --> w
46 cblas_dgemv(CblasColMajor, CblasNoTrans, n, n, 1.0, problem->M->matrix0, n, z, 1, 1.0, w, 1);
47 }
48 else
49 {
50 /* Links to problem data */
51 double *a = problem->q;
52 double *b = &problem->q[n];
53 double *A = problem->A;
54 double *B = problem->B;
55 double *C = problem->C;
56 double *D = problem->D;
57
58 /* Compute "equalities" part, we = Au + Cv + a - Must be equal to 0 */
59 cblas_dcopy(n, a, 1, w, 1); // we = w[0..n-1] <-- a
60 cblas_dgemv(CblasColMajor, CblasNoTrans, n, n, 1.0, A, n, z, 1, 1.0, w, 1); // we <-- A*u + we
61 cblas_dgemv(CblasColMajor, CblasNoTrans, n, m, 1.0, C, m, &z[n], 1, 1.0, w, 1); // we <-- C*v + we
62
63 /* Computes part which corresponds to complementarity */
64 double* w_c = &w[n]; // No copy!!
65 cblas_dcopy(m, b, 1, w_c, 1); // wi = w[n..m] <-- b
66 cblas_dgemv(CblasColMajor, CblasNoTrans, m, n, 1.0, D, n, z, 1, 1.0, w_c, 1); // we <-- D*u + we
67 cblas_dgemv(CblasColMajor, CblasNoTrans, m, m, 1.0, B, m, &z[n], 1, 1.0, w_c, 1); // we <-- B*v + we
68 }
69 }
70
FB_compute_H_mlcp(void * data_opaque,double * z,double * w,double * workV1,double * workV2,NumericsMatrix * H)71 static void FB_compute_H_mlcp(void* data_opaque, double* z, double* w, double* workV1, double* workV2, NumericsMatrix* H)
72 {
73 printf("MLCP FB_compute_H_mlcp not implemented yet");
74 exit(1);
75 #if 0
76 MixedLinearComplementarityProblem* data = (MixedLinearComplementarityProblem *)data_opaque;
77 unsigned int n = data->size;
78 assert(data->M);
79 assert(data->M->matrix0);
80 double* M = data->M->matrix0;
81 double normi;
82
83 // workV1 = "z" in Facchibei--Pang p. 808
84 // "z_i" = 1 if z_i = w_i = 0.0
85 // M^T.workV1 --> workV2
86 cblas_dgemv(CblasColMajor, CblasTrans, n, n, 1.0, M, n, workV1, 1, 0.0, workV2, 1);
87 for(unsigned int i = 0; i < n; ++i)
88 {
89 if(workV1[i] != 0.0) // i in beta
90 {
91 normi = sqrt(workV1[i] * workV1[i] + workV2[i] * workV2[i]);
92 for(unsigned int j = 0; j < n; j++)
93 {
94 H[j * n + i] = (workV2[i] / normi - 1.0) * M[j * n + i];
95 }
96 H[i * n + i] += (workV1[i] / normi - 1.0);
97
98 }
99 else // i not in beta
100 {
101 normi = sqrt(z[i] * z[i] + w[i] * w[i]);
102 for(unsigned int j = 0; j < n; j++)
103 {
104 H[j * n + i] = (w[i] / normi - 1.0) * M[j * n + i];
105 }
106 H[i * n + i] += (z[i] / normi - 1.0);
107 }
108
109 }
110 #endif
111 }
112
mlcp_mixed_FB(void * data_opaque,double * z,double * F,double * F_FB)113 void mlcp_mixed_FB(void* data_opaque, double* z, double* F, double* F_FB)
114 {
115 phi_Mixed_FB(((MixedLinearComplementarityProblem *)data_opaque)->n, ((MixedLinearComplementarityProblem *)data_opaque)->m, z, F, F_FB);
116 }
117
FB_compute_error_mlcp(void * data_opaque,double * z,double * w,double * nabla_theta,double tol,double * err)118 void FB_compute_error_mlcp(void* data_opaque, double* z, double* w, double* nabla_theta, double tol, double* err)
119 {
120 mlcp_compute_error((MixedLinearComplementarityProblem *)data_opaque, z, w, tol, err);
121 }
122
mlcp_newton_FB(MixedLinearComplementarityProblem * problem,double * z,double * w,int * info,SolverOptions * options)123 void mlcp_newton_FB(MixedLinearComplementarityProblem* problem, double *z, double *w, int *info, SolverOptions* options)
124 {
125 functions_LSA functions_FBLSA_mlcp;
126 init_lsa_functions(&functions_FBLSA_mlcp, &FB_compute_F_mlcp, (compute_F_merit_ptr)&mlcp_FB);
127 functions_FBLSA_mlcp.compute_H = &FB_compute_H_mlcp;
128 functions_FBLSA_mlcp.compute_error = &FB_compute_error_mlcp;
129
130 set_lsa_params_data(options, problem->M);
131 newton_LSA(problem->n + problem->m, z, w, info, (void *)problem, options, &functions_FBLSA_mlcp);
132 }
133
134
135