/* * Copyright (C) 2007 Snorre Gylterud, Stein Magnus Jodal, Johannes Knutsen, * Erik Bagge Ottesen, Ralf Bjarne Taraldset, and Iterate AS * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. */ package no.ntnu.mmfplanner.model; import static org.junit.Assert.*; import java.util.List; import no.ntnu.mmfplanner.model.ProjectSorter.Result; import org.junit.Test; /** * Test suite for {@link OptimalProjectSorter} */ public class OptimalProjectSorterTest { private static final int REVENUE_2[][] = new int[][] { new int[] { -20, -20, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }, new int[] { -50, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 } }; private static final int REVENUE_5[][] = new int[][] { new int[] { -50, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }, new int[] { -20, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 }, new int[] { -20, -20, 10, 13, 16, 19, 22, 25, 25, 25, 25, 25, 25, 25, 25, 25 }, new int[] { -20, -20, 10, 14, 18, 22, 26, 30, 34, 38, 40, 40, 40, 40, 40, 40 }, new int[] { -50, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35 } }; Project project; public void initProject(int revenue[][]) throws MmfException { project = new Project(); project.setInterestRate(0.1); project.setMaxMmfsPerPeriod(1); project.setPeriods(revenue[0].length); for (int i = 0; i < revenue.length; i++) { String id = "" + (char) ('A' + i); Mmf mmf = new Mmf(id, "MMF " + id); for (int j = 0; j < revenue[i].length; j++) { mmf.setRevenue(j + 1, revenue[i][j]); } project.add(mmf); } } protected ProjectSorter runSorter() { ProjectSorter sorter = new OptimalProjectSorter(project); sorter.start(false); return sorter; } /** * Compares a list of results with the expected sequences and npvs * * @param eseence * @param npv * @param results * @throws MmfException */ private void assertResults(int progress, String[] sequence, int npv[]) throws MmfException { // run project sorter ProjectSorter sorter = runSorter(); List<Result> results = sorter.getResults(); // basic checks assertTrue(sorter.isDone()); assertEquals(project, sorter.getProject()); assertEquals(progress, sorter.getProgress()); assertEquals(progress, sorter.getProgressMax()); assertEquals(sequence.length, npv.length); assertEquals(sequence.length, results.size()); // check results (sequence, npv, loss, optimal) int maxNpv = results.get(0).npv; int maxPeriod = project.getPeriods() + 1; int npvDelta = (project.getMmfs().size() + 1) / 2; for (int i = 0; i < sequence.length; i++) { Result r = results.get(i); assertEquals(sequence[i], r.sequence); assertEquals(npv[i], r.npv); assertEquals(maxNpv - npv[i], r.loss); assertEquals((double) npv[i] / maxNpv, r.optimal, 0.00); for (int j = 0; j < r.periods.length; j++) { int p = (r.periods[j] > 0 ? r.periods[j] : maxPeriod); project.get(j).setPeriod(p); } ProjectRoi roi = ProjectRoi.getRoiTable(project, project .getInterestRate(), false); assertEquals(roi.presentValue[roi.presentValue.length - 1], r.npv, npvDelta); } } /** * Test method for {@link GreedyProjectSorter#sort()} with two MMFs. */ @Test public void testSort2() throws MmfException { initProject(REVENUE_2); String expSeq[] = new String[] { "BA", "AB", "A", "B", "" }; int expNpv[] = new int[] { 26, 22, 16, 14, 0 }; assertResults(5, expSeq, expNpv); } /** * Test method for {@link GreedyProjectSorter#sort()} with two MMFs and one * dependency. */ @Test public void testSort2D1() throws MmfException { initProject(REVENUE_2); project.get(0).addPrecursor(project.get(1)); String expSeq[] = new String[] { "BA", "B", "" }; int expNpv[] = new int[] { 26, 14, 0 }; assertResults(5, expSeq, expNpv); } /** * Test method for {@link GreedyProjectSorter#sort()} with two MMFs and one * locked. */ @Test public void testSort2L1() throws MmfException { initProject(REVENUE_2); project.get(1).setPeriod(2); project.get(1).setLocked(true); String expSeq[] = new String[] { "BA", "B" }; int expNpv[] = new int[] { 17, 9 }; assertResults(2, expSeq, expNpv); } /** * Test method for {@link GreedyProjectSorter#sort()} with two MMFs. */ @Test public void testSort5() throws MmfException { initProject(REVENUE_5); String expSeq[] = new String[] { "EDCAB", "EDCBA", "EDACB", "EDCB", "EDBCA", "EDABC", "ECDAB", "EDBAC", "EDBC", "ECDBA", "EDCA", "EADCB", "EDAC", "ECDB", "EDC", "EADBC", "ECADB", "EBDCA", "ECDA", "EACDB", "ECBDA", "EADC", "EBDAC", "EBDC", "DECAB", "ECBD", "DECBA", "ECD", "DEACB", "ECABD", "EABDC", "EBCDA", "ECAD", "DECB", "ECBAD", "AEDCB", "EBADC", "DEBCA", "EACBD", "EBCD" }; int expNpv[] = new int[] { 377, 376, 374, 372, 370, 368, 366, 366, 366, 365, 365, 364, 362, 361, 359, 358, 357, 356, 354, 353, 353, 352, 352, 352, 349, 349, 348, 348, 346, 346, 345, 345, 345, 344, 344, 343, 343, 342, 342, 341 }; assertResults(326, expSeq, expNpv); } /** * Test method for {@link GreedyProjectSorter#sort()} with two MMFs and two * dependencies. */ @Test public void testSort5D2() throws MmfException { initProject(REVENUE_5); project.get(4).addPrecursor(project.get(1)); project.get(1).addPrecursor(project.get(0)); String expSeq[] = new String[] { "DABEC", "ABEDC", "ADBEC", "DCABE", "ABECD", "DACBE", "DABCE", "ABDEC", "CDABE", "ADCBE", "CABED", "ACBED", "DABE", "ADBCE", "CADBE", "ABED", "ACDBE", "ABCED", "ADBE", "CABDE", "ABDCE", "ACBDE", "ABCDE", "ABDE", "ABEC", "CABE", "ACBE", "ABCE", "DCAB", "DACB", "DABC", "CDAB", "DCA", "ADCB", "DAC", "ABE", "ADBC", "CADB", "DC", "CDA" }; int expNpv[] = new int[] { 306, 303, 294, 293, 292, 289, 283, 280, 280, 277, 277, 272, 272, 271, 271, 269, 266, 264, 260, 259, 257, 254, 246, 246, 245, 230, 225, 217, 215, 211, 205, 202, 202, 199, 198, 193, 193, 193, 193, 189 }; assertResults(326, expSeq, expNpv); } /** * Test method for {@link GreedyProjectSorter#sort()} with two MMFs, two * dependencies and one locked. */ @Test public void testSort5D2L1() throws MmfException { initProject(REVENUE_5); project.get(4).addPrecursor(project.get(1)); project.get(1).addPrecursor(project.get(0)); project.get(3).setPeriod(1); project.get(3).setLocked(true); String expSeq[] = new String[] { "DABEC", "DCABE", "DACBE", "DABCE", "DABE", "DCAB", "DACB", "DABC", "DCA", "DAC", "DC", "DAB", "DA", "D" }; int expNpv[] = new int[] { 306, 293, 289, 283, 272, 215, 211, 205, 202, 198, 193, 162, 146, 130 }; assertResults(65, expSeq, expNpv); } /** * Test method for {@link GreedyProjectSorter#sort()} with two MMFs, two * dependencies and one locked. Using two mmfs per period. */ @Test public void testSort5D2L1M2() throws MmfException { initProject(REVENUE_5); project.get(4).addPrecursor(project.get(1)); project.get(1).addPrecursor(project.get(0)); project.get(3).setPeriod(1); project.get(3).setLocked(true); project.setMaxMmfsPerPeriod(2); String expSeq[] = new String[] { "ADBCE", "ADCBE", "CDABE", "ADBE", "CDAB", "ADCB", "ADBC", "CDA", "ADC", "CD", "ADB", "AD", "D" }; int expNpv[] = new int[] { 386, 376, 360, 323, 250, 247, 237, 234, 229, 218, 174, 154, 130 }; assertResults(65, expSeq, expNpv); } }