package dmi_demo; import java.sql.*; import java.util.*; public class Solution { private static final int maxTransactions = 50; private Transaction[] transactions; private int[] sellers, buyers; // "busy" property is a lookup that indicates which companies are already // involved in transactions with the current solution private HashMap busy; private float value; public Solution () { sellers = new int[maxTransactions]; buyers = new int[maxTransactions]; transactions = new Transaction[maxTransactions]; busy = new HashMap(); value = 0; for (int i = 0; i < maxTransactions; i ++) { sellers[i] = 0; buyers[i] = 0; transactions[i] = null; } } public boolean canSetTransaction (int i, int s, int b) { Integer S = new Integer(s), B = new Integer(b); if (i < 0 || i >= maxTransactions) { //System.out.println("Error: transaction out of bounds"); return false; } else if (s == b) { //System.out.println("Buyer and seller can't be the same, silly!"); return false; } else if (busy.get(S) == Boolean.TRUE && !(transactions[i] != null && ( transactions[i].getSeller() != s || transactions[i].getBuyer() != s) ) ) { //System.out.println("Error: Cannot update transaction "+i+", seller already busy"); return false; } else if (busy.get(B) == Boolean.TRUE && !(transactions[i] != null && ( transactions[i].getSeller() != b || transactions[i].getBuyer() != b) ) ) { //System.out.println("Error: Cannot update transaction "+i+", buyer already busy"); return false; } return true; } public void setTransaction(int i, int s, int b, int p, float c) { Integer S = new Integer(s), B = new Integer(b); if (!canSetTransaction(i, s, b)) { System.out.println ("Error: Cannot set transaction"); } else { if (transactions[i] != null) { // clear the busy table of the old members value -= transactions[i].getPrice(); Integer oldS = new Integer(transactions[i].getSeller()); Integer oldB = new Integer(transactions[i].getBuyer()); busy.put(oldS, Boolean.FALSE); busy.put(oldB, Boolean.FALSE); } Transaction t = new Transaction (s, b, p, c); transactions[i] = t; busy.put(S, Boolean.TRUE); busy.put(B, Boolean.TRUE); value += c; //System.out.println("adding "+c+", value is now "+value); } } public void populateRandom(Connection conn) { // We want a query to find two random requests, SUCH THAT: // * The first request is a sell (1) // * The second request is a buy (2) // * The first item matches the second item // * Each buyer and seller are used once at most try { String sql = "SELECT * FROM " + "(" + " SELECT * FROM" + " (" + " SELECT Price, sreq.Company_Id AS seller, breq.Company_Id AS buyer, DMI_Part.Id AS part" + " FROM DMI_Request AS sreq, DMI_Request AS breq, DMI_Part" + " WHERE sreq.Type=1 AND breq.Type=2" + " AND sreq.Part_Id=DMI_Part.Id" + " AND breq.Part_Id=DMI_Part.Id" + " ORDER BY RAND()" + " limit 5000" + " ) AS alltrans" + " GROUP BY seller" + " ORDER BY RAND()" + ") AS uniqseller " + "GROUP BY buyer " + "ORDER BY RAND() LIMIT "+maxTransactions; PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery(); int i = 0; while (rs.next()) { int seller = rs.getInt("seller"); int buyer = rs.getInt("buyer"); int part = rs.getInt("part"); float price = rs.getFloat("price"); setTransaction(i++, seller, buyer, part, price); } rs.close(); ps.close(); } catch (SQLException e) { System.out.println("SQL Exception while trying to generate random solution: "+e.getMessage()); } } // improve method: attempts to make better choices for all buyers if // possible. Returns true if any improvements were found. public boolean improve (Connection conn) { boolean result = false; try { String sql = "SELECT Price, seller.Id, DMI_Part.Id AS part " + "FROM DMI_Company AS seller, " + "DMI_Request AS sreq, DMI_Request AS breq, DMI_Part " + "WHERE DMI_Part.Price > ? " + "AND breq.Company_Id = ? " + "AND sreq.Type=1 " + "AND breq.Part_Id = sreq.Part_Id " + "AND sreq.Part_Id=DMI_Part.Id " + "AND seller.Id=sreq.Company_Id"; PreparedStatement findBetterPs = conn.prepareStatement(sql); for (int i = 0; i < maxTransactions; i ++) { // Find a better transaction with this buyer Transaction oldt = transactions[i]; if (oldt != null) { int buyer = oldt.getBuyer(); findBetterPs.setFloat(1, oldt.getPrice()); findBetterPs.setInt(2, buyer); ResultSet rs = findBetterPs.executeQuery(); boolean improved = false; while (rs.next() && !improved) { int seller = rs.getInt("seller.Id"); int part = rs.getInt("part"); float price = rs.getFloat("Price"); if (canSetTransaction(i, seller, buyer)) { setTransaction(i, seller, buyer, part, price); // System.out.println("Improved transaction "+i+" by going from "+oldt.getPrice()+" to "+price); improved = true; result = true; } } rs.close(); } } findBetterPs.close(); } catch (SQLException e) { System.out.println("SQL Exception while trying to improve on solution: "+e.getMessage()); } return result; } // Save a solution to the Transaction table public void record (Connection conn) { try { String sql = "DELETE FROM DMI_Transaction"; PreparedStatement ps = conn.prepareStatement(sql); ps.execute(); ps.close(); sql = "INSERT INTO DMI_Transaction (Seller_Id, Buyer_Id, Part_Id) " + "VALUES (?, ?, ?)"; ps = conn.prepareStatement(sql); for (int i = 0; i < maxTransactions; i ++) { Transaction t = transactions[i]; if (t != null) { ps.setInt(1, t.getSeller()); ps.setInt(2, t.getBuyer()); ps.setInt(3, t.getPart()); ps.execute(); } } //String sql = "UPDATE DMI_TransactionSELECT Price, seller.Id, DMI_Part.Id AS part " + conn.commit(); ps.close(); } catch (SQLException e) { System.out.println("SQL Exception while trying to record solution to database: "+e.getMessage()); } } public boolean isBusy(int company) { return busy.get(new Integer(company)).booleanValue(); } public float getValue() { return value; } public void dump() { for (int i = 0; i < maxTransactions; i ++) { if (transactions[i] != null) { transactions[i].dump(); } } System.out.println("Value of all transactions: $"+value); } }