Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save smackesey/11ba2cec407f67ee7e5c to your computer and use it in GitHub Desktop.
Save smackesey/11ba2cec407f67ee7e5c to your computer and use it in GitHub Desktop.
#!/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