Advertisement
VladNitu

ProjectSelection(Explorer)_Vlad

Jan 24th, 2023
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.96 KB | None | 0 0
  1. package weblab;
  2.  
  3. import java.io.*;
  4. import java.util.*;
  5.  
  6. /**
  7. * WARNING: The spec tests are not necessarily equal to your grade! You can use them help you test
  8. * for the correctness of your algorithm, but the final grade is determined by a manual inspection
  9. * of your implementation.
  10. */
  11. class ProjectSelection {
  12.  
  13. /**
  14. * You should implement this method
  15. *
  16. * @param projects List of projects, you can ignore list.get(0)
  17. * @return A set of feasible projects that yield the maximum possible profit.
  18. */
  19. public static int maximumProjects(List<Project> projects) {
  20. List<Node> nodes = new ArrayList<>();
  21. // Add nodes for each project
  22. int n = projects.size();
  23. Node[] nodesArr = new Node[n + 1];
  24.  
  25. for (Project project : projects) {
  26. nodesArr[project.getId()] = new Node(project.getId());
  27. nodes.add(nodesArr[project.getId()]);
  28. }
  29. // Add source and sink
  30. Node source = new Node(-1, 0);
  31. Node sink = new Node(-2, 0);
  32. nodes.add(source);
  33. nodes.add(sink);
  34. // TODO
  35.  
  36. // TODO Add projects and their prerequisites to the NF graph
  37. for (Project proj: projects) {
  38.  
  39. Node node = nodesArr[proj.getId()];
  40.  
  41. if (proj.getCost() > 0) { // edge with sink
  42. node.addEdge(sink, proj.getCost());
  43. }
  44. if (proj.getRevenue() > 0) { // edge with source
  45. for (Integer dependencyId: proj.getRequirements())
  46. node.addEdge(nodesArr[dependencyId], Integer.MAX_VALUE / 2);
  47. source.addEdge(node, proj.getRevenue());
  48. }
  49.  
  50. // System.out.println(node == source || node == sink);
  51. // System.out.println(proj);
  52. // System.out.println("---");
  53.  
  54. }
  55.  
  56. Graph g = new Graph(nodes, source, sink);
  57. // for (Node node: g.getNodes())
  58. // System.out.println(node);
  59.  
  60. // TODO Calculate max profit
  61. int minCost = MaxFlow.maximizeFlow(g);
  62. int C = 0;
  63. for (Edge e: source.getEdges()) // sum all possible profits
  64. C += e.getCapacity();
  65. int maxProfit = C - minCost;
  66. // TODO
  67.  
  68. return maxProfit;
  69. }
  70. }
  71.  
  72. class Connection {
  73.  
  74. int x;
  75.  
  76. int y;
  77.  
  78. public Connection(int x, int y) {
  79. this.x = x;
  80. this.y = y;
  81. }
  82. }
  83.  
  84. class Project {
  85.  
  86. private int id;
  87.  
  88. private int cost;
  89.  
  90. private int revenue;
  91.  
  92. private List<Integer> requirements;
  93.  
  94. public Project(int revenue, int cost) {
  95. this.revenue = revenue;
  96. this.cost = cost;
  97. this.requirements = new ArrayList<>();
  98. }
  99.  
  100. public Project(int id, int revenue, int cost) {
  101. this(revenue, cost);
  102. this.id = id;
  103. }
  104.  
  105. public void addRequirement(int requirement) {
  106. requirements.add(requirement);
  107. }
  108.  
  109. public void addRequirements(List<Integer> requirements) {
  110. this.requirements.addAll(requirements);
  111. }
  112.  
  113. public int getId() {
  114. return id;
  115. }
  116.  
  117. public int getCost() {
  118. return cost;
  119. }
  120.  
  121. public int getRevenue() {
  122. return revenue;
  123. }
  124.  
  125. public List<Integer> getRequirements() {
  126. return requirements;
  127. }
  128.  
  129. @Override
  130. public String toString() {
  131. return "Project{"
  132. + "id="
  133. + id
  134. + ", cost="
  135. + cost
  136. + ", revenue="
  137. + revenue
  138. + ", requirements="
  139. + requirements
  140. + '}'
  141. + "\n";
  142. }
  143. }
  144.  
  145. class Graph {
  146.  
  147. private List<Node> nodes;
  148.  
  149. private Node source;
  150.  
  151. private Node sink;
  152.  
  153. public Graph(List<Node> nodes) {
  154. this.nodes = nodes;
  155. this.source = null;
  156. this.sink = null;
  157. }
  158.  
  159. public Graph(List<Node> nodes, Node source, Node sink) {
  160. this.nodes = nodes;
  161. this.source = source;
  162. this.sink = sink;
  163. }
  164.  
  165. public Node getSink() {
  166. return sink;
  167. }
  168.  
  169. public Node getSource() {
  170. return source;
  171. }
  172.  
  173. public List<Node> getNodes() {
  174. return nodes;
  175. }
  176.  
  177. public boolean equals(Object other) {
  178. if (other instanceof Graph) {
  179. Graph that = (Graph) other;
  180. return this.nodes.equals(that.nodes);
  181. }
  182. return false;
  183. }
  184.  
  185. public boolean hasCirculation() {
  186. this.removeLowerBounds();
  187. int D = this.removeSupplyDemand();
  188. int x = MaxFlow.maximizeFlow(this);
  189. return x == D;
  190. }
  191.  
  192. private void removeLowerBounds() {
  193. for (Node n : this.getNodes()) {
  194. for (Edge e : n.edges) {
  195. if (e.lower > 0) {
  196. e.capacity -= e.lower;
  197. e.backwards.capacity -= e.lower;
  198. e.backwards.flow -= e.lower;
  199. e.from.d += e.lower;
  200. e.to.d -= e.lower;
  201. e.lower = 0;
  202. }
  203. }
  204. }
  205. }
  206.  
  207. private int removeSupplyDemand() {
  208. int Dplus = 0, Dmin = 0;
  209. int maxId = 0;
  210. for (Node n : this.getNodes()) {
  211. maxId = Math.max(n.id, maxId);
  212. }
  213. Node newSource = new Node(maxId + 1, 0);
  214. Node newSink = new Node(maxId + 2, 0);
  215. for (Node n : this.getNodes()) {
  216. if (n.d < 0) {
  217. newSource.addEdge(n, 0, -n.d);
  218. Dmin -= n.d;
  219. } else if (n.d > 0) {
  220. n.addEdge(newSink, 0, n.d);
  221. Dplus += n.d;
  222. }
  223. n.d = 0;
  224. }
  225. if (Dmin != Dplus) {
  226. throw new IllegalArgumentException("Demand and supply are not equal!");
  227. }
  228. this.nodes.add(newSource);
  229. this.nodes.add(newSink);
  230. this.source = newSource;
  231. this.sink = newSink;
  232. return Dplus;
  233. }
  234. }
  235.  
  236. class Node {
  237.  
  238. protected int id;
  239.  
  240. protected int d;
  241.  
  242. protected Collection<Edge> edges;
  243.  
  244. /**
  245. * Create a new node
  246. *
  247. * @param id: Id for the node.
  248. */
  249. public Node(int id) {
  250. this(id, 0);
  251. }
  252.  
  253. /**
  254. * Create a new node
  255. *
  256. * @param id: Id for the node.
  257. * @param d: demand for the node. Remember that supply is represented as a negative demand.
  258. */
  259. public Node(int id, int d) {
  260. this.id = id;
  261. this.d = d;
  262. this.edges = new ArrayList<>();
  263. }
  264.  
  265. public void addEdge(Node destination, int capacity) {
  266. this.addEdge(destination, 0, capacity);
  267. }
  268.  
  269. public void addEdge(Node to, int lower, int upper) {
  270. Edge e = new Edge(lower, upper, this, to);
  271. edges.add(e);
  272. to.getEdges().add(e.getBackwards());
  273. }
  274.  
  275. public Collection<Edge> getEdges() {
  276. return edges;
  277. }
  278.  
  279. public int getId() {
  280. return id;
  281. }
  282.  
  283. public boolean equals(Object other) {
  284. if (other instanceof Node) {
  285. Node that = (Node) other;
  286. if (id == that.getId()) return edges.equals(that.getEdges());
  287. }
  288. return false;
  289. }
  290.  
  291. public String toString() {
  292. StringBuilder sb = new StringBuilder();
  293. sb.append(this.getId());
  294. sb.append(" ");
  295. sb.append(this.getEdges().size());
  296. sb.append(":");
  297. for (Edge e : this.getEdges()) {
  298. sb.append("(");
  299. sb.append(e.from.getId());
  300. sb.append(" --[");
  301. sb.append(e.lower);
  302. sb.append(',');
  303. sb.append(e.capacity);
  304. sb.append("]-> ");
  305. sb.append(e.to.getId());
  306. sb.append(")");
  307. }
  308. return sb.toString();
  309. }
  310. }
  311.  
  312. class Edge {
  313.  
  314. protected int lower;
  315.  
  316. protected int capacity;
  317.  
  318. protected int flow;
  319.  
  320. protected Node from;
  321.  
  322. protected Node to;
  323.  
  324. protected Edge backwards;
  325.  
  326. private Edge(Edge e) {
  327. this.lower = 0;
  328. this.flow = e.getCapacity();
  329. this.capacity = e.getCapacity();
  330. this.from = e.getTo();
  331. this.to = e.getFrom();
  332. this.backwards = e;
  333. }
  334.  
  335. protected Edge(int lower, int capacity, Node from, Node to) {
  336. this.lower = lower;
  337. this.capacity = capacity;
  338. this.from = from;
  339. this.to = to;
  340. this.flow = 0;
  341. this.backwards = new Edge(this);
  342. }
  343.  
  344. public void augmentFlow(int add) {
  345. assert (flow + add <= capacity);
  346. flow += add;
  347. backwards.setFlow(getResidual());
  348. }
  349.  
  350. public Edge getBackwards() {
  351. return backwards;
  352. }
  353.  
  354. public int getCapacity() {
  355. return capacity;
  356. }
  357.  
  358. public int getFlow() {
  359. return flow;
  360. }
  361.  
  362. public Node getFrom() {
  363. return from;
  364. }
  365.  
  366. public int getResidual() {
  367. return capacity - flow;
  368. }
  369.  
  370. public Node getTo() {
  371. return to;
  372. }
  373.  
  374. private void setFlow(int f) {
  375. assert (f <= capacity);
  376. this.flow = f;
  377. }
  378.  
  379. public boolean equals(Object other) {
  380. if (other instanceof Edge) {
  381. Edge that = (Edge) other;
  382. return this.capacity == that.capacity
  383. && this.flow == that.flow
  384. && this.from.getId() == that.getFrom().getId()
  385. && this.to.getId() == that.getTo().getId();
  386. }
  387. return false;
  388. }
  389. }
  390.  
  391. class MaxFlow {
  392.  
  393. private static List<Edge> findPath(Graph g, Node start, Node end) {
  394. Map<Node, Edge> mapPath = new HashMap<Node, Edge>();
  395. Queue<Node> sQueue = new LinkedList<Node>();
  396. Node currentNode = start;
  397. sQueue.add(currentNode);
  398. while (!sQueue.isEmpty() && currentNode != end) {
  399. currentNode = sQueue.remove();
  400. for (Edge e : currentNode.getEdges()) {
  401. Node to = e.getTo();
  402. if (to != start && mapPath.get(to) == null && e.getResidual() > 0) {
  403. sQueue.add(e.getTo());
  404. mapPath.put(to, e);
  405. }
  406. }
  407. }
  408. if (sQueue.isEmpty() && currentNode != end) return null;
  409. LinkedList<Edge> path = new LinkedList<Edge>();
  410. Node current = end;
  411. while (mapPath.get(current) != null) {
  412. Edge e = mapPath.get(current);
  413. path.addFirst(e);
  414. current = e.getFrom();
  415. }
  416. return path;
  417. }
  418.  
  419. public static int maximizeFlow(Graph g) {
  420. int f = 0;
  421. Node sink = g.getSink();
  422. Node source = g.getSource();
  423. List<Edge> path;
  424. while ((path = findPath(g, source, sink)) != null) {
  425. int r = Integer.MAX_VALUE;
  426. for (Edge e : path) {
  427. r = Math.min(r, e.getResidual());
  428. }
  429. for (Edge e : path) {
  430. e.augmentFlow(r);
  431. }
  432. f += r;
  433. }
  434. return f;
  435. }
  436. }
  437.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement