Print

Print


Commit in lcsim on MAIN
src/org/lcsim/event/base/BaseRelationalTable.java+16-21.2 -> 1.3
test/org/lcsim/event/base/BaseRelationalTableTest.java+257added 1.1
+273-2
1 added + 1 modified, total 2 files
Bug fix in relational table handling, plus test case

lcsim/src/org/lcsim/event/base
BaseRelationalTable.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- BaseRelationalTable.java	16 Jul 2007 20:11:19 -0000	1.2
+++ BaseRelationalTable.java	10 Sep 2007 23:45:49 -0000	1.3
@@ -317,7 +317,14 @@
       {
          double w1 = weightFromTo(from,o1);
          double w2 = weightFromTo(from,o2);
-         return (int) Math.signum(w2 - w1);
+         if (w1 == w2)
+         {
+            // FIXME: TreeSet bases equality on the return code from the comparator, with equal
+            // elements being eliminated. Thus we only want to return 0 for object which are really equal.
+            // Using hashcode is not strictly correct, since unequal object can have the same hashcode.
+            return o1.hashCode() - o2.hashCode();
+         }
+         else return (int) Math.signum(w2 - w1);
       }
    }
    private class ToWeightComparator implements Comparator<F>
@@ -331,7 +338,14 @@
       {
          double w1 = weightFromTo(o1,to);
          double w2 = weightFromTo(o2,to);
-         return (int) Math.signum(w2 - w1);
+         if (w1 == w2)
+         {
+            // FIXME: TreeSet bases equality on the return code from the comparator, with equal
+            // elements being eliminated. Thus we only want to return 0 for object which are really equal.
+            // Using hashcode is not strictly correct, since unequal object can have the same hashcode.
+            return o1.hashCode() - o2.hashCode();
+         }
+         else return (int) Math.signum(w2 - w1);
       }
    }
 }
\ No newline at end of file

lcsim/test/org/lcsim/event/base
BaseRelationalTableTest.java added at 1.1
diff -N BaseRelationalTableTest.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ BaseRelationalTableTest.java	10 Sep 2007 23:45:49 -0000	1.1
@@ -0,0 +1,257 @@
+package org.lcsim.event.base;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+import junit.framework.*;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ * @author tonyj
+ */
+public class BaseRelationalTableTest extends TestCase
+{
+   public void testOneToOne()
+   {
+      BaseRelationalTable<Integer,Integer> squares = new BaseRelationalTable<Integer,Integer>(BaseRelationalTable.Mode.ONE_TO_ONE,BaseRelationalTable.Weighting.UNWEIGHTED);
+      assertEquals(BaseRelationalTable.Mode.ONE_TO_ONE,squares.getMode());
+      assertEquals(BaseRelationalTable.Weighting.UNWEIGHTED,squares.getWeighting());
+      
+      for (int i=0; i<1000; i++)
+      {
+         assertFalse(squares.add(i,i*i));
+      }
+      assertEquals(1000,squares.size());
+      
+      assertEquals(Integer.valueOf(100),squares.to(10));
+      assertEquals(Integer.valueOf(100),squares.from(10000));
+      
+      Set<Integer> list = squares.allFrom(10);
+      assertEquals(1,list.size());
+      assertEquals(Integer.valueOf(100),list.iterator().next());
+      
+      list = squares.allTo(100);
+      assertEquals(1,list.size());
+      assertEquals(Integer.valueOf(10),list.iterator().next());
+      
+      list = squares.allTo(99);
+      assertEquals(0,list.size());
+      
+      Map<Integer,Double> map = squares.allFromWithWeights(10);
+      assertEquals(1,map.size());
+      assertEquals(1.0,map.get(100),1e-16);
+      
+      map = squares.allToWithWeights(100);
+      assertEquals(1,map.size());
+      assertEquals(1.0,map.get(10),1e-16);
+      
+      map = squares.allToWithWeights(99);
+      assertEquals(0,map.size());
+      
+      assertEquals(1.0,squares.weightFromTo(10,100),1e-16);
+      assertEquals(0.0,squares.weightFromTo(10,99),1e-16);
+      
+      assertNull(squares.from(99));
+      
+      assertTrue(squares.add(10,99));
+      assertEquals(1000,squares.size());
+      assertEquals(Integer.valueOf(99),squares.to(10));
+      assertEquals(Integer.valueOf(10),squares.from(99));
+      
+      list = squares.allTo(99);
+      assertEquals(1,list.size());
+      assertEquals(Integer.valueOf(10),list.iterator().next());
+      
+      assertTrue(squares.remove(10,99));
+      assertEquals(999,squares.size());
+      
+      assertFalse(squares.remove(10,99));
+      assertEquals(999,squares.size());
+   }
+   public void testManyToMany()
+   {
+      BaseRelationalTable<Integer,Integer> diffs = new BaseRelationalTable<Integer,Integer>(BaseRelationalTable.Mode.MANY_TO_MANY,BaseRelationalTable.Weighting.WEIGHTED);
+      assertEquals(BaseRelationalTable.Mode.MANY_TO_MANY,diffs.getMode());
+      assertEquals(BaseRelationalTable.Weighting.WEIGHTED,diffs.getWeighting());
+      
+      for (int i=0; i<100; i++)
+      {
+         for (int j=0; j<100; j++)
+         {
+            assertFalse(diffs.add(i,j,i-j));
+         }
+      }
+      assertEquals(10000,diffs.size());
+      
+      try
+      {
+         diffs.to(10);
+         fail("Should have thrown an exception");
+      }
+      catch (IllegalArgumentException x)
+      {
+         // OK
+      }
+      try
+      {
+         diffs.from(10);
+         fail("Should have thrown an exception");
+      }
+      catch (IllegalArgumentException x)
+      {
+         // OK
+      }
+      
+      Set<Integer> list = diffs.allFrom(10);
+      assertEquals(100,list.size());
+      assertEquals(Integer.valueOf(0),list.iterator().next());
+      
+      list = diffs.allTo(10);
+      assertEquals(100,list.size());
+      assertEquals(Integer.valueOf(99),list.iterator().next());
+      
+      list = diffs.allTo(100);
+      assertEquals(0,list.size());
+      
+      Map<Integer,Double> map = diffs.allFromWithWeights(10);
+      assertEquals(100,map.size());
+      assertEquals(10-90,map.get(90),1e-16);
+      
+      map = diffs.allToWithWeights(10);
+      assertEquals(100,map.size());
+      assertEquals(90-10,map.get(90),1e-16);
+      
+      map = diffs.allToWithWeights(100);
+      assertEquals(0,map.size());
+      
+      assertEquals(0.0,diffs.weightFromTo(10,100),1e-16);
+      assertEquals(10-99,diffs.weightFromTo(10,99),1e-16);
+      
+      assertNull(diffs.from(100));
+      
+      assertTrue(diffs.add(10,99));
+      assertEquals(10000,diffs.size());
+      
+      list = diffs.allTo(99);
+      assertEquals(101,list.size());
+      assertEquals(Integer.valueOf(10),list.iterator().next());
+      
+      diffs.remove(10,99);
+      assertEquals(9999,diffs.size());
+   }
+   
+   public void testFactors()
+   {
+      BaseRelationalTable<Integer,Integer> factors = new BaseRelationalTable<Integer,Integer>(BaseRelationalTable.Mode.MANY_TO_MANY,BaseRelationalTable.Weighting.WEIGHTED);
+      assertEquals(BaseRelationalTable.Mode.MANY_TO_MANY,factors.getMode());
+      assertEquals(BaseRelationalTable.Weighting.WEIGHTED,factors.getWeighting());
+      
+      List<Integer> primes = getPrimes(1000);
+      for (int i=1; i<=1000; i++)
+      {
+         List<Integer> primeFactors = getPrimeFactors(primes,i);
+         for (int factor : primeFactors)
+         {
+            double w = factors.weightFromTo(i,factor) + 1;
+            boolean rc = factors.add(i,factor,w);
+         }
+      }
+      
+      for (int i=1; i<=1000; i++)
+      {
+         Map<Integer,Double> primeFactors = factors.allFromWithWeights(i);
+         int j=1; 
+         for (Map.Entry<Integer,Double> e : primeFactors.entrySet())
+         {
+            j *= Math.pow(e.getKey(),e.getValue());
+         }
+         assertEquals(i,j);
+      }
+      
+   }
+   private List<Integer> getPrimeFactors(List<Integer> primes, int n)
+   {
+      List<Integer> factors = new ArrayList<Integer>();
+      
+      // Step 1
+      int k = 0;
+      int divisor;
+      int quotient;
+      int remainder;
+      
+      // Step 2
+      while (n > 1)
+      {
+         
+         // Step 3
+         divisor = primes.get(k);
+         quotient = n / divisor;
+         remainder = n % divisor;
+         
+         // Step 4
+         if (remainder == 0)
+         {
+            
+            // Step 5
+            factors.add(divisor);
+            n = quotient;
+            
+         }
+         else
+         {
+            
+            // Step 6
+            if (quotient > divisor)
+            {
+               k++;
+            }
+            else
+            {
+               // Step 7
+               factors.add(n);
+               break;
+            }
+         }
+      }
+      return factors;
+   }
+   private List<Integer> getPrimes(int upTo)
+   {
+      int size = upTo + 1;
+      BitSet flags = new BitSet(size);
+      List<Integer> primes = new ArrayList<Integer>();
+      double limit = Math.sqrt(size);
+      
+      // Cross out multiples of 2
+      int j = 2;
+      for (int i = j + j; i < size; i = i + j)
+      {
+         flags.set(i);
+      }
+      
+      // Cross out multiples of odd numbers
+      for (j = 3; j <= limit; j = j + 2)
+      {
+         if (!flags.get(j))
+         {
+            for (int i = j + j; i < size; i = i + j)
+            {
+               flags.set(i);
+            }
+         }
+      }
+      
+      // Build list of primes from what is left
+      for (int i = 2; i < size; i++)
+      {
+         if (!flags.get(i))
+         {
+            primes.add(i);
+         }
+      }
+      
+      return primes;
+   }
+}
CVSspam 0.2.8