// Path: src/main/java/edu/harvard/econcs/jopt/solver/MIPInfeasibleException.java
// public static class Cause implements Serializable {
// 	public static Cause LOWER = new Cause(1);
// 	public static Cause UPPER = new Cause(2);
// 	private static final long serialVersionUID = 200504191645l;
// 	private int type;
// 		
// 	public Cause(int type) {
// 		this.type = type;
// 	}
// 		
// 	public boolean equals(Object o) {
// 		return o != null && o.getClass().equals(Cause.class) && ((Cause)o).type == type;
// 	}
// 		
// 	public int hashCode() {
// 		return type;
// 	}
// 		
// 	public String toString() {
//         switch(type) {
//         	case 1:
//         		return "Lower";
//         	case 2:
//         		return "Upper";
//         }
//         return "Unknown:ERROR";
// 	}
// 		
// 	/** Make serialization work. **/
// 	private Object readResolve () throws ObjectStreamException
//     {
//         switch(type) {
//         	case 1:
//         		return LOWER;
//         	case 2:
//         		return UPPER;
//         }
//         throw new InvalidObjectException("Unknown type: " + type);
//     }
// 
// }
// 
// Path: src/main/java/edu/harvard/econcs/jopt/solver/server/SolverServer.java
// public class SolverServer extends UnicastRemoteObject implements ISolverServer {
// 	/**
// 	 * 
// 	 */
// 	private static final long serialVersionUID = 3977583593201872945L;
// 	private static final Logger log = LogManager.getLogger(SolverServer.class);
// 	private Class solverClass;
// 	
// 	protected int port;
// 	
// 	/**
// 	 * Create a new Server
// 	 * @param port
// 	 * @param solverClass
// 	 */
// 	public static void createServer(int port, Class solverClass) throws MIPException {
// 		try {
// 			log.info("Binding server to port: " + port);
// 			Registry localreg = LocateRegistry.createRegistry(port);
// 			SolverServer server = new SolverServer(port, solverClass);
// 			localreg.bind(NAME, server);
// 		} catch (AccessException e) {
// 			throw new MIPException("Access", e);
// 		} catch (AlreadyBoundException e) {
// 			throw new MIPException("AlreadyBound",e);
// 		} catch (RemoteException e) {
// 			throw new MIPException("RemoteException",e);
// 		}
// 	}
// 	
// 	/**
// 	 * @param solverClass -- what class to use to create new instances 
// 	 * of the solver.
// 	 * @throws RemoteException
// 	 */
// 	protected SolverServer(int port, Class solverClass) throws RemoteException {
// 		super(port);
// 		this.port = port;
// 		this.solverClass = solverClass;
// 	}
// 
// 	/**
// 	 * @see edu.harvard.econcs.jopt.solver.server.ISolverServer#getSolver()
// 	 */
// 	public IRemoteMIPSolver getSolver() throws RemoteException {
// 		log.info("Creating a new Solver Instance");
// 		IMIPSolver solver = null;
// 		try {
// 			solver = (IMIPSolver)solverClass.newInstance();
// 		} catch (InstantiationException | IllegalAccessException e) {
// 			throw new MIPException("Could not create solver intance", e);
// 		}
// 		return new RemoteMIPSolver(port, solver);
// 	}
// }


import edu.harvard.econcs.jopt.solver.*;
import edu.harvard.econcs.jopt.solver.MIPInfeasibleException.Cause;
import edu.harvard.econcs.jopt.solver.mip.*;
import edu.harvard.econcs.jopt.solver.server.SolverServer;
import ilog.concert.*;
import ilog.cplex.IloCplex;
import ilog.cplex.IloCplex.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

        private PoolSolution createSolution() {
            Map<String, Double> values = new HashMap<String, Double>();
            for (String name : vars.keySet()) {
                IloNumVar var = vars.get(name);
                try {
                    values.put(name, getIncumbentValue(var));
                } catch (IloException e) {
                    throw new MIPException("Couldn't get incumbent value.", e);
                }
            }
            try {
                return new PoolSolution(getIncumbentObjValue(), getBestObjValue(), values);
            } catch (IloException e) {
                throw new MIPException("Couldn't get incumbent objective value.", e);
            }
        }
    }

    public static void main(String argv[]) {
        if (argv.length < 1 || argv.length > 2) {
            logger.error("Usage: edu.harvard.econcs.jopt.solver.server.cplex.CPlexMIPSolver <port> <num simultaneous>");
            System.exit(1);
        }
        int port = Integer.parseInt(argv[0]);
        int numSimultaneous = 10;
        if (argv.length >= 2) {
            numSimultaneous = Integer.parseInt(argv[1]);
        }
        InstanceManager.setNumSimultaneous(numSimultaneous);
// Path: src/main/java/edu/harvard/econcs/jopt/solver/MIPInfeasibleException.java
// public static class Cause implements Serializable {
// 	public static Cause LOWER = new Cause(1);
// 	public static Cause UPPER = new Cause(2);
// 	private static final long serialVersionUID = 200504191645l;
// 	private int type;
// 		
// 	public Cause(int type) {
// 		this.type = type;
// 	}
// 		
// 	public boolean equals(Object o) {
// 		return o != null && o.getClass().equals(Cause.class) && ((Cause)o).type == type;
// 	}
// 		
// 	public int hashCode() {
// 		return type;
// 	}
// 		
// 	public String toString() {
//         switch(type) {
//         	case 1:
//         		return "Lower";
//         	case 2:
//         		return "Upper";
//         }
//         return "Unknown:ERROR";
// 	}
// 		
// 	/** Make serialization work. **/
// 	private Object readResolve () throws ObjectStreamException
//     {
//         switch(type) {
//         	case 1:
//         		return LOWER;
//         	case 2:
//         		return UPPER;
//         }
//         throw new InvalidObjectException("Unknown type: " + type);
//     }
// 
// }
// 
// Path: src/main/java/edu/harvard/econcs/jopt/solver/server/SolverServer.java
// public class SolverServer extends UnicastRemoteObject implements ISolverServer {
// 	/**
// 	 * 
// 	 */
// 	private static final long serialVersionUID = 3977583593201872945L;
// 	private static final Logger log = LogManager.getLogger(SolverServer.class);
// 	private Class solverClass;
// 	
// 	protected int port;
// 	
// 	/**
// 	 * Create a new Server
// 	 * @param port
// 	 * @param solverClass
// 	 */
// 	public static void createServer(int port, Class solverClass) throws MIPException {
// 		try {
// 			log.info("Binding server to port: " + port);
// 			Registry localreg = LocateRegistry.createRegistry(port);
// 			SolverServer server = new SolverServer(port, solverClass);
// 			localreg.bind(NAME, server);
// 		} catch (AccessException e) {
// 			throw new MIPException("Access", e);
// 		} catch (AlreadyBoundException e) {
// 			throw new MIPException("AlreadyBound",e);
// 		} catch (RemoteException e) {
// 			throw new MIPException("RemoteException",e);
// 		}
// 	}
// 	
// 	/**
// 	 * @param solverClass -- what class to use to create new instances 
// 	 * of the solver.
// 	 * @throws RemoteException
// 	 */
// 	protected SolverServer(int port, Class solverClass) throws RemoteException {
// 		super(port);
// 		this.port = port;
// 		this.solverClass = solverClass;
// 	}
// 
// 	/**
// 	 * @see edu.harvard.econcs.jopt.solver.server.ISolverServer#getSolver()
// 	 */
// 	public IRemoteMIPSolver getSolver() throws RemoteException {
// 		log.info("Creating a new Solver Instance");
// 		IMIPSolver solver = null;
// 		try {
// 			solver = (IMIPSolver)solverClass.newInstance();
// 		} catch (InstantiationException | IllegalAccessException e) {
// 			throw new MIPException("Could not create solver intance", e);
// 		}
// 		return new RemoteMIPSolver(port, solver);
// 	}
// }


// Path: src/main/java/edu/harvard/econcs/jopt/solver/server/cplex/CPlexMIPSolver.java
import edu.harvard.econcs.jopt.solver.*;
import edu.harvard.econcs.jopt.solver.MIPInfeasibleException.Cause;
import edu.harvard.econcs.jopt.solver.mip.*;
import edu.harvard.econcs.jopt.solver.server.SolverServer;
import ilog.concert.*;
import ilog.cplex.IloCplex;
import ilog.cplex.IloCplex.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


        private PoolSolution createSolution() {
            Map<String, Double> values = new HashMap<String, Double>();
            for (String name : vars.keySet()) {
                IloNumVar var = vars.get(name);
                try {
                    values.put(name, getIncumbentValue(var));
                } catch (IloException e) {
                    throw new MIPException("Couldn't get incumbent value.", e);
                }
            }
            try {
                return new PoolSolution(getIncumbentObjValue(), getBestObjValue(), values);
            } catch (IloException e) {
                throw new MIPException("Couldn't get incumbent objective value.", e);
            }
        }
    }

    public static void main(String argv[]) {
        if (argv.length < 1 || argv.length > 2) {
            logger.error("Usage: edu.harvard.econcs.jopt.solver.server.cplex.CPlexMIPSolver <port> <num simultaneous>");
            System.exit(1);
        }
        int port = Integer.parseInt(argv[0]);
        int numSimultaneous = 10;
        if (argv.length >= 2) {
            numSimultaneous = Integer.parseInt(argv[1]);
        }
        InstanceManager.setNumSimultaneous(numSimultaneous);
        SolverServer.createServer(port, CPlexMIPSolver.class);