(c) 2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
*/
+/*
+ TODO:
+
+ * vsize vs. int: casts should not be necessary. Use VPOS iso -1 as
+ magic signaling value?
+
+ * The specification uses A j, k, n and m as variables.
+
+ Functions use start,end,sys_count,calc_subproblem as variables. Use the same naming
+ for the specification as for the code.
+
+
+ FURTHER REMARKS:
+
+ *
+
+ int a;
+ int b;
+
+ iso.
+
+ int a, b;
+
+
+ * no spurious * in <slash><star> <star><slash> comments.
+
+
+ */
+
+
#include "constrained-breaking.hh"
-#include "warn.hh"
+#include "international.hh"
#include "main.hh"
+#include "output-def.hh"
#include "paper-column.hh"
#include "paper-score.hh"
-#include "output-def.hh"
#include "simple-spacer.hh"
#include "system.hh"
-
-#include "international.hh"
+#include "warn.hh"
void
print_constrained_break_nodes (vector<Constrained_break_node> const &arr)
the piece)
Then A_{k+1, m} is contructed from
- min_ {k < j < m} ( W(A_{k,j} :: m) )
+ min_ {k < j < m} ( W(A_{k,j} :: m) )
where by A::m we denote appending m to the list A
+
*/
/* start and sys here are indexed from 0.
- * max_break is indexed from starting_breakpoints_[start]
- * (for max_break, starting_breakpoints_[start] is the beginning
- * of the piece; the smallest value we should ever see here is
- * starting_breakpoints_[start] + 1) */
+
+max_break is indexed from starting_breakpoints_[start] (for
+ max_break, starting_breakpoints_[start] is the beginning of the
+ piece; the smallest value we should ever see here is
+ starting_breakpoints_[start] + 1) */
bool
Constrained_breaking::calc_subproblem (int start, int sys, int max_break)
{
vector<Constrained_break_node> &st = state_[start];
int rank = breaks_.size () - start_col;
int max_index = max_break - start_col;
- for (int j=sys; j < max_index; j++)
+ for (int j = sys; j < max_index; j++)
{
if (0 == sys && j > 0)
break; /* the first line cannot have its first break after the beginning */
if (isinf (dem))
continue;
- if (isinf (st[sys*rank + max_index].demerits_)
- || dem < st[sys*rank + max_index].demerits_)
+ int k = sys*rank + max_index;
+ if (isinf (st[k].demerits_)
+ || dem < st[k].demerits_)
{
found_something = true;
- st[sys*rank + max_index].demerits_ = dem;
- st[sys*rank + max_index].force_ = force;
- st[sys*rank + max_index].penalty_ = pen;
- st[sys*rank + max_index].prev_ = j;
- st[sys*rank + max_index].line_config_ = cur;
+
+ /*
+ TODO: maybe just copy a Constrained_break_node ?
+ */
+ st[k].demerits_ = dem;
+ st[k].force_ = force;
+ st[k].penalty_ = pen;
+ st[k].prev_ = j;
+ st[k].line_config_ = cur;
}
}
return found_something;
}
vector<Column_x_positions>
-Constrained_breaking::do_solve ()
+Constrained_breaking::solve ()
{
if (!systems_)
{
programming_error (_f ("no system number set in constrained-breaking"));
- systems_ = 4;
+ systems_ = start_.size () / 2;
}
resize ();
- return get_solution(0, systems_, -1);
+ return get_solution (0, systems_, -1);
}
void
bool ragged_last = to_boolean (pscore_->layout ()->c_variable ("ragged-last"));
/* do all the rod/spring problems */
- breaks_ = find_break_indices ();
+ breaks_ = pscore_->find_break_indices ();
cols_rank_ = breaks_.size ();
all_ = pscore_->root_system ()->columns ();
cols_.resize (breaks_.size () * breaks_.size ());
for (vsize i = 0; i < breaks_.size () - 1; i++)
- for (vsize j = i + 1; j < breaks_.size (); j++)
- {
- vector<Grob*> line (all_.begin () + breaks_[i],
- all_.begin() + breaks_[j] + 1);
+ for (vsize j = i + 1; j < breaks_.size (); j++)
+ {
+ vector<Grob*> line (all_.begin () + breaks_[i],
+ all_.begin() + breaks_[j] + 1);
- line[0] = dynamic_cast<Item *> (line[0])->find_prebroken_piece (RIGHT);
- line.back () = dynamic_cast<Item *> (line.back ())->find_prebroken_piece (LEFT);
+ line[0] = dynamic_cast<Item *> (line[0])->find_prebroken_piece (RIGHT);
+ line.back () = dynamic_cast<Item *> (line.back ())->find_prebroken_piece (LEFT);
- cols_[i*cols_rank_ + j].cols_ = line;
+ cols_[i*cols_rank_ + j].cols_ = line;
- /* we have no idea what line this will be -- only whether it is the first */
- Interval line_dims = line_dimensions_int (pscore_->layout (), i);
- Simple_spacer_wrapper *sp = generate_spacing_problem (line, line_dims);
+ /* we have no idea what line this will be -- only whether it is the first */
+ Interval line_dims = line_dimensions_int (pscore_->layout (), i);
+ Simple_spacer_wrapper *sp = generate_spacing_problem (line, line_dims);
- /* TODO: support raggedness */
- bool last = j == breaks_.size () - 1;
- bool ragged = ragged_right || (last && ragged_last);
- sp->solve (&cols_[i*cols_rank_ + j], ragged);
+ bool last = j == breaks_.size () - 1;
+ bool ragged = ragged_right || (last && ragged_last);
+ sp->solve (&cols_[i*cols_rank_ + j], ragged);
- if (!cols_[i*cols_rank_ + j].satisfies_constraints_)
- break;
- delete sp;
- }
+ if (!cols_[i*cols_rank_ + j].satisfies_constraints_)
+ break;
+ delete sp;
+ }
/* work out all the starting indices */
for (vsize i = 0; i < start_.size (); i++)
for (vsize k = starting_breakpoints_[i] + j + 1; k < breaks_.size (); k++)
if (!calc_subproblem (i, j, k))
break; /* if we couldn't break this, it is too cramped already */
+
valid_systems_ = systems_;
}
vector<Column_x_positions>
Constrained_breaking::get_solution (int start, int end, int sys_count)
{
- int rank, brk;
+ int rank;
+ int brk;
prepare_solution (start, end, sys_count, &rank, &brk);
vector<Constrained_break_node> const &st = state_[start];
for (int sys = sys_count-1; sys >= 0; sys--)
{
assert (brk > 0);
- ret.push_back( st[sys*rank + brk].line_config_ );
+ ret.push_back (st[sys*rank + brk].line_config_);
brk = st[sys*rank + brk].prev_;
}
assert (brk == 0);
+
reverse (ret);
return ret;
}
Real
Constrained_breaking::get_demerits (int start, int end, int sys_count)
{
- int rank, brk;
+ int rank;
+ int brk;
prepare_solution (start, end, sys_count, &rank, &brk);
return state_[start][(sys_count-1)*rank + brk].demerits_;
Real
Constrained_breaking::get_force (int start, int end, int sys_count)
{
- int rank, brk;
+ int rank;
+ int brk;
prepare_solution (start, end, sys_count, &rank, &brk);
vector<Constrained_break_node> const &st = state_[start];
Real f = 0;
Real
Constrained_breaking::get_penalty (int start, int end, int sys_count)
{
- int rank, brk;
+ int rank;
+ int brk;
prepare_solution (start, end, sys_count, &rank, &brk);
return state_[start][(sys_count-1)*rank + brk].penalty_;
Real
Constrained_breaking::get_page_penalty (int start, int end, int sys_count, int sys_num)
{
- int rank, brk;
+ int rank;
+ int brk;
prepare_solution (start, end, sys_count, &rank, &brk);
int sys;
for (sys = sys_count-1; sys > sys_num; sys--)
- brk = state_[start][sys*rank + brk].prev_;
+ brk = state_[start][sys*rank + brk].prev_;
if (brk < 0) /* we didn't satisfy constraints */
return 0;
int
Constrained_breaking::get_min_systems (int start, int end)
{
- int rank, brk;
+ int rank;
+ int brk;
prepare_solution (start, end, 1, &rank, &brk);
int sys_count;
vector<Constrained_break_node> const &st = state_[start];
}
void
-Constrained_breaking::prepare_solution (int start, int end, int sys_count, int *rank, int *brk)
+Constrained_breaking::prepare_solution (vsize start, int end, int sys_count, int *rank, int *brk)
{
- assert (start < (int)start_.size () && end <= (int)start_.size ());
- assert (end < 0 || start < end);
+ assert (start < start_.size () && end <= int (start_.size ()));
+ assert (end < 0 || int (start) < end);
assert (sys_count > 0);
if (sys_count >= valid_systems_)
start_.push_back (0);
}
-Constrained_breaking::Constrained_breaking (vector<int> const &start):
- start_ (start)
+Constrained_breaking::Constrained_breaking (vector<int> const &start)
+ : start_ (start)
{
valid_systems_ = systems_ = 0;
}
struct Constrained_break_node
{
/** the number of bars in all the systems before this one
- */
+ */
int prev_;
/** unlike the Gourlay breaker, this is the sum of all demerits up to,
*/
class Constrained_breaking : public Break_algorithm
{
- public:
- std::vector<Column_x_positions> do_solve ();
- Constrained_breaking ();
- Constrained_breaking (std::vector<int> const &start_col_posns);
+public:
+ std::vector<Column_x_positions> solve ();
+ Constrained_breaking ();
+ Constrained_breaking (std::vector<int> const &start_col_posns);
- std::vector<Column_x_positions> get_solution(int start, int end, int sys_count);
- Real get_demerits (int start, int end, int sys_count);
- Real get_force (int start, int end, int sys_count);
- Real get_penalty (int start, int end, int sys_count);
- int get_max_systems (int start, int end);
- int get_min_systems (int start, int end);
+ std::vector<Column_x_positions> get_solution(int start, int end, int sys_count);
+ Real get_demerits (int start, int end, int sys_count);
+ Real get_force (int start, int end, int sys_count);
+ Real get_penalty (int start, int end, int sys_count);
+ int get_max_systems (int start, int end);
+ int get_min_systems (int start, int end);
- /* get the page penalty of system number sys with the given breaking */
- Real get_page_penalty (int start, int end, int sys_count, int sys);
+ /* get the page penalty of system number sys with the given breaking */
+ Real get_page_penalty (int start, int end, int sys_count, int sys);
- private:
- int valid_systems_;
- int systems_;
+ int systems_;
+private:
+ int valid_systems_;
- /* the (i,j)th entry is the column configuration for breaking between
- * columns i and j */
- std::vector<Column_x_positions> cols_;
- int cols_rank_;
+ /* the (i,j)th entry is the column configuration for breaking
+ between columns i and j */
+ std::vector<Column_x_positions> cols_;
+ int cols_rank_;
- /* the [i](j,k)th entry is the score for fitting the first k bars onto the
- * first j systems, starting at the i'th allowed starting column */
- std::vector<std::vector<Constrained_break_node> > state_;
+ /* the [i](j,k)th entry is the score for fitting the first k bars onto the
+ first j systems, starting at the i'th allowed starting column */
+ std::vector<std::vector<Constrained_break_node> > state_;
- vector<int> start_; /* the columns at which we might be asked to start breaking */
- vector<int> starting_breakpoints_; /* the corresponding index in breaks_ */
+ vector<int> start_; /* the columns at which we might be asked to start breaking */
+ vector<int> starting_breakpoints_; /* the corresponding index in breaks_ */
- vector<Grob*> all_;
- std::vector<int> breaks_;
+ vector<Grob*> all_;
+ std::vector<int> breaks_;
- void prepare_solution (int start, int end, int sys_count, int *rank, int *brk);
+ void prepare_solution (vsize start, int end, int sys_count, int *rank, int *brk);
- void combine_demerits (Column_x_positions const &, Column_x_positions const &,
- Real *force, Real *pen, Real *dem) const;
+ void combine_demerits (Column_x_positions const &, Column_x_positions const &,
+ Real *force, Real *pen, Real *dem) const;
- bool calc_subproblem(int start, int systems, int max_break_index);
- void resize ();
+ bool calc_subproblem(int start, int systems, int max_break_index);
+ void resize ();
};
#endif /* CONSTRAINED_BREAKING_HH */