(* :Title: MPS data manipulations *)

(* :Author: Yifan Hu *)

(* :Summary: This package performs manipulation of MPS data *)

(* :Context: Optimization`MPSData` *)

(* :Package Version: 1.0 *)

(* :Copyright: Copyright 2003, Wolfram Research, Inc. *)

(* :History:  *)

(* :Keywords: MPS, linear programming, sparse array *)

(* :Source: *)

(* : *)

(* :Mathematica Version: 5.0 *)

(* :Limitation: None known. *)

(* :Discussion: *)

BeginPackage["Optimization`MPSData`"];

ToLinearProgrammingData::"usage" = "mpsData@ToLinearProgrammingData[] converts an MPS data object MPSData
to a linear programming problem described by a list {c, m, b, bound}. The linear programming problem is solved by LinearProgramming[c, m, b, bound] ";

ConstraintMatrix::"usage" = "mpsData@ConstraintMatrix extracts the constraint matrix and return as an sparse array.";



Begin["`Private`"];

ImportExport`RegisterFormat["MPSData"]

ImportExport`RegisterImport["MPSData",
	System`Convert`MPSDump`ImportMPSData,
	"Sources" -> {"MPS.exe", "Convert`MPS`" }
]
 
(*MPS_INTVAR = 1<<1, MPS_MULTIPLE_RHS = 1<<2, MPS_BINARY_VARS = 1<<3*)
	MPSIntVar = 1;
	MPSMrhs = 2;
	MPSBinaryVars = 4;
	caller = MPSData;

ToLinearProgrammingData::fmterr = "`1` is not a valid MPSData object as generated by Import[file,\"MPSData\"]";
ToLinearProgrammingData::mpsiv = "Warning: integer variables found in MPS data input and treated as real."
ToLinearProgrammingData::mpsmr = "Warning: multiple right-hand-side found in MPS data input. Only the first one is used."
ToLinearProgrammingData::mpsbv = "Warning: binary variables found in MPS data input and treated as real."

Unprotect[MPSData];

MPSData[x__][ToLinearProgrammingData[]] := ToLinearProgrammingDataInternal[MPSData[x]];
ToLinearProgrammingData[x_MPSData] := ToLinearProgrammingDataInternal[x];

MPSData[x__][ConstraintMatrix[]] := ToLinearProgrammingDataInternal[MPSData[x]][[2]];
ConstraintMatrix[x_MPSData] := ToLinearProgrammingDataInternal[x][[2]];

(* Make LinearProgramming accept MPSData directly *)
MPSData /: LinearProgramming[p_MPSData,opts___?OptionQ] := 
    With[{res = LPWithMPS[p,opts]},
     res /; ListQ[res]
    ];

Protect[MPSData];

LPWithMPS[p_MPSData,opts___?OptionQ] := Block[{res},
   res = ToLinearProgrammingData[p];
   If [res == $Failed, Return[$Failed]];
   LinearProgramming[res[[1]],res[[2]],res[[3]],res[[4]],opts]
];

ToLinearProgrammingDataInternal[mpsData_MPSData] := Module[
{res, c, A, b, bd, flag, binaries},
	res = Optimization`LinearProgramming`Private`MPS2LP[mpsData];

	(*	in case being interrupted *)
	If [res === mpsData, Return[res]];

	(* invalid format *)
   If [res == $$Failure, Message[ToLinearProgrammingData::fmterr, mpsData]; Return[$Failed]];

   (* Warning messages *)
	If [BitAnd[flag, MPSMrhs] != 0, Message[ToLinearProgrammingData::mpsmr]];
	If [BitAnd[flag, MPSIntVar] != 0, Message[ToLinearProgrammingData::mpsiv]];
	If [BitAnd[flag, MPSBinaryVars] != 0, Message[ToLinearProgrammingData::mpsbv]];

	{{c,A,b,bd},flag,binaries} = res;
   {c,A,b,bd}
];

End[];(* end Private *)
EndPackage[];(*"Optimization`MPSData"*)
