From deb0d0988347d748a0582dfad3a12590ccf3aed2 Mon Sep 17 00:00:00 2001 From: fred Date: Sat, 5 Oct 1996 15:49:40 +0000 Subject: [PATCH] lilypond-0.0.1 --- parser.y | 121 ++++++++++++++++++++++++++ qlpsolve.cc | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++ rhythmstaf.cc | 150 ++++++++++++++++++++++++++++++++ 3 files changed, 501 insertions(+) create mode 100644 parser.y create mode 100644 qlpsolve.cc create mode 100644 rhythmstaf.cc diff --git a/parser.y b/parser.y new file mode 100644 index 0000000000..23987a273d --- /dev/null +++ b/parser.y @@ -0,0 +1,121 @@ +%{ // -*-Fundamental-*- +#include +//#include "mudobs.hh" +#include "lexer.hh" +#include "staff.hh" +#include "score.hh" +#include "keyword.hh" +#include "globvars.hh" +#include "debug.hh" +#include "parseconstruct.hh" +#define YYDEBUG 1 + + +%} + + +%union { + int i; + Real real; + Command *command; + Identifier *id; + + Voice *voice; + Voice_element *el; + Staff *staff; + String *string; + Score *score; +} + +%token VOICE STAFF SCORE TITLE RHYTHMSTAFF BAR NOTENAME + +%token IDENTIFIER +%token PITCH DURATION RESTNAME +%token REAL + + +%type voice_block voice_body voice_elts voice_elts_dollar +%type voice_elt +%type score_command +%type score_block score_body +%type staff_block rhythmstaff_block rhythmstaff_body + +%% + +mudela: + score_block { + delete the_score; + the_score = $1; + } + ; + + +score_block: SCORE '{' score_body '}' { $$ = $3; } + ; + +score_body: { $$ = new Score; } + | score_body staff_block { $$->add($2); } + | score_body score_command { $$->add($2); } + ; + +staff_block: + rhythmstaff_block + ; + +rhythmstaff_block: + RHYTHMSTAFF '{' rhythmstaff_body '}' { $$ = $3; } + ; + +rhythmstaff_body: + /* empty */ { $$ = get_new_rhythmstaff(); } + | rhythmstaff_body voice_block { $$->add_voice($2); } + ; + +voice_block: + VOICE '{' voice_body '}' { $$ = $3; } + ; + + +voice_body: + REAL voice_elts_dollar { $$ = $2; $$->start = $1; } + | voice_elts_dollar { $$ = $1; } + ; + +voice_elts_dollar: + '$' voice_elts '$' { $$ = $2; } + ; + +voice_elts: + /* empty */ { + $$ = new Voice; + } + | voice_elts voice_elt { + $$->add($2); + } + ; + +voice_elt: + PITCH DURATION { $$ = get_note_element(*$1, *$2); + + } + | RESTNAME DURATION { $$ = get_rest_element(*$1, *$2); + + } + ; + +score_command: + BAR REAL { + $$ = get_bar_command($2); + } + ; + +%% + +void +parse_file(String s) +{ + *mlog << "Parsing ... "; + yydebug = debug_flags & DEBUGPARSER; + new_input(s); + yyparse(); +} diff --git a/qlpsolve.cc b/qlpsolve.cc new file mode 100644 index 0000000000..0884223e6c --- /dev/null +++ b/qlpsolve.cc @@ -0,0 +1,230 @@ +#include "qlpsolve.hh" +#include "debug.hh" +#include "choleski.hh" + +const Real TOL=1e-2; // roughly 1/10 mm + +String +Active_constraints::status() const +{ + String s("Active|Inactive ["); + for (int i=0; i< active.sz(); i++) { + s += String(active[i]) + " "; + } + + s+="|"; + for (int i=0; i< inactive.sz(); i++) { + s += String(inactive[i]) + " "; + } + s+="]"; + + return s; +} + +void +Active_constraints::OK() { + H.OK(); + A.OK(); + assert(active.sz() +inactive.sz() == opt->cons.sz()); + assert(H.dim() == opt->dim()); + assert(active.sz() == A.rows()); + svec allcons; + + for (int i=0; i < opt->cons.sz(); i++) + allcons.add(0); + for (int i=0; i < active.sz(); i++) { + int j = active[i]; + allcons[j]++; + } + for (int i=0; i < inactive.sz(); i++) { + int j = inactive[i]; + allcons[j]++; + } + for (int i=0; i < allcons.sz(); i++) + assert(allcons[i] == 1); +} + +Vector +Active_constraints::get_lagrange(Vector gradient) +{ + Vector l(A*gradient); + + return l; +} + +void +Active_constraints::add(int k) +{ + // add indices + int cidx=inactive[k]; + active.add(cidx); + + inactive.swap(k,inactive.sz()-1); + inactive.pop(); + + Vector a( opt->cons[cidx] ); + // update of matrices + Vector Ha = H*a; + Real aHa = a*Ha; + + H -= Matrix(Ha , Ha)/(aHa); + + Vector addrow(Ha/(aHa)); + A -= Matrix(A*a, addrow); + A.insert_row(addrow,A.rows()); +} + +void +Active_constraints::drop(int k) +{ + int q=active.sz()-1; + + // drop indices + inactive.add(active[k]); + active.swap(k,q); + A.swap_rows(k,q); + active.pop(); + + Vector a(A.row(q)); + H += Matrix(a,a)/(a*opt->quad*a); + A -= A*opt->quad*Matrix(a,a)/(a*opt->quad*a); + + Vector rem_row(A.row(q)); + assert(rem_row.norm() < EPS); + A.delete_row(q); +} + + +Active_constraints::Active_constraints(Ineq_constrained_qp const *op) + : A(0,op->dim()), + H(op->dim()), + opt(op) +{ + for (int i=0; i < op->cons.sz(); i++) + inactive.add(i); + Choleski_decomposition chol(op->quad); + H=chol.inverse(); +} + +/* Find the optimum which is in the planes generated by the active + constraints. + */ +Vector +Active_constraints::find_active_optimum(Vector g) +{ + return H*g; +} + +/****************************************************************/ + +int +min_elt_index(Vector v) +{ + Real m=INFTY; int idx=-1; + for (int i = 0; i < v.dim(); i++) + if (v(i) < m) { + idx = i; + m = v(i); + } + return idx; +} + +///the numerical solving +Vector +Ineq_constrained_qp::solve(Vector start) const +{ + Active_constraints act(this); + + + act.OK(); + + + Vector x(start); + Vector gradient=quad*x+lin; + + + Vector last_gradient(gradient); + int iterations=0; + + while (iterations++ < MAXITER) { + Vector direction= - act.find_active_optimum(gradient); + + // mtor << "gradient "<< gradient<< "\ndirection " << direction<<"\n"; + + if (direction.norm() > EPS) { + // mtor << act.status() << '\n'; + + Real minalf = INFTY; + + Inactive_iter minidx(act); + + + /* + we know the optimum on this "hyperplane". Check if we + bump into the edges of the simplex + */ + + for (Inactive_iter ia(act); ia.ok(); ia++) { + + if (ia.vec() * direction >= 0) + continue; + Real alfa= - (ia.vec()*x - ia.rhs())/ + (ia.vec()*direction); + + if (minalf > alfa) { + minidx = ia; + minalf = alfa; + } + } + Real unbounded_alfa = 1.0; + Real optimal_step = MIN(minalf, unbounded_alfa); + + Vector deltax=direction * optimal_step; + x += deltax; + gradient += optimal_step * (quad * deltax); + + //mtor << "step = " << optimal_step<< " (|dx| = " << + //deltax.norm() << ")\n"; + + if (minalf < unbounded_alfa) { + /* bumped into an edge. try again, in smaller space. */ + act.add(minidx.idx()); + continue; + } + /*ASSERT: we are at optimal solution for this "plane"*/ + + + } + + Vector lagrange_mult=act.get_lagrange(gradient); + int m= min_elt_index(lagrange_mult); + + if (m>=0 && lagrange_mult(m) > 0) { + break; // optimal sol. + } else if (m<0 && gradient.norm() < EPS) { + break; + } + + mtor << "dropping cons " << m<<'\n'; + act.drop(m); + } + if (iterations >= MAXITER) + WARN<<"didn't converge!\n"; + + // mtor << ": found " << x<<" in " << iterations <<" iterations\n"; + assert_solution(x); + return x; +} + +/** Mordecai Avriel, Nonlinear Programming: analysis and methods (1976) + Prentice Hall. + + Section 13.3 + + This is a "projected gradient" algorithm. Starting + from a point x the next point is found in a direction determined by + projecting the gradient onto the active constraints. */ + +/* + thoroughly hacked to barely living tiny pieces by HW + */ diff --git a/rhythmstaf.cc b/rhythmstaf.cc new file mode 100644 index 0000000000..61eca843f8 --- /dev/null +++ b/rhythmstaf.cc @@ -0,0 +1,150 @@ +#include "request.hh" +#include "debug.hh" +#include "linestaff.hh" +#include "staff.hh" +#include "pstaff.hh" +#include "pscore.hh" +#include "command.hh" +#include "molecule.hh" +#include "rhythmstaf.hh" + + + +Rhythmic_column::Rhythmic_column(Score_column*s, Rhythmic_staff *rs) + : Staff_column(s) +{ + the_note = 0; + staff_ = rs; +} + + +void +Rhythmic_staff::set_output(PScore* ps ) +{ + theline = new Linestaff(1); + pscore_ = ps; + pscore_->add(theline); +} + +// should integrate handling of BREAK commands into Staff_column +void +Rhythmic_column::process_commands( ) +{ + int breakstat = BREAK_END; + for (int i = 0 ; i < s_commands.sz(); i++) { + Command *com = s_commands[i]; + switch (com->code){ + case INTERPRET: + break; + case BREAK_PRE: + case BREAK_MIDDLE: + case BREAK_POST: + case BREAK_END: + score_column->set_breakable(); + breakstat = com->code; + break; + + case TYPESET: + typeset_command ( com , breakstat); + break; + default : + break; + } + + } +} +/** + accept: + + BREAK: all + TYPESET: bar, meter + + */ + + + +void +Rhythmic_column::process_requests() +{ + for (int i = 0 ; i < v_elts.sz(); i ++) + for (PCursor rqc(v_elts[i]->reqs); rqc.ok(); rqc++) { + Request *rq= rqc; + switch(rq->tag){ + case Request::NOTE: + case Request::REST: + if (the_note){ + WARN << "too many notes.\n"; + return; + } + the_note = rq; + break; + + default: + return; + } + } + +} + + +void +Rhythmic_column::typeset_command(Command *com, int breakst) +{ + Item *i = new Item; + const Symbol*s=0; + + if (com -> args[0] == "|" ) { + s = Symbol::find_bar("|"); + } else + assert(false); + + i->output=new Molecule(Atom(s)); + staff_->pscore_->typeset_item(i, score_column->pcol, + staff_->theline,breakst); +} + +void +Rhythmic_column::typeset_req(Request *rq) +{ + Item *i = new Item; + const Symbol*s=0; + + switch(rq->tag){ + case Request::NOTE: + s = Symbol::find_ball(rq->note()->balltype); + break; + case Request::REST: + s = Symbol::find_rest(rq->rest()->balltype); + break; + default: + assert(false); + break; + } + i->output = new Molecule(Atom(s)); + + staff_->pscore_->typeset_item(i, score_column->pcol, staff_->theline,0 ); +} + +void +Rhythmic_staff::grant_requests() +{ + for (PCursor cc(cols); cc.ok(); cc++) { + Rhythmic_column *rp = (Rhythmic_column*)*cc; + if (rp->the_note) + rp->typeset_req( rp->the_note); + } +} + +Staff_column* +Rhythmic_staff::create_col(Score_column*s) +{ + Rhythmic_column *rc = new Rhythmic_column(s,this); + + return rc; +} + +Staff * +get_new_rhythmstaff() +{ + return new Rhythmic_staff; +} -- 2.39.5