Last active
August 29, 2015 14:10
-
-
Save smackesey/11ba2cec407f67ee7e5c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'csv' | |
require 'optparse' | |
# This script reads a CSV representation of the "Constraints" sheet of the | |
# Google Sheet at: | |
# | |
# https://docs.google.com/spreadsheets/d/1lJX_YRI-YKAxQs4C8q3ykws5it-zokSEXXq6yl6-xYg/edit#gid=0 | |
# | |
# The path to the CSV file should be provided with the option -p or --path. The | |
# output is a string encoding the objective function derived from this sheet. | |
# This can be generated as either R code or MATLAB code-- use the -f or | |
# --format options with the value "R" or "MATLAB" to set the format. | |
# | |
# Example: | |
# | |
# $ ./generate_hc_count_optimization_objective_function.rb --path /path/to/constraints.csv --format MATLAB | |
conf = {} | |
OptionParser.new do |opts| | |
opts.banner = "Usage: generate_objective.rb [options]" | |
opts.on("-f", "--format FORMAT", "Specify format (R, MATLAB)") { |f| conf[:format] = f } | |
opts.on("-p", "--path PATH-TO-CSV") { |p| conf[:path] = p } | |
end.parse! | |
weights = { 'A' => 1, 'M' => 1, 'S' => 5} | |
delims = case conf[:format] | |
when /r/i then %w{ [ ] } | |
when /matlab/i then %w{ ( ) } | |
end | |
rows = CSV.read(conf[:path]) | |
keys = [*rows[1].take(3), *rows[0].drop(3)] | |
eq_rows = rows.drop(2) | |
constraints = eq_rows.map { |r| Hash[ keys.zip(r) ] } | |
obj_terms = constraints.map do |c| | |
coeffs = c.select { |k,v| (k =~ /^\d+$/ or k == 'constant') and v != '0' } | |
num_signs = coeffs.values.map { |v| v.slice!(/^-/) ? '-' : '+' } | |
den_signs = ['+'] * coeffs.length | |
terms = coeffs.map { |k,v| k == 'constant' ? v : "#{v}*x#{delims[0]}#{k}#{delims[1]}" } | |
num, den = [num_signs, den_signs].map do |signs| | |
signs.zip(terms).map { |s,t| s + ' ' + t }.join(' ').sub(/^\+\s*/, '').sub(/^- /, '-') | |
end | |
"#{weights[c['type']]}*(abs(#{num}) / (#{den}))" | |
end | |
obj_lines = obj_terms[0..-2].map do |t| | |
case conf[:format] | |
when /r/i then t + " +" | |
when /matlab/i then t + " + ..." | |
end | |
end << obj_terms.last | |
if conf[:format] =~ /r/i | |
header, footer = ["obj_func <- function(x) {", "}"] | |
obj = [header, *obj_lines.map { |ln| ' ' + ln }, footer].join("\n") | |
elsif conf[:format] =~ /matlab/i | |
header = "function y = simple_objective(x)" | |
first_line = ' y = ' + obj_lines.take(1) | |
obj = [header, first_line, *obj_lines.drop(1).map { |ln| ' ' + ln }].join("\n") | |
end | |
puts obj |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment