2 #include "linespace.hh"
6 #include "unionfind.hh"
7 #include "idealspacing.hh"
9 const Real COLFUDGE
=1e-3;
13 Spacing_problem::contains(const PCol
*w
)
15 for (int i
=0; i
< cols
.size(); i
++)
16 if (cols
[i
].pcol_
== w
)
22 Spacing_problem::col_id(const PCol
*w
)const
24 for (int i
=0; i
< cols
.size(); i
++)
25 if (cols
[i
].pcol_
== w
)
32 Spacing_problem::OK() const
35 Union_find
connected(cols
.size());
37 for (int i
=0; i
< ideals
.size(); i
++) {
38 assert(ideals
[i
]->hooke
> 0);
39 int l
= col_id(ideals
[i
]->left
);
40 int r
= col_id(ideals
[i
]->right
);
41 connected
.connect(l
,r
);
43 for (int i
= 0; i
< cols
.size(); i
++)
46 for (int i
= 0; i
< cols
.size(); i
++) {
48 for (int j
=0; j
<fixed
.size(); j
++)
49 c
|= connected
.equiv(fixed
[j
],i
);
51 WARN
<< "You have unconnected columns. \n"
52 "Check if bars and music fit each other\n"
60 Spacing_problem::check_constraints(Vector v
) const
63 for (int i
=0; i
< dim
; i
++) {
66 abs(cols
[i
].fixed_position() - v(i
)) > COLFUDGE
)
72 Real mindist
=cols
[i
-1].minright()
76 Real dif
=v(i
) - v(i
-1)- mindist
;
77 bool b
= (dif
> - COLFUDGE
);
88 Spacing_problem::check_feasible() const
90 Vector
sol(try_initial_solution());
91 return check_constraints(sol
);
94 // generate a solution which obeys the min distances and fixed positions
96 Spacing_problem::try_initial_solution() const
100 for (int i
=0; i
< dim
; i
++) {
101 if (cols
[i
].fixed()) {
102 initsol(i
)=cols
[i
].fixed_position();
104 Real mindist
=cols
[i
-1].minright()
106 assert(mindist
>= 0.0);
107 initsol(i
)=initsol(i
-1)+mindist
;
111 // assert(initsol(i) > initsol(i-1));
118 Spacing_problem::find_initial_solution() const
120 Vector
v(try_initial_solution());
121 assert(check_constraints(v
));
125 // generate the matrices
127 Spacing_problem::make_matrices(Matrix
&quad
, Vector
&lin
, Real
&c
) const
132 for (int j
=0; j
< ideals
.size(); j
++){
133 Idealspacing
const*i
=ideals
[j
];
134 int l
= col_id(i
->left
);
135 int r
= col_id(i
->right
);
137 quad(r
,r
) += i
->hooke
;
138 quad(r
,l
) -= i
->hooke
;
139 quad(l
,r
) -= i
->hooke
;
140 quad(l
,l
) += i
->hooke
;
142 lin(r
) -= i
->space
*i
->hooke
;
143 lin(l
) += i
->space
*i
->hooke
;
149 // put the constraints into the LP problem
151 Spacing_problem::make_constraints(Mixed_qp
& lp
) const
154 for (int j
=0; j
< dim
; j
++) {
155 Colinfo
*c
=&(cols
[j
]);
157 lp
.add_fixed_var(j
,c
->fixed_position());
164 lp
.add_inequality_cons(c1
, cols
[j
-1].minright() +
171 Spacing_problem::solve() const
175 assert(check_feasible());
177 /* optimalisatiefunctie */
178 Mixed_qp
lp(cols
.size());
179 make_matrices(lp
.quad
,lp
.lin
, lp
.const_term
);
180 make_constraints(lp
);
181 Vector start
=find_initial_solution();
182 Vector
sol(lp
.solve(start
));
183 if (!check_constraints(sol
)) {
184 WARN
<< "solution doesn't satisfy constraints.\n" ;
188 Array
<Real
> posns(sol
);
189 posns
.push(lp
.eval(sol
));
194 add one column to the problem.
197 Spacing_problem::add_column(const PCol
*col
, bool fixed
, Real fixpos
)
199 Colinfo
c(col
,(fixed
)? &fixpos
: 0);
204 Spacing_problem::add_ideal(const Idealspacing
*i
)
206 const PCol
*l
=i
->left
;
207 const PCol
*r
= i
->right
;
209 if (!contains(l
) || !contains(r
)) {
216 Spacing_problem::print_ideal(const Idealspacing
*id
)const
219 int l
= col_id(id
->left
);
220 int r
= col_id(id
->right
);
222 mtor
<< "between " << l
<<","<<r
<<":" ;
228 Spacing_problem::print() const
231 for (int i
=0; i
< cols
.size(); i
++) {
232 mtor
<< "col " << i
<<' ';
235 for (int i
=0; i
< ideals
.size(); i
++) {
236 print_ideal(ideals
[i
]);
242 /* **************** */
245 Colinfo::print() const
250 mtor
<< "fixed at " << fixed_position()<<", ";
252 mtor
<< "[" << minleft() << ", " << minright() << "]";
257 Colinfo::Colinfo(Colinfo
const&c
)
259 fixpos
= (c
.fixpos
)?new Real(*c
.fixpos
):0;
264 Colinfo::Colinfo(const PCol
*col_p
, const Real
*fixed_r_p
)
266 fixpos
= (fixed_r_p
)? new Real(*fixed_r_p
) : 0;
268 width
= pcol_
->width();
282 Colinfo::operator=(Colinfo
const&c
)
285 fixpos
= (c
.fixpos
)?new Real(*c
.fixpos
):0;