Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First derivative #151

Open
wants to merge 78 commits into
base: outside_looporder
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
0b3cda2
adding a new command line argument for derivatives
sjanssen2 Oct 21, 2022
8dd2887
adding novel rtlib header file for derivative computation
sjanssen2 Oct 21, 2022
830d8d4
codestyle
sjanssen2 Oct 21, 2022
7820102
add a convenience function for debugging, which prints a list of stat…
sjanssen2 Oct 21, 2022
584f093
reorder declarations for better debugging
sjanssen2 Oct 21, 2022
fc73e8b
let the AST know that the user requested code generation for derivatives
sjanssen2 Oct 22, 2022
19458b7
enable adding another argument to the front
sjanssen2 Oct 22, 2022
5d388d2
injecting first statements in inside code
sjanssen2 Oct 22, 2022
60c364c
adding first derivatives test
sjanssen2 Oct 25, 2022
b35e257
add functions to generate getter and setter for derivatives
sjanssen2 Oct 25, 2022
50b95aa
report derivatives instead of outside results
sjanssen2 Oct 25, 2022
eb7ed8b
pass calling-NT to alt code generation
sjanssen2 Oct 25, 2022
4084123
moved additional functionallity from generated *.hh to here
sjanssen2 Oct 25, 2022
6afe046
make OUTSIDE_NT_PREFIX more visible in grammar.hh
sjanssen2 Oct 25, 2022
087fabc
record user provided axiom, since it will be changes in outside gener…
sjanssen2 Oct 25, 2022
60d2e7c
pass ast to init_ret_stmts
sjanssen2 Oct 25, 2022
44677b5
add "candidates" list in NT generation to record use of sub-solutions
sjanssen2 Oct 25, 2022
69cfed9
define functions for derivative reporting function generation
sjanssen2 Oct 25, 2022
ecef00b
inject and init new traces Vector in Table Declartion; define DERIVAT…
sjanssen2 Oct 25, 2022
58f7af2
pass calling-NT to alt code generation; for outside-NTs: retrieve pre…
sjanssen2 Oct 25, 2022
402a382
adding scoring algebra for derivative testing
sjanssen2 Oct 25, 2022
8f600a0
use proper return variable name
sjanssen2 Oct 25, 2022
40b4a23
move execution of statements to a) enable debugging and b) use same "…
sjanssen2 Oct 25, 2022
4da7e91
moving functionality into own function, since it need to be called in…
sjanssen2 Oct 25, 2022
ad1c566
alts might be parameterized Terminals. Don't inject in these cases
sjanssen2 Oct 25, 2022
e01e058
activating two more tests: needleman wunsch derivatives
sjanssen2 Oct 25, 2022
2f9cdc2
adding Gotoh grammar for further testing
sjanssen2 Oct 26, 2022
4af9441
in order to add statements for tracing within the IF condition for pu…
sjanssen2 Oct 26, 2022
edc2495
codestyle
sjanssen2 Oct 26, 2022
1255074
switch order of grammar definitions to pass mod tests
sjanssen2 Oct 26, 2022
2ccb881
add check for untabulated results
sjanssen2 Oct 26, 2022
73cfab3
adding a todo
sjanssen2 Oct 26, 2022
d9cf41d
use correct alt table, also consider direct link to other non-termina…
sjanssen2 Oct 26, 2022
e61d6d8
adding Gotoh test
sjanssen2 Oct 26, 2022
84c23e7
codestyle
sjanssen2 Oct 26, 2022
2cafbbe
add missing condition
sjanssen2 Oct 26, 2022
69d3d50
per definition outside_axiom table returns a list, i.e. cannot be red…
sjanssen2 Oct 26, 2022
3af1850
proper newline for 1D NTs
sjanssen2 Oct 26, 2022
b11535f
when sub-setting traces to those into a specific DP cell, not only th…
sjanssen2 Nov 4, 2022
a25d296
take advantage that main_out.cc first calls run() for forward pass, t…
sjanssen2 Nov 4, 2022
60e4e97
adding short nodangle test
sjanssen2 Nov 4, 2022
34ecb66
Merge pull request #155 from jlab/deriv_nodangle_short
sjanssen2 Nov 4, 2022
1521237
adding a longer example
sjanssen2 Nov 4, 2022
402fd8b
adding branch that shall execute tests
sjanssen2 Dec 2, 2022
2fe5793
rename "first derivatives" into "1. derivatives"
sjanssen2 Dec 5, 2022
041cb8c
Merge branch 'outside_looporder' of github.com:jlab/gapc into first_d…
sjanssen2 Dec 7, 2022
6ddebbe
Merge branch 'outside_looporder' of github.com:jlab/gapc into first_d…
sjanssen2 Dec 7, 2022
0ccb647
refactor: derivatives_create_candidate functions for different Alt ty…
sjanssen2 Dec 9, 2022
3beaaf3
linting
sjanssen2 Dec 9, 2022
efa94cf
Merge pull request #162 from jlab/todo_derivatives_create_candidate
sjanssen2 Dec 9, 2022
26c6eca
also inject derivative recording code for simple blocks like weak = {…
sjanssen2 Dec 9, 2022
5159bcf
enable trace recording for nested Blocks
sjanssen2 Dec 9, 2022
e06053f
throw warning when using blocks - for now
sjanssen2 Dec 9, 2022
23b388f
set recursion base to 1.0 for first derivative computation
sjanssen2 Dec 16, 2022
c9cf750
add Sonne-Regen test
sjanssen2 Dec 16, 2022
2de7319
add probabilistically proper Sonne Regen HMM
sjanssen2 Dec 16, 2022
d9fcd54
log space requires re-transformation here
sjanssen2 Dec 20, 2022
1ace193
replace h with sum
sjanssen2 Dec 20, 2022
6e59960
add function to replace h with sum in outside rules for derivative ge…
sjanssen2 Dec 20, 2022
e7eb90f
fixing type optimization for derivative versions of choice functions
sjanssen2 Dec 21, 2022
c6a3cd0
remove tab
sjanssen2 Dec 21, 2022
99962ec
adding normalize_derivative functions
sjanssen2 Dec 23, 2022
30a1b90
pass the user prodived normalization function as another argument
sjanssen2 Dec 23, 2022
0623602
lint & typo
sjanssen2 Dec 23, 2022
77c0f39
new semantic check that tests for presense of normalization function …
sjanssen2 Dec 23, 2022
acbef3a
make special normalization "static"
sjanssen2 Dec 23, 2022
75f306f
run check for derivative function
sjanssen2 Dec 23, 2022
2131890
use passed user function to normalize a trace VS partition function, …
sjanssen2 Dec 23, 2022
c7979c5
when searching for answer type, skip choice functions
sjanssen2 Dec 23, 2022
76d87dd
revert stupid error: type inference independent on actual check
sjanssen2 Dec 23, 2022
634ed8e
definding alternative algebras with different probability normalizati…
sjanssen2 Jan 10, 2023
09383e1
fix error msg generation and print body of missing function
sjanssen2 Jan 10, 2023
8bd63fb
add checks for normalize_derivative addition
sjanssen2 Jan 10, 2023
5044024
add choice function for summation over negative logarithms
sjanssen2 Jan 10, 2023
7a1656a
Merge pull request #164 from jlab/hSUM
sjanssen2 Jan 13, 2023
fa97cd9
Merge branch 'master' of github.com:jlab/gapc into hSUM
sjanssen2 Jan 13, 2023
68ab4f0
Merge pull request #169 from jlab/hSUM
sjanssen2 Jan 13, 2023
ac5fa8f
Merge branch 'outside_looporder' into first_derivative
sjanssen2 Jan 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/c-cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: [ master ]
pull_request:
branches: [ master, outside_looporder ]
branches: [ master, outside_looporder, first_derivative ]
workflow_dispatch:
inputs:
logLevel:
Expand Down
4 changes: 4 additions & 0 deletions rtlib/generic_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,11 @@ int main(int argc, char **argv) {
std::cout << "Answer: \n";
obj.print_result(std::cout, res);
#else
#ifndef DERIVATIVES
obj.report_insideoutside(std::cout);
#else
obj.report_derivative(std::cout);
#endif
#endif

gapc::add_event("end_result_pp");
Expand Down
172 changes: 172 additions & 0 deletions rtlib/traces.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/* {{{

This file is part of gapc (GAPC - Grammars, Algebras, Products - Compiler;
a system to compile algebraic dynamic programming programs)

Copyright (C) 2008-2011 Georg Sauthoff
email: gsauthof@techfak.uni-bielefeld.de or gsauthof@sdf.lonestar.org

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

}}} */


#ifndef RTLIB_TRACES_HH_
#define RTLIB_TRACES_HH_

#include <vector>
#include <tuple>
#include <cstdarg>
#include <string>

/* this records the use of a sub-solution of another NT result <name of other
* NT, index in other NT table with variable number of dimensions, weight
* of edge> */
typedef std::tuple<std::string, std::vector<unsigned int>, double > Trace;
/* Since a candidate can be composed of multiple sub-solutions e.g.
* mult(A, '*', B), we collect Traces for A and B */
typedef std::tuple<double, std::vector<Trace> > NTtrace;
/* collection of all traces of an NT in forward pass, together with their
* values. This later normalized into edge weights. */
// typedef std::vector<NTtrace> NTtraces;


/* create a vector of index components (one or multitrack, linear or quadratic
* tables) for a variable number of components therefore, the first argument
* must be the number of those components!
* https://stackoverflow.com/questions/1579719/variable-number-of-parameters\
* -in-function-in-c */
inline
std::vector<unsigned int> *make_index(unsigned int num_components, ...) {
std::vector<unsigned int> *indices = new std::vector<unsigned int>();
// Requires the last fixed parameter (to get the address)
va_list idx_components;
va_start(idx_components, num_components);
for (unsigned int j = 0; j < num_components; j++) {
indices->push_back(va_arg(idx_components, unsigned int));
}
va_end(idx_components);

return indices;
}

inline
bool is_same_index(std::vector<unsigned int> a, std::vector<unsigned int> b) {
if (a.size() != b.size()) {
return false;
}
std::vector<unsigned int>::const_iterator bi = b.begin();
for (std::vector<unsigned int>::const_iterator ai = a.begin();
ai != a.end(); ++ai, ++bi) {
if (*ai != *bi) {
return false;
}
}
return true;
}

class candidate {
private:
double value;
std::vector<Trace> sub_components;

public:
explicit candidate(double value) {
this->value = value;
}

candidate() {
this->value = 0.0;
}

void set_value(double value) {
this->value = value;
}

void add_sub_component(std::string otherNT,
std::vector<unsigned int> *indices) {
sub_components.push_back({otherNT, *indices, NULL});
}

std::vector<Trace> *get_sub_components() {
return &sub_components;
}

double get_value() const {
return value;
}

/* we need to normalize the individual trace values into probabilities
* trace values can come in different flavors, depending on what the
* user uses as scoring schema. See Algebra::check_derivative
*/
std::vector<Trace> get_normalized_candidate(
double eval, double (func)(double a, double b)) const {
std::vector<Trace> res;
for (std::vector<Trace>::const_iterator part = this->sub_components.begin();
part != this->sub_components.end(); ++part) {
res.push_back({std::get<0>(*part), std::get<1>(*part),
func(this->get_value() , eval)});
}
return res;
}
// void empty() {
// empty(this->value);
// }
};
typedef std::vector<candidate> NTtraces;

// once all use of sub-solutions for candidates is finished, we need to
// normalize their contributions
inline
std::vector<Trace> normalize_traces(std::vector<Trace> *tabulated,
const std::vector<candidate> &candidates,
double eval,
double (func)(double a, double b)) {
std::vector<std::tuple<std::string, std::vector<unsigned int>, double > > res;
for (std::vector<candidate>::const_iterator i = candidates.begin();
i != candidates.end(); ++i) {
std::vector<Trace> comp = (*i).get_normalized_candidate(eval, func);
res.insert(res.end(), comp.begin(), comp.end());
}
return res;
}

inline
double get_trace_weights(const std::vector<Trace> &traces,
const std::string &to_nt,
const std::vector<unsigned int> &to_indices,
double e) {
double res = 0.0;
for (std::vector<Trace>::const_iterator trace = traces.begin();
trace != traces.end(); ++trace) {
// TODO(sjanssen): move both conditions into is_same_index
if (is_same_index(std::get<1>(*trace), to_indices) &&
(std::get<0>(*trace) == to_nt)) {
res += e * std::get<2>(*trace);
}
}

return res;
}

// template<typename answer>
// using NTtraces = typename std::vector<candidate<answer> >::NTtraces;
/* collection of all traces of an NT in forward pass, together with their
* values. This later normalized into edge weights. */
/* collection of all traces of an NT in forward pass, together with their
* values. This later normalized into edge weights. */
// typedef std::vector<candidate<double> > NTtraces;

#endif // RTLIB_TRACES_HH_
52 changes: 51 additions & 1 deletion src/algebra.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
#include "printer.hh"

#include "mode.hh"

#include "grammar.hh"



Expand Down Expand Up @@ -304,6 +304,12 @@ void Algebra::derive_role() {
o << "Declared role of algebra choice function "
<< *fn->name << " (in algebra " << *name
<< ") does not match autodetected role " << tmp << '.';
/* do not raise the warning, if the choice function has been
* automatically generated for derivative outside application */
if ((*i).first.substr(0, sizeof(PREFIX_DERIVATIVE)-1).compare(
PREFIX_DERIVATIVE) == 0) {
continue;
}
Log::instance()->warning(fn->location, o.str());
}
}
Expand Down Expand Up @@ -386,3 +392,47 @@ Algebra *Algebra::copy() const {
}
return o;
}

// tests if Signature and Algebra for derivative computation contain
// a special function that normalizes traces
bool Algebra::check_derivative() {
bool r = true;

std::string ans_type = "unknown type";
for (hashtable<std::string, Fn_Def*>::const_iterator i = this->fns.begin();
i != this->fns.end(); ++i) {
if ((*i).second->is_Choice_Fn()) {
continue;
} else {
std::ostringstream o1;
o1 << *i->second->return_type;
ans_type = o1.str();
break;
}
}

hashtable<std::string, Fn_Def*>::const_iterator i = this->fns.find(
FN_NAME_DERIVATIVE_NORMALIZER);
if (i == this->fns.end()) {
std::string msg =
"You requested the computation of derivatives. This requires the "
"conversion of\n"
"weights of alternative sub-solutions (q) into probabilities. Please"
" provide\n"
"an additional algebra function, e.g.:\n\n " + ans_type + " " + \
FN_NAME_DERIVATIVE_NORMALIZER + "(" + ans_type + " q, " + ans_type + \
" pfunc) {\n return q <OPERATOR> pfunc;\n }\n\n"
"to your algebra \"" + *this->name + "\". Depending on your scoring "
"schema and\n"
"choice function, the body of " + FN_NAME_DERIVATIVE_NORMALIZER + \
" should normalize e.g.\n\n"
" scoring schema | choice func. | normalization \n"
" -----------------------------------------------\n"
" prob. | sum | q / pfunc \n"
" log(prob.) | expsum | exp(q - pfunc) \n"
" log(1/prob.) | negexpsum | exp(pfunc - q) \n"
" exp(score) | sum | q / pfunc \n";
Log::instance()->error(msg);
}
return r;
}
3 changes: 3 additions & 0 deletions src/algebra.hh
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class Fn_Def;
class Signature;
class Filter;

const char FN_NAME_DERIVATIVE_NORMALIZER[] = "normalize_derivative";

class Algebra : public Signature_Base {
private:
Expand Down Expand Up @@ -110,6 +111,8 @@ class Algebra : public Signature_Base {

bool check_signature(Signature &s);

bool check_derivative();

void set_fns(const hashtable<std::string, Fn_Def*> &h);

Fn_Def *fn_def(const std::string &name);
Expand Down
Loading