Commit 7e23f18a authored by Jason Rhinelander's avatar Jason Rhinelander

Added taxes and total spending variables

Also renamed books_written to books_written_pc to reflect that it's a
per-capita (actually per hundred readers) value.

Added (commented-out) stubs for reader_fines and readers_caught_pc;
these need deeper changes (and a simulation re-run) as they aren't
currently tracked in the creativity state file.
parent c8ca4f27
......@@ -39,6 +39,9 @@ void CopyrightPolice::interApply() {
}
void CopyrightPolice::intraFinish() {
// FIXME: record the number of people accused, and number guilty for analysis. (Will need to
// store them here, then extract them into the state object/file).
//
auto lock = writeLock();
for (auto &r : simulation()->agents<Reader>()) {
lock.add(r);
......@@ -57,6 +60,7 @@ void CopyrightPolice::intraFinish() {
bool caught = rcoin(prob(pirated));
bool guilty = pirated > 0;
if (caught) {
// FIXME: record this status (so that it is tracked in the reader state)
r->alterUtility(-creativity_.parameters.policy_catch_cost);
if (guilty) {
......
......@@ -290,15 +290,19 @@ bool Creativity::catchPiratesActive() const {
return parameters.policy.catchPirates() && policyActive();
}
double Creativity::policyTaxes() const {
if (!setup_sim_) throw std::logic_error("Cannot call policyTaxes() on a non-live or unconfigured simulation");
double Creativity::policyTaxes(const CreativitySettings &parameters) {
double tax = 0;
if (catchPiratesActive()) tax += parameters.policy_catch_tax;
if (publicSharingActive()) tax += parameters.policy_public_sharing_tax;
if (publicVotingActive()) tax += parameters.policy_public_voting_tax;
if (parameters.policy.catchPirates()) tax += parameters.policy_catch_tax;
if (parameters.policy.publicSharing()) tax += parameters.policy_public_sharing_tax;
if (parameters.policy.publicVoting()) tax += parameters.policy_public_voting_tax;
return tax;
}
double Creativity::policyTaxes() const {
if (!setup_sim_) throw std::logic_error("Cannot call policyTaxes() on a non-live or unconfigured simulation");
return policyActive() ? policyTaxes(parameters) : 0.0;
}
double Creativity::disposableIncome() const {
if (!setup_sim_) throw std::logic_error("Cannot call disposableIncome() on a non-live or unconfigured simulation");
return parameters.income - policyTaxes();
......
......@@ -169,6 +169,11 @@ class Creativity : private eris::noncopyable {
*/
double policyTaxes() const;
/** Returns the policy taxes that will be in effect in a simulation using the given
* CreativitySettings during the policy period.
*/
static double policyTaxes(const CreativitySettings &s);
/** Returns the level of exogenous, disposable income, i.e. income minus policy taxes. This
* is simply a shortcut for `creativity.parameters.income - creativity.policyTaxes()`. Note
* that this does not include any income or costs associated with authorship.
......
......@@ -15,7 +15,7 @@ class Series : public CmdArgs {
/** comma-separated list of series to display
*/
std::string series = "net_u,reader_spending,reader_market_spending,reader_piracy_spending,reader_public_spending,books_bought,books_pirated,books_public_copies,books_written,book_quality,book_sales,book_revenue,book_profit,book_author_effort,book_author_scale,book_p0";
std::string series = "net_u,reader_spending,reader_market_spending,reader_piracy_spending,reader_public_spending,reader_taxes,reader_spending_total,books_bought,books_pirated,books_public_copies,books_written_pc,book_quality,book_sales,book_revenue,book_profit,book_author_effort,book_author_scale,book_p0";
/// A plea for help about possible series values
bool help_series = false;
......
......@@ -11,11 +11,11 @@ namespace creativity { namespace data {
*
* Treatment data("some.csv");
* TreatmentFilter data_filtered(data, [](const TreatmentFilter::Properties &p) {
* return p.piracy and p.piracy->value("books_written") >= 0.2;
* return p.piracy and p.piracy->value("books_written_pc") >= 0.2;
* });
*
* constructs a filter that only includes data observations that have piracy data with at a piracy
* books_written value of at least 0.2.
* books_written_pc value of at least 0.2.
*
* The filter is applied on a simulation-by-simulation row, which typically corresponds to multiple
* treatment rows at once.
......
......@@ -289,7 +289,7 @@ DIST_FNS(book_author_effort)
#undef QUANTILE_FN
#undef DIST_FNS
double books_written(const Storage &cs, eris_time_t from, eris_time_t to) {
double books_written_pc(const Storage &cs, eris_time_t from, eris_time_t to) {
if (from > to) throw std::logic_error("from > to");
double count = 0;
for (eris_time_t t = from; t <= to; t++) {
......@@ -438,6 +438,25 @@ double reader_spending(const Storage &cs, eris_time_t from, eris_time_t to) {
return avg_spending / (to-from+1);
}
double reader_taxes(const Storage &cs, eris_time_t from, eris_time_t to) {
if (from > to) throw std::logic_error("from > to");
// If the range doesn't include the policy the tax is 0:
if (cs.settings.policy_begins > to) return 0.0;
double tax = Creativity::policyTaxes(cs.settings);
if (cs.settings.policy_begins > from) {
// If policy_begins \in (from,to] then the average tax is the per-period tax multiplied
// by the proportion of periods that include the policy:
tax *= (to - cs.settings.policy_begins + 1) / double(to + - from + 1);
}
// Otherwise the average per-period tax is just the average of a constant, i.e. the actual tax value.
return tax;
}
double reader_spending_total(const Storage &cs, eris_time_t from, eris_time_t to) {
return reader_spending(cs, from, to) + reader_taxes(cs, from, to);
}
std::vector<initial_datum> initial_data_fields() {
std::vector<initial_datum> initial_data;
......@@ -522,14 +541,18 @@ std::vector<datum> data_fields() {
ADD_DATUM(book_gross_margin);
ADD_DATUM(book_profit);
ADD_DIST_DATA(book_quality);
ADD_DATUM(books_written);
ADD_DATUM(books_written_pc);
ADD_DATUM(books_bought);
ADD_DATUM(books_pirated, false, true, true);
ADD_DATUM(books_public_copies, false, false, true);
ADD_DATUM(books_pirated, false);
ADD_DATUM(books_public_copies, false, false);
ADD_DATUM(reader_spending);
ADD_DATUM(reader_market_spending);
ADD_DATUM(reader_piracy_spending, false, true, true);
ADD_DATUM(reader_public_spending, false, false, true);
ADD_DATUM(reader_piracy_spending, false);
ADD_DATUM(reader_public_spending, false, false);
// ADD_DATUM(readers_caught_pc, false, false);
// ADD_DATUM(reader_fines, false, false);
ADD_DATUM(reader_taxes, false, false);
ADD_DATUM(reader_spending_total);
ADD_DIST_DATA(book_author_scale);
ADD_DIST_DATA(book_author_effort);
#undef ADD_DATUM
......
......@@ -184,7 +184,7 @@ DIST_FNS(net_u)
/** Average number of books written per 100 agents per period.
*/
double books_written(const state::Storage &cs, eris::eris_time_t from, eris::eris_time_t to);
double books_written_pc(const state::Storage &cs, eris::eris_time_t from, eris::eris_time_t to);
/** Average number of books purchased per reader per period
*/
......@@ -228,6 +228,27 @@ double reader_public_spending(const state::Storage &cs, eris::eris_time_t from,
*/
double reader_spending(const state::Storage &cs, eris::eris_time_t from, eris::eris_time_t to);
/** Returns the average per-reader lump-sum taxes collected, averaged over the given period.
*
* If the period doesn't overlap the beginning of the policy period, this will simply be 0 (if
* before the policy period begins) or the per-period tax value (if during the policy period).
*/
double reader_taxes(const state::Storage &cs, eris::eris_time_t from, eris::eris_time_t to);
/** Average per-reader expenditure on books, including lump-sum taxes (e.g. policing or public
* sharing prize costs).
*
* This is simply a shortcut for `reader_spending(...) + reader_taxes(...)`.
*/
double reader_spending_total(const state::Storage &cs, eris::eris_time_t from, eris::eris_time_t to);
// FIXME: don't have this info stored yet
/** Average number of readers caught per 100 readers per period for piracy. */
//double readers_caught_pc(const state::Storage &cs, eris::eris_time_t from, eris::eris_time_t to);
/** Average fines paid (e.g. for being caught pirating) per reader. */
//double reader_fines(const state::Storage &cs, eris::eris_time_t from, eris::eris_time_t to);
/** Returns a vector of all supported initial datum values. */
std::vector<initial_datum> initial_data_fields();
......
......@@ -68,7 +68,7 @@ int main(int argc, char *argv[]) {
}
std::ostream &out = args.output.filename.empty() ? std::cout : f;
// The minimum value of books_written that needs to be satisified to count as writing occuring
// The minimum value of books_written_pc that needs to be satisified to count as writing occuring
// during a period:
double writing_threshold = 0.2;
// If we're not doing shortrun, filter out any shortrun rows:
......@@ -88,7 +88,7 @@ int main(int argc, char *argv[]) {
// Macro that is true if at least writing_threshold books were written and the mean initial price is
// a number
#define WRITING_AND_MARKET(var) ((var)->value("books_written") >= writing_threshold and not std::isnan((var)->value("book_p0")))
#define WRITING_AND_MARKET(var) ((var)->value("books_written_pc") >= writing_threshold and not std::isnan((var)->value("book_p0")))
// Macro that is true whenever WRITING_AND_MARKET is true and either the shortrun variable does not
// exist, or else it also satisfied the above.
#define WRITING_AND_MARKET_SRLR(var) (WRITING_AND_MARKET(var) and (not args.analysis.shortrun or not (var##_SR) or WRITING_AND_MARKET(var##_SR)))
......@@ -195,7 +195,7 @@ int main(int argc, char *argv[]) {
"policy_public_sharing_tax", "policy_public_voting_tax", "policy_public_voting_votes",
"policy_catch_tax", "policy_catch_fine[1]"});
const std::vector<std::string> pre_fields({
"net_u", "book_p0", "book_sales", "book_profit", "book_quality", "books_written"});
"net_u", "book_p0", "book_sales", "book_profit", "book_quality", "books_written_pc"});
std::vector<std::string> params_abbrev;
std::regex word_re("([a-zA-Z0-9])[a-zA-Z0-9]+");
for (const auto &p : params) params_abbrev.push_back(std::regex_replace(p, word_re, "$1"));
......@@ -281,7 +281,7 @@ int main(int argc, char *argv[]) {
#define VALUE_PLUS_DIST(v) v, v"_5th", v"_median", v"_95th"
for (auto &y : {
VALUE_PLUS_DIST("net_u"),
"books_written",
"books_written_pc",
VALUE_PLUS_DIST("book_quality"),
"book_p0",
"book_revenue",
......@@ -344,7 +344,7 @@ int main(int argc, char *argv[]) {
#define LATEX_NAME_QUANTILE(v, t) LATEX_NAME(v, t), LATEX_NAME_SUB(v"_5th", t, "(Q=.05)"), LATEX_NAME_SUB(v"_median", t, "(Q=.50)"), LATEX_NAME_SUB(v"_95th", t, "(Q=.95)")
std::unordered_map<std::string, std::string> latex_name({
LATEX_NAME_QUANTILE("net_u", "net\\ utility"),
LATEX_NAME("books_written", "books\\ written"),
LATEX_NAME("books_written_pc", "books\\ written"),
LATEX_NAME_QUANTILE("book_quality", "book\\ quality"),
LATEX_NAME_SUB("book_p0", "book\\ p", "t=0"),
LATEX_NAME("book_revenue", "book\\ revenue"),
......@@ -399,7 +399,7 @@ int main(int argc, char *argv[]) {
out << "\n\n\nMarginal effects:\n=================\n";
SUR marg_effects;
for (auto &y : {"net_u", "books_written", "book_quality", "book_p0", "book_revenue", "book_profit"}) {
for (auto &y : {"net_u", "books_written_pc", "book_quality", "book_p0", "book_revenue", "book_profit"}) {
Equation eq(data_writing_always[y]);
eq % 1;
if (data_writing_always.hasPiracy()) eq % data_writing_always["piracy"];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment