#!/usr/bin/python
"""
This program will genereate the cash flow matching problem in free MPS format.

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/>.
"""
import sys
import math
from optparse import OptionParser


def main():
    usage = "usage: %prog [option] coupon file"
    version = "%prog 1.0"
    parser = OptionParser(usage=usage, version=version)
    parser.add_option("--horizon", "-T", dest="T", action="store",
            help="time horizon (T) in year", default=0, type = 'int')
    parser.add_option("--frequency", "-q", dest="freq", action="store",
            help="number of time steps in a year, (>= 1)", 
            default=4, type = 'int')
    parser.add_option("--coupon", "-c", dest="coupon", action="store",
            help="file of coupon payoffs", default=None, type = 'string')
    parser.add_option("--liability", "-l", dest="liability", action="store",
            help="liability streams", default=None, type = 'string')
    parser.add_option("--price", "-p", dest="price", action="store",
            help="simulated price", default=None, type = 'string')
    parser.add_option("--name", "-n", dest="name", action="store",
            help="name of the problem", default="LP", type = 'string')
    parser.add_option("--epsilon", "-e", dest="epsilon", action="store",
            help="epsilon of CVaR", default="0.05", type = 'string')
    parser.add_option("--samplesize", "-N", dest="N", action="store",
            help="Number of samples", default=1, type = 'int')

    (option, arg) = parser.parse_args()

    # check with the option
    if option.coupon is None:
        parser.error("please input the coupon file (-c)")
    if option.liability is None:
        parser.error("please input the liability stream file (-l)")
    if option.price is None:
        parser.error("please input the simulated price file (-p)")
    if option.N is None:
        parser.error("please input the number of samples to use (-N)")
    try:
        option.epsilon = float(option.epsilon)
    except:
        parser.error("please check the epsilon (-e)")

    # get the data
    T = option.T * option.freq
    fc = open(option.coupon, 'r')
    coupon = []
    for i in fc:
        try:
            coupon.append(map(float, i.split()))
        except:
            parser.error("please check the coupon file")
        if len(coupon[-1]) != T:
            parser.error("please check the size of the coupon payoff")
    fc.close()
    M = len(coupon)

    fl = open(option.liability, 'r')
    liability = []
    for i in fl:
        try:
            liability.append(float(i))
        except:
            parser.error("please check the liability stream file")
    fl.close()
    if len(liability) != T + 1:
        parser.error("please check the size of the liability stream")

    fp = open(option.price, 'r')
    price = []
    for ii, i in enumerate(fp):
        if ii < option.N:
            try:
                temp = []
                sample = map(float, i.split())
                if len(sample) != M * T:
                    parser.error("please check the dimension of the simulated price")
                for j in range(option.T * option.freq):
                    temp.append(sample[0:M])
                    del sample[0:M]
                price.append(temp)
            except:
                parser.error("please check the simulated price file")
        else:
            break
    fp.close()
    N = len(price)

    tab = "    "
    # start making mps file
    print "NAME", option.name

    print "ROWS"
    print tab + "N" + tab + "COST"
    print tab + "L" + tab + "CVAR"
    for k in range(N):
        for t in range(1, T + 1):
            print tab + "L" + tab + "CS" + str(k) + "T" + str(t)
    print tab + "E" + tab + "EQ0"
    for t in range(1, T + 1):
        for k in range(N):
            print tab + "E" + tab + "EQ" + str(k) + "T" + str(t)

    print "COLUMNS"
    print tab + "ALPHA" + tab + "CVAR" + tab + "1"
    for k in range(N):
        for t in range(1, T + 1):
            print tab + "ALPHA" + tab + "CS" + str(k) + "T" + str(t) + tab + "-1"

    # U dummy
    for k in range(N):
        print tab + "U" + str(k) + tab + "CVAR" + tab + str(1.0 / N 
                / option.epsilon)
        for t in range(1, T + 1):
            print tab + "U" + str(k) + tab + "CS" + str(k) + "T" + str(t) \
                    + tab + "-1"

    print tab + "W0" + tab + "EQ0" + tab + "1" + tab + "COST" + tab + "1"

    # Y dummy
    for t in range(1, T + 1):
        for k in range(N):
            print tab + "Y" + str(k) + "T" + str(t) + tab + \
                    "EQ" + str(k) + "T" + str(t) + tab + "1" + tab + \
                    "CS" + str(k) + "T" + str(t) + tab + "1"

    # X, t from 0, ..., T - 1, j from 0, ..., M
    for t in range(T):
        for j in range(M):
            for k in range(N):
                if t == 0:
                    if k == 0:
                        print tab + "X" + str(j) + "T" + str(t) + tab + \
                                "EQ" + str(t) + tab + str(-price[k][t][j])
                else:
                    print tab + "X" + str(j) + "T" + str(t) + tab + \
                            "EQ" + str(k) + "T" + str(t) + tab + \
                            str(-price[k][t][j])
            for tt in range(1, T - t + 1):
                for k in range(N):
                    if coupon[j][tt - 1] != 0:
                        print tab + "X" + str(j) + "T" + str(t) + tab + \
                                "EQ" + str(k) + "T" + str(tt + t) + tab + \
                                str(coupon[j][tt - 1])
    print "RHS"
    for t in range(T + 1):
        for k in range(N):
            if t == 0:
                if k == 0:
                    print tab + "RHS1" + tab + "EQ" + str(t) + tab + str(liability[t])
            else:
                print tab + "RHS1" + tab + "EQ" + str(k) + "T" + str(t) + tab + str(liability[t])

    print "BOUNDS"
    print tab + "FR" + tab + "B1" + tab + "ALPHA" + tab + "0"
    for t in range(1, T + 1):
        for k in range(N):
            print tab + "FR" + tab + "B1" + tab + "Y" + str(k) + "T" + str(t) \
                    + tab + "0"

    print "ENDATA"



if __name__ == "__main__":
    main()

