Vector cost proposed to TST on 2016-07-13

First part implemented: weight interface introduced and integrated, default weight implementation added.

Change-Id: Ia46f1b44139069aa171a3c13faf168351bd7cc56
diff --git a/apps/newoptical/src/test/java/org/onosproject/newoptical/OpticalConnectivityTest.java b/apps/newoptical/src/test/java/org/onosproject/newoptical/OpticalConnectivityTest.java
index 1202db3..4f122e1 100644
--- a/apps/newoptical/src/test/java/org/onosproject/newoptical/OpticalConnectivityTest.java
+++ b/apps/newoptical/src/test/java/org/onosproject/newoptical/OpticalConnectivityTest.java
@@ -20,6 +20,7 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.onlab.graph.Weight;
 import org.onlab.util.Bandwidth;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.DefaultApplicationId;
@@ -287,5 +288,10 @@
         public double cost() {
             return 0;
         }
+
+        @Override
+        public Weight weight() {
+            return null;
+        }
     }
 }
\ No newline at end of file
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PathComputationTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PathComputationTest.java
index c49fb27..60a84cc 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PathComputationTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PathComputationTest.java
@@ -58,6 +58,7 @@
 import org.onosproject.net.provider.ProviderId;
 import org.onosproject.net.topology.DefaultTopologyEdge;
 import org.onosproject.net.topology.DefaultTopologyVertex;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.LinkWeight;
 import org.onosproject.net.topology.TopologyEdge;
 import org.onosproject.net.topology.TopologyVertex;
@@ -92,6 +93,7 @@
 import static org.onosproject.net.Link.Type.DIRECT;
 import static org.onosproject.net.Link.State.ACTIVE;
 import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.topology.AdapterLinkWeigher.adapt;
 import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.COST;
 import static org.onosproject.pce.pceservice.constraint.CostConstraint.Type.TE_COST;
 
@@ -184,8 +186,8 @@
      * @param constraints path constraints
      * @return edge-weight function
      */
-    private LinkWeight weight(List<Constraint> constraints) {
-        return new MockTeConstraintBasedLinkWeight(constraints);
+    private LinkWeigher weight(List<Constraint> constraints) {
+        return adapt(new MockTeConstraintBasedLinkWeight(constraints));
     }
 
     private Set<Path> computePath(Link link1, Link link2, Link link3, Link link4, List<Constraint> constraints) {
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
index 54cc1a9..beeabdd 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/PceManagerTest.java
@@ -22,6 +22,7 @@
 import static org.onosproject.incubator.net.tunnel.Tunnel.State.UNSTABLE;
 import static org.onosproject.net.MastershipRole.MASTER;
 import static org.onosproject.net.resource.Resources.continuous;
+import static org.onosproject.net.topology.AdapterLinkWeigher.adapt;
 import static org.onosproject.pce.pceservice.LspType.SR_WITHOUT_SIGNALLING;
 import static org.onosproject.pce.pceservice.LspType.WITHOUT_SIGNALLING_AND_WITHOUT_SR;
 import static org.onosproject.pce.pceservice.LspType.WITH_SIGNALLING;
@@ -119,7 +120,8 @@
 public class PceManagerTest {
 
     private PathComputationTest pathCompTest = new PathComputationTest();
-    private MockPathResourceService resourceService = pathCompTest.new MockPathResourceService();
+    private MockPathResourceService resourceService =
+            pathCompTest.new MockPathResourceService();
     private MockTopologyService topologyService = new MockTopologyService();
     private MockMastershipService mastershipService = new MockMastershipService();
     private MockPathService pathService = new MockPathService();
@@ -128,7 +130,8 @@
     private MockTunnelServiceAdapter tunnelService = new MockTunnelServiceAdapter();
     private TestStorageService storageService = new TestStorageService();
     private MockDeviceService deviceService = new MockDeviceService();
-    private MockNetConfigRegistryAdapter netConfigRegistry = new PathComputationTest.MockNetConfigRegistryAdapter();
+    private MockNetConfigRegistryAdapter netConfigRegistry =
+            new PathComputationTest.MockNetConfigRegistryAdapter();
     private PceStore pceStore = new PceStoreAdapter();
 
     public static ProviderId providerId = new ProviderId("pce", "foo");
@@ -137,12 +140,12 @@
     private static final String PCECC_CAPABILITY = "pceccCapability";
     private static final String SR_CAPABILITY = "srCapability";
     private static final String LABEL_STACK_CAPABILITY = "labelStackCapability";
+    private static final String TUNNEL_NAME = "T123";
 
     private TopologyGraph graph = null;
     private Device deviceD1, deviceD2, deviceD3, deviceD4, deviceD5;
     private Device pcepDeviceD1, pcepDeviceD2, pcepDeviceD3, pcepDeviceD4;
     private Link link1, link2, link3, link4, link5, link6;
-    protected static int flowsDownloaded;
     private TunnelListener tunnelListener;
     private TopologyListener listener;
     private Topology topology;
@@ -177,8 +180,9 @@
         }
     }
 
-    private void build4RouterTopo(boolean setCost, boolean setPceccCap, boolean setSrCap,
-                                 boolean setLabelStackCap, int bandwidth) {
+    private void build4RouterTopo(boolean setCost, boolean setPceccCap,
+                                  boolean setSrCap, boolean setLabelStackCap,
+                                  int bandwidth) {
         link1 = PathComputationTest.addLink(DEVICE1, 10, DEVICE2, 20, setCost, 50);
         link2 = PathComputationTest.addLink(DEVICE2, 30, DEVICE4, 40, setCost, 20);
         link3 = PathComputationTest.addLink(DEVICE1, 80, DEVICE3, 70, setCost, 100);
@@ -252,65 +256,63 @@
         deviceService.addDevice(deviceD4);
         deviceService.addDevice(deviceD5);
 
-        DeviceCapability device1Cap = netConfigRegistry.addConfig(DeviceId.deviceId("1.1.1.1"), DeviceCapability.class);
-        device1Cap.setLabelStackCap(setLabelStackCap)
-        .setLocalLabelCap(setPceccCap)
-        .setSrCap(setSrCap)
-        .apply();
-
-        DeviceCapability device2Cap = netConfigRegistry.addConfig(DeviceId.deviceId("2.2.2.2"), DeviceCapability.class);
-        device2Cap.setLabelStackCap(setLabelStackCap)
-        .setLocalLabelCap(setPceccCap)
-        .setSrCap(setSrCap)
-        .apply();
-
-        DeviceCapability device3Cap = netConfigRegistry.addConfig(DeviceId.deviceId("3.3.3.3"), DeviceCapability.class);
-        device3Cap.setLabelStackCap(setLabelStackCap)
-        .setLocalLabelCap(setPceccCap)
-        .setSrCap(setSrCap)
-        .apply();
-
-        DeviceCapability device4Cap = netConfigRegistry.addConfig(DeviceId.deviceId("4.4.4.4"), DeviceCapability.class);
-        device4Cap.setLabelStackCap(setLabelStackCap)
-        .setLocalLabelCap(setPceccCap)
-        .setSrCap(setSrCap)
-        .apply();
-
-        DeviceCapability device5Cap = netConfigRegistry.addConfig(DeviceId.deviceId("5.5.5.5"), DeviceCapability.class);
-        device4Cap.setLabelStackCap(setLabelStackCap)
-                .setLocalLabelCap(setPceccCap)
-                .setSrCap(setSrCap)
-                .apply();
+        mkDevCap("1.1.1.1", setLabelStackCap, setPceccCap, setSrCap);
+        mkDevCap("2.2.2.2", setLabelStackCap, setPceccCap, setSrCap);
+        mkDevCap("3.3.3.3", setLabelStackCap, setPceccCap, setSrCap);
+        mkDevCap("4.4.4.4", setLabelStackCap, setPceccCap, setSrCap);
+        mkDevCap("5.5.5.5", setLabelStackCap, setPceccCap, setSrCap);
 
         if (bandwidth != 0) {
             List<Resource> resources = new LinkedList<>();
-            resources.add(continuous(link1.src().deviceId(), link1.src().port(), Bandwidth.class).resource(bandwidth));
-            resources.add(continuous(link2.src().deviceId(), link2.src().port(), Bandwidth.class).resource(bandwidth));
-            resources.add(continuous(link3.src().deviceId(), link3.src().port(), Bandwidth.class).resource(bandwidth));
-            resources.add(continuous(link4.src().deviceId(), link4.src().port(), Bandwidth.class).resource(bandwidth));
-            resources.add(continuous(link5.src().deviceId(), link5.src().port(), Bandwidth.class).resource(bandwidth));
 
-            resources.add(continuous(link1.dst().deviceId(), link1.dst().port(), Bandwidth.class).resource(bandwidth));
-            resources.add(continuous(link2.dst().deviceId(), link2.dst().port(), Bandwidth.class).resource(bandwidth));
-            resources.add(continuous(link3.dst().deviceId(), link3.dst().port(), Bandwidth.class).resource(bandwidth));
-            resources.add(continuous(link4.dst().deviceId(), link4.dst().port(), Bandwidth.class).resource(bandwidth));
-            resources.add(continuous(link5.dst().deviceId(), link5.dst().port(), Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link1.src().deviceId(), link1.src().port(),
+                    Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link2.src().deviceId(), link2.src().port(),
+                    Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link3.src().deviceId(), link3.src().port(),
+                    Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link4.src().deviceId(), link4.src().port(),
+                    Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link5.src().deviceId(), link5.src().port(),
+                    Bandwidth.class).resource(bandwidth));
+
+            resources.add(continuous(link1.dst().deviceId(), link1.dst().port(),
+                    Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link2.dst().deviceId(), link2.dst().port(),
+                    Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link3.dst().deviceId(), link3.dst().port(),
+                    Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link4.dst().deviceId(), link4.dst().port(),
+                    Bandwidth.class).resource(bandwidth));
+            resources.add(continuous(link5.dst().deviceId(), link5.dst().port(),
+                    Bandwidth.class).resource(bandwidth));
 
             resourceService.allocate(IntentId.valueOf(bandwidth), resources);
         }
     }
 
+    private void mkDevCap(String strDeviceId, boolean setLabelStackCap,
+                          boolean setPceccCap, boolean setSrCap) {
+        DeviceCapability deviceCap = netConfigRegistry.addConfig(
+                DeviceId.deviceId(strDeviceId), DeviceCapability.class);
+        deviceCap.setLabelStackCap(setLabelStackCap)
+                .setLocalLabelCap(setPceccCap)
+                .setSrCap(setSrCap)
+                .apply();
+    }
+
     /**
      * Tests path success with (IGP) cost constraint for signalled LSP.
      */
     @Test
-    public void setupPathTest1() {
+    public void setupPathSuccessIgpCostSignalledLsp() {
         build4RouterTopo(true, false, false, false, 0); // IGP cost is set here.
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
     }
 
@@ -318,13 +320,15 @@
      * Tests path failure with (IGP) cost constraint for signalled LSP.
      */
     @Test
-    public void setupPathTest2() {
-        build4RouterTopo(false, false, false, false, 0); // TE cost is set here, not IGP.
-        List<Constraint> constraints = new LinkedList<Constraint>();
+    public void setupPathFailureIgpCostSignalledLsp() {
+        // TE cost is set here, not IGP.
+        build4RouterTopo(false, false, false, false, 0);
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -332,14 +336,16 @@
      * Tests path success with TE-cost constraint for signalled LSP.
      */
     @Test
-    public void setupPathTest3() {
-        build4RouterTopo(false, false, false, false, 0); // TE cost is set here.
+    public void setupPathSuccessTeCostSignalledLsp() {
+        // TE cost is set here.
+        build4RouterTopo(false, false, false, false, 0);
 
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
     }
 
@@ -347,14 +353,16 @@
      * Tests path failure with TE-cost constraint for signalled LSP.
      */
     @Test
-    public void setupPathTest4() {
-        build4RouterTopo(true, false, false, false, 0); // IGP cost is set here, not TE.
+    public void setupPathFailureTeCostSignalledLsp() {
+        // IGP cost is set here, not TE.
+        build4RouterTopo(true, false, false, false, 0);
 
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -362,15 +370,16 @@
      * Tests path success with (IGP) cost constraint for non-SR non-signalled LSP.
      */
     @Test
-    public void setupPathTest5() {
+    public void setupPathSuccessIgpCostNonSignalledLsp() {
         build4RouterTopo(true, true, false, false, 0);
 
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
-                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, WITHOUT_SIGNALLING_AND_WITHOUT_SR,
+                null);
         assertThat(result, is(true));
     }
 
@@ -378,31 +387,34 @@
      * Tests path success with TE-cost constraint for non-SR non-sgnalled LSP.
      */
     @Test
-    public void setupPathTest6() {
+    public void setupPathSuccessTeCostNonSignalledLsp() {
         build4RouterTopo(false, true, false, false, 0);
 
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
-                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, WITHOUT_SIGNALLING_AND_WITHOUT_SR,
+                null);
         assertThat(result, is(true));
     }
 
     /**
-     * Tests path failure with TE-cost constraint for non-SR non-signalled LSP(CR). Label capability not registered.
+     * Tests path failure with TE-cost constraint for non-SR
+     * non-signalled LSP(CR). Label capability not registered.
      */
     @Test
-    public void setupPathTest7() {
+    public void setupPathFailureTeCostNonSignalledLsp() {
         build4RouterTopo(true, false, false, false, 0);
 
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
-                                              WITHOUT_SIGNALLING_AND_WITHOUT_SR, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, WITHOUT_SIGNALLING_AND_WITHOUT_SR,
+                null);
         assertThat(result, is(false));
     }
 
@@ -410,17 +422,18 @@
      * Tests path failure as bandwidth is requested but is not registered.
      */
     @Test
-    public void setupPathTest8() {
+    public void setupPathFailureBandwidthNotRegistered() {
         build4RouterTopo(true, false, false, false, 0);
-        List<Constraint> constraints = new LinkedList<Constraint>();
-        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        List<Constraint> constraints = new LinkedList<>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(
+                Bandwidth.bps(10.0));
         CostConstraint costConstraint = new CostConstraint(TE_COST);
 
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
-                WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -428,32 +441,34 @@
      * Tests path failure as bandwidth requested is more than registered.
      */
     @Test
-    public void setupPathTest9() {
+    public void setupPathFailureNotEnoughBandwidthRegistered() {
         build4RouterTopo(false, false, false, false, 5);
-        List<Constraint> constraints = new LinkedList<Constraint>();
-        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        List<Constraint> constraints = new LinkedList<>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(
+                Bandwidth.bps(10.0));
         CostConstraint costConstraint = new CostConstraint(TE_COST);
 
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
     /**
-     * Tests path setup failure(without signalling). Label capability is not present.
+     * Tests path setup failure(without signalling). Label capability is not
+     * present.
      */
     @Test
-    public void setupPathTest10() {
+    public void setupPathFailureNoLabelCapability() {
         build4RouterTopo(false, false, false, false, 0);
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints,
-             SR_WITHOUT_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, SR_WITHOUT_SIGNALLING, null);
         assertThat(result, is(false));
     }
 
@@ -461,17 +476,18 @@
      * Tests path setup without signalling and with bandwidth reservation.
      */
     @Test
-    public void setupPathTest12() {
+    public void setupPathSuccessWithoutSignalling() {
         build4RouterTopo(false, true, true, true, 15);
-        List<Constraint> constraints = new LinkedList<Constraint>();
-        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        List<Constraint> constraints = new LinkedList<>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(
+                Bandwidth.bps(10.0));
         CostConstraint costConstraint = new CostConstraint(TE_COST);
 
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
-                constraints, SR_WITHOUT_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, SR_WITHOUT_SIGNALLING, null);
         assertThat(result, is(true));
     }
 
@@ -479,26 +495,28 @@
      * Tests path setup without cost/bandwidth constraints.
      */
     @Test
-    public void setupPathTest13() {
+    public void setupPathSuccessWithoutConstraints() {
         build4RouterTopo(false, false, false, false, 0);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", null, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, null, WITH_SIGNALLING, null);
         assertThat(result, is(true));
     }
 
     /**
      * Tests path setup with explicit path with loose node D2.
      */
-   @Test
-    public void setupPathTest14() {
+    @Test
+    public void setupPathExplicitPathInfoLooseD2() {
         build4RouterTopo(false, false, false, false, 0);
 
         List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
-        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE,
+                D2.deviceId());
         explicitPathInfoList.add(obj);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123", null, WITH_SIGNALLING,
-                explicitPathInfoList);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(),
+                TUNNEL_NAME, null, WITH_SIGNALLING, explicitPathInfoList);
 
         Tunnel tunnel = pceManager.queryAllPath().iterator().next();
         List<Link> links = new LinkedList<>();
@@ -512,129 +530,136 @@
     /**
      * Tests path setup with explicit path with loose node D3.
      */
-   @Test
-   public void setupPathTest15() {
-       build4RouterTopo(false, false, false, false, 0);
+    @Test
+    public void setupPathExplicitPathInfoLooseD3() {
+        build4RouterTopo(false, false, false, false, 0);
 
-       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
-       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D3.deviceId());
-       explicitPathInfoList.add(obj);
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE,
+                D3.deviceId());
+        explicitPathInfoList.add(obj);
 
-       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
-               explicitPathInfoList);
+        boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(),
+                TUNNEL_NAME, null, WITH_SIGNALLING, explicitPathInfoList);
 
-       Tunnel tunnel = pceManager.queryAllPath().iterator().next();
-       List<Link> links = new LinkedList<>();
-       links.add(link3);
-       links.add(link4);
-       links.add(link6);
+        Tunnel tunnel = pceManager.queryAllPath().iterator().next();
+        List<Link> links = new LinkedList<>();
+        links.add(link3);
+        links.add(link4);
+        links.add(link6);
 
-       assertThat(result, is(true));
-       assertThat(tunnel.path().links().equals(links), is(true));
-   }
+        assertThat(result, is(true));
+        assertThat(tunnel.path().links().equals(links), is(true));
+    }
 
     /**
      * Tests path setup with explicit path with loose node D4 , D3 - path fails.
      */
-   @Test
-   public void setupPathTest16() {
-       build4RouterTopo(false, false, false, false, 0);
+    @Test
+    public void setupPathExplicitPathInfoFail() {
+        build4RouterTopo(false, false, false, false, 0);
 
-       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
-       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D4.deviceId());
-       explicitPathInfoList.add(obj);
-       obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D3.deviceId());
-       explicitPathInfoList.add(obj);
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE,
+                D4.deviceId());
+        explicitPathInfoList.add(obj);
+        obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D3.deviceId());
+        explicitPathInfoList.add(obj);
 
-       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
-               explicitPathInfoList);
+        boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(),
+                TUNNEL_NAME, null, WITH_SIGNALLING, explicitPathInfoList);
 
-       assertThat(result, is(false));
-   }
+        assertThat(result, is(false));
+    }
 
     /**
-     * Tests path setup with explicit path with strict node D2 - without reacble to src - path fails.
+     * Tests path setup with explicit path with strict node D2 - without reacble
+     * to src - path fails.
      */
-   @Test
-   public void setupPathTest17() {
-       build4RouterTopo(false, false, false, false, 0);
+    @Test
+    public void setupPathExplicitPathInfoStrictD2Fail() {
+        build4RouterTopo(false, false, false, false, 0);
 
-       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
-       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
-       explicitPathInfoList.add(obj);
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT,
+                D2.deviceId());
+        explicitPathInfoList.add(obj);
 
-       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
-               explicitPathInfoList);
+        boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(),
+                TUNNEL_NAME, null, WITH_SIGNALLING, explicitPathInfoList);
 
-       assertThat(result, is(false));
-   }
+        assertThat(result, is(false));
+    }
 
     /**
      * Tests path setup with explicit path with loose node D2, strict D2.
      */
-   @Test
-   public void setupPathTest18() {
-       build4RouterTopo(false, false, false, false, 0);
+    @Test
+    public void setupPathExplicitPathInfoLooseAndStrictD2() {
+        build4RouterTopo(false, false, false, false, 0);
 
-       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
-       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, D2.deviceId());
-       explicitPathInfoList.add(obj);
-       obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
-       explicitPathInfoList.add(obj);
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE,
+                D2.deviceId());
+        explicitPathInfoList.add(obj);
+        obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+        explicitPathInfoList.add(obj);
 
-       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
-               explicitPathInfoList);
+        boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(),
+                TUNNEL_NAME, null, WITH_SIGNALLING, explicitPathInfoList);
 
-       Tunnel tunnel = pceManager.queryAllPath().iterator().next();
-       List<Link> links = new LinkedList<>();
-       links.add(link1);
-       links.add(link5);
+        Tunnel tunnel = pceManager.queryAllPath().iterator().next();
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link5);
 
-       assertThat(result, is(true));
-       assertThat(tunnel.path().links().equals(links), is(true));
-   }
+        assertThat(result, is(true));
+        assertThat(tunnel.path().links().equals(links), is(true));
+    }
 
     /**
      * Tests path setup with explicit path with loose D1-D2, strict D2.
      */
-   @Test
-   public void setupPathTest19() {
-       build4RouterTopo(false, false, false, false, 0);
+    @Test
+    public void setupPathExplicitPathInfoLooseLink1StrictD2() {
+        build4RouterTopo(false, false, false, false, 0);
 
-       List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
-       ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
-       explicitPathInfoList.add(obj);
-       obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
-       explicitPathInfoList.add(obj);
+        List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE,
+                link1);
+        explicitPathInfoList.add(obj);
+        obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
+        explicitPathInfoList.add(obj);
 
-       boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(), "T123", null, WITH_SIGNALLING,
-               explicitPathInfoList);
+        boolean result = pceManager.setupPath(D1.deviceId(), D5.deviceId(),
+                TUNNEL_NAME, null, WITH_SIGNALLING, explicitPathInfoList);
 
-       Tunnel tunnel = pceManager.queryAllPath().iterator().next();
-       List<Link> links = new LinkedList<>();
-       links.add(link1);
-       links.add(link5);
+        Tunnel tunnel = pceManager.queryAllPath().iterator().next();
+        List<Link> links = new LinkedList<>();
+        links.add(link1);
+        links.add(link5);
 
-       assertThat(result, is(true));
-       assertThat(tunnel.path().links().equals(links), is(true));
-   }
+        assertThat(result, is(true));
+        assertThat(tunnel.path().links().equals(links), is(true));
+    }
 
     /**
      * Tests path update with increase in bandwidth.
      */
     @Test
-    public void updatePathTest1() {
+    public void updatePathIncreaseBandwidth() {
         build4RouterTopo(false, true, true, true, 100);
 
         // Setup tunnel.
         List<Constraint> constraints = new LinkedList<>();
-        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(60.0));
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(
+                Bandwidth.bps(60.0));
         constraints.add(bwConstraint);
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         // Change constraint and update it.
@@ -662,18 +687,19 @@
      * Tests path update with decrease in bandwidth.
      */
     @Test
-    public void updatePathTest2() {
+    public void updatePathDecreaseBandwidth() {
         build4RouterTopo(false, true, true, true, 100);
 
         // Setup tunnel.
-        List<Constraint> constraints = new LinkedList<Constraint>();
-        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(60.0));
+        List<Constraint> constraints = new LinkedList<>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(
+                Bandwidth.bps(60.0));
         constraints.add(bwConstraint);
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
-                constraints, SR_WITHOUT_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, SR_WITHOUT_SIGNALLING, null);
         assertThat(result, is(true));
 
         // Change constraint and update it.
@@ -697,15 +723,15 @@
      * Tests path update without cost/bandwidth constraints.
      */
     @Test
-    public void updatePathTest3() {
+    public void updatePathWithoutConstraints() {
         build4RouterTopo(false, true, true, true, 100);
 
         // Setup tunnel.
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
-        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D2.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
@@ -717,31 +743,35 @@
         }
 
         Iterable<Tunnel> queryTunnelResult = pceManager.queryAllPath();
-        assertThat((int) queryTunnelResult.spliterator().getExactSizeIfKnown(), is(2));
+        assertThat((int) queryTunnelResult.spliterator().getExactSizeIfKnown(),
+                is(2));
     }
 
     /**
-     * Tests path update without cost/bandwidth constraints and with explicit path object.
+     * Tests path update without cost/bandwidth constraints and with explicit
+     * path object.
      */
     @Test
-    public void updatePathTest4() {
+    public void updatePathExplicitPathInfo() {
         build4RouterTopo(false, true, true, true, 100);
 
         // Setup tunnel.
         List<Constraint> constraints = new LinkedList<>();
-        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(60.0));
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(
+                Bandwidth.bps(60.0));
         constraints.add(bwConstraint);
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
         List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
-        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE,
+                link1);
         explicitPathInfoList.add(obj);
         obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
         explicitPathInfoList.add(obj);
 
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, explicitPathInfoList);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, explicitPathInfoList);
         assertThat(result, is(true));
 
         // Change constraint and update it.
@@ -766,12 +796,12 @@
     }
 
     /**
-     * Tests path release.
+     * Tests path release with explicit info.
      */
     @Test
-    public void releasePathTest1() {
+    public void releasePathExplicitPathInfo() {
         build4RouterTopo(false, false, false, false, 5);
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         BandwidthConstraint bwConst = new BandwidthConstraint(Bandwidth.bps(3));
         constraints.add(bwConst);
@@ -783,7 +813,8 @@
         obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
         explicitPathInfoList.add(obj);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, explicitPathInfoList);
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), TUNNEL_NAME,
+                constraints, WITH_SIGNALLING, explicitPathInfoList);
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
         assertThat(tunnels.size(), is(1));
@@ -800,13 +831,14 @@
      * Tests path release failure.
      */
     @Test
-    public void releasePathTest2() {
+    public void releasePathFailure() {
         build4RouterTopo(false, false, false, false, 5);
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(TE_COST);
         constraints.add(costConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), TUNNEL_NAME,
+                constraints, WITH_SIGNALLING, null);
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
         assertThat(tunnels.size(), is(1));
@@ -820,10 +852,10 @@
     }
 
     /**
-     * Tests path release failure.
+     * Tests path release.
      */
     @Test
-    public void releasePathTest3() {
+    public void releasePath() {
         build4RouterTopo(false, false, false, false, 5);
         List<Constraint> constraints = new LinkedList<Constraint>();
         CostConstraint costConstraint = new CostConstraint(TE_COST);
@@ -831,7 +863,8 @@
         constraints.add(bwConst);
         constraints.add(costConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T123", constraints, WITH_SIGNALLING, null);
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), TUNNEL_NAME,
+                constraints, WITH_SIGNALLING, null);
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
         assertThat(tunnels.size(), is(1));
@@ -848,22 +881,25 @@
      * Tests tunnel events added and removed.
      */
     @Test
-    public void tunnelEventTest1() {
+    public void tunnelEventAddedRemoved() {
         build4RouterTopo(false, true, true, true, 15);
-        List<Constraint> constraints = new LinkedList<Constraint>();
-        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        List<Constraint> constraints = new LinkedList<>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(
+                Bandwidth.bps(10.0));
         CostConstraint costConstraint = new CostConstraint(TE_COST);
 
         constraints.add(costConstraint);
         constraints.add(bwConstraint);
 
-        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T1", constraints, SR_WITHOUT_SIGNALLING, null);
+        pceManager.setupPath(D1.deviceId(), D2.deviceId(), "T1", constraints,
+                SR_WITHOUT_SIGNALLING, null);
         assertThat(pceStore.getTunnelInfoCount(), is(1));
 
         Collection<Tunnel> tunnels = (Collection<Tunnel>) pceManager.queryAllPath();
 
         for (Tunnel tunnel : tunnels) {
-            TunnelEvent event = new TunnelEvent(TunnelEvent.Type.TUNNEL_ADDED, tunnel);
+            TunnelEvent event = new TunnelEvent(TunnelEvent.Type.TUNNEL_ADDED,
+                    tunnel);
             tunnelListener.event(event);
 
             pceManager.releasePath(tunnel.tunnelId());
@@ -879,10 +915,11 @@
      * Tests label allocation/removal in CR case based on tunnel event.
      */
     @Test
-    public void tunnelEventTest2() {
+    public void labelAllocationRemoval() {
         build4RouterTopo(false, true, true, true, 15);
-        List<Constraint> constraints = new LinkedList<Constraint>();
-        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        List<Constraint> constraints = new LinkedList<>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(
+                Bandwidth.bps(10.0));
         CostConstraint costConstraint = new CostConstraint(TE_COST);
 
         constraints.add(costConstraint);
@@ -920,10 +957,11 @@
      * Tests handling UNSTABLE state based on tunnel event.
      */
     @Test
-    public void tunnelEventTest3() {
+    public void tunnelEventUnstable() {
         build4RouterTopo(false, true, true, true, 15);
-        List<Constraint> constraints = new LinkedList<Constraint>();
-        BandwidthConstraint bwConstraint = new BandwidthConstraint(Bandwidth.bps(10.0));
+        List<Constraint> constraints = new LinkedList<>();
+        BandwidthConstraint bwConstraint = new BandwidthConstraint(
+                Bandwidth.bps(10.0));
         CostConstraint costConstraint = new CostConstraint(TE_COST);
 
         constraints.add(costConstraint);
@@ -954,28 +992,30 @@
     }
 
     /**
-     * Tests resilency when L2 link is down.
+     * Tests resiliency when L2 link is down.
      */
     @Test
-    public void resilencyTest1() {
+    public void resiliencyLinkFail() {
         build4RouterTopo(true, false, false, false, 10);
 
 
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
-        BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
+        BandwidthConstraint localBwConst = new BandwidthConstraint(
+                Bandwidth.bps(10));
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
         assertThat(pceStore.getTunnelInfoCount(), is(1));
         assertThat(pceStore.getFailedPathInfoCount(), is(0));
 
         List<Event> reasons = new LinkedList<>();
-        final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link2);
+        final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED,
+                link2);
         reasons.add(linkEvent);
         final TopologyEvent event = new TopologyEvent(
                 TopologyEvent.Type.TOPOLOGY_CHANGED,
@@ -985,7 +1025,7 @@
         //Change Topology : remove link2
         Set<TopologyEdge> tempEdges = new HashSet<>();
         tempEdges.add(new DefaultTopologyEdge(D2, D4, link2));
-        topologyService.changeInTopology(getGraph(null,  tempEdges));
+        topologyService.changeInTopology(getGraph(null, tempEdges));
         listener.event(event);
 
         List<Link> links = new LinkedList<>();
@@ -998,21 +1038,22 @@
     }
 
     /**
-     * Tests resilency when L2 and L4 link is down.
+     * Tests resiliency when L2 and L4 link is down.
      */
     @Test
-    public void resilencyTest2() {
+    public void resiliencyMultipleLinkFailsNoAlternativePath() {
         build4RouterTopo(true, false, false, false, 10);
 
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
-        BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
+        BandwidthConstraint localBwConst = new BandwidthConstraint(
+                Bandwidth.bps(10));
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -1029,7 +1070,7 @@
         Set<TopologyEdge> tempEdges = new HashSet<>();
         tempEdges.add(new DefaultTopologyEdge(D2, D4, link2));
         tempEdges.add(new DefaultTopologyEdge(D3, D4, link4));
-        topologyService.changeInTopology(getGraph(null,  tempEdges));
+        topologyService.changeInTopology(getGraph(null, tempEdges));
         listener.event(event);
 
         //No Path
@@ -1037,21 +1078,22 @@
     }
 
     /**
-     * Tests resilency when D2 device is down.
+     * Tests resiliency when D2 device is down.
      */
     @Test
-    public void resilencyTest3() {
+    public void resiliencyDeviceFail() {
         build4RouterTopo(true, false, false, false, 10);
 
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
-        BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
+        BandwidthConstraint localBwConst = new BandwidthConstraint(
+                Bandwidth.bps(10));
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -1068,7 +1110,7 @@
         Set<TopologyEdge> tempEdges = new HashSet<>();
         tempEdges.add(new DefaultTopologyEdge(D2, D4, link2));
         tempEdges.add(new DefaultTopologyEdge(D1, D2, link1));
-        topologyService.changeInTopology(getGraph(null,  tempEdges));
+        topologyService.changeInTopology(getGraph(null, tempEdges));
         listener.event(event);
 
         List<Link> links = new LinkedList<>();
@@ -1081,21 +1123,22 @@
     }
 
     /**
-     * Tests resilency when ingress device is down.
+     * Tests resiliency when ingress device is down.
      */
     @Test
-    public void resilencyTest4() {
+    public void resiliencyIngressDeviceFail() {
         build4RouterTopo(true, false, false, false, 10);
 
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
-        BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
+        BandwidthConstraint localBwConst = new BandwidthConstraint(
+                Bandwidth.bps(10));
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -1120,21 +1163,22 @@
     }
 
     /**
-     * Tests resilency when D2 and D3 devices are down.
+     * Tests resiliency when D2 and D3 devices are down.
      */
     @Test
-    public void resilencyTest5() {
+    public void resiliencyMultipleDevicesFailNoAlternativePath() {
         build4RouterTopo(true, false, false, false, 10);
 
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
-        BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
+        BandwidthConstraint localBwConst = new BandwidthConstraint(
+                Bandwidth.bps(10));
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -1169,21 +1213,22 @@
     }
 
     /**
-     * Tests resilency when egress device is down.
+     * Tests resiliency when egress device is down.
      */
     @Test
-    public void resilencyTest6() {
+    public void resiliencyEgressDeviceFail() {
         build4RouterTopo(true, false, false, false, 10);
 
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
-        BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
+        BandwidthConstraint localBwConst = new BandwidthConstraint(
+                Bandwidth.bps(10));
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -1211,110 +1256,22 @@
     }
 
     /**
-     * Tests resilency when egress device is down.
+     * Tests resiliency when D2 device is suspended.
      */
     @Test
-    public void resilencyTest7() {
+    public void resiliencyDeviceSuspended() {
         build4RouterTopo(true, false, false, false, 10);
 
-        List<Constraint> constraints = new LinkedList<Constraint>();
+        List<Constraint> constraints = new LinkedList<>();
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
-        BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
+        BandwidthConstraint localBwConst = new BandwidthConstraint(
+                Bandwidth.bps(10));
         constraints.add(localBwConst);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, null);
-        assertThat(result, is(true));
-
-        List<Event> reasons = new LinkedList<>();
-        LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link2);
-        reasons.add(linkEvent);
-        linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link4);
-        reasons.add(linkEvent);
-
-        final TopologyEvent event = new TopologyEvent(
-                TopologyEvent.Type.TOPOLOGY_CHANGED,
-                topology,
-                reasons);
-
-        //Change Topology : remove device4 , link2 and link4
-        Set<TopologyEdge> tempEdges = new HashSet<>();
-        tempEdges.add(new DefaultTopologyEdge(D2, D4, link2));
-        tempEdges.add(new DefaultTopologyEdge(D3, D4, link4));
-        Set<TopologyVertex> tempVertexes = new HashSet<>();
-        tempVertexes.add(D4);
-        topologyService.changeInTopology(getGraph(tempVertexes, tempEdges));
-        listener.event(event);
-
-        //No path
-        assertThat(pathService.paths().size(), is(0));
-    }
-
-    /**
-     * Tests resilency when D2 device is suspended.
-     */
-    @Test
-    public void resilencyTest8() {
-        build4RouterTopo(true, false, false, false, 10);
-
-        List<Constraint> constraints = new LinkedList<Constraint>();
-        CostConstraint costConstraint = new CostConstraint(COST);
-        constraints.add(costConstraint);
-        BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
-        constraints.add(localBwConst);
-
-        //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, null);
-        assertThat(result, is(true));
-
-        List<Event> reasons = new LinkedList<>();
-        LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link1);
-        reasons.add(linkEvent);
-        linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link2);
-        reasons.add(linkEvent);
-
-        final TopologyEvent event = new TopologyEvent(
-                TopologyEvent.Type.TOPOLOGY_CHANGED,
-                topology,
-                reasons);
-
-        //Change Topology : remove device2 , link1 and link2
-        Set<TopologyEdge> tempEdges = new HashSet<>();
-        tempEdges.add(new DefaultTopologyEdge(D1, D2, link1));
-        tempEdges.add(new DefaultTopologyEdge(D2, D4, link2));
-        Set<TopologyVertex> tempVertexes = new HashSet<>();
-        tempVertexes.add(D2);
-        topologyService.changeInTopology(getGraph(tempVertexes, tempEdges));
-        listener.event(event);
-
-        List<Link> links = new LinkedList<>();
-        links.add(link3);
-        links.add(link4);
-
-        //Path is D1-D3-D4
-        assertThat(pathService.paths().iterator().next().links(), is(links));
-        assertThat(pathService.paths().iterator().next().cost(), is((double) 180));
-    }
-
-    /**
-     * Tests resilency when D2 device availability is changed.
-     */
-    @Test
-    public void resilencyTest11() {
-        build4RouterTopo(true, false, false, false, 10);
-
-        List<Constraint> constraints = new LinkedList<Constraint>();
-        CostConstraint costConstraint = new CostConstraint(COST);
-        constraints.add(costConstraint);
-        BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
-        constraints.add(localBwConst);
-
-        //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, null);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, null);
         assertThat(result, is(true));
 
         List<Event> reasons = new LinkedList<>();
@@ -1350,30 +1307,33 @@
      * Tests resilency when link2 availability is changed.
      */
     @Test
-    public void resilencyTest12() {
+    public void resilencyExplicitPathInfoSpecified() {
         build4RouterTopo(true, false, false, false, 10);
 
         List<Constraint> constraints = new LinkedList<Constraint>();
         CostConstraint costConstraint = new CostConstraint(COST);
         constraints.add(costConstraint);
-        BandwidthConstraint localBwConst = new BandwidthConstraint(Bandwidth.bps(10));
+        BandwidthConstraint localBwConst = new BandwidthConstraint(
+                Bandwidth.bps(10));
         constraints.add(localBwConst);
 
         List<ExplicitPathInfo> explicitPathInfoList = Lists.newLinkedList();
-        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE, link1);
+        ExplicitPathInfo obj = new ExplicitPathInfo(ExplicitPathInfo.Type.LOOSE,
+                link1);
         explicitPathInfoList.add(obj);
         obj = new ExplicitPathInfo(ExplicitPathInfo.Type.STRICT, D2.deviceId());
         explicitPathInfoList.add(obj);
 
         //Setup the path , tunnel created
-        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(), "T123",
-                constraints, WITH_SIGNALLING, explicitPathInfoList);
+        boolean result = pceManager.setupPath(D1.deviceId(), D4.deviceId(),
+                TUNNEL_NAME, constraints, WITH_SIGNALLING, explicitPathInfoList);
         assertThat(result, is(true));
         assertThat(pceStore.getTunnelInfoCount(), is(1));
         assertThat(pceStore.getFailedPathInfoCount(), is(0));
 
         List<Event> reasons = new LinkedList<>();
-        final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link2);
+        final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED,
+                link2);
         reasons.add(linkEvent);
         final TopologyEvent event = new TopologyEvent(
                 TopologyEvent.Type.TOPOLOGY_CHANGED,
@@ -1407,7 +1367,6 @@
         pceManager.pceStore = null;
         pceManager.topologyService = null;
         pceManager.mastershipService = null;
-        flowsDownloaded = 0;
     }
 
     private class MockTopologyService extends TopologyServiceAdapter {
@@ -1416,7 +1375,8 @@
         }
 
         @Override
-        public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeight weight) {
+        public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
+                                  LinkWeight weight) {
             DefaultTopologyVertex srcV = new DefaultTopologyVertex(src);
             DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst);
             Set<TopologyVertex> vertices = graph.getVertexes();
@@ -1425,8 +1385,9 @@
                 return ImmutableSet.of();
             }
 
-            GraphPathSearch.Result<TopologyVertex, TopologyEdge> result = PathComputationTest.graphSearch()
-                    .search(graph, srcV, dstV, weight, ALL_PATHS);
+            GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
+                    PathComputationTest.graphSearch()
+                            .search(graph, srcV, dstV, adapt(weight), ALL_PATHS);
             ImmutableSet.Builder<Path> builder = ImmutableSet.builder();
             for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
                 builder.add(PathComputationTest.networkPath(path));
@@ -1435,20 +1396,14 @@
         }
     }
 
-    private TopologyGraph getGraph(Set<TopologyVertex> removedVertex, Set<TopologyEdge> removedEdges) {
+    private TopologyGraph getGraph(Set<TopologyVertex> removedVertex,
+                                   Set<TopologyEdge> removedEdges) {
         if (removedVertex != null) {
-            vertexes.remove(removedVertex);
-            removedVertex.forEach(v ->
-            {
-                vertexes.remove(v);
-            });
+            removedVertex.forEach(vertexes::remove);
         }
 
         if (removedEdges != null) {
-            removedEdges.forEach(e ->
-            {
-                edges.remove(e);
-            });
+            removedEdges.forEach(edges::remove);
         }
 
         return new DefaultTopologyGraph(vertexes, edges);
@@ -1465,7 +1420,8 @@
 
             // Otherwise get all paths between the source and destination edge
             // devices.
-            computedPaths = topologyService.getPaths(null, (DeviceId) src, (DeviceId) dst, weight);
+            computedPaths = topologyService.getPaths(null, (DeviceId) src,
+                    (DeviceId) dst, weight);
             return computedPaths;
         }
 
@@ -1475,15 +1431,18 @@
     }
 
     private class MockTunnelServiceAdapter extends TunnelServiceAdapter {
-        private HashMap<TunnelId, Tunnel> tunnelIdAsKeyStore = new HashMap<TunnelId, Tunnel>();
+        private HashMap<TunnelId, Tunnel> tunnelIdAsKeyStore = new HashMap<>();
         private int tunnelIdCounter = 0;
 
         @Override
-        public TunnelId setupTunnel(ApplicationId producerId, ElementId srcElementId, Tunnel tunnel, Path path) {
+        public TunnelId setupTunnel(ApplicationId producerId,
+                                    ElementId srcElementId,
+                                    Tunnel tunnel, Path path) {
             TunnelId tunnelId = TunnelId.valueOf(String.valueOf(++tunnelIdCounter));
-            Tunnel tunnelToInsert = new DefaultTunnel(tunnel.providerId(), tunnel.src(), tunnel.dst(), tunnel.type(),
-                                                      tunnel.state(), tunnel.groupId(), tunnelId, tunnel.tunnelName(),
-                                                      path, tunnel.annotations());
+            Tunnel tunnelToInsert = new DefaultTunnel(tunnel.providerId(),
+                    tunnel.src(), tunnel.dst(), tunnel.type(),
+                    tunnel.state(), tunnel.groupId(), tunnelId,
+                    tunnel.tunnelName(), path, tunnel.annotations());
             tunnelIdAsKeyStore.put(tunnelId, tunnelToInsert);
             return tunnelId;
         }
@@ -1494,28 +1453,33 @@
         }
 
         /**
-         * Stimulates the effect of receiving PLSP id and LSP id from protocol PCRpt msg.
+         * Stimulates the effect of receiving PLSP id and LSP id from protocol
+         * PCRpt msg.
          */
-        public TunnelId updateTunnelWithLspIds(Tunnel tunnel, String pLspId, String localLspId, State state) {
+        public TunnelId updateTunnelWithLspIds(Tunnel tunnel, String pLspId,
+                                               String localLspId, State state) {
             TunnelId tunnelId = tunnel.tunnelId();
             Builder annotationBuilder = DefaultAnnotations.builder();
             annotationBuilder.putAll(tunnel.annotations());
 
-            // PCRpt in response to PCInitate msg will carry PLSP id allocated by PCC.
+            // PCRpt in response to PCInitate msg will carry PLSP id allocated
+            // by PCC.
             if (tunnel.annotations().value(PLSP_ID) == null) {
                 annotationBuilder.set(PLSP_ID, pLspId);
             }
 
-            // Signalled LSPs will carry local LSP id allocated by signalling protocol(PCC).
+            // Signalled LSPs will carry local LSP id allocated by signalling
+            // protocol(PCC).
             if (tunnel.annotations().value(LOCAL_LSP_ID) == null) {
                 annotationBuilder.set(LOCAL_LSP_ID, localLspId);
             }
             SparseAnnotations annotations = annotationBuilder.build();
             tunnelIdAsKeyStore.remove(tunnelId, tunnel);
 
-            Tunnel tunnelToInsert = new DefaultTunnel(tunnel.providerId(), tunnel.src(), tunnel.dst(), tunnel.type(),
-                                                      state, tunnel.groupId(), tunnelId, tunnel.tunnelName(),
-                                                      tunnel.path(), annotations);
+            Tunnel tunnelToInsert = new DefaultTunnel(tunnel.providerId(),
+                    tunnel.src(), tunnel.dst(), tunnel.type(),
+                    state, tunnel.groupId(), tunnelId, tunnel.tunnelName(),
+                    tunnel.path(), annotations);
 
             tunnelIdAsKeyStore.put(tunnelId, tunnelToInsert);
 
@@ -1544,40 +1508,45 @@
         }
 
         @Override
-        public Collection<Tunnel> queryTunnel(TunnelEndPoint src, TunnelEndPoint dst) {
-            Collection<Tunnel> result = new HashSet<Tunnel>();
+        public Collection<Tunnel> queryTunnel(TunnelEndPoint src,
+                                              TunnelEndPoint dst) {
+            Collection<Tunnel> result = new HashSet<>();
             Tunnel tunnel = null;
             for (TunnelId tunnelId : tunnelIdAsKeyStore.keySet()) {
                 tunnel = tunnelIdAsKeyStore.get(tunnelId);
 
-                if ((null != tunnel) && (src.equals(tunnel.src())) && (dst.equals(tunnel.dst()))) {
+                if ((null != tunnel) && (src.equals(tunnel.src())) &&
+                        (dst.equals(tunnel.dst()))) {
                     result.add(tunnel);
                 }
             }
 
-            return result.size() == 0 ? Collections.emptySet() : ImmutableSet.copyOf(result);
+            return result.size() == 0 ? Collections.emptySet() :
+                    ImmutableSet.copyOf(result);
         }
 
         @Override
         public Collection<Tunnel> queryTunnel(Tunnel.Type type) {
-            Collection<Tunnel> result = new HashSet<Tunnel>();
+            Collection<Tunnel> result = new HashSet<>();
 
             for (TunnelId tunnelId : tunnelIdAsKeyStore.keySet()) {
                 result.add(tunnelIdAsKeyStore.get(tunnelId));
             }
 
-            return result.size() == 0 ? Collections.emptySet() : ImmutableSet.copyOf(result);
+            return result.size() == 0 ? Collections.emptySet() :
+                    ImmutableSet.copyOf(result);
         }
 
         @Override
         public Collection<Tunnel> queryAllTunnels() {
-            Collection<Tunnel> result = new HashSet<Tunnel>();
+            Collection<Tunnel> result = new HashSet<>();
 
             for (TunnelId tunnelId : tunnelIdAsKeyStore.keySet()) {
                 result.add(tunnelIdAsKeyStore.get(tunnelId));
             }
 
-            return result.size() == 0 ? Collections.emptySet() : ImmutableSet.copyOf(result);
+            return result.size() == 0 ? Collections.emptySet() :
+                    ImmutableSet.copyOf(result);
         }
 
         @Override
@@ -1586,7 +1555,8 @@
 
             for (Tunnel t : tunnelIdAsKeyStore.values()) {
                 for (Link l : t.path().links()) {
-                    if (l.src().deviceId().equals(deviceId) || l.dst().deviceId().equals(deviceId)) {
+                    if (l.src().deviceId().equals(deviceId) ||
+                            l.dst().deviceId().equals(deviceId)) {
                         tunnelList.add(t);
                         break;
                     }
diff --git a/core/api/src/main/java/org/onosproject/net/DefaultDisjointPath.java b/core/api/src/main/java/org/onosproject/net/DefaultDisjointPath.java
index c4e0398..b68110d 100644
--- a/core/api/src/main/java/org/onosproject/net/DefaultDisjointPath.java
+++ b/core/api/src/main/java/org/onosproject/net/DefaultDisjointPath.java
@@ -16,6 +16,7 @@
 
 package org.onosproject.net;
 
+import org.onlab.graph.Weight;
 import org.onosproject.net.provider.ProviderId;
 
 import java.util.List;
@@ -40,7 +41,7 @@
      */
     public DefaultDisjointPath(ProviderId providerId, DefaultPath path1, DefaultPath path2) {
         // Note: cost passed to super will never be used
-        super(providerId, path1.links(), path1.cost());
+        super(providerId, path1.links(), path1.weight());
         this.path1 = path1;
         this.path2 = path2;
     }
@@ -66,10 +67,12 @@
 
     @Override
     public double cost() {
-        if (usingPath1) {
-            return path1.cost();
-        }
-        return path2.cost();
+        return usingPath1 ? path1.cost() : path2.cost();
+    }
+
+    @Override
+    public Weight weight() {
+        return usingPath1 ? path1.weight() : path2.weight();
     }
 
     @Override
diff --git a/core/api/src/main/java/org/onosproject/net/DefaultPath.java b/core/api/src/main/java/org/onosproject/net/DefaultPath.java
index e4c3d8c..79677ac 100644
--- a/core/api/src/main/java/org/onosproject/net/DefaultPath.java
+++ b/core/api/src/main/java/org/onosproject/net/DefaultPath.java
@@ -17,6 +17,8 @@
 
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableList;
+import org.onlab.graph.ScalarWeight;
+import org.onlab.graph.Weight;
 import org.onosproject.net.provider.ProviderId;
 
 import java.util.List;
@@ -31,7 +33,27 @@
 public class DefaultPath extends DefaultLink implements Path {
 
     private final List<Link> links;
-    private final double cost;
+    private final Weight cost;
+
+    /**
+     * Creates a path from the specified source and destination using the
+     * supplied list of links.
+     *
+     * @param providerId provider identity
+     * @param links      contiguous links that comprise the path
+     * @param cost       unit-less path cost
+     * @param annotations optional key/value annotations
+     *
+     * @deprecated in Junco (1.9.0)
+     */
+    @Deprecated
+    public DefaultPath(ProviderId providerId, List<Link> links, double cost,
+                       Annotations... annotations) {
+        super(providerId, source(links), destination(links), Type.INDIRECT,
+                State.ACTIVE, annotations);
+        this.links = ImmutableList.copyOf(links);
+        this.cost = new ScalarWeight(cost);
+    }
 
     /**
      * Creates a path from the specified source and destination using the
@@ -42,7 +64,7 @@
      * @param cost       unit-less path cost
      * @param annotations optional key/value annotations
      */
-    public DefaultPath(ProviderId providerId, List<Link> links, double cost,
+    public DefaultPath(ProviderId providerId, List<Link> links, Weight cost,
                        Annotations... annotations) {
         super(providerId, source(links), destination(links), Type.INDIRECT, State.ACTIVE, annotations);
         this.links = ImmutableList.copyOf(links);
@@ -56,6 +78,14 @@
 
     @Override
     public double cost() {
+        if (cost instanceof ScalarWeight) {
+            return ((ScalarWeight) cost).value();
+        }
+        return 0;
+    }
+
+    @Override
+    public Weight weight() {
         return cost;
     }
 
diff --git a/core/api/src/main/java/org/onosproject/net/Path.java b/core/api/src/main/java/org/onosproject/net/Path.java
index fdff4e0..13fae0a 100644
--- a/core/api/src/main/java/org/onosproject/net/Path.java
+++ b/core/api/src/main/java/org/onosproject/net/Path.java
@@ -15,13 +15,16 @@
  */
 package org.onosproject.net;
 
+import org.onlab.graph.Weight;
+
 import java.util.List;
 
 /**
  * Representation of a contiguous directed path in a network. Path comprises
  * of a sequence of links, where adjacent links must share the same device,
  * meaning that destination of the source of one link must coincide with the
- * destination of the previous link.
+ * destination of the previous link. Path weight (cost) is an aggregation
+ * of the weights of the links the path consists of.
  */
 public interface Path extends Link {
 
@@ -36,7 +39,17 @@
      * Returns the path cost as a unit-less value.
      *
      * @return unit-less path cost
+     *
+     * @deprecated in Junco (1.9.0), use weight() instead
      */
+    @Deprecated
     double cost();
 
+    /**
+     * Returns the path cost as an weight instance.
+     *
+     * @return weight path cost
+     */
+    Weight weight();
+
 }
diff --git a/core/api/src/main/java/org/onosproject/net/topology/AbstractPathService.java b/core/api/src/main/java/org/onosproject/net/topology/AbstractPathService.java
index 8b24cbb..2c43fc7 100644
--- a/core/api/src/main/java/org/onosproject/net/topology/AbstractPathService.java
+++ b/core/api/src/main/java/org/onosproject/net/topology/AbstractPathService.java
@@ -18,6 +18,7 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
+import org.onlab.graph.Weight;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DefaultDisjointPath;
 import org.onosproject.net.DefaultEdgeLink;
@@ -40,6 +41,7 @@
 import java.util.Set;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.topology.AdapterLinkWeigher.adapt;
 
 /**
  * Helper class for path service.
@@ -56,15 +58,25 @@
     private static final ProviderId PID = new ProviderId("core", "org.onosproject.core");
     private static final PortNumber P0 = PortNumber.portNumber(0);
 
+    protected static final LinkWeigher DEFAULT_WEIGHER =
+            adapt(new HopCountLinkWeight());
+
     protected TopologyService topologyService;
 
     protected HostService hostService;
 
     @Override
     public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
+        return getPaths(src, dst, adapt(weight));
+    }
+
+    @Override
+    public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
         checkNotNull(src, ELEMENT_ID_NULL);
         checkNotNull(dst, ELEMENT_ID_NULL);
 
+        LinkWeigher internalWeigher = weigher != null ? weigher : DEFAULT_WEIGHER;
+
         // Get the source and destination edge locations
         EdgeLink srcEdge = getEdgeLink(src, true);
         EdgeLink dstEdge = getEdgeLink(dst, false);
@@ -80,24 +92,30 @@
         // If the source and destination are on the same edge device, there
         // is just one path, so build it and return it.
         if (srcDevice.equals(dstDevice)) {
-            return edgeToEdgePaths(srcEdge, dstEdge);
+            return edgeToEdgePaths(srcEdge, dstEdge, internalWeigher);
         }
 
         // Otherwise get all paths between the source and destination edge
         // devices.
         Topology topology = topologyService.currentTopology();
-        Set<Path> paths = weight == null ?
-                topologyService.getPaths(topology, srcDevice, dstDevice) :
-                topologyService.getPaths(topology, srcDevice, dstDevice, weight);
+        Set<Path> paths = topologyService.getPaths(topology, srcDevice,
+                dstDevice, internalWeigher);
 
-        return edgeToEdgePaths(srcEdge, dstEdge, paths);
+        return edgeToEdgePaths(srcEdge, dstEdge, paths, internalWeigher);
     }
 
     @Override
     public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight) {
+        return getDisjointPaths(src, dst, adapt(weight));
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
         checkNotNull(src, ELEMENT_ID_NULL);
         checkNotNull(dst, ELEMENT_ID_NULL);
 
+        LinkWeigher internalWeigher = weigher != null ? weigher : DEFAULT_WEIGHER;
+
         // Get the source and destination edge locations
         EdgeLink srcEdge = getEdgeLink(src, true);
         EdgeLink dstEdge = getEdgeLink(dst, false);
@@ -113,25 +131,32 @@
         // If the source and destination are on the same edge device, there
         // is just one path, so build it and return it.
         if (srcDevice.equals(dstDevice)) {
-            return edgeToEdgePathsDisjoint(srcEdge, dstEdge);
+            return edgeToEdgePathsDisjoint(srcEdge, dstEdge, internalWeigher);
         }
 
         // Otherwise get all paths between the source and destination edge
         // devices.
         Topology topology = topologyService.currentTopology();
-        Set<DisjointPath> paths = weight == null ?
-                topologyService.getDisjointPaths(topology, srcDevice, dstDevice) :
-                topologyService.getDisjointPaths(topology, srcDevice, dstDevice, weight);
+        Set<DisjointPath> paths = topologyService.getDisjointPaths(topology,
+                srcDevice, dstDevice, internalWeigher);
 
-        return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths);
+        return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths, internalWeigher);
     }
 
     @Override
     public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight,
                                               Map<Link, Object> riskProfile) {
+        return getDisjointPaths(src, dst, adapt(weight), riskProfile);
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst,
+                                              LinkWeigher weigher, Map<Link, Object> riskProfile) {
         checkNotNull(src, ELEMENT_ID_NULL);
         checkNotNull(dst, ELEMENT_ID_NULL);
 
+        LinkWeigher internalWeigher = weigher != null ? weigher : DEFAULT_WEIGHER;
+
         // Get the source and destination edge locations
         EdgeLink srcEdge = getEdgeLink(src, true);
         EdgeLink dstEdge = getEdgeLink(dst, false);
@@ -147,17 +172,16 @@
         // If the source and destination are on the same edge device, there
         // is just one path, so build it and return it.
         if (srcDevice.equals(dstDevice)) {
-            return edgeToEdgePathsDisjoint(srcEdge, dstEdge);
+            return edgeToEdgePathsDisjoint(srcEdge, dstEdge, internalWeigher);
         }
 
         // Otherwise get all paths between the source and destination edge
         // devices.
         Topology topology = topologyService.currentTopology();
-        Set<DisjointPath> paths = weight == null ?
-                topologyService.getDisjointPaths(topology, srcDevice, dstDevice, riskProfile) :
-                topologyService.getDisjointPaths(topology, srcDevice, dstDevice, weight, riskProfile);
+        Set<DisjointPath> paths = topologyService.getDisjointPaths(topology,
+                srcDevice, dstDevice, internalWeigher, riskProfile);
 
-        return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths);
+        return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths, internalWeigher);
     }
 
     // Finds the host edge link if the element ID is a host id of an existing
@@ -178,61 +202,63 @@
 
     // Produces a set of edge-to-edge paths using the set of infrastructure
     // paths and the given edge links.
-    private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink) {
+    private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink, LinkWeigher weigher) {
         Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(1);
-        endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, null));
+        endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, null, weigher));
         return endToEndPaths;
     }
 
     // Produces a set of edge-to-edge paths using the set of infrastructure
     // paths and the given edge links.
-    private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink, Set<Path> paths) {
+    private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink, Set<Path> paths,
+                                      LinkWeigher weigher) {
         Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size());
         for (Path path : paths) {
-            endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, path));
+            endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, path, weigher));
         }
         return endToEndPaths;
     }
 
-    private Set<DisjointPath> edgeToEdgePathsDisjoint(EdgeLink srcLink, EdgeLink dstLink) {
+    private Set<DisjointPath> edgeToEdgePathsDisjoint(EdgeLink srcLink, EdgeLink dstLink, LinkWeigher weigher) {
         Set<DisjointPath> endToEndPaths = Sets.newHashSetWithExpectedSize(1);
-        endToEndPaths.add(edgeToEdgePathD(srcLink, dstLink, null));
+        endToEndPaths.add(edgeToEdgePathD(srcLink, dstLink, null, weigher));
         return endToEndPaths;
     }
 
     private Set<DisjointPath> edgeToEdgePathsDisjoint(EdgeLink srcLink, EdgeLink dstLink,
-                                                             Set<DisjointPath> paths) {
+                                                             Set<DisjointPath> paths, LinkWeigher weigher) {
         Set<DisjointPath> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size());
         for (DisjointPath path : paths) {
-            endToEndPaths.add(edgeToEdgePathD(srcLink, dstLink, path));
+            endToEndPaths.add(edgeToEdgePathD(srcLink, dstLink, path, weigher));
         }
         return endToEndPaths;
     }
 
     // Produces a direct edge-to-edge path.
-    private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path path) {
+    private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path path, LinkWeigher weigher) {
         List<Link> links = Lists.newArrayListWithCapacity(2);
-        double cost = 0;
+        Weight cost = weigher.getInitialWeight();
 
         // Add source and destination edge links only if they are real and
         // add the infrastructure path only if it is not null.
         if (srcLink != NOT_HOST) {
             links.add(srcLink);
-            cost++;
+            cost = cost.merge(weigher.weight(new DefaultTopologyEdge(null, null, srcLink)));
         }
         if (path != null) {
             links.addAll(path.links());
-            cost += path.cost();
+            cost = cost.merge(path.weight());
         }
         if (dstLink != NOT_HOST) {
             links.add(dstLink);
-            cost++;
+            cost = cost.merge(weigher.weight(new DefaultTopologyEdge(null, null, srcLink)));
         }
         return new DefaultPath(PID, links, cost);
     }
 
     // Produces a direct edge-to-edge path.
-    private DisjointPath edgeToEdgePathD(EdgeLink srcLink, EdgeLink dstLink, DisjointPath path) {
+    private DisjointPath edgeToEdgePathD(EdgeLink srcLink, EdgeLink dstLink, DisjointPath path,
+                                         LinkWeigher weigher) {
         Path primary = null;
         Path backup = null;
         if (path != null) {
@@ -240,10 +266,12 @@
             backup = path.backup();
         }
         if (backup == null) {
-        return new DefaultDisjointPath(PID, (DefaultPath) edgeToEdgePath(srcLink, dstLink, primary));
+        return new DefaultDisjointPath(PID,
+                (DefaultPath) edgeToEdgePath(srcLink, dstLink, primary, weigher));
         }
-        return new DefaultDisjointPath(PID, (DefaultPath) edgeToEdgePath(srcLink, dstLink, primary),
-                                       (DefaultPath) edgeToEdgePath(srcLink, dstLink, backup));
+        return new DefaultDisjointPath(PID,
+                (DefaultPath) edgeToEdgePath(srcLink, dstLink, primary, weigher),
+                (DefaultPath) edgeToEdgePath(srcLink, dstLink, backup, weigher));
     }
 
 
diff --git a/core/api/src/main/java/org/onosproject/net/topology/AdapterLinkWeigher.java b/core/api/src/main/java/org/onosproject/net/topology/AdapterLinkWeigher.java
new file mode 100644
index 0000000..1bb2729
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/topology/AdapterLinkWeigher.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.topology;
+
+import org.onlab.graph.DefaultEdgeWeigher;
+import org.onlab.graph.ScalarWeight;
+import org.onlab.graph.Weight;
+
+/**
+ * Wrapper which transforms double-based link weigher to {@link Weight}-based
+ * link weigher.
+ */
+public final class AdapterLinkWeigher
+        extends DefaultEdgeWeigher<TopologyVertex, TopologyEdge>
+        implements LinkWeigher {
+
+    private final LinkWeight doubleWeigher;
+
+    private AdapterLinkWeigher(LinkWeight doubleWeigher) {
+        this.doubleWeigher = doubleWeigher;
+    }
+
+    @Override
+    public Weight weight(TopologyEdge edge) {
+        return new ScalarWeight(doubleWeigher.weight(edge));
+    }
+
+    /**
+     * Transforms double-based link weigher to {@link Weight}-based weigher.
+     *
+     * @param lw double-based weigher
+     * @return {@link Weight}-based weigher
+     */
+    public static LinkWeigher adapt(LinkWeight lw) {
+        return lw == null ? null : new AdapterLinkWeigher(lw);
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/topology/LinkWeigher.java b/core/api/src/main/java/org/onosproject/net/topology/LinkWeigher.java
new file mode 100644
index 0000000..9008811
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/topology/LinkWeigher.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.topology;
+
+import org.onlab.graph.EdgeWeigher;
+
+/**
+ * Entity capable of determining cost or weight of a specified topology
+ * graph edge. Returns {@link org.onlab.graph.Weight} instances.
+ */
+public interface LinkWeigher extends EdgeWeigher<TopologyVertex, TopologyEdge> {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/topology/LinkWeight.java b/core/api/src/main/java/org/onosproject/net/topology/LinkWeight.java
index 99fa38c..22eb7d1 100644
--- a/core/api/src/main/java/org/onosproject/net/topology/LinkWeight.java
+++ b/core/api/src/main/java/org/onosproject/net/topology/LinkWeight.java
@@ -15,11 +15,19 @@
  */
 package org.onosproject.net.topology;
 
-import org.onlab.graph.EdgeWeight;
-
 /**
  * Entity capable of determining cost or weight of a specified topology
  * graph edge.
+ * @deprecated in Junco (1.9.0), use {@link LinkWeigher} instead
  */
-public interface LinkWeight extends EdgeWeight<TopologyVertex, TopologyEdge> {
+@Deprecated
+public interface LinkWeight {
+
+    /**
+     * Returns the weight of the given edge.
+     *
+     * @param edge edge to be weighed
+     * @return edge weight
+     */
+    double weight(TopologyEdge edge);
 }
diff --git a/core/api/src/main/java/org/onosproject/net/topology/PathAdminService.java b/core/api/src/main/java/org/onosproject/net/topology/PathAdminService.java
index 0214e57..d88d729 100644
--- a/core/api/src/main/java/org/onosproject/net/topology/PathAdminService.java
+++ b/core/api/src/main/java/org/onosproject/net/topology/PathAdminService.java
@@ -29,10 +29,22 @@
      * used.
      *
      * @param linkWeight default link-weight function
+     *
+     * @deprecated in Junco (1.9.0), use setDefaultLinkWeigher() instead
      */
+    @Deprecated
     void setDefaultLinkWeight(LinkWeight linkWeight);
 
     /**
+     * Sets the specified link-weight function to be used as a default.
+     * If null is specified, the builtin default hop-count link-weight will be
+     * used.
+     *
+     * @param linkWeigher link-weight function to be used as default
+     */
+    void setDefaultLinkWeigher(LinkWeigher linkWeigher);
+
+    /**
      * Sets the specified graph path search algorightm to be used as a default.
      * If null is specified, the builtin default all-shortest-paths Dijkstra
      * algorithm will be used.
diff --git a/core/api/src/main/java/org/onosproject/net/topology/PathService.java b/core/api/src/main/java/org/onosproject/net/topology/PathService.java
index 6ed4799..adfca3d 100644
--- a/core/api/src/main/java/org/onosproject/net/topology/PathService.java
+++ b/core/api/src/main/java/org/onosproject/net/topology/PathService.java
@@ -49,10 +49,25 @@
      * @param dst    destination element
      * @param weight edge-weight entity
      * @return set of all shortest paths between the two element
+     *
+     * @deprecated in Junco (1.9.0), use version with LinkWeigher instead
      */
+    @Deprecated
     Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight);
 
     /**
+     * Returns the set of all shortest paths between the specified source and
+     * destination network elements.  The path is computed using the supplied
+     * edge-weight function.
+     *
+     * @param src     source element
+     * @param dst     destination element
+     * @param weigher edge-weight entity
+     * @return set of all shortest paths between the two element
+     */
+    Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher);
+
+    /**
      * Returns the set of all disjoint shortest path pairs between the
      * specified source and destination elements. The path is computed using
      * the default edge-weight function, which by default is hop-count.
@@ -72,12 +87,28 @@
      * @param dst    destination device
      * @param weight edge-weight entity
      * @return set of all shortest paths between the two devices
+     *
+     * @deprecated in Junco (1.9.0), use version with LinkWeigher instead
      */
+    @Deprecated
     Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst,
                                        LinkWeight weight);
 
     /**
      * Returns the set of all disjoint shortest path pairs between the
+     * specified source and destination elements. The path is computed using
+     * the supplied edge-weight function.
+     *
+     * @param src     source device
+     * @param dst     destination device
+     * @param weigher edge-weight entity
+     * @return set of all shortest paths between the two devices
+     */
+    Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst,
+                                       LinkWeigher weigher);
+
+    /**
+     * Returns the set of all disjoint shortest path pairs between the
      * specified source and destination elements and taking into consideration
      * the provided risk profile. The path is computed using the default
      * edge-weight function, which by default is hop-count.
@@ -101,9 +132,28 @@
      * @param weight      edge-weight entity
      * @param riskProfile map of edges to risk profiles
      * @return set of all shortest paths between the two devices
+     *
+     * @deprecated in Junco (1.9.0), use version with LinkWeigher instead
      */
+    @Deprecated
     Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst,
                                        LinkWeight weight,
                                        Map<Link, Object> riskProfile);
 
+    /**
+     * Returns the set of all disjoint shortest path pairs between the
+     * specified source and destination elements and taking into consideration
+     * the provided risk profile. The path is computed using the supplied
+     * edge-weight function.
+     *
+     * @param src         source device
+     * @param dst         destination device
+     * @param weigher     edge-weight entity
+     * @param riskProfile map of edges to risk profiles
+     * @return set of all shortest paths between the two devices
+     */
+    Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst,
+                                       LinkWeigher weigher,
+                                       Map<Link, Object> riskProfile);
+
 }
diff --git a/core/api/src/main/java/org/onosproject/net/topology/TopologyService.java b/core/api/src/main/java/org/onosproject/net/topology/TopologyService.java
index e4504c5..13d1842 100644
--- a/core/api/src/main/java/org/onosproject/net/topology/TopologyService.java
+++ b/core/api/src/main/java/org/onosproject/net/topology/TopologyService.java
@@ -109,11 +109,27 @@
      * @param dst      destination device
      * @param weight   edge-weight entity
      * @return set of all shortest paths between the two devices
+     *
+     * @deprecated in Junco (1.9.0), use version with LinkWeigher instead
      */
+    @Deprecated
     Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
                        LinkWeight weight);
 
     /**
+     * Returns the set of all shortest paths, computed using the supplied
+     * edge-weight entity, between the specified source and destination devices.
+     *
+     * @param topology topology descriptor
+     * @param src      source device
+     * @param dst      destination device
+     * @param weigher  edge-weight entity
+     * @return set of all shortest paths between the two devices
+     */
+    Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
+                       LinkWeigher weigher);
+
+    /**
      * Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count,
      * between the specified source and destination devices.
      *
@@ -133,11 +149,27 @@
      * @param dst      destination device
      * @param weight   edge-weight entity
      * @return set of all shortest paths between the two devices
+     *
+     * @deprecated in Junco (1.9.0), use version with LinkWeigher instead
      */
+    @Deprecated
     Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
                                        LinkWeight weight);
 
     /**
+     * Returns the set of all disjoint shortest path pairs, computed using the supplied
+     * edge-weight entity, between the specified source and destination devices.
+     *
+     * @param topology topology descriptor
+     * @param src      source device
+     * @param dst      destination device
+     * @param weigher  edge-weight entity
+     * @return set of all shortest paths between the two devices
+     */
+    Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
+                                       LinkWeigher weigher);
+
+    /**
      * Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count,
      * between the specified source and destination devices.
      *
@@ -160,11 +192,28 @@
      * @param weight      edge-weight entity
      * @param riskProfile map of edges to risk profiles
      * @return set of all shortest paths between the two devices
+     *
+     * @deprecated in Junco (1.9.0), use version with LinkWeigher instead
      */
+    @Deprecated
     Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
                                        LinkWeight weight, Map<Link, Object> riskProfile);
 
     /**
+     * Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count,
+     * between the specified source and destination devices.
+     *
+     * @param topology    topology descriptor
+     * @param src         source device
+     * @param dst         destination device
+     * @param weigher     edge-weight entity
+     * @param riskProfile map of edges to risk profiles
+     * @return set of all shortest paths between the two devices
+     */
+    Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
+                                       LinkWeigher weigher, Map<Link, Object> riskProfile);
+
+    /**
      * Indicates whether the specified connection point is part of the network
      * infrastructure or part of network edge.
      *
diff --git a/core/api/src/main/java/org/onosproject/net/topology/TopologyStore.java b/core/api/src/main/java/org/onosproject/net/topology/TopologyStore.java
index 61ab526..907beb2 100644
--- a/core/api/src/main/java/org/onosproject/net/topology/TopologyStore.java
+++ b/core/api/src/main/java/org/onosproject/net/topology/TopologyStore.java
@@ -109,11 +109,26 @@
      * @param dst      destination device
      * @param weight   link weight function
      * @return set of shortest paths
+     *
+     * @deprecated in Junco (1.9.0), use version with LinkWeigher instead
      */
+    @Deprecated
     Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
                        LinkWeight weight);
 
     /**
+     * Computes and returns the set of shortest paths between src and dest.
+     *
+     * @param topology topology descriptor
+     * @param src      source device
+     * @param dst      destination device
+     * @param weigher  link weight function
+     * @return set of shortest paths
+     */
+    Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
+                       LinkWeigher weigher);
+
+    /**
      * Computes and returns the set of disjoint shortest path pairs
      * between src and dst.
      *
@@ -122,7 +137,10 @@
      * @param dst      destination device
      * @param weight   link weight function
      * @return set of shortest paths
+     *
+     * @deprecated in Junco (1.9.0), use version with LinkWeigher instead
      */
+    @Deprecated
     Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
                                        LinkWeight weight);
 
@@ -133,6 +151,19 @@
      * @param topology topology descriptor
      * @param src      source device
      * @param dst      destination device
+     * @param weigher  link weight function
+     * @return set of shortest paths
+     */
+    Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
+                                       LinkWeigher weigher);
+
+    /**
+     * Computes and returns the set of disjoint shortest path pairs
+     * between src and dst.
+     *
+     * @param topology topology descriptor
+     * @param src      source device
+     * @param dst      destination device
      * @return set of shortest paths
      */
     Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst);
@@ -141,24 +172,42 @@
      * Computes and returns the set of SRLG disjoint shortest path pairs between source
      * and dst, given a mapping of edges to SRLG risk groups.
      *
-     * @param topology topology descriptor
-     * @param src      source device
-     * @param dst      destination device
-     * @param weight   link weight function
-     * @param riskProfile   map of edges to objects. Edges that map to the same object will
+     * @param topology    topology descriptor
+     * @param src         source device
+     * @param dst         destination device
+     * @param weight      link weight function
+     * @param riskProfile map of edges to objects. Edges that map to the same object will
      * be treated as if they were in the same risk group.
      * @return set of shortest paths
+     *
+     * @deprecated in Junco (1.9.0), use version with LinkWeigher instead
      */
+    @Deprecated
     Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
                                        LinkWeight weight, Map<Link, Object> riskProfile);
 
     /**
+     * Computes and returns the set of SRLG disjoint shortest path pairs between source
+     * and dst, given a mapping of edges to SRLG risk groups.
+     *
+     * @param topology    topology descriptor
+     * @param src         source device
+     * @param dst         destination device
+     * @param weigher     link weight function
+     * @param riskProfile map of edges to objects. Edges that map to the same object will
+     * be treated as if they were in the same risk group.
+     * @return set of shortest paths
+     */
+    Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
+                                       LinkWeigher weigher, Map<Link, Object> riskProfile);
+
+    /**
      * Returns the set of pre-computed SRLG shortest paths between src and dest.
      *
-     * @param topology topology descriptor
-     * @param src      source device
-     * @param dst      destination device
-     * @param riskProfile   map of edges to objects. Edges that map to the same object will
+     * @param topology    topology descriptor
+     * @param src         source device
+     * @param dst         destination device
+     * @param riskProfile map of edges to objects. Edges that map to the same object will
      * be treated as if they were in the same risk group.
      * @return set of shortest paths
      */
diff --git a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
index 931ac72..a944ca6 100644
--- a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
+++ b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
@@ -16,6 +16,7 @@
 package org.onosproject.net.intent;
 
 import com.google.common.base.MoreObjects;
+import org.onlab.graph.Weight;
 import org.onlab.util.Bandwidth;
 import org.onosproject.core.DefaultGroupId;
 import org.onosproject.core.GroupId;
@@ -46,7 +47,7 @@
 import org.onosproject.net.resource.ResourceService;
 import org.onosproject.net.topology.DefaultTopologyEdge;
 import org.onosproject.net.topology.DefaultTopologyVertex;
-import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.PathServiceAdapter;
 import org.onosproject.net.topology.TopologyVertex;
 import org.onosproject.store.Timestamp;
@@ -159,19 +160,19 @@
         }
 
         @Override
-        public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
-            final Set<Path> paths = getPaths(src, dst);
+        public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
+            Set<Path> paths = getPaths(src, dst);
 
             for (Path path : paths) {
-                final DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
-                final DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
+                DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
+                DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
                 if (srcDevice != null && dstDevice != null) {
-                    final TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
-                    final TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
-                    final Link link = link(src.toString(), 1, dst.toString(), 1);
+                    TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
+                    TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
+                    Link link = link(src.toString(), 1, dst.toString(), 1);
 
-                    final double weightValue = weight.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
-                    if (weightValue < 0) {
+                    Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
+                    if (weightValue.isNegative()) {
                         return new HashSet<>();
                     }
                 }
@@ -220,7 +221,7 @@
         }
 
         @Override
-        public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
+        public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
             final Set<Path> paths = getPaths(src, dst);
 
             for (Path path : paths) {
@@ -231,8 +232,8 @@
                     final TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
                     final Link link = link(src.toString(), 1, dst.toString(), 1);
 
-                    final double weightValue = weight.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
-                    if (weightValue < 0) {
+                    final Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
+                    if (weightValue.isNegative()) {
                         return new HashSet<>();
                     }
                 }
diff --git a/core/api/src/test/java/org/onosproject/net/topology/PathServiceAdapter.java b/core/api/src/test/java/org/onosproject/net/topology/PathServiceAdapter.java
index eecb73e..f0494b1 100644
--- a/core/api/src/test/java/org/onosproject/net/topology/PathServiceAdapter.java
+++ b/core/api/src/test/java/org/onosproject/net/topology/PathServiceAdapter.java
@@ -38,12 +38,25 @@
     }
 
     @Override
+    public Set<Path> getPaths(ElementId src, ElementId dst,
+                              LinkWeigher weigher) {
+        return null;
+    }
+
+    @Override
     public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst) {
         return null;
     }
 
     @Override
-    public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight) {
+    public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst,
+                                              LinkWeight weight) {
+        return null;
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst,
+                                              LinkWeigher weigher) {
         return null;
     }
 
@@ -59,4 +72,11 @@
                                               Map<Link, Object> riskProfile) {
         return null;
     }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst,
+                                              LinkWeigher weigher,
+                                              Map<Link, Object> riskProfile) {
+        return null;
+    }
 }
diff --git a/core/api/src/test/java/org/onosproject/net/topology/TopologyServiceAdapter.java b/core/api/src/test/java/org/onosproject/net/topology/TopologyServiceAdapter.java
index f86bb3b..79ec17c 100644
--- a/core/api/src/test/java/org/onosproject/net/topology/TopologyServiceAdapter.java
+++ b/core/api/src/test/java/org/onosproject/net/topology/TopologyServiceAdapter.java
@@ -54,12 +54,14 @@
     }
 
     @Override
-    public Set<DeviceId> getClusterDevices(Topology topology, TopologyCluster cluster) {
+    public Set<DeviceId> getClusterDevices(Topology topology,
+                                           TopologyCluster cluster) {
         return null;
     }
 
     @Override
-    public Set<Link> getClusterLinks(Topology topology, TopologyCluster cluster) {
+    public Set<Link> getClusterLinks(Topology topology,
+                                     TopologyCluster cluster) {
         return null;
     }
 
@@ -69,17 +71,26 @@
     }
 
     @Override
-    public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeight weight) {
+    public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
+                              LinkWeight weight) {
         return null;
     }
 
     @Override
-    public boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) {
+    public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
+                              LinkWeigher weigher) {
+        return null;
+    }
+
+    @Override
+    public boolean isInfrastructure(Topology topology,
+                                    ConnectPoint connectPoint) {
         return false;
     }
 
     @Override
-    public boolean isBroadcastPoint(Topology topology, ConnectPoint connectPoint) {
+    public boolean isBroadcastPoint(Topology topology,
+                                    ConnectPoint connectPoint) {
         return false;
     }
 
@@ -92,18 +103,28 @@
     }
 
     @Override
-    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst) {
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst) {
         return null;
     }
 
     @Override
     public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
-                                              DeviceId dst, LinkWeight weight) {
+                                              DeviceId dst,
+                                              LinkWeight weight) {
         return null;
     }
 
     @Override
-    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst,
+                                              LinkWeigher weigher) {
+        return null;
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst,
                                               Map<Link, Object> riskProfile) {
         return null;
     }
@@ -115,4 +136,12 @@
         return null;
     }
 
+    @Override
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst,
+                                              LinkWeigher weigher,
+                                              Map<Link, Object> riskProfile) {
+        return null;
+    }
+
 }
diff --git a/core/common/src/main/java/org/onosproject/common/DefaultTopology.java b/core/common/src/main/java/org/onosproject/common/DefaultTopology.java
index 8ed8513..53bebb6 100644
--- a/core/common/src/main/java/org/onosproject/common/DefaultTopology.java
+++ b/core/common/src/main/java/org/onosproject/common/DefaultTopology.java
@@ -22,14 +22,17 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSetMultimap;
 import com.google.common.collect.ImmutableSetMultimap.Builder;
+import org.onlab.graph.DefaultEdgeWeigher;
 import org.onlab.graph.DijkstraGraphSearch;
 import org.onlab.graph.DisjointPathPair;
 import org.onlab.graph.GraphPathSearch;
 import org.onlab.graph.GraphPathSearch.Result;
+import org.onlab.graph.ScalarWeight;
 import org.onlab.graph.SrlgGraphSearch;
 import org.onlab.graph.SuurballeGraphSearch;
 import org.onlab.graph.TarjanGraphSearch;
 import org.onlab.graph.TarjanGraphSearch.SccResult;
+import org.onlab.graph.Weight;
 import org.onosproject.net.AbstractModel;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DefaultDisjointPath;
@@ -45,7 +48,7 @@
 import org.onosproject.net.topology.DefaultTopologyVertex;
 import org.onosproject.net.topology.GraphDescription;
 import org.onosproject.net.topology.HopCountLinkWeight;
-import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.Topology;
 import org.onosproject.net.topology.TopologyCluster;
 import org.onosproject.net.topology.TopologyEdge;
@@ -67,6 +70,7 @@
 import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
 import static org.onosproject.net.Link.State.INACTIVE;
 import static org.onosproject.net.Link.Type.INDIRECT;
+import static org.onosproject.net.topology.AdapterLinkWeigher.adapt;
 
 /**
  * Default implementation of the topology descriptor. This carries the backing
@@ -76,11 +80,14 @@
 
     private static final Logger log = LoggerFactory.getLogger(DefaultTopology.class);
 
-    private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA = new DijkstraGraphSearch<>();
-    private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN = new TarjanGraphSearch<>();
-    private static final SuurballeGraphSearch<TopologyVertex, TopologyEdge> SUURBALLE = new SuurballeGraphSearch<>();
+    private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA =
+            new DijkstraGraphSearch<>();
+    private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN =
+            new TarjanGraphSearch<>();
+    private static final SuurballeGraphSearch<TopologyVertex, TopologyEdge> SUURBALLE =
+            new SuurballeGraphSearch<>();
 
-    private static LinkWeight defaultLinkWeight = null;
+    private static LinkWeigher defaultLinkWeigher = null;
     private static GraphPathSearch<TopologyVertex, TopologyEdge> defaultGraphPathSearch = null;
 
     private final long time;
@@ -88,7 +95,7 @@
     private final long computeCost;
     private final TopologyGraph graph;
 
-    private final LinkWeight hopCountWeight;
+    private final LinkWeigher hopCountWeigher;
 
     private final Supplier<SccResult<TopologyVertex, TopologyEdge>> clusterResults;
     private final Supplier<ImmutableMap<ClusterId, TopologyCluster>> clusters;
@@ -102,11 +109,11 @@
      * specified, the builtin default link-weight measuring hop-counts will be
      * used.
      *
-     * @param linkWeight new default link-weight
+     * @param linkWeigher new default link-weight
      */
-    public static void setDefaultLinkWeight(LinkWeight linkWeight) {
-        log.info("Setting new default link-weight function to {}", linkWeight);
-        defaultLinkWeight = linkWeight;
+    public static void setDefaultLinkWeigher(LinkWeigher linkWeigher) {
+        log.info("Setting new default link-weight function to {}", linkWeigher);
+        defaultLinkWeigher = linkWeigher;
     }
 
     /**
@@ -115,7 +122,8 @@
      *
      * @param graphPathSearch new default algorithm
      */
-    public static void setDefaultGraphPathSearch(GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch) {
+    public static void setDefaultGraphPathSearch(
+            GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch) {
         log.info("Setting new default graph path algorithm to {}", graphPathSearch);
         defaultGraphPathSearch = graphPathSearch;
     }
@@ -137,16 +145,16 @@
 
         // Build the graph
         this.graph = new DefaultTopologyGraph(description.vertexes(),
-                                              description.edges());
+                description.edges());
 
-        this.clusterResults = Suppliers.memoize(() -> searchForClusters());
-        this.clusters = Suppliers.memoize(() -> buildTopologyClusters());
+        this.clusterResults = Suppliers.memoize(this::searchForClusters);
+        this.clusters = Suppliers.memoize(this::buildTopologyClusters);
 
-        this.clusterIndexes = Suppliers.memoize(() -> buildIndexes());
+        this.clusterIndexes = Suppliers.memoize(this::buildIndexes);
 
-        this.hopCountWeight = new HopCountLinkWeight(graph.getVertexes().size());
-        this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets());
-        this.infrastructurePoints = Suppliers.memoize(() -> findInfrastructurePoints());
+        this.hopCountWeigher = adapt(new HopCountLinkWeight(graph.getVertexes().size()));
+        this.broadcastSets = Suppliers.memoize(this::buildBroadcastSets);
+        this.infrastructurePoints = Suppliers.memoize(this::findInfrastructurePoints);
         this.computeCost = Math.max(0, System.nanoTime() - time);
     }
 
@@ -288,7 +296,8 @@
 
         // Find the cluster to which the device belongs.
         TopologyCluster cluster = clustersByDevice().get(connectPoint.deviceId());
-        checkArgument(cluster != null, "No cluster found for device %s", connectPoint.deviceId());
+        checkArgument(cluster != null,
+                "No cluster found for device %s", connectPoint.deviceId());
 
         // If the broadcast set is null or empty, or if the point explicitly
         // belongs to it, return true.
@@ -328,18 +337,17 @@
         return getPaths(src, dst, linkWeight(), ALL_PATHS);
     }
 
-
     /**
      * Computes on-demand the set of shortest paths between source and
      * destination devices.
      *
-     * @param src    source device
-     * @param dst    destination device
-     * @param weight link weight function
+     * @param src     source device
+     * @param dst     destination device
+     * @param weigher link weight function
      * @return set of shortest paths
      */
-    public Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) {
-        return getPaths(src, dst, weight, ALL_PATHS);
+    public Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeigher weigher) {
+        return getPaths(src, dst, weigher, ALL_PATHS);
     }
 
     /**
@@ -355,11 +363,11 @@
      *
      * @param src    source device
      * @param dst    destination device
-     * @param weight link weight function
+     * @param weigher link weight function
      * @param maxPaths maximum number of paths
      * @return set of shortest paths
      */
-    public Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight,
+    public Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeigher weigher,
                               int maxPaths) {
         DefaultTopologyVertex srcV = new DefaultTopologyVertex(src);
         DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst);
@@ -370,7 +378,7 @@
         }
 
         GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
-                graphPathSearch().search(graph, srcV, dstV, weight, maxPaths);
+                graphPathSearch().search(graph, srcV, dstV, weigher, maxPaths);
         ImmutableSet.Builder<Path> builder = ImmutableSet.builder();
         for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
             builder.add(networkPath(path));
@@ -380,8 +388,8 @@
 
     /**
      * /**
-     * Returns the set of pre-computed shortest disjoint path pairs between source and
-     * destination devices.
+     * Returns the set of pre-computed shortest disjoint path pairs between
+     * source and destination devices.
      *
      * @param src source device
      * @param dst destination device
@@ -392,15 +400,16 @@
     }
 
     /**
-     * Computes on-demand the set of shortest disjoint path pairs between source and
-     * destination devices.
+     * Computes on-demand the set of shortest disjoint path pairs between
+     * source and destination devices.
      *
-     * @param src    source device
-     * @param dst    destination device
-     * @param weight link weight function
+     * @param src     source device
+     * @param dst     destination device
+     * @param weigher link weight function
      * @return set of disjoint shortest path pairs
      */
-    public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst, LinkWeight weight) {
+    public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst,
+                                              LinkWeigher weigher) {
         DefaultTopologyVertex srcV = new DefaultTopologyVertex(src);
         DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst);
         Set<TopologyVertex> vertices = graph.getVertexes();
@@ -410,11 +419,11 @@
         }
 
         GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
-                SUURBALLE.search(graph, srcV, dstV, weight, ALL_PATHS);
+                SUURBALLE.search(graph, srcV, dstV, weigher, ALL_PATHS);
         ImmutableSet.Builder<DisjointPath> builder = ImmutableSet.builder();
         for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
             DisjointPath disjointPath =
-                    networkDisjointPath((org.onlab.graph.DisjointPathPair<TopologyVertex, TopologyEdge>) path);
+                    networkDisjointPath((DisjointPathPair<TopologyVertex, TopologyEdge>) path);
             if (disjointPath.backup() != null) {
                 builder.add(disjointPath);
             }
@@ -423,16 +432,17 @@
     }
 
     /**
-     * Computes on-demand the set of shortest disjoint risk groups path pairs between source and
-     * destination devices.
+     * Computes on-demand the set of shortest disjoint risk groups path pairs
+     * between source and destination devices.
      *
      * @param src         source device
      * @param dst         destination device
-     * @param weight      edge weight object
+     * @param weigher     edge weight object
      * @param riskProfile map representing risk groups for each edge
      * @return set of shortest disjoint paths
      */
-    private Set<DisjointPath> disjointPaths(DeviceId src, DeviceId dst, LinkWeight weight,
+    private Set<DisjointPath> disjointPaths(DeviceId src, DeviceId dst,
+                                            LinkWeigher weigher,
                                             Map<TopologyEdge, Object> riskProfile) {
         DefaultTopologyVertex srcV = new DefaultTopologyVertex(src);
         DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst);
@@ -443,13 +453,14 @@
             return ImmutableSet.of();
         }
 
-        SrlgGraphSearch<TopologyVertex, TopologyEdge> srlg = new SrlgGraphSearch<>(riskProfile);
+        SrlgGraphSearch<TopologyVertex, TopologyEdge> srlg =
+                new SrlgGraphSearch<>(riskProfile);
         GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
-                srlg.search(graph, srcV, dstV, weight, ALL_PATHS);
+                srlg.search(graph, srcV, dstV, weigher, ALL_PATHS);
         ImmutableSet.Builder<DisjointPath> builder = ImmutableSet.builder();
         for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
             DisjointPath disjointPath =
-                    networkDisjointPath((org.onlab.graph.DisjointPathPair<TopologyVertex, TopologyEdge>) path);
+                    networkDisjointPath((DisjointPathPair<TopologyVertex, TopologyEdge>) path);
             if (disjointPath.backup() != null) {
                 builder.add(disjointPath);
             }
@@ -458,16 +469,17 @@
     }
 
     /**
-     * Computes on-demand the set of shortest disjoint risk groups path pairs between source and
-     * destination devices.
+     * Computes on-demand the set of shortest disjoint risk groups path pairs
+     * between source and destination devices.
      *
      * @param src         source device
      * @param dst         destination device
-     * @param weight      edge weight object
+     * @param weigher     edge weight object
      * @param riskProfile map representing risk groups for each link
      * @return set of shortest disjoint paths
      */
-    public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst, LinkWeight weight,
+    public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst,
+                                              LinkWeigher weigher,
                                               Map<Link, Object> riskProfile) {
         Map<TopologyEdge, Object> riskProfile2 = new HashMap<>();
         for (Link l : riskProfile.keySet()) {
@@ -490,49 +502,53 @@
                 }
             }, riskProfile.get(l));
         }
-        return disjointPaths(src, dst, weight, riskProfile2);
+        return disjointPaths(src, dst, weigher, riskProfile2);
     }
 
     /**
-     * Computes on-demand the set of shortest disjoint risk groups path pairs between source and
-     * destination devices.
+     * Computes on-demand the set of shortest disjoint risk groups path pairs
+     * between source and destination devices.
      *
      * @param src         source device
      * @param dst         destination device
      * @param riskProfile map representing risk groups for each link
      * @return set of shortest disjoint paths
      */
-    public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst, Map<Link, Object> riskProfile) {
+    public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst,
+                                              Map<Link, Object> riskProfile) {
         return getDisjointPaths(src, dst, linkWeight(), riskProfile);
     }
 
     // Converts graph path to a network path with the same cost.
     private Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) {
-        List<Link> links = path.edges().stream().map(TopologyEdge::link).collect(Collectors.toList());
+        List<Link> links = path.edges().stream().map(TopologyEdge::link)
+                .collect(Collectors.toList());
         return new DefaultPath(CORE_PROVIDER_ID, links, path.cost());
     }
 
-    private DisjointPath networkDisjointPath(DisjointPathPair<TopologyVertex, TopologyEdge> path) {
+    private DisjointPath networkDisjointPath(
+            DisjointPathPair<TopologyVertex, TopologyEdge> path) {
         if (!path.hasBackup()) {
             // There was no secondary path available.
             return new DefaultDisjointPath(CORE_PROVIDER_ID,
-                                           (DefaultPath) networkPath(path.primary()),
-                                           null);
+                    (DefaultPath) networkPath(path.primary()),
+                    null);
         }
         return new DefaultDisjointPath(CORE_PROVIDER_ID,
-                                       (DefaultPath) networkPath(path.primary()),
-                                       (DefaultPath) networkPath(path.secondary()));
+                (DefaultPath) networkPath(path.primary()),
+                (DefaultPath) networkPath(path.secondary()));
     }
 
     // Searches for SCC clusters in the network topology graph using Tarjan
     // algorithm.
     private SccResult<TopologyVertex, TopologyEdge> searchForClusters() {
-        return TARJAN.search(graph, new NoIndirectLinksWeight());
+        return TARJAN.search(graph, new NoIndirectLinksWeigher());
     }
 
     // Builds the topology clusters and returns the id-cluster bindings.
     private ImmutableMap<ClusterId, TopologyCluster> buildTopologyClusters() {
-        ImmutableMap.Builder<ClusterId, TopologyCluster> clusterBuilder = ImmutableMap.builder();
+        ImmutableMap.Builder<ClusterId, TopologyCluster> clusterBuilder =
+                ImmutableMap.builder();
         SccResult<TopologyVertex, TopologyEdge> results = clusterResults.get();
 
         // Extract both vertexes and edges from the results; the lists form
@@ -547,9 +563,9 @@
 
             ClusterId cid = ClusterId.clusterId(i);
             DefaultTopologyCluster cluster = new DefaultTopologyCluster(cid,
-                                                                        vertexSet.size(),
-                                                                        edgeSet.size(),
-                                                                        findRoot(vertexSet));
+                    vertexSet.size(),
+                    edgeSet.size(),
+                    findRoot(vertexSet));
             clusterBuilder.put(cid, cluster);
         }
         return clusterBuilder.build();
@@ -580,10 +596,13 @@
     // Finds all broadcast points for the cluster. These are those connection
     // points which lie along the shortest paths between the cluster root and
     // all other devices within the cluster.
-    private void addClusterBroadcastSet(TopologyCluster cluster, Builder<ClusterId, ConnectPoint> builder) {
+    private void addClusterBroadcastSet(TopologyCluster cluster,
+                                        Builder<ClusterId, ConnectPoint> builder) {
         // Use the graph root search results to build the broadcast set.
-        Result<TopologyVertex, TopologyEdge> result = DIJKSTRA.search(graph, cluster.root(), null, hopCountWeight, 1);
-        for (Map.Entry<TopologyVertex, Set<TopologyEdge>> entry : result.parents().entrySet()) {
+        Result<TopologyVertex, TopologyEdge> result =
+                DIJKSTRA.search(graph, cluster.root(), null, hopCountWeigher, 1);
+        for (Map.Entry<TopologyVertex, Set<TopologyEdge>> entry :
+                result.parents().entrySet()) {
             TopologyVertex vertex = entry.getKey();
 
             // Ignore any parents that lead outside the cluster.
@@ -649,24 +668,27 @@
 
         // Finalize all indexes.
         return new ClusterIndexes(clusterBuilder.build(),
-                                  devicesBuilder.build(),
-                                  linksBuilder.build());
+                devicesBuilder.build(),
+                linksBuilder.build());
     }
 
     private GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch() {
         return defaultGraphPathSearch != null ? defaultGraphPathSearch : DIJKSTRA;
     }
 
-    private LinkWeight linkWeight() {
-        return defaultLinkWeight != null ? defaultLinkWeight : hopCountWeight;
+    private LinkWeigher linkWeight() {
+        return defaultLinkWeigher != null ? defaultLinkWeigher : hopCountWeigher;
     }
 
     // Link weight for preventing traversal over indirect links.
-    private static class NoIndirectLinksWeight implements LinkWeight {
+    private static class NoIndirectLinksWeigher
+            extends DefaultEdgeWeigher<TopologyVertex, TopologyEdge>
+            implements LinkWeigher {
         @Override
-        public double weight(TopologyEdge edge) {
-            return (edge.link().state() == INACTIVE)
-                    || (edge.link().type() == INDIRECT) ? -1 : 1;
+        public Weight weight(TopologyEdge edge) {
+            return (edge.link().state() == INACTIVE) ||
+                    (edge.link().type() == INDIRECT) ?
+                    getNonViableWeight() : new ScalarWeight(HOP_WEIGHT_VALUE);
         }
     }
 
diff --git a/core/common/src/test/java/org/onosproject/common/DefaultTopologyTest.java b/core/common/src/test/java/org/onosproject/common/DefaultTopologyTest.java
index 2bf8cb7..48403d5 100644
--- a/core/common/src/test/java/org/onosproject/common/DefaultTopologyTest.java
+++ b/core/common/src/test/java/org/onosproject/common/DefaultTopologyTest.java
@@ -17,6 +17,9 @@
 
 import org.junit.Before;
 import org.junit.Test;
+import org.onlab.graph.DefaultEdgeWeigher;
+import org.onlab.graph.ScalarWeight;
+import org.onlab.graph.Weight;
 import org.onlab.packet.ChassisId;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DefaultDevice;
@@ -31,8 +34,9 @@
 import org.onosproject.net.topology.DefaultGraphDescription;
 import org.onosproject.net.topology.DefaultTopologyVertex;
 import org.onosproject.net.topology.GraphDescription;
-import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.TopologyCluster;
+import org.onosproject.net.topology.TopologyEdge;
 import org.onosproject.net.topology.TopologyVertex;
 
 import java.util.Set;
@@ -61,9 +65,19 @@
     public static final PortNumber P1 = portNumber(1);
     public static final PortNumber P2 = portNumber(2);
 
-    public static final LinkWeight WEIGHT = edge ->
-            edge.src().deviceId().equals(D4) || edge.dst().deviceId().equals(D4)
-                    ? 2.0 : 1.0;
+    public static final class TestLinkWeigher
+            extends DefaultEdgeWeigher<TopologyVertex, TopologyEdge>
+            implements LinkWeigher {
+        @Override
+        public Weight weight(TopologyEdge edge) {
+            double value = edge.src().deviceId().equals(D4) ||
+                    edge.dst().deviceId().equals(D4)
+                    ? 2.0 : HOP_WEIGHT_VALUE;
+            return new ScalarWeight(value);
+        }
+    }
+    public static final LinkWeigher WEIGHER = new TestLinkWeigher();
+
 
     private DefaultTopology dt;
 
@@ -105,7 +119,7 @@
         paths = dt.getPaths(D1, D5);
         assertTrue("no paths expected", paths.isEmpty());
 
-        paths = dt.getPaths(D1, D3, WEIGHT);
+        paths = dt.getPaths(D1, D3, WEIGHER);
         assertEquals("incorrect path count", 1, paths.size());
     }
 
diff --git a/core/common/src/test/java/org/onosproject/store/trivial/SimpleTopologyStore.java b/core/common/src/test/java/org/onosproject/store/trivial/SimpleTopologyStore.java
index 313d08e..708e38d 100644
--- a/core/common/src/test/java/org/onosproject/store/trivial/SimpleTopologyStore.java
+++ b/core/common/src/test/java/org/onosproject/store/trivial/SimpleTopologyStore.java
@@ -29,6 +29,7 @@
 import org.onosproject.net.provider.ProviderId;
 import org.onosproject.net.topology.ClusterId;
 import org.onosproject.net.topology.GraphDescription;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.LinkWeight;
 import org.onosproject.net.topology.Topology;
 import org.onosproject.net.topology.TopologyCluster;
@@ -43,6 +44,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import static org.onosproject.net.topology.AdapterLinkWeigher.adapt;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -112,7 +114,13 @@
     @Override
     public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
                               LinkWeight weight) {
-        return defaultTopology(topology).getPaths(src, dst, weight);
+        return getPaths(topology, src, dst, adapt(weight));
+    }
+
+    @Override
+    public Set<Path> getPaths(Topology topology, DeviceId src,
+                              DeviceId dst, LinkWeigher weigher) {
+        return defaultTopology(topology).getPaths(src, dst, weigher);
     }
 
     @Override
@@ -123,7 +131,13 @@
     @Override
     public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
                                               LinkWeight weight) {
-        return defaultTopology(topology).getDisjointPaths(src, dst, weight);
+        return getDisjointPaths(topology, src, dst, adapt(weight));
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst, LinkWeigher weigher) {
+        return defaultTopology(topology).getDisjointPaths(src, dst, weigher);
     }
 
     @Override
@@ -135,7 +149,15 @@
     @Override
     public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
                                                   LinkWeight weight, Map<Link, Object> riskProfile) {
-        return defaultTopology(topology).getDisjointPaths(src, dst, weight, riskProfile);
+        return getDisjointPaths(topology, src, dst, adapt(weight), riskProfile);
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst,
+                                              LinkWeigher weigher,
+                                              Map<Link, Object> riskProfile) {
+        return defaultTopology(topology).getDisjointPaths(src, dst, weigher, riskProfile);
     }
 
     @Override
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java
index cb57aee..81e0fcc8 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java
@@ -20,6 +20,9 @@
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.graph.DefaultEdgeWeigher;
+import org.onlab.graph.ScalarWeight;
+import org.onlab.graph.Weight;
 import org.onosproject.net.DisjointPath;
 import org.onosproject.net.ElementId;
 import org.onosproject.net.Path;
@@ -30,9 +33,10 @@
 import org.onosproject.net.intent.impl.PathNotFoundException;
 import org.onosproject.net.resource.ResourceQueryService;
 import org.onosproject.net.provider.ProviderId;
-import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.PathService;
 import org.onosproject.net.topology.TopologyEdge;
+import org.onosproject.net.topology.TopologyVertex;
 
 import java.util.Collections;
 import java.util.Iterator;
@@ -65,8 +69,8 @@
      * @param constraints path constraints
      * @return edge-weight function
      */
-    protected LinkWeight weight(List<Constraint> constraints) {
-        return new ConstraintBasedLinkWeight(constraints);
+    protected LinkWeigher weigher(List<Constraint> constraints) {
+        return new ConstraintBasedLinkWeigher(constraints);
     }
 
     /**
@@ -115,7 +119,7 @@
      */
     protected Path getPath(ConnectivityIntent intent,
                            ElementId one, ElementId two) {
-        Set<Path> paths = pathService.getPaths(one, two, weight(intent.constraints()));
+        Set<Path> paths = pathService.getPaths(one, two, weigher(intent.constraints()));
         final List<Constraint> constraints = intent.constraints();
         ImmutableList<Path> filtered = FluentIterable.from(paths)
                 .filter(path -> checkPath(path, constraints))
@@ -138,7 +142,7 @@
      */
     protected DisjointPath getDisjointPath(ConnectivityIntent intent,
                            ElementId one, ElementId two) {
-        Set<DisjointPath> paths = pathService.getDisjointPaths(one, two, weight(intent.constraints()));
+        Set<DisjointPath> paths = pathService.getDisjointPaths(one, two, weigher(intent.constraints()));
         final List<Constraint> constraints = intent.constraints();
         ImmutableList<DisjointPath> filtered = FluentIterable.from(paths)
                 .filter(path -> checkPath(path, constraints))
@@ -153,7 +157,8 @@
     /**
      * Edge-weight capable of evaluating link cost using a set of constraints.
      */
-    protected class ConstraintBasedLinkWeight implements LinkWeight {
+    protected class ConstraintBasedLinkWeigher extends DefaultEdgeWeigher<TopologyVertex, TopologyEdge>
+            implements LinkWeigher {
 
         private final List<Constraint> constraints;
 
@@ -163,7 +168,7 @@
          *
          * @param constraints path constraints
          */
-        ConstraintBasedLinkWeight(List<Constraint> constraints) {
+        ConstraintBasedLinkWeigher(List<Constraint> constraints) {
             if (constraints == null) {
                 this.constraints = Collections.emptyList();
             } else {
@@ -172,23 +177,23 @@
         }
 
         @Override
-        public double weight(TopologyEdge edge) {
+        public Weight weight(TopologyEdge edge) {
 
             // iterate over all constraints in order and return the weight of
             // the first one with fast fail over the first failure
             Iterator<Constraint> it = constraints.iterator();
 
             if (!it.hasNext()) {
-                return 1.0;
+                return new ScalarWeight(HOP_WEIGHT_VALUE);
             }
 
             double cost = it.next().cost(edge.link(), resourceService::isAvailable);
             while (it.hasNext() && cost > 0) {
                 if (it.next().cost(edge.link(), resourceService::isAvailable) < 0) {
-                    return -1;
+                    cost = -1;
                 }
             }
-            return cost;
+            return new ScalarWeight(cost);
 
         }
     }
diff --git a/core/net/src/main/java/org/onosproject/net/topology/impl/PathManager.java b/core/net/src/main/java/org/onosproject/net/topology/impl/PathManager.java
index 5c41ff4..ec650da 100644
--- a/core/net/src/main/java/org/onosproject/net/topology/impl/PathManager.java
+++ b/core/net/src/main/java/org/onosproject/net/topology/impl/PathManager.java
@@ -26,6 +26,7 @@
 import org.onosproject.net.Link;
 import org.onosproject.net.Path;
 import org.onosproject.net.host.HostService;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.LinkWeight;
 import org.onosproject.net.topology.PathService;
 import org.onosproject.net.topology.TopologyService;
@@ -74,7 +75,7 @@
     public Set<Path> getPaths(ElementId src, ElementId dst) {
         checkPermission(TOPOLOGY_READ);
 
-        return getPaths(src, dst, null);
+        return getPaths(src, dst, (LinkWeigher) null);
     }
 
     @Override
@@ -83,11 +84,17 @@
         return super.getPaths(src, dst, weight);
     }
 
+    @Override
+    public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
+        checkPermission(TOPOLOGY_READ);
+        return super.getPaths(src, dst, weigher);
+    }
+
 
     @Override
     public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst) {
         checkPermission(TOPOLOGY_READ);
-        return getDisjointPaths(src, dst, (LinkWeight) null);
+        return getDisjointPaths(src, dst, (LinkWeigher) null);
     }
 
     @Override
@@ -97,10 +104,16 @@
     }
 
     @Override
+    public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
+        checkPermission(TOPOLOGY_READ);
+        return super.getDisjointPaths(src, dst, weigher);
+    }
+
+    @Override
     public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst,
                                               Map<Link, Object> riskProfile) {
         checkPermission(TOPOLOGY_READ);
-        return getDisjointPaths(src, dst, null, riskProfile);
+        return getDisjointPaths(src, dst, (LinkWeigher) null, riskProfile);
     }
 
     @Override
@@ -110,4 +123,11 @@
         return super.getDisjointPaths(src, dst, weight, riskProfile);
     }
 
+    @Override
+    public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeigher weigher,
+                                              Map<Link, Object> riskProfile) {
+        checkPermission(TOPOLOGY_READ);
+        return super.getDisjointPaths(src, dst, weigher, riskProfile);
+    }
+
 }
diff --git a/core/net/src/main/java/org/onosproject/net/topology/impl/TopologyManager.java b/core/net/src/main/java/org/onosproject/net/topology/impl/TopologyManager.java
index 4203a8e..ecf7e25 100644
--- a/core/net/src/main/java/org/onosproject/net/topology/impl/TopologyManager.java
+++ b/core/net/src/main/java/org/onosproject/net/topology/impl/TopologyManager.java
@@ -31,6 +31,7 @@
 import org.onosproject.net.provider.AbstractProviderService;
 import org.onosproject.net.topology.ClusterId;
 import org.onosproject.net.topology.GraphDescription;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.LinkWeight;
 import org.onosproject.net.topology.Topology;
 import org.onosproject.net.topology.TopologyCluster;
@@ -50,6 +51,7 @@
 import java.util.Map;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.topology.AdapterLinkWeigher.adapt;
 import static org.onosproject.security.AppGuard.checkPermission;
 import static org.slf4j.LoggerFactory.getLogger;
 import static org.onosproject.security.AppPermission.Type.*;
@@ -154,18 +156,26 @@
     }
 
     @Override
-    public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeight weight) {
+    public Set<Path> getPaths(Topology topology, DeviceId src,
+                              DeviceId dst, LinkWeight weight) {
+        return getPaths(topology, src, dst, adapt(weight));
+    }
+
+    @Override
+    public Set<Path> getPaths(Topology topology, DeviceId src,
+                              DeviceId dst, LinkWeigher weigher) {
         checkPermission(TOPOLOGY_READ);
 
         checkNotNull(topology, TOPOLOGY_NULL);
         checkNotNull(src, DEVICE_ID_NULL);
         checkNotNull(dst, DEVICE_ID_NULL);
-        checkNotNull(weight, "Link weight cannot be null");
-        return store.getPaths(topology, src, dst, weight);
+        checkNotNull(weigher, "Link weight cannot be null");
+        return store.getPaths(topology, src, dst, weigher);
     }
 
     @Override
-    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst) {
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst) {
         checkPermission(TOPOLOGY_READ);
         checkNotNull(topology, TOPOLOGY_NULL);
         checkNotNull(src, DEVICE_ID_NULL);
@@ -175,17 +185,26 @@
 
     @Override
     public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
-                                              DeviceId dst, LinkWeight weight) {
+                                              DeviceId dst,
+                                              LinkWeight weight) {
+        return getDisjointPaths(topology, src, dst, adapt(weight));
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst,
+                                              LinkWeigher weigher) {
         checkPermission(TOPOLOGY_READ);
         checkNotNull(topology, TOPOLOGY_NULL);
         checkNotNull(src, DEVICE_ID_NULL);
         checkNotNull(dst, DEVICE_ID_NULL);
-        checkNotNull(weight, LINK_WEIGHT_NULL);
-        return store.getDisjointPaths(topology, src, dst, weight);
+        checkNotNull(weigher, LINK_WEIGHT_NULL);
+        return store.getDisjointPaths(topology, src, dst, weigher);
     }
 
     @Override
-    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst,
                                               Map<Link, Object> riskProfile) {
         checkPermission(TOPOLOGY_READ);
         checkNotNull(topology, TOPOLOGY_NULL);
@@ -198,12 +217,20 @@
     public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
                                               DeviceId dst, LinkWeight weight,
                                               Map<Link, Object> riskProfile) {
+        return getDisjointPaths(topology, src, dst, adapt(weight), riskProfile);
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst,
+                                              LinkWeigher weigher,
+                                              Map<Link, Object> riskProfile) {
         checkPermission(TOPOLOGY_READ);
         checkNotNull(topology, TOPOLOGY_NULL);
         checkNotNull(src, DEVICE_ID_NULL);
         checkNotNull(dst, DEVICE_ID_NULL);
-        checkNotNull(weight, LINK_WEIGHT_NULL);
-        return store.getDisjointPaths(topology, src, dst, weight, riskProfile);
+        checkNotNull(weigher, LINK_WEIGHT_NULL);
+        return store.getDisjointPaths(topology, src, dst, weigher, riskProfile);
     }
 
     @Override
diff --git a/core/net/src/test/java/org/onosproject/net/topology/impl/PathManagerTest.java b/core/net/src/test/java/org/onosproject/net/topology/impl/PathManagerTest.java
index 18e6402..cca8b4a 100644
--- a/core/net/src/test/java/org/onosproject/net/topology/impl/PathManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/topology/impl/PathManagerTest.java
@@ -26,7 +26,7 @@
 import org.onosproject.net.Path;
 import org.onosproject.net.host.HostServiceAdapter;
 import org.onosproject.net.provider.ProviderId;
-import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.PathService;
 import org.onosproject.net.topology.Topology;
 import org.onosproject.net.topology.TopologyServiceAdapter;
@@ -140,12 +140,14 @@
         Set<Path> paths = new HashSet<>();
 
         @Override
-        public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
+        public Set<Path> getPaths(Topology topology, DeviceId src,
+                                  DeviceId dst) {
             return paths;
         }
 
         @Override
-        public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeight weight) {
+        public Set<Path> getPaths(Topology topology, DeviceId src,
+                                  DeviceId dst, LinkWeigher weight) {
             return paths;
         }
     }
diff --git a/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java b/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java
index cbfacad..db5b83b 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java
@@ -40,6 +40,7 @@
 import org.onosproject.net.topology.DefaultGraphDescription;
 import org.onosproject.net.topology.GeoDistanceLinkWeight;
 import org.onosproject.net.topology.GraphDescription;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.LinkWeight;
 import org.onosproject.net.topology.MetricLinkWeight;
 import org.onosproject.net.topology.PathAdminService;
@@ -72,6 +73,7 @@
 import static com.google.common.base.Preconditions.checkArgument;
 import static org.onlab.util.Tools.get;
 import static org.onlab.util.Tools.isNullOrEmpty;
+import static org.onosproject.net.topology.AdapterLinkWeigher.adapt;
 import static org.onosproject.net.topology.TopologyEvent.Type.TOPOLOGY_CHANGED;
 import static org.slf4j.LoggerFactory.getLogger;
 
@@ -214,7 +216,13 @@
     @Override
     public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
                               LinkWeight weight) {
-        return defaultTopology(topology).getPaths(src, dst, weight);
+        return getPaths(topology, src, dst, adapt(weight));
+    }
+
+    @Override
+    public Set<Path> getPaths(Topology topology, DeviceId src,
+                              DeviceId dst, LinkWeigher weigher) {
+        return defaultTopology(topology).getPaths(src, dst, weigher);
     }
 
     @Override
@@ -225,7 +233,13 @@
     @Override
     public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
                                               LinkWeight weight) {
-        return defaultTopology(topology).getDisjointPaths(src, dst, weight);
+        return getDisjointPaths(topology, src, dst, adapt(weight));
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst, LinkWeigher weigher) {
+        return defaultTopology(topology).getDisjointPaths(src, dst, weigher);
     }
 
     @Override
@@ -237,7 +251,14 @@
     @Override
     public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
                                               LinkWeight weight, Map<Link, Object> riskProfile) {
-        return defaultTopology(topology).getDisjointPaths(src, dst, weight, riskProfile);
+        return getDisjointPaths(topology, src, dst, adapt(weight), riskProfile);
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst, LinkWeigher weigher,
+                                              Map<Link, Object> riskProfile) {
+        return defaultTopology(topology).getDisjointPaths(src, dst, weigher, riskProfile);
     }
 
     @Override
@@ -315,7 +336,12 @@
 
     @Override
     public void setDefaultLinkWeight(LinkWeight linkWeight) {
-        DefaultTopology.setDefaultLinkWeight(linkWeight);
+        DefaultTopology.setDefaultLinkWeigher(adapt(linkWeight));
+    }
+
+    @Override
+    public void setDefaultLinkWeigher(LinkWeigher linkWeigher) {
+        DefaultTopology.setDefaultLinkWeigher(linkWeigher);
     }
 
     @Override
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkPathManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkPathManager.java
index 7d6555a..b3c26ec 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkPathManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkPathManager.java
@@ -23,7 +23,7 @@
 import org.onosproject.net.Link;
 import org.onosproject.net.Path;
 import org.onosproject.net.host.HostService;
-import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.PathService;
 import org.onosproject.net.topology.AbstractPathService;
 import org.onosproject.net.topology.TopologyService;
@@ -57,18 +57,18 @@
 
     @Override
     public Set<Path> getPaths(ElementId src, ElementId dst) {
-        return getPaths(src, dst, null);
+        return super.getPaths(src, dst, (LinkWeigher) null);
     }
 
     @Override
     public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst) {
-        return getDisjointPaths(src, dst, (LinkWeight) null);
+        return getDisjointPaths(src, dst, (LinkWeigher) null);
     }
 
     @Override
     public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst,
                                               Map<Link, Object> riskProfile) {
-        return getDisjointPaths(src, dst, null, riskProfile);
+        return getDisjointPaths(src, dst, (LinkWeigher) null, riskProfile);
     }
 
     @Override
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkTopologyManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkTopologyManager.java
index e361a3b..c55829d 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkTopologyManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkTopologyManager.java
@@ -28,6 +28,7 @@
 import org.onosproject.net.Path;
 import org.onosproject.net.topology.ClusterId;
 import org.onosproject.net.topology.DefaultGraphDescription;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.LinkWeight;
 import org.onosproject.net.topology.Topology;
 import org.onosproject.net.topology.TopologyCluster;
@@ -43,6 +44,7 @@
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onosproject.incubator.net.virtual.DefaultVirtualLink.PID;
+import static org.onosproject.net.topology.AdapterLinkWeigher.adapt;
 
 /**
  * Topology service implementation built on the virtual network service.
@@ -136,15 +138,23 @@
     }
 
     @Override
-    public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeight weight) {
-        checkNotNull(src, DEVICE_ID_NULL);
-        checkNotNull(dst, DEVICE_ID_NULL);
-        checkNotNull(weight, LINK_WEIGHT_NULL);
-        return defaultTopology(topology).getPaths(src, dst, weight);
+    public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
+                              LinkWeight weight) {
+        return getPaths(topology, src, dst, adapt(weight));
     }
 
     @Override
-    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst) {
+    public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
+                              LinkWeigher weigher) {
+        checkNotNull(src, DEVICE_ID_NULL);
+        checkNotNull(dst, DEVICE_ID_NULL);
+        checkNotNull(weigher, LINK_WEIGHT_NULL);
+        return defaultTopology(topology).getPaths(src, dst, weigher);
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst) {
         checkNotNull(src, DEVICE_ID_NULL);
         checkNotNull(dst, DEVICE_ID_NULL);
         return defaultTopology(topology).getDisjointPaths(src, dst);
@@ -153,14 +163,22 @@
     @Override
     public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
                                               DeviceId dst, LinkWeight weight) {
-        checkNotNull(src, DEVICE_ID_NULL);
-        checkNotNull(dst, DEVICE_ID_NULL);
-        checkNotNull(weight, LINK_WEIGHT_NULL);
-        return defaultTopology(topology).getDisjointPaths(src, dst, weight);
+        return getDisjointPaths(topology, src, dst, adapt(weight));
     }
 
     @Override
-    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst,
+                                              LinkWeigher weigher) {
+        checkNotNull(src, DEVICE_ID_NULL);
+        checkNotNull(dst, DEVICE_ID_NULL);
+        checkNotNull(weigher, LINK_WEIGHT_NULL);
+        return defaultTopology(topology).getDisjointPaths(src, dst, weigher);
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst,
                                               Map<Link, Object> riskProfile) {
         checkNotNull(src, DEVICE_ID_NULL);
         checkNotNull(dst, DEVICE_ID_NULL);
@@ -168,12 +186,22 @@
     }
 
     @Override
-    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst,
-                                              LinkWeight weight, Map<Link, Object> riskProfile) {
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst, LinkWeight weight,
+                                              Map<Link, Object> riskProfile) {
+        return getDisjointPaths(topology, src, dst, adapt(weight), riskProfile);
+    }
+
+    @Override
+    public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+                                              DeviceId dst,
+                                              LinkWeigher weigher,
+                                              Map<Link, Object> riskProfile) {
         checkNotNull(src, DEVICE_ID_NULL);
         checkNotNull(dst, DEVICE_ID_NULL);
-        checkNotNull(weight, LINK_WEIGHT_NULL);
-        return defaultTopology(topology).getDisjointPaths(src, dst, weight, riskProfile);
+        checkNotNull(weigher, LINK_WEIGHT_NULL);
+        return defaultTopology(topology).getDisjointPaths(src, dst, weigher,
+                riskProfile);
     }
 
     @Override
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkTopologyManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkTopologyManagerTest.java
index 4e5a81c..11bfdc8 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkTopologyManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkTopologyManagerTest.java
@@ -42,6 +42,7 @@
 import org.onosproject.net.TestDeviceParams;
 import org.onosproject.net.intent.FakeIntentManager;
 import org.onosproject.net.intent.TestableIntentService;
+import org.onosproject.net.topology.LinkWeigher;
 import org.onosproject.net.topology.LinkWeight;
 import org.onosproject.net.topology.Topology;
 import org.onosproject.net.topology.TopologyCluster;
@@ -391,7 +392,8 @@
         VirtualDevice dstVirtualDevice = getVirtualDevice(virtualNetwork.id(), DID2);
 
         // test the getPaths() method using a null weight.
-        Set<Path> paths = topologyService.getPaths(topology, srcVirtualDevice.id(), dstVirtualDevice.id(), null);
+        Set<Path> paths = topologyService.getPaths(topology, srcVirtualDevice.id(),
+                dstVirtualDevice.id(), (LinkWeigher) null);
     }
 
     /**
diff --git a/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java b/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
index c47ba56..b1c661c 100644
--- a/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
+++ b/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
@@ -56,7 +56,6 @@
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceServiceAdapter;
-import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.host.HostDescription;
 import org.onosproject.net.host.HostProvider;
 import org.onosproject.net.host.HostProviderRegistry;
@@ -64,8 +63,7 @@
 import org.onosproject.net.host.HostServiceAdapter;
 import org.onosproject.net.packet.DefaultInboundPacket;
 import org.onosproject.net.packet.InboundPacket;
-import org.onosproject.net.packet.OutboundPacket;
-import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketContextAdapter;
 import org.onosproject.net.packet.PacketProcessor;
 import org.onosproject.net.packet.PacketServiceAdapter;
 import org.onosproject.net.provider.AbstractProviderService;
@@ -306,9 +304,9 @@
      * When receiving ARP, updates location and IP.
      */
     @Test
-    public void testReceiveArp() {
+    public void receiveArp() {
         testProcessor.process(new TestArpPacketContext(DEV1));
-        assertThat("testReceiveArp. One host description expected",
+        assertThat("receiveArp. One host description expected",
                 providerService.descriptions.size(), is(1));
         HostDescription descr = providerService.descriptions.get(0);
         assertThat(descr.location(), is(LOCATION));
@@ -321,9 +319,9 @@
      * When receiving IPv4, updates location only.
      */
     @Test
-    public void testReceiveIpv4() {
+    public void receiveIpv4() {
         testProcessor.process(new TestIpv4PacketContext(DEV1));
-        assertThat("testReceiveIpv4. One host description expected",
+        assertThat("receiveIpv4. One host description expected",
                 providerService.descriptions.size(), is(1));
         HostDescription descr = providerService.descriptions.get(0);
         assertThat(descr.location(), is(LOCATION));
@@ -337,10 +335,10 @@
      * When receiving DHCP ACK, update MAC, location of server and IP of client.
      */
     @Test
-    public void testReceiveDhcp() {
+    public void receiveDhcp() {
         // DHCP Request
         testProcessor.process(new TestDhcpRequestPacketContext(DEV1));
-        assertThat("testReceiveDhcpRequest. One host description expected",
+        assertThat("receiveDhcpRequest. One host description expected",
                 providerService.descriptions.size(), is(1));
         // Should learn the MAC and location of DHCP client
         HostDescription descr = providerService.descriptions.get(0);
@@ -351,7 +349,7 @@
 
         // DHCP Ack
         testProcessor.process(new TestDhcpAckPacketContext(DEV1));
-        assertThat("testReceiveDhcpAck. Two additional host descriptions expected",
+        assertThat("receiveDhcpAck. Two additional host descriptions expected",
                 providerService.descriptions.size(), is(3));
         // Should learn the IP of DHCP client
         HostDescription descr2 = providerService.descriptions.get(1);
@@ -373,9 +371,9 @@
      * When receiving NeighborAdvertisement, updates location and IP.
      */
     @Test
-    public void testReceiveNa() {
+    public void receiveNa() {
         testProcessor.process(new TestNaPacketContext(DEV4));
-        assertThat("testReceiveNa. One host description expected",
+        assertThat("receiveNa. One host description expected",
                 providerService.descriptions.size(), is(1));
         HostDescription descr = providerService.descriptions.get(0);
         assertThat(descr.location(), is(LOCATION2));
@@ -388,9 +386,9 @@
      * When receiving NeighborSolicitation, updates location and IP.
      */
     @Test
-    public void testReceiveNs() {
+    public void receiveNs() {
         testProcessor.process(new TestNsPacketContext(DEV4));
-        assertThat("testReceiveNs. One host description expected",
+        assertThat("receiveNs. One host description expected",
                 providerService.descriptions.size(), is(1));
         HostDescription descr = providerService.descriptions.get(0);
         assertThat(descr.location(), is(LOCATION2));
@@ -403,9 +401,9 @@
      * When receiving RouterAdvertisement, ignores it.
      */
     @Test
-    public void testReceivesRa() {
+    public void receivesRa() {
         testProcessor.process(new TestRAPacketContext(DEV4));
-        assertThat("testReceiveRa. No host description expected",
+        assertThat("receivesRa. No host description expected",
                 providerService.descriptions.size(), is(0));
     }
 
@@ -413,9 +411,9 @@
      * When receiving RouterSolicitation, ignores it.
      */
     @Test
-    public void testReceiveRs() {
+    public void receiveRs() {
         testProcessor.process(new TestRSPacketContext(DEV4));
-        assertThat("testReceiveRs. No host description expected",
+        assertThat("receiveRs. No host description expected",
                 providerService.descriptions.size(), is(0));
     }
 
@@ -423,9 +421,9 @@
      * When receiving Duplicate Address Detection (DAD), ignores it.
      */
     @Test
-    public void testReceiveDad() {
+    public void receiveDad() {
         testProcessor.process(new TestDadPacketContext(DEV4));
-        assertThat("testReceiveDad. No host description expected",
+        assertThat("receiveDad. No host description expected",
                 providerService.descriptions.size(), is(0));
     }
 
@@ -433,9 +431,9 @@
      * When receiving IPv6 multicast packet, ignores it.
      */
     @Test
-    public void testReceiveIpv6Multicast() {
+    public void receiveIpv6Multicast() {
         testProcessor.process(new TestIpv6McastPacketContext(DEV4));
-        assertThat("testReceiveIpv6Multicast. No host description expected",
+        assertThat("receiveIpv6Multicast. No host description expected",
                 providerService.descriptions.size(), is(0));
     }
 
@@ -443,9 +441,9 @@
      * When receiving IPv6 unicast packet, updates location only.
      */
     @Test
-    public void testReceiveIpv6Unicast() {
+    public void receiveIpv6Unicast() {
         testProcessor.process(new TestIpv6PacketContext(DEV4));
-        assertThat("testReceiveIpv6Unicast. One host description expected",
+        assertThat("receiveIpv6Unicast. One host description expected",
                 providerService.descriptions.size(), is(1));
         HostDescription descr = providerService.descriptions.get(0);
         assertThat(descr.location(), is(LOCATION2));
@@ -535,19 +533,15 @@
     /**
      * Generates ARP packet.
      */
-    private class TestArpPacketContext implements PacketContext {
+    private class TestArpPacketContext extends PacketContextAdapter {
         private final String deviceId;
 
         public TestArpPacketContext(String deviceId) {
+            super(0, null, null, false);
             this.deviceId = deviceId;
         }
 
         @Override
-        public long time() {
-            return 0;
-        }
-
-        @Override
         public InboundPacket inPacket() {
             ARP arp = new ARP();
             arp.setSenderProtocolAddress(IP)
@@ -566,49 +560,20 @@
             return new DefaultInboundPacket(receivedFrom, eth,
                                             ByteBuffer.wrap(eth.serialize()));
         }
-
-        @Override
-        public OutboundPacket outPacket() {
-            return null;
-        }
-
-        @Override
-        public TrafficTreatment.Builder treatmentBuilder() {
-            return null;
-        }
-
-        @Override
-        public void send() {
-
-        }
-
-        @Override
-        public boolean block() {
-            return false;
-        }
-
-        @Override
-        public boolean isHandled() {
-            return false;
-        }
     }
 
     /**
      * Generates IPv4 Unicast packet.
      */
-    private class TestIpv4PacketContext implements PacketContext {
+    private class TestIpv4PacketContext extends PacketContextAdapter {
         private final String deviceId;
 
         public TestIpv4PacketContext(String deviceId) {
+            super(0, null, null, false);
             this.deviceId = deviceId;
         }
 
         @Override
-        public long time() {
-            return 0;
-        }
-
-        @Override
         public InboundPacket inPacket() {
             IPv4 ipv4 = new IPv4();
             ipv4.setDestinationAddress("10.0.0.1");
@@ -624,48 +589,19 @@
             return new DefaultInboundPacket(receivedFrom, eth,
                                             ByteBuffer.wrap(eth.serialize()));
         }
-
-        @Override
-        public OutboundPacket outPacket() {
-            return null;
-        }
-
-        @Override
-        public TrafficTreatment.Builder treatmentBuilder() {
-            return null;
-        }
-
-        @Override
-        public void send() {
-
-        }
-
-        @Override
-        public boolean block() {
-            return false;
-        }
-
-        @Override
-        public boolean isHandled() {
-            return false;
-        }
     }
     /**
      * Generates DHCP REQUEST packet.
      */
-    private class TestDhcpRequestPacketContext implements PacketContext {
+    private class TestDhcpRequestPacketContext extends PacketContextAdapter {
         private final String deviceId;
 
         public TestDhcpRequestPacketContext(String deviceId) {
+            super(0, null, null, false);
             this.deviceId = deviceId;
         }
 
         @Override
-        public long time() {
-            return 0;
-        }
-
-        @Override
         public InboundPacket inPacket() {
             byte[] dhcpMsgType = new byte[1];
             dhcpMsgType[0] = (byte) DHCPPacketType.DHCPREQUEST.getValue();
@@ -696,49 +632,20 @@
             return new DefaultInboundPacket(receivedFrom, eth,
                     ByteBuffer.wrap(eth.serialize()));
         }
-
-        @Override
-        public OutboundPacket outPacket() {
-            return null;
-        }
-
-        @Override
-        public TrafficTreatment.Builder treatmentBuilder() {
-            return null;
-        }
-
-        @Override
-        public void send() {
-
-        }
-
-        @Override
-        public boolean block() {
-            return false;
-        }
-
-        @Override
-        public boolean isHandled() {
-            return false;
-        }
     }
 
     /**
      * Generates DHCP ACK packet.
      */
-    private class TestDhcpAckPacketContext implements PacketContext {
+    private class TestDhcpAckPacketContext extends PacketContextAdapter {
         private final String deviceId;
 
         public TestDhcpAckPacketContext(String deviceId) {
+            super(0, null, null, false);
             this.deviceId = deviceId;
         }
 
         @Override
-        public long time() {
-            return 0;
-        }
-
-        @Override
         public InboundPacket inPacket() {
             byte[] dhcpMsgType = new byte[1];
             dhcpMsgType[0] = (byte) DHCPPacketType.DHCPACK.getValue();
@@ -770,49 +677,20 @@
             return new DefaultInboundPacket(receivedFrom, eth,
                     ByteBuffer.wrap(eth.serialize()));
         }
-
-        @Override
-        public OutboundPacket outPacket() {
-            return null;
-        }
-
-        @Override
-        public TrafficTreatment.Builder treatmentBuilder() {
-            return null;
-        }
-
-        @Override
-        public void send() {
-
-        }
-
-        @Override
-        public boolean block() {
-            return false;
-        }
-
-        @Override
-        public boolean isHandled() {
-            return false;
-        }
     }
 
     /**
      * Generates NeighborAdvertisement packet.
      */
-    private class TestNaPacketContext implements PacketContext {
+    private class TestNaPacketContext extends PacketContextAdapter {
         private final String deviceId;
 
         public TestNaPacketContext(String deviceId) {
+            super(0, null, null, false);
             this.deviceId = deviceId;
         }
 
         @Override
-        public long time() {
-            return 0;
-        }
-
-        @Override
         public InboundPacket inPacket() {
             NeighborAdvertisement na = new NeighborAdvertisement();
             ICMP6 icmp6 = new ICMP6();
@@ -832,49 +710,20 @@
             return new DefaultInboundPacket(receivedFrom, eth,
                                             ByteBuffer.wrap(eth.serialize()));
         }
-
-        @Override
-        public OutboundPacket outPacket() {
-            return null;
-        }
-
-        @Override
-        public TrafficTreatment.Builder treatmentBuilder() {
-            return null;
-        }
-
-        @Override
-        public void send() {
-
-        }
-
-        @Override
-        public boolean block() {
-            return false;
-        }
-
-        @Override
-        public boolean isHandled() {
-            return false;
-        }
     }
 
     /**
      * Generates NeighborSolicitation packet.
      */
-    private class TestNsPacketContext implements PacketContext {
+    private class TestNsPacketContext extends PacketContextAdapter {
         private final String deviceId;
 
         public TestNsPacketContext(String deviceId) {
+            super(0, null, null, false);
             this.deviceId = deviceId;
         }
 
         @Override
-        public long time() {
-            return 0;
-        }
-
-        @Override
         public InboundPacket inPacket() {
             NeighborSolicitation ns = new NeighborSolicitation();
             ICMP6 icmp6 = new ICMP6();
@@ -894,49 +743,20 @@
             return new DefaultInboundPacket(receivedFrom, eth,
                                             ByteBuffer.wrap(eth.serialize()));
         }
-
-        @Override
-        public OutboundPacket outPacket() {
-            return null;
-        }
-
-        @Override
-        public TrafficTreatment.Builder treatmentBuilder() {
-            return null;
-        }
-
-        @Override
-        public void send() {
-
-        }
-
-        @Override
-        public boolean block() {
-            return false;
-        }
-
-        @Override
-        public boolean isHandled() {
-            return false;
-        }
     }
 
     /**
      * Generates Duplicate Address Detection packet.
      */
-    private class TestDadPacketContext implements PacketContext {
+    private class TestDadPacketContext extends PacketContextAdapter {
         private final String deviceId;
 
         public TestDadPacketContext(String deviceId) {
+            super(0, null, null, false);
             this.deviceId = deviceId;
         }
 
         @Override
-        public long time() {
-            return 0;
-        }
-
-        @Override
         public InboundPacket inPacket() {
             NeighborSolicitation ns = new NeighborSolicitation();
             ICMP6 icmp6 = new ICMP6();
@@ -956,49 +776,20 @@
             return new DefaultInboundPacket(receivedFrom, eth,
                                             ByteBuffer.wrap(eth.serialize()));
         }
-
-        @Override
-        public OutboundPacket outPacket() {
-            return null;
-        }
-
-        @Override
-        public TrafficTreatment.Builder treatmentBuilder() {
-            return null;
-        }
-
-        @Override
-        public void send() {
-
-        }
-
-        @Override
-        public boolean block() {
-            return false;
-        }
-
-        @Override
-        public boolean isHandled() {
-            return false;
-        }
     }
 
     /**
      * Generates Router Solicitation packet.
      */
-    private class TestRSPacketContext implements PacketContext {
+    private class TestRSPacketContext extends PacketContextAdapter {
         private final String deviceId;
 
         public TestRSPacketContext(String deviceId) {
+            super(0, null, null, false);
             this.deviceId = deviceId;
         }
 
         @Override
-        public long time() {
-            return 0;
-        }
-
-        @Override
         public InboundPacket inPacket() {
             RouterSolicitation ns = new RouterSolicitation();
             ICMP6 icmp6 = new ICMP6();
@@ -1018,49 +809,20 @@
             return new DefaultInboundPacket(receivedFrom, eth,
                                             ByteBuffer.wrap(eth.serialize()));
         }
-
-        @Override
-        public OutboundPacket outPacket() {
-            return null;
-        }
-
-        @Override
-        public TrafficTreatment.Builder treatmentBuilder() {
-            return null;
-        }
-
-        @Override
-        public void send() {
-
-        }
-
-        @Override
-        public boolean block() {
-            return false;
-        }
-
-        @Override
-        public boolean isHandled() {
-            return false;
-        }
     }
 
     /**
      * Generates Router Advertisement packet.
      */
-    private class TestRAPacketContext implements PacketContext {
+    private class TestRAPacketContext extends PacketContextAdapter {
         private final String deviceId;
 
         public TestRAPacketContext(String deviceId) {
+            super(0, null, null, false);
             this.deviceId = deviceId;
         }
 
         @Override
-        public long time() {
-            return 0;
-        }
-
-        @Override
         public InboundPacket inPacket() {
             RouterAdvertisement ns = new RouterAdvertisement();
             ICMP6 icmp6 = new ICMP6();
@@ -1080,49 +842,20 @@
             return new DefaultInboundPacket(receivedFrom, eth,
                                             ByteBuffer.wrap(eth.serialize()));
         }
-
-        @Override
-        public OutboundPacket outPacket() {
-            return null;
-        }
-
-        @Override
-        public TrafficTreatment.Builder treatmentBuilder() {
-            return null;
-        }
-
-        @Override
-        public void send() {
-
-        }
-
-        @Override
-        public boolean block() {
-            return false;
-        }
-
-        @Override
-        public boolean isHandled() {
-            return false;
-        }
     }
 
     /**
      * Generates IPv6 Multicast packet.
      */
-    private class TestIpv6McastPacketContext implements PacketContext {
+    private class TestIpv6McastPacketContext extends PacketContextAdapter {
         private final String deviceId;
 
         public TestIpv6McastPacketContext(String deviceId) {
+            super(0, null, null, false);
             this.deviceId = deviceId;
         }
 
         @Override
-        public long time() {
-            return 0;
-        }
-
-        @Override
         public InboundPacket inPacket() {
             IPv6 ipv6 = new IPv6();
             ipv6.setDestinationAddress(Ip6Address.valueOf("ff02::1").toOctets());
@@ -1138,49 +871,20 @@
             return new DefaultInboundPacket(receivedFrom, eth,
                                             ByteBuffer.wrap(eth.serialize()));
         }
-
-        @Override
-        public OutboundPacket outPacket() {
-            return null;
-        }
-
-        @Override
-        public TrafficTreatment.Builder treatmentBuilder() {
-            return null;
-        }
-
-        @Override
-        public void send() {
-
-        }
-
-        @Override
-        public boolean block() {
-            return false;
-        }
-
-        @Override
-        public boolean isHandled() {
-            return false;
-        }
     }
 
     /**
      * Generates IPv6 Unicast packet.
      */
-    private class TestIpv6PacketContext implements PacketContext {
+    private class TestIpv6PacketContext extends PacketContextAdapter {
         private final String deviceId;
 
         public TestIpv6PacketContext(String deviceId) {
+            super(0, null, null, false);
             this.deviceId = deviceId;
         }
 
         @Override
-        public long time() {
-            return 0;
-        }
-
-        @Override
         public InboundPacket inPacket() {
             IPv6 ipv6 = new IPv6();
             ipv6.setDestinationAddress(Ip6Address.valueOf("1000::1").toOctets());
@@ -1196,31 +900,6 @@
             return new DefaultInboundPacket(receivedFrom, eth,
                                             ByteBuffer.wrap(eth.serialize()));
         }
-
-        @Override
-        public OutboundPacket outPacket() {
-            return null;
-        }
-
-        @Override
-        public TrafficTreatment.Builder treatmentBuilder() {
-            return null;
-        }
-
-        @Override
-        public void send() {
-
-        }
-
-        @Override
-        public boolean block() {
-            return false;
-        }
-
-        @Override
-        public boolean isHandled() {
-            return false;
-        }
     }
 
     private class TestDeviceService extends DeviceServiceAdapter {
diff --git a/utils/misc/src/main/java/org/onlab/graph/AbstractGraphPathSearch.java b/utils/misc/src/main/java/org/onlab/graph/AbstractGraphPathSearch.java
index 01f17efa..95f99dc 100644
--- a/utils/misc/src/main/java/org/onlab/graph/AbstractGraphPathSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/AbstractGraphPathSearch.java
@@ -33,27 +33,6 @@
 public abstract class AbstractGraphPathSearch<V extends Vertex, E extends Edge<V>>
         implements GraphPathSearch<V, E> {
 
-    private double samenessThreshold = Double.MIN_VALUE;
-
-    /**
-     * Sets a new sameness threshold for comparing cost values; default is
-     * is {@link Double#MIN_VALUE}.
-     *
-     * @param threshold fractional double value
-     */
-    public void setSamenessThreshold(double threshold) {
-        samenessThreshold = threshold;
-    }
-
-    /**
-     * Returns the current sameness threshold for comparing cost values.
-     *
-     * @return current threshold
-     */
-    public double samenessThreshold() {
-        return samenessThreshold;
-    }
-
     /**
      * Default path search result that uses the DefaultPath to convey paths
      * in a graph.
@@ -63,7 +42,7 @@
         private final V src;
         private final V dst;
         protected final Set<Path<V, E>> paths = new HashSet<>();
-        protected final Map<V, Double> costs = new HashMap<>();
+        protected final Map<V, Weight> costs = new HashMap<>();
         protected final Map<V, Set<E>> parents = new HashMap<>();
         protected final int maxPaths;
 
@@ -108,7 +87,7 @@
         }
 
         @Override
-        public Map<V, Double> costs() {
+        public Map<V, Weight> costs() {
             return costs;
         }
 
@@ -124,18 +103,20 @@
          * @return true if the vertex has cost already
          */
         boolean hasCost(V v) {
-            return costs.get(v) != null;
+            return costs.containsKey(v);
         }
 
         /**
          * Returns the current cost to reach the specified vertex.
+         * If the vertex has not been accessed yet, it has no cost
+         * associated and null will be returned.
          *
          * @param v vertex to reach
-         * @return cost to reach the vertex
+         * @return weight cost to reach the vertex if already accessed;
+         *         null otherwise
          */
-        double cost(V v) {
-            Double c = costs.get(v);
-            return c == null ? Double.MAX_VALUE : c;
+        Weight cost(V v) {
+            return costs.get(v);
         }
 
         /**
@@ -151,7 +132,7 @@
          *                added to the previously accrued edges as they yield
          *                the same cost
          */
-        void updateVertex(V vertex, E edge, double cost, boolean replace) {
+        void updateVertex(V vertex, E edge, Weight cost, boolean replace) {
             costs.put(vertex, cost);
             if (edge != null) {
                 Set<E> edges = parents.get(vertex);
@@ -187,22 +168,27 @@
          * @param forbidNegatives if true negative values will forbid the link
          * @return true if the edge was relaxed; false otherwise
          */
-        boolean relaxEdge(E edge, double cost, EdgeWeight<V, E> ew,
+        boolean relaxEdge(E edge, Weight cost, EdgeWeigher<V, E> ew,
                           boolean... forbidNegatives) {
             V v = edge.dst();
-            double oldCost = cost(v);
-            double hopCost = ew == null ? 1.0 : ew.weight(edge);
-            if (hopCost < 0 && forbidNegatives.length == 1 && forbidNegatives[0]) {
+
+            Weight hopCost = ew.weight(edge);
+            if ((!hopCost.isViable()) ||
+                    (hopCost.isNegative() && forbidNegatives.length == 1 && forbidNegatives[0])) {
                 return false;
             }
+            Weight newCost = cost.merge(hopCost);
 
-            double newCost = cost + hopCost;
-            boolean relaxed = newCost < oldCost;
-            boolean same = Math.abs(newCost - oldCost) <= samenessThreshold;
-            if (same || relaxed) {
-                updateVertex(v, edge, newCost, !same);
+            int compareResult = -1;
+            if (hasCost(v)) {
+                Weight oldCost = cost(v);
+                compareResult = newCost.compareTo(oldCost);
             }
-            return relaxed;
+
+            if (compareResult <= 0) {
+                updateVertex(v, edge, newCost, compareResult < 0);
+            }
+            return compareResult < 0;
         }
 
         /**
@@ -328,4 +314,16 @@
                       "Destination not in graph");
     }
 
+    @Override
+    public Result<V, E> search(Graph<V, E> graph, V src, V dst,
+                               EdgeWeigher<V, E> weigher, int maxPaths) {
+        checkArguments(graph, src, dst);
+
+        return internalSearch(graph, src, dst,
+                weigher != null ? weigher : new DefaultEdgeWeigher<>(),
+                maxPaths);
+    }
+
+    protected abstract Result<V, E> internalSearch(Graph<V, E> graph, V src, V dst,
+                                          EdgeWeigher<V, E> weigher, int maxPaths);
 }
diff --git a/utils/misc/src/main/java/org/onlab/graph/BellmanFordGraphSearch.java b/utils/misc/src/main/java/org/onlab/graph/BellmanFordGraphSearch.java
index 88aca6b..9bd6c63 100644
--- a/utils/misc/src/main/java/org/onlab/graph/BellmanFordGraphSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/BellmanFordGraphSearch.java
@@ -23,22 +23,21 @@
         extends AbstractGraphPathSearch<V, E> {
 
     @Override
-    public Result<V, E> search(Graph<V, E> graph, V src, V dst,
-                               EdgeWeight<V, E> weight, int maxPaths) {
-        checkArguments(graph, src, dst);
+    protected Result<V, E> internalSearch(Graph<V, E> graph, V src, V dst,
+                               EdgeWeigher<V, E> weigher, int maxPaths) {
 
         // Prepare the graph search result.
         DefaultResult result = new DefaultResult(src, dst, maxPaths);
 
         // The source vertex has cost 0, of course.
-        result.updateVertex(src, null, 0.0, true);
+        result.updateVertex(src, null, weigher.getInitialWeight(), true);
 
         int max = graph.getVertexes().size() - 1;
         for (int i = 0; i < max; i++) {
             // Relax, if possible, all egress edges of the current vertex.
             for (E edge : graph.getEdges()) {
                 if (result.hasCost(edge.src())) {
-                    result.relaxEdge(edge, result.cost(edge.src()), weight);
+                    result.relaxEdge(edge, result.cost(edge.src()), weigher);
                 }
             }
         }
@@ -46,7 +45,7 @@
         // Remove any vertexes reached by traversing edges with negative weights.
         for (E edge : graph.getEdges()) {
             if (result.hasCost(edge.src())) {
-                if (result.relaxEdge(edge, result.cost(edge.src()), weight)) {
+                if (result.relaxEdge(edge, result.cost(edge.src()), weigher)) {
                     result.removeVertex(edge.dst());
                 }
             }
@@ -56,5 +55,4 @@
         result.buildPaths();
         return result;
     }
-
 }
diff --git a/utils/misc/src/main/java/org/onlab/graph/BreadthFirstSearch.java b/utils/misc/src/main/java/org/onlab/graph/BreadthFirstSearch.java
index 48bfe03..c5b0f4f 100644
--- a/utils/misc/src/main/java/org/onlab/graph/BreadthFirstSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/BreadthFirstSearch.java
@@ -25,16 +25,15 @@
         extends AbstractGraphPathSearch<V, E> {
 
     @Override
-    public Result<V, E> search(Graph<V, E> graph, V src, V dst,
-                               EdgeWeight<V, E> weight, int maxPaths) {
-        checkArguments(graph, src, dst);
+    protected Result<V, E> internalSearch(Graph<V, E> graph, V src, V dst,
+                               EdgeWeigher<V, E> weigher, int maxPaths) {
 
         // Prepare the graph result.
         DefaultResult result = new DefaultResult(src, dst, maxPaths);
 
         // Setup the starting frontier with the source as the sole vertex.
         Set<V> frontier = new HashSet<>();
-        result.updateVertex(src, null, 0.0, true);
+        result.updateVertex(src, null, weigher.getInitialWeight(), true);
         frontier.add(src);
 
         boolean reachedEnd = false;
@@ -44,14 +43,14 @@
 
             // Visit all vertexes in the current frontier.
             for (V vertex : frontier) {
-                double cost = result.cost(vertex);
+                Weight cost = result.cost(vertex);
 
                 // Visit all egress edges of the current frontier vertex.
                 for (E edge : graph.getEdgesFrom(vertex)) {
                     V nextVertex = edge.dst();
                     if (!result.hasCost(nextVertex)) {
                         // If this vertex has not been visited yet, update it.
-                        double newCost = cost + (weight == null ? 1.0 : weight.weight(edge));
+                        Weight newCost = cost.merge(weigher.weight(edge));
                         result.updateVertex(nextVertex, edge, newCost, true);
                         // If we have reached our intended destination, bail.
                         if (nextVertex.equals(dst)) {
diff --git a/utils/misc/src/main/java/org/onlab/graph/DefaultEdgeWeigher.java b/utils/misc/src/main/java/org/onlab/graph/DefaultEdgeWeigher.java
new file mode 100644
index 0000000..e280391
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/graph/DefaultEdgeWeigher.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onlab.graph;
+
+/**
+ * Default weigher returns identical weight for every graph edge. Basically it
+ * is a hop count weigher.
+ * Produces weights of {@link ScalarWeight} type.
+ *
+ * @param <V> vertex type
+ * @param <E> edge type
+ */
+public class DefaultEdgeWeigher<V extends Vertex, E extends Edge<V>>
+        implements EdgeWeigher<V, E> {
+
+    /**
+     * Common weight value for any link.
+     */
+    protected static final double HOP_WEIGHT_VALUE = 1;
+    /**
+     * Weight value for null path (without links).
+     */
+    protected static final double NULL_WEIGHT_VALUE = 0;
+
+    @Override
+    public Weight weight(E edge) {
+        return new ScalarWeight(HOP_WEIGHT_VALUE);
+    }
+
+    @Override
+    public Weight getInitialWeight() {
+        return new ScalarWeight(NULL_WEIGHT_VALUE);
+    }
+
+    @Override
+    public Weight getNonViableWeight() {
+        return ScalarWeight.NON_VIABLE_WEIGHT;
+    }
+}
diff --git a/utils/misc/src/main/java/org/onlab/graph/DefaultMutablePath.java b/utils/misc/src/main/java/org/onlab/graph/DefaultMutablePath.java
index b6c5e38..c8f8f86 100644
--- a/utils/misc/src/main/java/org/onlab/graph/DefaultMutablePath.java
+++ b/utils/misc/src/main/java/org/onlab/graph/DefaultMutablePath.java
@@ -31,7 +31,7 @@
 public class DefaultMutablePath<V extends Vertex, E extends Edge<V>> implements MutablePath<V, E> {
 
     private final List<E> edges = new ArrayList<>();
-    private double cost = 0.0;
+    private Weight cost;
 
     /**
      * Creates a new empty path.
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public double cost() {
+    public Weight cost() {
         return cost;
     }
 
@@ -71,7 +71,7 @@
     }
 
     @Override
-    public void setCost(double cost) {
+    public void setCost(Weight cost) {
         this.cost = cost;
     }
 
diff --git a/utils/misc/src/main/java/org/onlab/graph/DefaultPath.java b/utils/misc/src/main/java/org/onlab/graph/DefaultPath.java
index c1aa802..4a29adf 100644
--- a/utils/misc/src/main/java/org/onlab/graph/DefaultPath.java
+++ b/utils/misc/src/main/java/org/onlab/graph/DefaultPath.java
@@ -33,15 +33,15 @@
     private final V src;
     private final V dst;
     private final List<E> edges;
-    private double cost = 0.0;
+    private Weight cost;
 
     /**
      * Creates a new path from the specified list of edges and cost.
      *
      * @param edges list of path edges
-     * @param cost  path cost as a unit-less number
+     * @param cost  path cost as a weight object
      */
-    public DefaultPath(List<E> edges, double cost) {
+    public DefaultPath(List<E> edges, Weight cost) {
         checkNotNull(edges, "Edges list must not be null");
         checkArgument(!edges.isEmpty(), "There must be at least one edge");
         this.edges = ImmutableList.copyOf(edges);
@@ -61,7 +61,7 @@
     }
 
     @Override
-    public double cost() {
+    public Weight cost() {
         return cost;
     }
 
diff --git a/utils/misc/src/main/java/org/onlab/graph/DepthFirstSearch.java b/utils/misc/src/main/java/org/onlab/graph/DepthFirstSearch.java
index 218ce39..a5b33b3 100644
--- a/utils/misc/src/main/java/org/onlab/graph/DepthFirstSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/DepthFirstSearch.java
@@ -35,15 +35,14 @@
     }
 
     @Override
-    public SpanningTreeResult search(Graph<V, E> graph, V src, V dst,
-                                     EdgeWeight<V, E> weight, int maxPaths) {
-        checkArguments(graph, src, dst);
+    protected SpanningTreeResult internalSearch(Graph<V, E> graph, V src, V dst,
+                                             EdgeWeigher<V, E> weigher, int maxPaths) {
 
         // Prepare the search result.
         SpanningTreeResult result = new SpanningTreeResult(src, dst, maxPaths);
 
         // The source vertex has cost 0, of course.
-        result.updateVertex(src, null, 0.0, true);
+        result.updateVertex(src, null, weigher.getInitialWeight(), true);
 
         // Track finished vertexes and keep a stack of vertexes that have been
         // started; start this stack with the source on it.
@@ -58,7 +57,7 @@
                 break;
             }
 
-            double cost = result.cost(vertex);
+            Weight cost = result.cost(vertex);
             boolean tangent = false;
 
             // Visit all egress edges of the current vertex.
@@ -74,7 +73,7 @@
                     // If this vertex have not finished this vertex yet,
                     // not started it, then start it as a tree-edge.
                     result.markEdge(edge, EdgeType.TREE_EDGE);
-                    double newCost = cost + (weight == null ? 1.0 : weight.weight(edge));
+                    Weight newCost = cost.merge(weigher.weight(edge));
                     result.updateVertex(nextVertex, edge, newCost, true);
                     stack.push(nextVertex);
                     tangent = true;
diff --git a/utils/misc/src/main/java/org/onlab/graph/DijkstraGraphSearch.java b/utils/misc/src/main/java/org/onlab/graph/DijkstraGraphSearch.java
index 4990718..0dd1898 100644
--- a/utils/misc/src/main/java/org/onlab/graph/DijkstraGraphSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/DijkstraGraphSearch.java
@@ -27,16 +27,15 @@
         extends AbstractGraphPathSearch<V, E> {
 
     @Override
-    public Result<V, E> search(Graph<V, E> graph, V src, V dst,
-                               EdgeWeight<V, E> weight, int maxPaths) {
-        checkArguments(graph, src, dst);
+    protected Result<V, E> internalSearch(Graph<V, E> graph, V src, V dst,
+                               EdgeWeigher<V, E> weigher, int maxPaths) {
 
         // Use the default result to remember cumulative costs and parent
         // edges to each each respective vertex.
         DefaultResult result = new DefaultResult(src, dst, maxPaths);
 
         // Cost to reach the source vertex is 0 of course.
-        result.updateVertex(src, null, 0.0, false);
+        result.updateVertex(src, null, weigher.getInitialWeight(), false);
 
         if (graph.getEdges().isEmpty()) {
             result.buildPaths();
@@ -56,11 +55,12 @@
             }
 
             // Find its cost and use it to determine if the vertex is reachable.
-            double cost = result.cost(nearest);
-            if (cost < Double.MAX_VALUE) {
+            if (result.hasCost(nearest)) {
+                Weight cost = result.cost(nearest);
+
                 // If the vertex is reachable, relax all its egress edges.
                 for (E e : graph.getEdgesFrom(nearest)) {
-                    result.relaxEdge(e, cost, weight, true);
+                    result.relaxEdge(e, cost, weigher, true);
                 }
             }
 
@@ -84,8 +84,16 @@
 
         @Override
         public int compare(V v1, V v2) {
-            double delta = result.cost(v2) - result.cost(v1);
-            return delta < 0 ? -1 : (delta > 0 ? 1 : 0);
+            //not accessed vertices should be pushed to the back of the queue
+            if (!result.hasCost(v1) && !result.hasCost(v2)) {
+                return 0;
+            } else if (!result.hasCost(v1)) {
+                return -1;
+            } else if (!result.hasCost(v2)) {
+                return 1;
+            }
+
+            return result.cost(v2).compareTo(result.cost(v1));
         }
     }
 
diff --git a/utils/misc/src/main/java/org/onlab/graph/DisjointPathPair.java b/utils/misc/src/main/java/org/onlab/graph/DisjointPathPair.java
index 1e8d3d6..6436ad4 100644
--- a/utils/misc/src/main/java/org/onlab/graph/DisjointPathPair.java
+++ b/utils/misc/src/main/java/org/onlab/graph/DisjointPathPair.java
@@ -73,8 +73,8 @@
     }
 
     @Override
-    public double cost() {
-        return hasBackup() ? primary.cost() + secondary.cost() : primary.cost();
+    public Weight cost() {
+        return hasBackup() ? primary.cost().merge(secondary.cost()) : primary.cost();
     }
 
     @Override
diff --git a/utils/misc/src/main/java/org/onlab/graph/EdgeWeigher.java b/utils/misc/src/main/java/org/onlab/graph/EdgeWeigher.java
new file mode 100644
index 0000000..f52c4dd
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/graph/EdgeWeigher.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2014-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onlab.graph;
+
+/**
+ * Abstraction of a graph edge weight function.
+ */
+public interface EdgeWeigher<V extends Vertex, E extends Edge<V>> {
+
+    /**
+     * Returns the weight of the given edge.
+     *
+     * @param edge edge to be weighed
+     * @return edge weight
+     */
+    Weight weight(E edge);
+
+    /**
+     * Returns initial weight value (i.e. weight of a "path" starting and
+     * terminating in the same vertex; typically 0 value is used).
+     *
+     * @return null path weight
+     */
+    Weight getInitialWeight();
+
+    /**
+     * Returns weight of a link/path that should be skipped
+     * (can be considered as an infinite weight).
+     *
+     * @return non viable weight
+     */
+    Weight getNonViableWeight();
+}
diff --git a/utils/misc/src/main/java/org/onlab/graph/EdgeWeight.java b/utils/misc/src/main/java/org/onlab/graph/EdgeWeight.java
deleted file mode 100644
index 5b1c806..0000000
--- a/utils/misc/src/main/java/org/onlab/graph/EdgeWeight.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2014-present Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onlab.graph;
-
-/**
- * Abstraction of a graph edge weight function.
- */
-public interface EdgeWeight<V extends Vertex, E extends Edge<V>> {
-
-    /**
-     * Returns the weight of the given edge as a unit-less number.
-     *
-     * @param edge edge to be weighed
-     * @return edge weight as a unit-less number
-     */
-    double weight(E edge);
-
-}
diff --git a/utils/misc/src/main/java/org/onlab/graph/GAOrganism.java b/utils/misc/src/main/java/org/onlab/graph/GAOrganism.java
index 4deed2fa..1384c9a 100644
--- a/utils/misc/src/main/java/org/onlab/graph/GAOrganism.java
+++ b/utils/misc/src/main/java/org/onlab/graph/GAOrganism.java
@@ -28,7 +28,7 @@
      *
      * @return fitness of organism
      */
-    double fitness();
+    Comparable fitness();
 
     /**
      * A method that slightly mutates an organism.
diff --git a/utils/misc/src/main/java/org/onlab/graph/GAPopulation.java b/utils/misc/src/main/java/org/onlab/graph/GAPopulation.java
index 5f9dfcc..4017485 100644
--- a/utils/misc/src/main/java/org/onlab/graph/GAPopulation.java
+++ b/utils/misc/src/main/java/org/onlab/graph/GAPopulation.java
@@ -33,15 +33,8 @@
      * 25% (as well as some "random" newcomers).
      */
     void step() {
-        Collections.sort(this, (org1, org2) -> {
-            double d = org1.fitness() - org2.fitness();
-            if (d < 0) {
-                return -1;
-            } else if (d == 0) {
-                return 0;
-            }
-            return 1;
-        });
+        Collections.sort(this, (org1, org2) ->
+                org1.fitness().compareTo(org2.fitness()));
         int maxSize = size();
         for (int i = size() - 1; i > maxSize / 4; i--) {
             remove(i);
diff --git a/utils/misc/src/main/java/org/onlab/graph/GraphPathSearch.java b/utils/misc/src/main/java/org/onlab/graph/GraphPathSearch.java
index d5513a7..1c1099d 100644
--- a/utils/misc/src/main/java/org/onlab/graph/GraphPathSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/GraphPathSearch.java
@@ -66,7 +66,7 @@
          *
          * @return map of vertex to path cost bindings
          */
-        Map<V, Double> costs();
+        Map<V, Weight> costs();
     }
 
     /**
@@ -76,12 +76,12 @@
      * @param src      optional source vertex
      * @param dst      optional destination vertex; if null paths to all vertex
      *                 destinations will be searched
-     * @param weight   optional edge-weight; if null cost of each edge will be
-     *                 assumed to be 1.0
+     * @param weigher  optional edge-weigher; if null, {@link DefaultEdgeWeigher}
+     *                 will be used (assigns equal weights to all links)
      * @param maxPaths limit on number of paths; {@link GraphPathSearch#ALL_PATHS} if no limit
      * @return search results
      */
     Result<V, E> search(Graph<V, E> graph, V src, V dst,
-                        EdgeWeight<V, E> weight, int maxPaths);
+                        EdgeWeigher<V, E> weigher, int maxPaths);
 
 }
diff --git a/utils/misc/src/main/java/org/onlab/graph/GraphSearch.java b/utils/misc/src/main/java/org/onlab/graph/GraphSearch.java
index 4ef6e6d..6f0d606 100644
--- a/utils/misc/src/main/java/org/onlab/graph/GraphSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/GraphSearch.java
@@ -32,12 +32,12 @@
     /**
      * Searches the specified graph.
      *
-     * @param graph  graph to be searched
-     * @param weight optional edge-weight; if null cost of each edge will be
-     *               assumed to be 1.0
+     * @param graph   graph to be searched
+     * @param weigher optional edge-weigher; if null, {@link DefaultEdgeWeigher}
+     *                will be used (assigns equal weights to all links)
      *
      * @return search results
      */
-    Result search(Graph<V, E> graph, EdgeWeight<V, E> weight);
+    Result search(Graph<V, E> graph, EdgeWeigher<V, E> weigher);
 
 }
diff --git a/utils/misc/src/main/java/org/onlab/graph/KShortestPathsSearch.java b/utils/misc/src/main/java/org/onlab/graph/KShortestPathsSearch.java
index c07b00a..00bda43 100644
--- a/utils/misc/src/main/java/org/onlab/graph/KShortestPathsSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/KShortestPathsSearch.java
@@ -40,11 +40,9 @@
     private final Logger log = getLogger(getClass());
 
     @Override
-    public Result<V, E> search(Graph<V, E> graph, V src, V dst, EdgeWeight<V, E> weight, int maxPaths) {
-        checkNotNull(src);
-        checkNotNull(dst);
-        //The modified edge weight removes any need to modify the original graph
-        InnerEdgeWeighter modifiedWeighter = new InnerEdgeWeighter(checkNotNull(weight));
+    protected Result<V, E> internalSearch(Graph<V, E> graph, V src, V dst, EdgeWeigher<V, E> weigher, int maxPaths) {
+        //The modified edge weigher removes any need to modify the original graph
+        InnerEdgeWeigher modifiedWeighter = new InnerEdgeWeigher(checkNotNull(weigher));
         checkArgument(maxPaths != ALL_PATHS, "KShortestPath search cannot" +
                 "be used with ALL_PATHS.");
         checkArgument(maxPaths > 0, "The max number of paths must be greater" +
@@ -87,11 +85,11 @@
                 if (!dijkstraResults.isEmpty()) {
                     Path<V, E> spurPath = dijkstraResults.iterator().next();
                     List<E> totalPath = new ArrayList<>(rootPathEdgeList);
-                    spurPath.edges().forEach(e -> totalPath.add(e));
-                    //The following line must use the original weighter not the modified weighter because the modified
-                    //weighter will count -1 values used for modifying the graph and return an inaccurate cost.
+                    spurPath.edges().forEach(totalPath::add);
+                    //The following line must use the original weigher not the modified weigher because the modified
+                    //weigher will count -1 values used for modifying the graph and return an inaccurate cost.
                     potentialPaths.add(new DefaultPath<V, E>(totalPath,
-                                                             calculatePathCost(weight, totalPath)));
+                            calculatePathCost(weigher, totalPath)));
                 }
 
                 //Restore all removed paths and nodes
@@ -125,10 +123,10 @@
         return true;
     }
 
-    private Double calculatePathCost(EdgeWeight<V, E> weighter, List<E> edges) {
-        Double totalCost = 0.0;
+    private Weight calculatePathCost(EdgeWeigher<V, E> weighter, List<E> edges) {
+        Weight totalCost = weighter.getInitialWeight();
         for (E edge : edges) {
-            totalCost += weighter.weight(edge);
+            totalCost = totalCost.merge(weighter.weight(edge));
         }
         return totalCost;
     }
@@ -136,23 +134,31 @@
     /**
      * Weights edges to make them inaccessible if set, otherwise returns the result of the original EdgeWeight.
      */
-    private class InnerEdgeWeighter implements EdgeWeight<V, E> {
+    private final class InnerEdgeWeigher implements EdgeWeigher<V, E> {
 
         private Set<E> removedEdges = Sets.newConcurrentHashSet();
-        private EdgeWeight<V, E> innerEdgeWeight;
+        private EdgeWeigher<V, E> innerEdgeWeigher;
 
-        public InnerEdgeWeighter(EdgeWeight<V, E> weight) {
-            this.innerEdgeWeight = weight;
+        private InnerEdgeWeigher(EdgeWeigher<V, E> weigher) {
+            this.innerEdgeWeigher = weigher;
         }
 
         @Override
-        public double weight(E edge) {
+        public Weight weight(E edge) {
             if (removedEdges.contains(edge)) {
-                //THIS RELIES ON THE LOCAL DIJKSTRA ALGORITHM AVOIDING NEGATIVES
-                return -1;
-            } else {
-                return innerEdgeWeight.weight(edge);
+                return innerEdgeWeigher.getNonViableWeight();
             }
+            return innerEdgeWeigher.weight(edge);
+        }
+
+        @Override
+        public Weight getInitialWeight() {
+            return innerEdgeWeigher.getInitialWeight();
+        }
+
+        @Override
+        public Weight getNonViableWeight() {
+            return innerEdgeWeigher.getNonViableWeight();
         }
     }
 
@@ -184,7 +190,7 @@
 
         @Override
         public int compare(Path<V, E> pathOne, Path<V, E> pathTwo) {
-            int comparisonValue = Double.compare(pathOne.cost(), pathTwo.cost());
+            int comparisonValue = pathOne.cost().compareTo(pathTwo.cost());
             if  (comparisonValue != 0) {
                 return comparisonValue;
             } else if (edgeListsAreEqual(pathOne.edges(), pathTwo.edges())) {
diff --git a/utils/misc/src/main/java/org/onlab/graph/MutablePath.java b/utils/misc/src/main/java/org/onlab/graph/MutablePath.java
index 22412b1..3a3b479 100644
--- a/utils/misc/src/main/java/org/onlab/graph/MutablePath.java
+++ b/utils/misc/src/main/java/org/onlab/graph/MutablePath.java
@@ -46,11 +46,11 @@
     void removeEdge(E edge);
 
     /**
-     * Sets the total path cost as a unit-less double.
+     * Sets the total path cost as a weight object.
      *
      * @param cost new path cost
      */
-    void setCost(double cost);
+    void setCost(Weight cost);
 
     /**
      * Returns an immutable copy of this path.
diff --git a/utils/misc/src/main/java/org/onlab/graph/Path.java b/utils/misc/src/main/java/org/onlab/graph/Path.java
index 0f74aae..85ac420 100644
--- a/utils/misc/src/main/java/org/onlab/graph/Path.java
+++ b/utils/misc/src/main/java/org/onlab/graph/Path.java
@@ -36,10 +36,10 @@
     List<E> edges();
 
     /**
-     * Returns the total cost of the path as a unit-less number.
+     * Returns the total cost of the path as a weight object.
      *
-     * @return path cost as a unit-less number
+     * @return path cost as a weight object
      */
-    double cost();
+    Weight cost();
 
 }
diff --git a/utils/misc/src/main/java/org/onlab/graph/ScalarWeight.java b/utils/misc/src/main/java/org/onlab/graph/ScalarWeight.java
new file mode 100644
index 0000000..ccf0c2a
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/graph/ScalarWeight.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onlab.graph;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+import com.google.common.math.DoubleMath;
+
+import java.util.Objects;
+
+/**
+ * Weight implementation based on a double value.
+ */
+public class ScalarWeight implements Weight {
+
+    /**
+     * Instance of scalar weight to mark links/paths which
+     * can not be traversed.
+     */
+    public static final ScalarWeight NON_VIABLE_WEIGHT =
+            new ScalarWeight(Double.POSITIVE_INFINITY);
+
+    private static double samenessThreshold = Double.MIN_VALUE;
+
+    private double value;
+
+    /**
+     * Creates a new scalar weight with the given double value.
+     * @param value double value
+     */
+    public ScalarWeight(double value) {
+        this.value = value;
+    }
+
+    @Override
+    public Weight merge(Weight otherWeight) {
+        return new ScalarWeight(value + ((ScalarWeight) otherWeight).value);
+    }
+
+    @Override
+    public Weight subtract(Weight otherWeight) {
+        return new ScalarWeight(value - ((ScalarWeight) otherWeight).value);
+    }
+
+    @Override
+    public boolean isViable() {
+        return this != NON_VIABLE_WEIGHT;
+    }
+
+    @Override
+    public int compareTo(Weight otherWeight) {
+        //check equality with samenessThreshold
+        if (equals(otherWeight)) {
+            return 0;
+        }
+        return Double.compare(value, ((ScalarWeight) otherWeight).value);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return ((obj instanceof ScalarWeight) &&
+                (DoubleMath.fuzzyEquals(value, ((ScalarWeight) obj).value,
+                        samenessThreshold)));
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(value);
+    }
+
+    @Override
+    public boolean isNegative() {
+        return value < 0;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this).add("value", value).toString();
+    }
+
+    /**
+     * Returns inner double value.
+     *
+     * @return double value
+     */
+    public double value() {
+        return value;
+    }
+
+    /**
+     * Sets a new sameness threshold for comparing cost values; default is
+     * is {@link Double#MIN_VALUE}.
+     *
+     * @param threshold fractional double value
+     */
+    public static void setSamenessThreshold(double threshold) {
+        samenessThreshold = threshold;
+    }
+
+    /**
+     * Returns the current sameness threshold for comparing cost values.
+     *
+     * @return current threshold
+     */
+    public static double samenessThreshold() {
+        return samenessThreshold;
+    }
+}
diff --git a/utils/misc/src/main/java/org/onlab/graph/SrlgGraphSearch.java b/utils/misc/src/main/java/org/onlab/graph/SrlgGraphSearch.java
index 5ac35a0..82107ca 100644
--- a/utils/misc/src/main/java/org/onlab/graph/SrlgGraphSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/SrlgGraphSearch.java
@@ -46,7 +46,7 @@
 
     Graph<V, E> orig;
     V src, dst;
-    EdgeWeight<V, E> weight;
+    EdgeWeigher<V, E> weigher;
 
     /**
      * Creates an SRLG graph search object with the given number
@@ -86,22 +86,18 @@
     }
 
     @Override
-    public Result<V, E> search(Graph<V, E> graph, V src, V dst,
-                               EdgeWeight<V, E> weight, int maxPaths) {
+    protected Result<V, E> internalSearch(Graph<V, E> graph, V src, V dst,
+                               EdgeWeigher<V, E> weigher, int maxPaths) {
         if (maxPaths == ALL_PATHS) {
             maxPaths = POPSIZE;
         }
         if (useSuurballe) {
-            return new SuurballeGraphSearch<V, E>().search(graph, src, dst, weight, ALL_PATHS);
+            return new SuurballeGraphSearch<V, E>().search(graph, src, dst, weigher, ALL_PATHS);
         }
-        if (weight == null) {
-            weight = edge -> 1;
-        }
-        checkArguments(graph, src, dst);
         orig = graph;
         this.src = src;
         this.dst = dst;
-        this.weight = weight;
+        this.weigher = weigher;
         List<Subset> best = new GAPopulation<Subset>()
                 .runGA(ITERATIONS, POPSIZE, maxPaths, new Subset(new boolean[numGroups]));
         Set<DisjointPathPair> dpps = new HashSet<DisjointPathPair>();
@@ -109,7 +105,7 @@
             dpps.addAll(s.buildPaths());
         }
         Result<V, E> firstDijkstra = new DijkstraGraphSearch<V, E>()
-                .search(orig, src, dst, weight, 1);
+                .search(orig, src, dst, weigher, 1);
         return new Result<V, E>() {
             final DefaultResult search = (DefaultResult) firstDijkstra;
 
@@ -127,7 +123,7 @@
                 }
                 return pathsD;
             }
-            public Map<V, Double> costs() {
+            public Map<V, Weight> costs() {
                 return search.costs();
 
             }
@@ -141,15 +137,25 @@
     //finds the shortest path in the graph given a subset of edge types to use
     private Result<V, E> findShortestPathFromSubset(boolean[] subset) {
         Graph<V, E> graph = orig;
-        EdgeWeight<V, E> modified = new EdgeWeight<V, E>() {
+        EdgeWeigher<V, E> modified = new EdgeWeigher<V, E>() {
             final boolean[] subsetF = subset;
 
             @Override
-            public double weight(E edge) {
+            public Weight weight(E edge) {
                 if (subsetF[riskGrouping.get(edge)]) {
-                    return weight.weight(edge);
+                    return weigher.weight(edge);
                 }
-                return INF;
+                return weigher.getNonViableWeight();
+            }
+
+            @Override
+            public Weight getInitialWeight() {
+                return weigher.getInitialWeight();
+            }
+
+            @Override
+            public Weight getNonViableWeight() {
+                return weigher.getNonViableWeight();
             }
         };
 
@@ -181,13 +187,13 @@
         }
 
         @Override
-        public double fitness() {
+        public Comparable fitness() {
             Set<Path<V, E>> paths1 = findShortestPathFromSubset(subset).paths();
             Set<Path<V, E>> paths2 = findShortestPathFromSubset(not).paths();
             if (paths1.isEmpty() || paths2.isEmpty()) {
-                return INF;
+                return weigher.getNonViableWeight();
             }
-            return paths1.iterator().next().cost() + paths2.iterator().next().cost();
+            return paths1.iterator().next().cost().merge(paths2.iterator().next().cost());
         }
 
         @Override
@@ -236,13 +242,7 @@
         public Set<DisjointPathPair> buildPaths() {
             Set<DisjointPathPair> dpps = new HashSet<>();
             for (Path<V, E> path1: findShortestPathFromSubset(subset).paths()) {
-                if (path1.cost() >= INF) {
-                    continue;
-                }
                 for (Path<V, E> path2: findShortestPathFromSubset(not).paths()) {
-                    if (path2.cost() >= INF) {
-                        continue;
-                    }
                     DisjointPathPair<V, E> dpp = new DisjointPathPair<>(path1, path2);
                     dpps.add(dpp);
                 }
diff --git a/utils/misc/src/main/java/org/onlab/graph/SuurballeGraphSearch.java b/utils/misc/src/main/java/org/onlab/graph/SuurballeGraphSearch.java
index f517d5a..d945192 100644
--- a/utils/misc/src/main/java/org/onlab/graph/SuurballeGraphSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/SuurballeGraphSearch.java
@@ -34,8 +34,8 @@
 public class SuurballeGraphSearch<V extends Vertex, E extends Edge<V>> extends DijkstraGraphSearch<V, E> {
 
     @Override
-    public Result<V, E> search(Graph<V, E> graph, V src, V dst,
-                               EdgeWeight<V, E> weight, int maxPaths) {
+    protected Result<V, E> internalSearch(Graph<V, E> graph, V src, V dst,
+                               EdgeWeigher<V, E> weigher, int maxPaths) {
         // FIXME: This method needs to be refactored as it is difficult to follow and debug.
 
         // FIXME: There is a defect here triggered by 3+ edges between the same vertices,
@@ -46,13 +46,12 @@
         // This class needs to filter its own results to make sure that the
         // paths are indeed disjoint. Temporary fix for this is provided, but
         // the issue needs to be addressed through refactoring.
-        if (weight == null) {
-            weight = edge -> 1;
-        }
 
-        final EdgeWeight weightf = weight;
-        DefaultResult firstDijkstraS = (DefaultResult) super.search(graph, src, dst, weight, ALL_PATHS);
-        DefaultResult firstDijkstra = (DefaultResult) super.search(graph, src, null, weight, ALL_PATHS);
+        EdgeWeigher weightf = weigher;
+        DefaultResult firstDijkstraS = (DefaultResult) super.internalSearch(
+                graph, src, dst, weigher, ALL_PATHS);
+        DefaultResult firstDijkstra = (DefaultResult) super.internalSearch(
+                graph, src, null, weigher, ALL_PATHS);
 
         //choose an arbitrary shortest path to run Suurballe on
         Path<V, E> shortPath = null;
@@ -65,11 +64,43 @@
         for (Path p: firstDijkstraS.paths()) {
             shortPath = p;
             //transforms the graph so tree edges have 0 weight
-            EdgeWeight<V, E> modified = edge ->
-                edge instanceof ReverseEdge ? 0 :
-                    weightf.weight(edge) + firstDijkstra.cost(edge.src()) - firstDijkstra.cost(edge.dst());
-            EdgeWeight<V, E> modified2 = edge ->
-                    weightf.weight(edge) + firstDijkstra.cost(edge.src()) - firstDijkstra.cost(edge.dst());
+            EdgeWeigher<V, E> modified = new EdgeWeigher<V, E>() {
+                @Override
+                public Weight weight(E edge) {
+                    return edge instanceof ReverseEdge ?
+                            weightf.getInitialWeight() :
+                            weightf.weight(edge).merge(firstDijkstra.cost(edge.src()))
+                                    .subtract(firstDijkstra.cost(edge.dst()));
+                }
+
+                @Override
+                public Weight getInitialWeight() {
+                    return weightf.getInitialWeight();
+                }
+
+                @Override
+                public Weight getNonViableWeight() {
+                    return weightf.getNonViableWeight();
+                }
+            };
+
+            EdgeWeigher<V, E> modified2 = new EdgeWeigher<V, E>() {
+                @Override
+                public Weight weight(E edge) {
+                    return weightf.weight(edge).merge(firstDijkstra.cost(edge.src()))
+                            .subtract(firstDijkstra.cost(edge.dst()));
+                }
+
+                @Override
+                public Weight getInitialWeight() {
+                    return weightf.getInitialWeight();
+                }
+
+                @Override
+                public Weight getNonViableWeight() {
+                    return weightf.getNonViableWeight();
+                }
+            };
 
             //create a residual graph g' by removing all src vertices and reversing 0 length path edges
             MutableGraph<V, E> gt = mutableCopy(graph);
@@ -114,11 +145,13 @@
                     }
                 }
                 //Actually build the final result
-                DefaultResult lastSearch = (DefaultResult) super.search(roundTrip, src, dst, weight, ALL_PATHS);
+                DefaultResult lastSearch = (DefaultResult)
+                        super.internalSearch(roundTrip, src, dst, weigher, ALL_PATHS);
                 Path<V, E> primary = lastSearch.paths().iterator().next();
                 primary.edges().forEach(roundTrip::removeEdge);
 
-                Set<Path<V, E>> backups = super.search(roundTrip, src, dst, weight, ALL_PATHS).paths();
+                Set<Path<V, E>> backups = super.internalSearch(roundTrip, src, dst,
+                        weigher, ALL_PATHS).paths();
 
                 // Find first backup path that does not share any nodes with the primary
                 for (Path<V, E> backup : backups) {
@@ -220,7 +253,7 @@
         }
 
         @Override
-        public Map<V, Double> costs() {
+        public Map<V, Weight> costs() {
             return searchResult.costs();
         }
     }
diff --git a/utils/misc/src/main/java/org/onlab/graph/TarjanGraphSearch.java b/utils/misc/src/main/java/org/onlab/graph/TarjanGraphSearch.java
index 94cb609..ad07d4b 100644
--- a/utils/misc/src/main/java/org/onlab/graph/TarjanGraphSearch.java
+++ b/utils/misc/src/main/java/org/onlab/graph/TarjanGraphSearch.java
@@ -37,17 +37,17 @@
      * SCCs within the graph.
      * </p>
      * <p>
-     * To prevent traversal of an edge, the {@link EdgeWeight#weight} should
-     * return a negative value as an edge weight.
+     * To prevent traversal of an edge, the {@link EdgeWeigher#weight} should
+     * return a negative value as an edge weigher.
      * </p>
      */
     @Override
-    public SccResult<V, E> search(Graph<V, E> graph, EdgeWeight<V, E> weight) {
+    public SccResult<V, E> search(Graph<V, E> graph, EdgeWeigher<V, E> weigher) {
         SccResult<V, E> result = new SccResult<>(graph);
         for (V vertex : graph.getVertexes()) {
             VertexData data = result.data(vertex);
             if (data == null) {
-                connect(graph, vertex, weight, result);
+                connect(graph, vertex, weigher, result);
             }
         }
         return result.build();
@@ -56,14 +56,14 @@
     /**
      * Scans the specified graph, using recursion, and produces SCC results.
      *
-     * @param graph  graph to search
-     * @param vertex current vertex to scan and connect
-     * @param weight optional edge weight
-     * @param result graph search result
+     * @param graph   graph to search
+     * @param vertex  current vertex to scan and connect
+     * @param weigher optional edge weigher
+     * @param result  graph search result
      * @return augmentation vertexData for the current vertex
      */
     private VertexData<V> connect(Graph<V, E> graph, V vertex,
-                                  EdgeWeight<V, E> weight,
+                                  EdgeWeigher<V, E> weigher,
                                   SccResult<V, E> result) {
         VertexData<V> data = result.addData(vertex);
 
@@ -71,8 +71,8 @@
         for (E edge : graph.getEdgesFrom(vertex)) {
             V nextVertex = edge.dst();
 
-            // If edge weight is negative, skip it.
-            if (weight != null && weight.weight(edge) < 0) {
+            // If edge is not viable, skip it.
+            if (weigher != null && !weigher.weight(edge).isViable()) {
                 continue;
             }
 
@@ -80,7 +80,7 @@
             VertexData<V> nextData = result.data(nextVertex);
             if (nextData == null) {
                 // Next vertex has not been visited yet, so do this now.
-                nextData = connect(graph, nextVertex, weight, result);
+                nextData = connect(graph, nextVertex, weigher, result);
                 data.lowLink = Math.min(data.lowLink, nextData.lowLink);
 
             } else if (result.visited(nextData)) {
diff --git a/utils/misc/src/main/java/org/onlab/graph/Weight.java b/utils/misc/src/main/java/org/onlab/graph/Weight.java
new file mode 100644
index 0000000..9f5326d
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/graph/Weight.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onlab.graph;
+
+/**
+ * Abstraction of a graph edge weight.
+ */
+public interface Weight extends Comparable<Weight> {
+
+    /**
+     * Merges the given weight with this one returning a new aggregated
+     * weight.
+     *
+     * @param otherWeight weight to add
+     * @return aggregated weight
+     */
+    Weight merge(Weight otherWeight);
+
+    /**
+     * Subtracts the given weight from this one and produces a new weight.
+     *
+     * @param otherWeight weight to subtract
+     * @return residual weight
+     */
+    Weight subtract(Weight otherWeight);
+
+    /**
+     * Returns true if the weighted subject (link/path) can be traversed; false otherwise.
+     *
+     * @return true if weight is adequate, false if weight is infinite
+     */
+    boolean isViable();
+
+    /**
+     * Returns true if the weight is negative (means that aggregated
+     * path cost will decrease if we add weighted subject to it).
+     *
+     * @return true if the weight is negative, false otherwise
+     */
+    boolean isNegative();
+}
diff --git a/utils/misc/src/test/java/org/onlab/graph/AbstractEdgeTest.java b/utils/misc/src/test/java/org/onlab/graph/AbstractEdgeTest.java
index 65bc741..dcf951e 100644
--- a/utils/misc/src/test/java/org/onlab/graph/AbstractEdgeTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/AbstractEdgeTest.java
@@ -28,9 +28,9 @@
         TestVertex v1 = new TestVertex("1");
         TestVertex v2 = new TestVertex("2");
         new EqualsTester()
-                .addEqualityGroup(new TestEdge(v1, v2, 1),
-                                  new TestEdge(v1, v2, 1))
-                .addEqualityGroup(new TestEdge(v2, v1, 1))
+                .addEqualityGroup(new TestEdge(v1, v2),
+                                  new TestEdge(v1, v2))
+                .addEqualityGroup(new TestEdge(v2, v1))
                 .testEquals();
     }
 
diff --git a/utils/misc/src/test/java/org/onlab/graph/AbstractGraphPathSearchTest.java b/utils/misc/src/test/java/org/onlab/graph/AbstractGraphPathSearchTest.java
index e585449..fa0d522 100644
--- a/utils/misc/src/test/java/org/onlab/graph/AbstractGraphPathSearchTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/AbstractGraphPathSearchTest.java
@@ -18,7 +18,6 @@
 import org.junit.Test;
 
 import static com.google.common.collect.ImmutableSet.of;
-import static org.junit.Assert.assertEquals;
 
 /**
  * Base for all graph search tests.
@@ -35,27 +34,19 @@
     @Test(expected = IllegalArgumentException.class)
     public void noSuchSourceArgument() {
         graphSearch().search(new AdjacencyListsGraph<>(of(B, C),
-                                                       of(new TestEdge(B, C, 1))),
-                             A, H, weight, 1);
+                                                       of(new TestEdge(B, C))),
+                             A, H, weigher, 1);
     }
 
     @Test(expected = NullPointerException.class)
     public void nullGraphArgument() {
-        graphSearch().search(null, A, H, weight, 1);
+        graphSearch().search(null, A, H, weigher, 1);
     }
 
     @Test(expected = NullPointerException.class)
     public void nullSourceArgument() {
         graphSearch().search(new AdjacencyListsGraph<>(of(B, C),
-                                                       of(new TestEdge(B, C, 1))),
-                             null, H, weight, 1);
+                        of(new TestEdge(B, C))),
+                null, H, weigher, 1);
     }
-
-    @Test
-    public void samenessThreshold() {
-        AbstractGraphPathSearch<TestVertex, TestEdge> search = graphSearch();
-        search.setSamenessThreshold(0.3);
-        assertEquals("incorrect threshold", 0.3, search.samenessThreshold(), 0.01);
-    }
-
 }
diff --git a/utils/misc/src/test/java/org/onlab/graph/AdjacencyListsGraphTest.java b/utils/misc/src/test/java/org/onlab/graph/AdjacencyListsGraphTest.java
index 9089550..f795027 100644
--- a/utils/misc/src/test/java/org/onlab/graph/AdjacencyListsGraphTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/AdjacencyListsGraphTest.java
@@ -37,9 +37,11 @@
     private static final TestVertex G = new TestVertex("G");
 
     private final Set<TestEdge> edges =
-            ImmutableSet.of(new TestEdge(A, B, 1), new TestEdge(B, C, 1),
-                            new TestEdge(C, D, 1), new TestEdge(D, A, 1),
-                            new TestEdge(B, D, 1));
+            ImmutableSet.of(new TestEdge(A, B),
+                            new TestEdge(B, C),
+                            new TestEdge(C, D),
+                            new TestEdge(D, A),
+                            new TestEdge(B, D));
 
     @Test
     public void equality() {
diff --git a/utils/misc/src/test/java/org/onlab/graph/BellmanFordGraphSearchTest.java b/utils/misc/src/test/java/org/onlab/graph/BellmanFordGraphSearchTest.java
index cfa313c..0a36d77 100644
--- a/utils/misc/src/test/java/org/onlab/graph/BellmanFordGraphSearchTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/BellmanFordGraphSearchTest.java
@@ -36,13 +36,13 @@
     @Test
     @Override
     public void defaultGraphTest() {
-        executeDefaultTest(7, 5, 5.0);
+        executeDefaultTest(7, 5, new TestDoubleWeight(5.0));
     }
 
     @Test
     public void defaultHopCountWeight() {
-        weight = null;
-        executeDefaultTest(10, 3, 3.0);
+        weigher = null;
+        executeDefaultTest(10, 3, new ScalarWeight(3.0));
     }
 
     @Test
@@ -51,25 +51,25 @@
         vertexes.add(Z);
 
         Set<TestEdge> edges = new HashSet<>(edges());
-        edges.add(new TestEdge(G, Z, 1.0));
-        edges.add(new TestEdge(Z, G, -2.0));
+        edges.add(new TestEdge(G, Z, new TestDoubleWeight(1.0)));
+        edges.add(new TestEdge(Z, G, new TestDoubleWeight(-2.0)));
 
         graph = new AdjacencyListsGraph<>(vertexes, edges);
 
         GraphPathSearch<TestVertex, TestEdge> search = graphSearch();
-        Set<Path<TestVertex, TestEdge>> paths = search.search(graph, A, H, weight, ALL_PATHS).paths();
+        Set<Path<TestVertex, TestEdge>> paths = search.search(graph, A, H, weigher, ALL_PATHS).paths();
         assertEquals("incorrect paths count", 1, paths.size());
 
         Path p = paths.iterator().next();
         assertEquals("incorrect src", A, p.src());
         assertEquals("incorrect dst", H, p.dst());
         assertEquals("incorrect path length", 5, p.edges().size());
-        assertEquals("incorrect path cost", 5.0, p.cost(), 0.1);
+        assertEquals("incorrect path cost", new TestDoubleWeight(5), p.cost());
 
-        paths = search.search(graph, A, G, weight, ALL_PATHS).paths();
+        paths = search.search(graph, A, G, weigher, ALL_PATHS).paths();
         assertEquals("incorrect paths count", 0, paths.size());
 
-        paths = search.search(graph, A, null, weight, ALL_PATHS).paths();
+        paths = search.search(graph, A, null, weigher, ALL_PATHS).paths();
         printPaths(paths);
         assertEquals("incorrect paths count", 6, paths.size());
     }
diff --git a/utils/misc/src/test/java/org/onlab/graph/BreadthFirstSearchTest.java b/utils/misc/src/test/java/org/onlab/graph/BreadthFirstSearchTest.java
index 3d02dc1..c19268c 100644
--- a/utils/misc/src/test/java/org/onlab/graph/BreadthFirstSearchTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/BreadthFirstSearchTest.java
@@ -34,31 +34,31 @@
 
     @Test
     public void defaultGraphTest() {
-        executeDefaultTest(7, 3, 8.0);
+        executeDefaultTest(7, 3, new TestDoubleWeight(8.0));
     }
 
     @Test
     public void defaultHopCountWeight() {
-        weight = null;
-        executeDefaultTest(7, 3, 3.0);
+        weigher = null;
+        executeDefaultTest(7, 3, new ScalarWeight(3.0));
     }
 
     // Executes the default test
-    protected void executeDefaultTest(int pathCount, int pathLength, double pathCost) {
+    protected void executeDefaultTest(int pathCount, int pathLength, Weight pathCost) {
         graph = new AdjacencyListsGraph<>(vertexes(), edges());
 
         GraphPathSearch<TestVertex, TestEdge> search = graphSearch();
         Set<Path<TestVertex, TestEdge>> paths =
-                search.search(graph, A, H, weight, ALL_PATHS).paths();
+                search.search(graph, A, H, weigher, ALL_PATHS).paths();
         assertEquals("incorrect paths count", 1, paths.size());
 
         Path p = paths.iterator().next();
         assertEquals("incorrect src", A, p.src());
         assertEquals("incorrect dst", H, p.dst());
         assertEquals("incorrect path length", pathLength, p.edges().size());
-        assertEquals("incorrect path cost", pathCost, p.cost(), 0.1);
+        assertEquals("incorrect path cost", pathCost, p.cost());
 
-        paths = search.search(graph, A, null, weight, ALL_PATHS).paths();
+        paths = search.search(graph, A, null, weigher, ALL_PATHS).paths();
         printPaths(paths);
         assertEquals("incorrect paths count", pathCount, paths.size());
     }
@@ -67,16 +67,16 @@
     protected void executeSearch(GraphPathSearch<TestVertex, TestEdge> search,
                                  Graph<TestVertex, TestEdge> graph,
                                  TestVertex src, TestVertex dst,
-                                 EdgeWeight<TestVertex, TestEdge> weight,
-                                 int pathCount, double pathCost) {
+                                 EdgeWeigher<TestVertex, TestEdge> weigher,
+                                 int pathCount, Weight pathCost) {
         GraphPathSearch.Result<TestVertex, TestEdge> result =
-                search.search(graph, src, dst, weight, ALL_PATHS);
+                search.search(graph, src, dst, weigher, ALL_PATHS);
         Set<Path<TestVertex, TestEdge>> paths = result.paths();
         printPaths(paths);
         assertEquals("incorrect paths count", pathCount, paths.size());
         if (pathCount > 0) {
             Path<TestVertex, TestEdge> path = paths.iterator().next();
-            assertEquals("incorrect path cost", pathCost, path.cost(), 0.1);
+            assertEquals("incorrect path cost", pathCost, path.cost());
         }
     }
 
@@ -84,16 +84,16 @@
     protected void executeSinglePathSearch(GraphPathSearch<TestVertex, TestEdge> search,
                                            Graph<TestVertex, TestEdge> graph,
                                            TestVertex src, TestVertex dst,
-                                           EdgeWeight<TestVertex, TestEdge> weight,
-                                           int pathCount, double pathCost) {
+                                           EdgeWeigher<TestVertex, TestEdge> weigher,
+                                           int pathCount, Weight pathCost) {
         GraphPathSearch.Result<TestVertex, TestEdge> result =
-                search.search(graph, src, dst, weight, 1);
+                search.search(graph, src, dst, weigher, 1);
         Set<Path<TestVertex, TestEdge>> paths = result.paths();
         printPaths(paths);
         assertEquals("incorrect paths count", Math.min(pathCount, 1), paths.size());
         if (pathCount > 0) {
             Path<TestVertex, TestEdge> path = paths.iterator().next();
-            assertEquals("incorrect path cost", pathCost, path.cost(), 0.1);
+            assertEquals("incorrect path cost", pathCost, path.cost());
         }
     }
 
diff --git a/utils/misc/src/test/java/org/onlab/graph/DefaultMutablePathTest.java b/utils/misc/src/test/java/org/onlab/graph/DefaultMutablePathTest.java
index 89b7201..d196fa0 100644
--- a/utils/misc/src/test/java/org/onlab/graph/DefaultMutablePathTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/DefaultMutablePathTest.java
@@ -30,11 +30,13 @@
     @Test
     public void equality() {
         DefaultPath<TestVertex, TestEdge> p1 =
-                new DefaultPath<>(of(new TestEdge(A, B, 1),
-                                     new TestEdge(B, C, 1)), 2.0);
+                new DefaultPath<>(of(new TestEdge(A, B),
+                                     new TestEdge(B, C)),
+                        new TestDoubleWeight(2.0));
         DefaultPath<TestVertex, TestEdge> p2 =
-                new DefaultPath<>(of(new TestEdge(A, B, 1),
-                                     new TestEdge(B, D, 1)), 2.0);
+                new DefaultPath<>(of(new TestEdge(A, B),
+                                     new TestEdge(B, D)),
+                        new TestDoubleWeight(2.0));
         new EqualsTester().addEqualityGroup(new DefaultMutablePath<>(p1),
                                             new DefaultMutablePath<>(p1))
                 .addEqualityGroup(new DefaultMutablePath<>(p2))
@@ -47,61 +49,62 @@
         assertNull("src should be null", p.src());
         assertNull("dst should be null", p.dst());
         assertEquals("incorrect edge count", 0, p.edges().size());
-        assertEquals("incorrect path cost", 0.0, p.cost(), 0.1);
+        assertEquals("incorrect path cost", null, p.cost());
     }
 
     @Test
     public void pathCost() {
         MutablePath<TestVertex, TestEdge> p = new DefaultMutablePath<>();
-        p.setCost(4);
-        assertEquals("incorrect path cost", 4.0, p.cost(), 0.1);
+        Weight weight = new TestDoubleWeight(4);
+        p.setCost(weight);
+        assertEquals("incorrect path cost", weight, p.cost());
     }
 
     private void validatePath(Path<TestVertex, TestEdge> p,
                               TestVertex src, TestVertex dst, int length) {
-        validatePath(p, src, dst, length, 0.0);
+        validatePath(p, src, dst, length, null);
     }
 
     @Test
     public void insertEdge() {
         MutablePath<TestVertex, TestEdge> p = new DefaultMutablePath<>();
-        p.insertEdge(new TestEdge(B, C, 1));
-        p.insertEdge(new TestEdge(A, B, 1));
+        p.insertEdge(new TestEdge(B, C));
+        p.insertEdge(new TestEdge(A, B));
         validatePath(p, A, C, 2);
     }
 
     @Test
     public void appendEdge() {
         MutablePath<TestVertex, TestEdge> p = new DefaultMutablePath<>();
-        p.appendEdge(new TestEdge(A, B, 1));
-        p.appendEdge(new TestEdge(B, C, 1));
+        p.appendEdge(new TestEdge(A, B));
+        p.appendEdge(new TestEdge(B, C));
         validatePath(p, A, C, 2);
     }
 
     @Test
     public void removeEdge() {
         MutablePath<TestVertex, TestEdge> p = new DefaultMutablePath<>();
-        p.appendEdge(new TestEdge(A, B, 1));
-        p.appendEdge(new TestEdge(B, C, 1));
-        p.appendEdge(new TestEdge(C, C, 2));
-        p.appendEdge(new TestEdge(C, D, 1));
+        p.appendEdge(new TestEdge(A, B));
+        p.appendEdge(new TestEdge(B, C));
+        p.appendEdge(new TestEdge(C, C));
+        p.appendEdge(new TestEdge(C, D));
         validatePath(p, A, D, 4);
 
-        p.removeEdge(new TestEdge(A, B, 1));
+        p.removeEdge(new TestEdge(A, B));
         validatePath(p, B, D, 3);
 
-        p.removeEdge(new TestEdge(C, C, 2));
+        p.removeEdge(new TestEdge(C, C));
         validatePath(p, B, D, 2);
 
-        p.removeEdge(new TestEdge(C, D, 1));
+        p.removeEdge(new TestEdge(C, D));
         validatePath(p, B, C, 1);
     }
 
     @Test
     public void toImmutable() {
         MutablePath<TestVertex, TestEdge> p = new DefaultMutablePath<>();
-        p.appendEdge(new TestEdge(A, B, 1));
-        p.appendEdge(new TestEdge(B, C, 1));
+        p.appendEdge(new TestEdge(A, B));
+        p.appendEdge(new TestEdge(B, C));
         validatePath(p, A, C, 2);
 
         assertEquals("immutables should equal", p.toImmutable(), p.toImmutable());
diff --git a/utils/misc/src/test/java/org/onlab/graph/DefaultPathTest.java b/utils/misc/src/test/java/org/onlab/graph/DefaultPathTest.java
index bcfe35c..891a768 100644
--- a/utils/misc/src/test/java/org/onlab/graph/DefaultPathTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/DefaultPathTest.java
@@ -30,28 +30,29 @@
 
     @Test
     public void equality() {
-        List<TestEdge> edges = of(new TestEdge(A, B, 1), new TestEdge(B, C, 1));
-        new EqualsTester().addEqualityGroup(new DefaultPath<>(edges, 2.0),
-                                            new DefaultPath<>(edges, 2.0))
-                .addEqualityGroup(new DefaultPath<>(edges, 3.0))
+        List<TestEdge> edges = of(new TestEdge(A, B), new TestEdge(B, C));
+        new EqualsTester().addEqualityGroup(new DefaultPath<>(edges, new TestDoubleWeight(2.0)),
+                                            new DefaultPath<>(edges, new TestDoubleWeight(2.0)))
+                .addEqualityGroup(new DefaultPath<>(edges, new TestDoubleWeight(3.0)))
                 .testEquals();
     }
 
     @Test
     public void basics() {
-        Path<TestVertex, TestEdge> p = new DefaultPath<>(of(new TestEdge(A, B, 1),
-                                                            new TestEdge(B, C, 1)), 2.0);
-        validatePath(p, A, C, 2, 2.0);
+        Path<TestVertex, TestEdge> p = new DefaultPath<>(of(new TestEdge(A, B),
+                                                            new TestEdge(B, C)),
+                new TestDoubleWeight(2.0));
+        validatePath(p, A, C, 2, new TestDoubleWeight(2.0));
     }
 
     // Validates the path against expected attributes
     protected void validatePath(Path<TestVertex, TestEdge> p,
                                 TestVertex src, TestVertex dst,
-                                int length, double cost) {
+                                int length, Weight cost) {
         assertEquals("incorrect path length", length, p.edges().size());
         assertEquals("incorrect source", src, p.src());
         assertEquals("incorrect destination", dst, p.dst());
-        assertEquals("incorrect path cost", cost, p.cost(), 0.1);
+        assertEquals("incorrect path cost", cost, p.cost());
     }
 
 }
diff --git a/utils/misc/src/test/java/org/onlab/graph/DepthFirstSearchTest.java b/utils/misc/src/test/java/org/onlab/graph/DepthFirstSearchTest.java
index e164f7e..e855b33 100644
--- a/utils/misc/src/test/java/org/onlab/graph/DepthFirstSearchTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/DepthFirstSearchTest.java
@@ -36,24 +36,25 @@
 
     @Test
     public void defaultGraphTest() {
-        executeDefaultTest(3, 6, 5.0, 12.0);
+        executeDefaultTest(3, 6, new TestDoubleWeight(5.0), new TestDoubleWeight(12.0));
         executeBroadSearch();
     }
 
     @Test
     public void defaultHopCountWeight() {
-        weight = null;
-        executeDefaultTest(3, 6, 3.0, 6.0);
+        weigher = null;
+        executeDefaultTest(3, 6, new ScalarWeight(3.0), new ScalarWeight(6.0));
         executeBroadSearch();
     }
 
     protected void executeDefaultTest(int minLength, int maxLength,
-                                      double minCost, double maxCost) {
+                                      Weight minCost, Weight maxCost) {
         graph = new AdjacencyListsGraph<>(vertexes(), edges());
         DepthFirstSearch<TestVertex, TestEdge> search = graphSearch();
 
         DepthFirstSearch<TestVertex, TestEdge>.SpanningTreeResult result =
-                search.search(graph, A, H, weight, 1);
+                (DepthFirstSearch<TestVertex, TestEdge>.SpanningTreeResult)
+                        search.search(graph, A, H, weigher, 1);
         Set<Path<TestVertex, TestEdge>> paths = result.paths();
         assertEquals("incorrect path count", 1, paths.size());
 
@@ -66,7 +67,8 @@
         assertTrue("incorrect path length " + l,
                    minLength <= l && l <= maxLength);
         assertTrue("incorrect path cost " + path.cost(),
-                   minCost <= path.cost() && path.cost() <= maxCost);
+                   path.cost().compareTo(minCost) >= 0 &&
+                   path.cost().compareTo(maxCost) <= 0);
 
         System.out.println(result.edges());
         printPaths(paths);
@@ -78,7 +80,8 @@
 
         // Perform narrow path search to a specific destination.
         DepthFirstSearch<TestVertex, TestEdge>.SpanningTreeResult result =
-                search.search(graph, A, null, weight, ALL_PATHS);
+                (DepthFirstSearch<TestVertex, TestEdge>.SpanningTreeResult)
+                        search.search(graph, A, null, weigher, ALL_PATHS);
         assertEquals("incorrect paths count", 7, result.paths().size());
 
         int[] types = new int[]{0, 0, 0, 0};
diff --git a/utils/misc/src/test/java/org/onlab/graph/DijkstraGraphSearchTest.java b/utils/misc/src/test/java/org/onlab/graph/DijkstraGraphSearchTest.java
index f2a19b8..cfd0a4b 100644
--- a/utils/misc/src/test/java/org/onlab/graph/DijkstraGraphSearchTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/DijkstraGraphSearchTest.java
@@ -37,99 +37,105 @@
     @Test
     @Override
     public void defaultGraphTest() {
-        executeDefaultTest(7, 5, 5.0);
+        executeDefaultTest(7, 5, new TestDoubleWeight(5.0));
     }
 
     @Test
     @Override
     public void defaultHopCountWeight() {
-        weight = null;
-        executeDefaultTest(10, 3, 3.0);
+        weigher = null;
+        executeDefaultTest(10, 3, new ScalarWeight(3.0));
     }
 
     @Test
     public void noPath() {
         graph = new AdjacencyListsGraph<>(of(A, B, C, D),
-                                          of(new TestEdge(A, B, 1),
-                                             new TestEdge(B, A, 1),
-                                             new TestEdge(C, D, 1),
-                                             new TestEdge(D, C, 1)));
+                                          of(new TestEdge(A, B, W1),
+                                             new TestEdge(B, A, W1),
+                                             new TestEdge(C, D, W1),
+                                             new TestEdge(D, C, W1)));
         GraphPathSearch<TestVertex, TestEdge> gs = graphSearch();
-        Set<Path<TestVertex, TestEdge>> paths = gs.search(graph, A, B, weight, 1).paths();
+        Set<Path<TestVertex, TestEdge>> paths = gs.search(graph, A, B, weigher, 1).paths();
         printPaths(paths);
         assertEquals("incorrect paths count", 1, paths.size());
-        assertEquals("incorrect path cost", 1.0, paths.iterator().next().cost(), 0.1);
+        assertEquals("incorrect path cost", new TestDoubleWeight(1.0), paths.iterator().next().cost());
 
-        paths = gs.search(graph, A, D, weight, 1).paths();
+        paths = gs.search(graph, A, D, weigher, 1).paths();
         printPaths(paths);
         assertEquals("incorrect paths count", 0, paths.size());
 
-        paths = gs.search(graph, A, null, weight, 1).paths();
+        paths = gs.search(graph, A, null, weigher, 1).paths();
         printPaths(paths);
         assertEquals("incorrect paths count", 1, paths.size());
-        assertEquals("incorrect path cost", 1.0, paths.iterator().next().cost(), 0.1);
+        assertEquals("incorrect path cost", new TestDoubleWeight(1.0), paths.iterator().next().cost());
     }
 
     @Test
     public void simpleMultiplePath() {
         graph = new AdjacencyListsGraph<>(of(A, B, C, D),
-                                          of(new TestEdge(A, B, 1),
-                                             new TestEdge(A, C, 1),
-                                             new TestEdge(B, D, 1),
-                                             new TestEdge(C, D, 1)));
-        executeSearch(graphSearch(), graph, A, D, weight, 2, 2.0);
-        executeSinglePathSearch(graphSearch(), graph, A, D, weight, 1, 2.0);
+                                          of(new TestEdge(A, B, W1),
+                                             new TestEdge(A, C, W1),
+                                             new TestEdge(B, D, W1),
+                                             new TestEdge(C, D, W1)));
+        executeSearch(graphSearch(), graph, A, D, weigher, 2, W2);
+        executeSinglePathSearch(graphSearch(), graph, A, D, weigher, 1, W2);
     }
 
     @Test
     public void denseMultiplePath() {
         graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F, G),
-                                          of(new TestEdge(A, B, 1),
-                                             new TestEdge(A, C, 1),
-                                             new TestEdge(B, D, 1),
-                                             new TestEdge(C, D, 1),
-                                             new TestEdge(D, E, 1),
-                                             new TestEdge(D, F, 1),
-                                             new TestEdge(E, G, 1),
-                                             new TestEdge(F, G, 1),
-                                             new TestEdge(A, G, 4)));
-        executeSearch(graphSearch(), graph, A, G, weight, 5, 4.0);
-        executeSinglePathSearch(graphSearch(), graph, A, G, weight, 1, 4.0);
+                                          of(new TestEdge(A, B, W1),
+                                             new TestEdge(A, C, W1),
+                                             new TestEdge(B, D, W1),
+                                             new TestEdge(C, D, W1),
+                                             new TestEdge(D, E, W1),
+                                             new TestEdge(D, F, W1),
+                                             new TestEdge(E, G, W1),
+                                             new TestEdge(F, G, W1),
+                                             new TestEdge(A, G, W4)));
+        executeSearch(graphSearch(), graph, A, G, weigher, 5, W4);
+        executeSinglePathSearch(graphSearch(), graph, A, G, weigher, 1, W4);
     }
 
     @Test
     public void dualEdgeMultiplePath() {
         graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F, G, H),
-                                          of(new TestEdge(A, B, 1), new TestEdge(A, C, 3),
-                                             new TestEdge(B, D, 2), new TestEdge(B, C, 1),
-                                             new TestEdge(B, E, 4), new TestEdge(C, E, 1),
-                                             new TestEdge(D, H, 5), new TestEdge(D, E, 1),
-                                             new TestEdge(E, F, 1), new TestEdge(F, D, 1),
-                                             new TestEdge(F, G, 1), new TestEdge(F, H, 1),
-                                             new TestEdge(A, E, 3), new TestEdge(B, D, 1)));
-        executeSearch(graphSearch(), graph, A, E, weight, 3, 3.0);
-        executeSinglePathSearch(graphSearch(), graph, A, E, weight, 1, 3.0);
+                                          of(new TestEdge(A, B, W1),
+                                             new TestEdge(A, C, W3),
+                                             new TestEdge(B, D, W2),
+                                             new TestEdge(B, C, W1),
+                                             new TestEdge(B, E, W4),
+                                             new TestEdge(C, E, W1),
+                                             new TestEdge(D, H, W5),
+                                             new TestEdge(D, E, W1),
+                                             new TestEdge(E, F, W1),
+                                             new TestEdge(F, D, W1),
+                                             new TestEdge(F, G, W1),
+                                             new TestEdge(F, H, W1),
+                                             new TestEdge(A, E, W3),
+                                             new TestEdge(B, D, W1)));
+        executeSearch(graphSearch(), graph, A, E, weigher, 3, W3);
+        executeSinglePathSearch(graphSearch(), graph, A, E, weigher, 1, W3);
     }
 
     @Test
     public void negativeWeights() {
         graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F, G),
-                                          of(new TestEdge(A, B, 1),
-                                             new TestEdge(A, C, -1),
-                                             new TestEdge(B, D, 1),
-                                             new TestEdge(D, A, -2),
-                                             new TestEdge(C, D, 1),
-                                             new TestEdge(D, E, 1),
-                                             new TestEdge(D, F, 1),
-                                             new TestEdge(E, G, 1),
-                                             new TestEdge(F, G, 1),
-                                             new TestEdge(G, A, -5),
-                                             new TestEdge(A, G, 4)));
-        executeSearch(graphSearch(), graph, A, G, weight, 3, 4.0);
-        executeSinglePathSearch(graphSearch(), graph, A, G, weight, 1, 4.0);
+                                          of(new TestEdge(A, B, W1),
+                                             new TestEdge(A, C, NW1),
+                                             new TestEdge(B, D, W1),
+                                             new TestEdge(D, A, NW2),
+                                             new TestEdge(C, D, W1),
+                                             new TestEdge(D, E, W1),
+                                             new TestEdge(D, F, W1),
+                                             new TestEdge(E, G, W1),
+                                             new TestEdge(F, G, W1),
+                                             new TestEdge(G, A, NW5),
+                                             new TestEdge(A, G, W4)));
+        executeSearch(graphSearch(), graph, A, G, weigher, 3, new TestDoubleWeight(4.0));
+        executeSinglePathSearch(graphSearch(), graph, A, G, weigher, 1, new TestDoubleWeight(4.0));
     }
 
-    @Test
     public void disconnectedPerf() {
         disconnected();
         disconnected();
@@ -143,8 +149,6 @@
         disconnected();
     }
 
-
-    @Test
     public void disconnected() {
         Set<TestVertex> vertexes = new HashSet<>();
         for (int i = 0; i < 200; i++) {
@@ -155,7 +159,7 @@
 
         long start = System.nanoTime();
         for (TestVertex src : vertexes) {
-            executeSearch(graphSearch(), graph, src, null, null, 0, 0);
+            executeSearch(graphSearch(), graph, src, null, null, 0, new TestDoubleWeight(0));
         }
         long end = System.nanoTime();
         DecimalFormat fmt = new DecimalFormat("#,###");
diff --git a/utils/misc/src/test/java/org/onlab/graph/DisjointPathPairTest.java b/utils/misc/src/test/java/org/onlab/graph/DisjointPathPairTest.java
index b5a415f..4d49048 100644
--- a/utils/misc/src/test/java/org/onlab/graph/DisjointPathPairTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/DisjointPathPairTest.java
@@ -16,6 +16,7 @@
 package org.onlab.graph;
 
 import static org.junit.Assert.*;
+import static org.onlab.graph.GraphTest.W1;
 
 import org.junit.Test;
 
@@ -32,15 +33,15 @@
     private static final TestVertex C = new TestVertex("C");
     private static final TestVertex D = new TestVertex("D");
 
-    private static final TestEdge AB = new TestEdge(A, B, 1.0);
-    private static final TestEdge BC = new TestEdge(B, C, 1.0);
-    private static final TestEdge AD = new TestEdge(A, D, 1.0);
-    private static final TestEdge DC = new TestEdge(D, C, 1.0);
+    private static final TestEdge AB = new TestEdge(A, B);
+    private static final TestEdge BC = new TestEdge(B, C);
+    private static final TestEdge AD = new TestEdge(A, D);
+    private static final TestEdge DC = new TestEdge(D, C);
 
-    private static final Path<TestVertex, TestEdge> ABC
-                            = new DefaultPath<>(ImmutableList.of(AB, BC), 1.0);
-    private static final Path<TestVertex, TestEdge> ADC
-                            = new DefaultPath<>(ImmutableList.of(AD, DC), 1.0);
+    private static final Path<TestVertex, TestEdge> ABC =
+            new DefaultPath<>(ImmutableList.of(AB, BC), W1);
+    private static final Path<TestVertex, TestEdge> ADC =
+            new DefaultPath<>(ImmutableList.of(AD, DC), W1);
 
     @Test
     public void testSwappingPrimarySecondaryDoesntImpactHashCode() {
diff --git a/utils/misc/src/test/java/org/onlab/graph/GraphTest.java b/utils/misc/src/test/java/org/onlab/graph/GraphTest.java
index 6acc986..d860928 100644
--- a/utils/misc/src/test/java/org/onlab/graph/GraphTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/GraphTest.java
@@ -34,14 +34,34 @@
     static final TestVertex H = new TestVertex("H");
     static final TestVertex Z = new TestVertex("Z");
 
+    static final TestDoubleWeight ZW = new TestDoubleWeight(0);
+    static final TestDoubleWeight NW5 = new TestDoubleWeight(-5);
+    static final TestDoubleWeight NW2 = new TestDoubleWeight(-2);
+    static final TestDoubleWeight NW1 = new TestDoubleWeight(-1);
+    static final TestDoubleWeight W1 = new TestDoubleWeight(1);
+    static final TestDoubleWeight W2 = new TestDoubleWeight(2);
+    static final TestDoubleWeight W3 = new TestDoubleWeight(3);
+    static final TestDoubleWeight W4 = new TestDoubleWeight(4);
+    static final TestDoubleWeight W5 = new TestDoubleWeight(5);
+
     protected Graph<TestVertex, TestEdge> graph;
 
-    protected EdgeWeight<TestVertex, TestEdge> weight =
-            new EdgeWeight<TestVertex, TestEdge>() {
+    protected EdgeWeigher<TestVertex, TestEdge> weigher =
+            new EdgeWeigher<TestVertex, TestEdge>() {
                 @Override
-                public double weight(TestEdge edge) {
+                public Weight weight(TestEdge edge) {
                     return edge.weight();
                 }
+
+                @Override
+                public Weight getInitialWeight() {
+                    return ZW;
+                }
+
+                @Override
+                public Weight getNonViableWeight() {
+                    return TestDoubleWeight.NON_VIABLE_WEIGHT;
+                }
             };
 
     protected void printPaths(Set<Path<TestVertex, TestEdge>> paths) {
@@ -55,12 +75,18 @@
     }
 
     protected Set<TestEdge> edges() {
-        return of(new TestEdge(A, B, 1), new TestEdge(A, C, 3),
-                  new TestEdge(B, D, 2), new TestEdge(B, C, 1),
-                  new TestEdge(B, E, 4), new TestEdge(C, E, 1),
-                  new TestEdge(D, H, 5), new TestEdge(D, E, 1),
-                  new TestEdge(E, F, 1), new TestEdge(F, D, 1),
-                  new TestEdge(F, G, 1), new TestEdge(F, H, 1));
+        return of(new TestEdge(A, B, W1),
+                  new TestEdge(A, C, W3),
+                  new TestEdge(B, D, W2),
+                  new TestEdge(B, C, W1),
+                  new TestEdge(B, E, W4),
+                  new TestEdge(C, E, W1),
+                  new TestEdge(D, H, W5),
+                  new TestEdge(D, E, W1),
+                  new TestEdge(E, F, W1),
+                  new TestEdge(F, D, W1),
+                  new TestEdge(F, G, W1),
+                  new TestEdge(F, H, W1));
     }
 
 }
diff --git a/utils/misc/src/test/java/org/onlab/graph/KShortestPathsSearchTest.java b/utils/misc/src/test/java/org/onlab/graph/KShortestPathsSearchTest.java
index 2b7c8d1..ed92be9 100644
--- a/utils/misc/src/test/java/org/onlab/graph/KShortestPathsSearchTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/KShortestPathsSearchTest.java
@@ -41,12 +41,12 @@
     @Test
     public void noPath() {
         graph = new AdjacencyListsGraph<>(of(A, B, C, D),
-                                          of(new TestEdge(A, B, 1),
-                                             new TestEdge(B, A, 1),
-                                             new TestEdge(C, D, 1),
-                                             new TestEdge(D, C, 1)));
+                                          of(new TestEdge(A, B),
+                                             new TestEdge(B, A),
+                                             new TestEdge(C, D),
+                                             new TestEdge(D, C)));
         KShortestPathsSearch<TestVertex, TestEdge> kShortestPathsSearch = new KShortestPathsSearch<>();
-        GraphPathSearch.Result<TestVertex, TestEdge> result = kShortestPathsSearch.search(graph, A, D, weight, 1);
+        GraphPathSearch.Result<TestVertex, TestEdge> result = kShortestPathsSearch.search(graph, A, D, weigher, 1);
         Set<Path<TestVertex, TestEdge>> resultPathSet = result.paths();
         assertTrue("There should not be any paths.", resultPathSet.isEmpty());
     }
@@ -55,11 +55,11 @@
     public void testSinglePath() {
         //Tests that there is only a single path possible between A and B
         graph = new AdjacencyListsGraph<>(vertexes(), edges());
-        this.result = kShortestPathsSearch.search(graph, A, B, weight, 2);
+        this.result = kShortestPathsSearch.search(graph, A, B, weigher, 2);
         Iterator<Path<TestVertex, TestEdge>> itr = result.paths().iterator();
         assertEquals("incorrect paths count", 1, result.paths().size());
         List<TestEdge> correctEdgeList = Lists.newArrayList();
-        correctEdgeList.add(new TestEdge(A, B, 1));
+        correctEdgeList.add(new TestEdge(A, B, W1));
         assertTrue("That wrong path was returned.",
                    edgeListsAreEqual(correctEdgeList, result.paths().iterator().next().edges()));
     }
@@ -67,16 +67,16 @@
     @Test
     public void testTwoPath() {
         //Tests that there are only two paths between A and C and that they are returned in the correct order
-        result = kShortestPathsSearch.search(graph, A, C, weight, 3);
+        result = kShortestPathsSearch.search(graph, A, C, weigher, 3);
         assertTrue("There are an unexpected number of paths.", result.paths().size() == 2);
         Iterator<Path<TestVertex, TestEdge>> edgeListIterator = result.paths().iterator();
         List<TestEdge> correctEdgeList = Lists.newArrayList();
-        correctEdgeList.add(new TestEdge(A, B, 1));
-        correctEdgeList.add(new TestEdge(B, C, 1));
+        correctEdgeList.add(new TestEdge(A, B, W1));
+        correctEdgeList.add(new TestEdge(B, C, W1));
         assertTrue("The first path from A to C was incorrect.",
                    edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
         correctEdgeList.clear();
-        correctEdgeList.add(new TestEdge(A, C, 3));
+        correctEdgeList.add(new TestEdge(A, C, W3));
         assertTrue("The second path from A to C was incorrect.",
                    edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
     }
@@ -85,23 +85,23 @@
     public void testFourPath() {
         //Tests that there are only four paths between A and E and that they are returned in the correct order
         //Also tests the special case where some correct solutions are equal
-        result = kShortestPathsSearch.search(graph, A, E, weight, 5);
+        result = kShortestPathsSearch.search(graph, A, E, weigher, 5);
         assertTrue("There are an unexpected number of paths.", result.paths().size() == 4);
         Iterator<Path<TestVertex, TestEdge>> edgeListIterator = result.paths().iterator();
         List<TestEdge> correctEdgeList = Lists.newArrayList();
-        correctEdgeList.add(new TestEdge(A, B, 1));
-        correctEdgeList.add(new TestEdge(B, C, 1));
-        correctEdgeList.add(new TestEdge(C, E, 1));
+        correctEdgeList.add(new TestEdge(A, B, W1));
+        correctEdgeList.add(new TestEdge(B, C, W1));
+        correctEdgeList.add(new TestEdge(C, E, W1));
         assertTrue("The first path from A to E was incorrect.",
                    edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
         correctEdgeList.clear();
         //There are two paths of equal length that should hold positions two and three
         List<TestEdge> alternateCorrectEdgeList = Lists.newArrayList();
-        correctEdgeList.add(new TestEdge(A, C, 3));
-        correctEdgeList.add(new TestEdge(C, E, 1));
-        alternateCorrectEdgeList.add(new TestEdge(A, B, 1));
-        alternateCorrectEdgeList.add(new TestEdge(B, D, 2));
-        alternateCorrectEdgeList.add(new TestEdge(D, E, 1));
+        correctEdgeList.add(new TestEdge(A, C, W3));
+        correctEdgeList.add(new TestEdge(C, E, W1));
+        alternateCorrectEdgeList.add(new TestEdge(A, B, W1));
+        alternateCorrectEdgeList.add(new TestEdge(B, D, W2));
+        alternateCorrectEdgeList.add(new TestEdge(D, E, W1));
         List<TestEdge> candidateOne = edgeListIterator.next().edges();
         List<TestEdge> candidateTwo = edgeListIterator.next().edges();
         if (candidateOne.size() == 2) {
@@ -116,8 +116,8 @@
                        edgeListsAreEqual(candidateTwo, correctEdgeList));
         }
         correctEdgeList.clear();
-        correctEdgeList.add(new TestEdge(A, B, 1));
-        correctEdgeList.add(new TestEdge(B, E, 4));
+        correctEdgeList.add(new TestEdge(A, B, W1));
+        correctEdgeList.add(new TestEdge(B, E, W4));
         assertTrue("The fourth path rom A to E was incorrect",
                    edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
 
@@ -128,16 +128,16 @@
         //H is a sink in this topology, insure there are no paths from it to any other location
         for (TestVertex vertex : vertexes()) {
             assertTrue("There should be no paths from vertex H to any other node.",
-                       kShortestPathsSearch.search(graph, H, vertex, weight, 1).paths().size() == 0);
+                       kShortestPathsSearch.search(graph, H, vertex, weigher, 1).paths().size() == 0);
         }
     }
 
     @Test
     public void testLimitPathSetSize() {
         //Checks to make sure that no more than K paths are returned
-        result = kShortestPathsSearch.search(graph, A, E, weight, 3);
+        result = kShortestPathsSearch.search(graph, A, E, weigher, 3);
         assertTrue("There are an unexpected number of paths.", result.paths().size() == 3);
-        result = kShortestPathsSearch.search(graph, A, G, weight, 1);
+        result = kShortestPathsSearch.search(graph, A, G, weigher, 1);
         assertTrue("There are an unexpected number of paths.", result.paths().size() == 1);
     }
 
@@ -157,47 +157,45 @@
          * +---+       +---+ +---+  +---+
          */
         graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F, G, H), of(
-                new TestEdge(A, B, 1),
-                new TestEdge(B, A, 1),
-                new TestEdge(B, C, 1),
-                new TestEdge(C, B, 1),
-                new TestEdge(C, D, 1),
-                new TestEdge(D, C, 1),
-                new TestEdge(D, E, 1),
-                new TestEdge(E, D, 1),
-                new TestEdge(E, H, 1),
-                new TestEdge(H, E, 1),
-                new TestEdge(H, G, 1),
-                new TestEdge(G, H, 1),
-                new TestEdge(G, F, 1),
-                new TestEdge(F, G, 1),
-                new TestEdge(F, B, 1),
-                new TestEdge(B, F, 1)
+                new TestEdge(A, B),
+                new TestEdge(B, A),
+                new TestEdge(B, C),
+                new TestEdge(C, B),
+                new TestEdge(C, D),
+                new TestEdge(D, C),
+                new TestEdge(D, E),
+                new TestEdge(E, D),
+                new TestEdge(E, H),
+                new TestEdge(H, E),
+                new TestEdge(H, G),
+                new TestEdge(G, H),
+                new TestEdge(G, F),
+                new TestEdge(F, G),
+                new TestEdge(F, B),
+                new TestEdge(B, F)
         ));
 
-        weight = edge -> 1.0;
-
         //Tests that there are only two paths between A and G and that they are returned in the correct order
-        result = kShortestPathsSearch.search(graph, A, G, weight, 5);
+        result = kShortestPathsSearch.search(graph, A, G, weigher, 5);
 
         assertEquals("There are an unexpected number of paths.", 2, result.paths().size());
 
         Iterator<Path<TestVertex, TestEdge>> edgeListIterator = result.paths().iterator();
 
         List<TestEdge> correctEdgeList = Lists.newArrayList();
-        correctEdgeList.add(new TestEdge(A, B, 1));
-        correctEdgeList.add(new TestEdge(B, F, 1));
-        correctEdgeList.add(new TestEdge(F, G, 1));
+        correctEdgeList.add(new TestEdge(A, B));
+        correctEdgeList.add(new TestEdge(B, F));
+        correctEdgeList.add(new TestEdge(F, G));
         assertTrue("The first path from A to G was incorrect.",
                 edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
 
         correctEdgeList.clear();
-        correctEdgeList.add(new TestEdge(A, B, 1));
-        correctEdgeList.add(new TestEdge(B, C, 1));
-        correctEdgeList.add(new TestEdge(C, D, 1));
-        correctEdgeList.add(new TestEdge(D, E, 1));
-        correctEdgeList.add(new TestEdge(E, H, 1));
-        correctEdgeList.add(new TestEdge(H, G, 1));
+        correctEdgeList.add(new TestEdge(A, B));
+        correctEdgeList.add(new TestEdge(B, C));
+        correctEdgeList.add(new TestEdge(C, D));
+        correctEdgeList.add(new TestEdge(D, E));
+        correctEdgeList.add(new TestEdge(E, H));
+        correctEdgeList.add(new TestEdge(H, G));
         assertTrue("The second path from A to G was incorrect.",
                 edgeListsAreEqual(edgeListIterator.next().edges(), correctEdgeList));
     }
diff --git a/utils/misc/src/test/java/org/onlab/graph/SrlgGraphSearchTest.java b/utils/misc/src/test/java/org/onlab/graph/SrlgGraphSearchTest.java
index 98b014c..07e4d05 100644
--- a/utils/misc/src/test/java/org/onlab/graph/SrlgGraphSearchTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/SrlgGraphSearchTest.java
@@ -39,7 +39,7 @@
     }
 
     public void setDefaultWeights() {
-        weight = null;
+        weigher = null;
     }
 
     @Override
@@ -53,10 +53,10 @@
     @Test
     public void onePathPair() {
         setDefaultWeights();
-        TestEdge aB = new TestEdge(A, B, 1);
-        TestEdge bC = new TestEdge(B, C, 1);
-        TestEdge aD = new TestEdge(A, D, 1);
-        TestEdge dC = new TestEdge(D, C, 1);
+        TestEdge aB = new TestEdge(A, B);
+        TestEdge bC = new TestEdge(B, C);
+        TestEdge aD = new TestEdge(A, D);
+        TestEdge dC = new TestEdge(D, C);
         Graph<TestVertex, TestEdge> graph = new AdjacencyListsGraph<>(of(A, B, C, D),
                                                                       of(aB, bC, aD, dC));
         Map<TestEdge, Integer> riskProfile = new HashMap<>();
@@ -65,7 +65,7 @@
         riskProfile.put(aD, 1);
         riskProfile.put(dC, 1);
         SrlgGraphSearch<TestVertex, TestEdge> search = new SrlgGraphSearch<>(2, riskProfile);
-        Set<Path<TestVertex, TestEdge>> paths = search.search(graph, A, C, weight, ALL_PATHS).paths();
+        Set<Path<TestVertex, TestEdge>> paths = search.search(graph, A, C, weigher, ALL_PATHS).paths();
         System.out.println("\n\n\n" + paths + "\n\n\n");
         assertEquals("one disjoint path pair found", 1, paths.size());
         checkIsDisjoint(paths.iterator().next(), riskProfile);
@@ -90,12 +90,12 @@
     @Test
     public void complexGraphTest() {
         setDefaultWeights();
-        TestEdge aB = new TestEdge(A, B, 1);
-        TestEdge bC = new TestEdge(B, C, 1);
-        TestEdge aD = new TestEdge(A, D, 1);
-        TestEdge dC = new TestEdge(D, C, 1);
-        TestEdge cE = new TestEdge(C, E, 1);
-        TestEdge bE = new TestEdge(B, E, 1);
+        TestEdge aB = new TestEdge(A, B);
+        TestEdge bC = new TestEdge(B, C);
+        TestEdge aD = new TestEdge(A, D);
+        TestEdge dC = new TestEdge(D, C);
+        TestEdge cE = new TestEdge(C, E);
+        TestEdge bE = new TestEdge(B, E);
         Graph<TestVertex, TestEdge> graph = new AdjacencyListsGraph<>(of(A, B, C, D, E),
                                                                       of(aB, bC, aD, dC, cE, bE));
         Map<TestEdge, Integer> riskProfile = new HashMap<>();
@@ -106,18 +106,18 @@
         riskProfile.put(cE, 2);
         riskProfile.put(bE, 3);
         SrlgGraphSearch<TestVertex, TestEdge> search = new SrlgGraphSearch<>(4, riskProfile);
-        search.search(graph, A, E, weight, ALL_PATHS).paths();
+        search.search(graph, A, E, weigher, ALL_PATHS).paths();
     }
 
     @Test
     public void multiplePathGraphTest() {
         setDefaultWeights();
-        TestEdge aB = new TestEdge(A, B, 1);
-        TestEdge bE = new TestEdge(B, E, 1);
-        TestEdge aD = new TestEdge(A, D, 1);
-        TestEdge dE = new TestEdge(D, E, 1);
-        TestEdge aC = new TestEdge(A, C, 1);
-        TestEdge cE = new TestEdge(C, E, 1);
+        TestEdge aB = new TestEdge(A, B);
+        TestEdge bE = new TestEdge(B, E);
+        TestEdge aD = new TestEdge(A, D);
+        TestEdge dE = new TestEdge(D, E);
+        TestEdge aC = new TestEdge(A, C);
+        TestEdge cE = new TestEdge(C, E);
         Graph<TestVertex, TestEdge> graph = new AdjacencyListsGraph<>(of(A, B, C, D, E),
                                                                       of(aB, bE, aD, dE, aC, cE));
         Map<TestEdge, Integer> riskProfile = new HashMap<>();
@@ -128,7 +128,7 @@
         riskProfile.put(aC, 4);
         riskProfile.put(cE, 5);
         SrlgGraphSearch<TestVertex, TestEdge> search = new SrlgGraphSearch<>(6, riskProfile);
-        Set<Path<TestVertex, TestEdge>> paths = search.search(graph, A, E, weight, ALL_PATHS).paths();
+        Set<Path<TestVertex, TestEdge>> paths = search.search(graph, A, E, weigher, ALL_PATHS).paths();
         assertTrue("> one disjoint path pair found", paths.size() >= 1);
         checkIsDisjoint(paths.iterator().next(), riskProfile);
     }
@@ -136,10 +136,10 @@
     @Test
     public void onePath() {
         setDefaultWeights();
-        TestEdge aB = new TestEdge(A, B, 1);
-        TestEdge bC = new TestEdge(B, C, 1);
-        TestEdge aD = new TestEdge(A, D, 1);
-        TestEdge dC = new TestEdge(D, C, 1);
+        TestEdge aB = new TestEdge(A, B);
+        TestEdge bC = new TestEdge(B, C);
+        TestEdge aD = new TestEdge(A, D);
+        TestEdge dC = new TestEdge(D, C);
         Graph<TestVertex, TestEdge> graph = new AdjacencyListsGraph<>(of(A, B, C, D),
                                                                       of(aB, bC, aD, dC));
         Map<TestEdge, Integer> riskProfile = new HashMap<>();
@@ -148,7 +148,7 @@
         riskProfile.put(aD, 1);
         riskProfile.put(dC, 0);
         SrlgGraphSearch<TestVertex, TestEdge> search = new SrlgGraphSearch<>(2, riskProfile);
-        Set<Path<TestVertex, TestEdge>> paths = search.search(graph, A, C, weight, ALL_PATHS).paths();
+        Set<Path<TestVertex, TestEdge>> paths = search.search(graph, A, C, weigher, ALL_PATHS).paths();
         System.out.println(paths);
         assertTrue("no disjoint path pairs found", paths.size() == 0);
     }
@@ -156,10 +156,10 @@
     @Test
     public void noPath() {
         setDefaultWeights();
-        TestEdge aB = new TestEdge(A, B, 1);
-        TestEdge bC = new TestEdge(B, C, 1);
-        TestEdge aD = new TestEdge(A, D, 1);
-        TestEdge dC = new TestEdge(D, C, 1);
+        TestEdge aB = new TestEdge(A, B);
+        TestEdge bC = new TestEdge(B, C);
+        TestEdge aD = new TestEdge(A, D);
+        TestEdge dC = new TestEdge(D, C);
         Graph<TestVertex, TestEdge> graph = new AdjacencyListsGraph<>(of(A, B, C, D, E),
                                                                       of(aB, bC, aD, dC));
         Map<TestEdge, Integer> riskProfile = new HashMap<>();
@@ -168,7 +168,7 @@
         riskProfile.put(aD, 1);
         riskProfile.put(dC, 0);
         SrlgGraphSearch<TestVertex, TestEdge> search = new SrlgGraphSearch<>(2, riskProfile);
-        Set<Path<TestVertex, TestEdge>> paths = search.search(graph, A, E, weight, ALL_PATHS).paths();
+        Set<Path<TestVertex, TestEdge>> paths = search.search(graph, A, E, weigher, ALL_PATHS).paths();
         assertTrue("no disjoint path pairs found", paths.size() == 0);
     }
 }
diff --git a/utils/misc/src/test/java/org/onlab/graph/SuurballeGraphSearchTest.java b/utils/misc/src/test/java/org/onlab/graph/SuurballeGraphSearchTest.java
index a86546a..5d0a032 100644
--- a/utils/misc/src/test/java/org/onlab/graph/SuurballeGraphSearchTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/SuurballeGraphSearchTest.java
@@ -34,17 +34,6 @@
         return new SuurballeGraphSearch<>();
     }
 
-    public void setWeights() {
-        weight = new EdgeWeight<TestVertex, TestEdge>() {
-            @Override
-            public double weight(TestEdge edge) {
-                return edge.weight();
-            }
-        };
-    }
-    public void setDefaultWeights() {
-        weight = null;
-    }
     @Override
     public void defaultGraphTest() {
 
@@ -57,41 +46,38 @@
 
     @Test
     public void basicGraphTest() {
-        setDefaultWeights();
         Graph<TestVertex, TestEdge> graph = new AdjacencyListsGraph<>(of(A, B, C, D),
-                                                                      of(new TestEdge(A, B, 1),
-                                                                         new TestEdge(B, C, 1),
-                                                                         new TestEdge(A, D, 1),
-                                                                         new TestEdge(D, C, 1)));
-        executeSearch(graphSearch(), graph, A, C, weight, 1, 4.0);
+                                                                      of(new TestEdge(A, B),
+                                                                         new TestEdge(B, C),
+                                                                         new TestEdge(A, D),
+                                                                         new TestEdge(D, C)));
+        executeSearch(graphSearch(), graph, A, C, null, 1, new ScalarWeight(4.0));
     }
 
     @Test
     public void multiplePathOnePairGraphTest() {
-        setWeights();
         Graph<TestVertex, TestEdge> graph = new AdjacencyListsGraph<>(of(A, B, C, D, E),
-                                                                      of(new TestEdge(A, B, 1),
-                                                                         new TestEdge(B, C, 1),
-                                                                         new TestEdge(A, D, 1),
-                                                                         new TestEdge(D, C, 1),
-                                                                         new TestEdge(B, E, 2),
-                                                                         new TestEdge(C, E, 1)));
-        executeSearch(graphSearch(), graph, A, E, weight, 1, 6.0);
+                                                                      of(new TestEdge(A, B, W1),
+                                                                         new TestEdge(B, C, W1),
+                                                                         new TestEdge(A, D, W1),
+                                                                         new TestEdge(D, C, W1),
+                                                                         new TestEdge(B, E, W2),
+                                                                         new TestEdge(C, E, W1)));
+        executeSearch(graphSearch(), graph, A, E, weigher, 1, new TestDoubleWeight(6.0));
     }
 
     @Test
     public void multiplePathsMultiplePairs() {
-        setWeights();
         Graph<TestVertex, TestEdge> graph = new AdjacencyListsGraph<>(of(A, B, C, D, E),
-                                                                      of(new TestEdge(A, B, 1),
-                                                                         new TestEdge(B, E, 1),
-                                                                         new TestEdge(A, C, 1),
-                                                                         new TestEdge(C, E, 1),
-                                                                         new TestEdge(A, D, 1),
-                                                                         new TestEdge(D, E, 1),
-                                                                         new TestEdge(A, E, 2)));
+                                                                      of(new TestEdge(A, B, W1),
+                                                                         new TestEdge(B, E, W1),
+                                                                         new TestEdge(A, C, W1),
+                                                                         new TestEdge(C, E, W1),
+                                                                         new TestEdge(A, D, W1),
+                                                                         new TestEdge(D, E, W1),
+                                                                         new TestEdge(A, E, W2)));
         GraphPathSearch.Result<TestVertex, TestEdge> result =
-                graphSearch().search(graph, A, E, weight, GraphPathSearch.ALL_PATHS);
+                graphSearch().search(graph, A, E, weigher, GraphPathSearch.ALL_PATHS);
         Set<Path<TestVertex, TestEdge>> paths = result.paths();
         System.out.println("\n\n" + paths + "\n\n\ndone\n");
         assertEquals("incorrect paths count", 3, paths.size());
@@ -101,27 +87,25 @@
 
     @Test
     public void differingPrimaryAndBackupPathLengths() {
-        setWeights();
         Graph<TestVertex, TestEdge> graph = new AdjacencyListsGraph<>(of(A, B, C, D, E),
-                                                                      of(new TestEdge(A, B, 1),
-                                                                         new TestEdge(B, C, 1),
-                                                                         new TestEdge(A, D, 1),
-                                                                         new TestEdge(D, C, 1),
-                                                                         new TestEdge(B, E, 1),
-                                                                         new TestEdge(C, E, 1)));
-        executeSearch(graphSearch(), graph, A, E, weight, 1, 5.0);
+                                                                      of(new TestEdge(A, B),
+                                                                         new TestEdge(B, C),
+                                                                         new TestEdge(A, D),
+                                                                         new TestEdge(D, C),
+                                                                         new TestEdge(B, E),
+                                                                         new TestEdge(C, E)));
+        executeSearch(graphSearch(), graph, A, E, weigher, 1, new TestDoubleWeight(5.0));
     }
 
     @Test
     public void onePath() {
-        setWeights();
         Graph<TestVertex, TestEdge> graph = new AdjacencyListsGraph<>(of(A, B, C, D),
-                                                                      of(new TestEdge(A, B, 1),
-                                                                         new TestEdge(B, C, 1),
-                                                                         new TestEdge(A, C, 4),
-                                                                         new TestEdge(C, D, 1)));
+                                                                      of(new TestEdge(A, B, W1),
+                                                                         new TestEdge(B, C, W1),
+                                                                         new TestEdge(A, C, W4),
+                                                                         new TestEdge(C, D, W1)));
         GraphPathSearch.Result<TestVertex, TestEdge> result =
-                graphSearch().search(graph, A, D, weight, GraphPathSearch.ALL_PATHS);
+                graphSearch().search(graph, A, D, weigher, GraphPathSearch.ALL_PATHS);
         Set<Path<TestVertex, TestEdge>> paths = result.paths();
         assertEquals("incorrect paths count", 1, paths.size());
         DisjointPathPair<TestVertex, TestEdge> dpp = (DisjointPathPair<TestVertex, TestEdge>) paths.iterator().next();
@@ -130,24 +114,22 @@
 
     @Test
     public void noPath() {
-        setWeights();
         Graph<TestVertex, TestEdge> graph = new AdjacencyListsGraph<>(of(A, B, C, D),
-                                                                      of(new TestEdge(A, B, 1),
-                                                                         new TestEdge(B, C, 1),
-                                                                         new TestEdge(A, C, 4)));
+                                                                      of(new TestEdge(A, B, W1),
+                                                                         new TestEdge(B, C, W1),
+                                                                         new TestEdge(A, C, W4)));
         GraphPathSearch.Result<TestVertex, TestEdge> result =
-                graphSearch().search(graph, A, D, weight, GraphPathSearch.ALL_PATHS);
+                graphSearch().search(graph, A, D, weigher, GraphPathSearch.ALL_PATHS);
         Set<Path<TestVertex, TestEdge>> paths = result.paths();
         assertEquals("incorrect paths count", paths.size(), 0);
     }
 
     @Test
     public void disconnected() {
-        setWeights();
         Graph<TestVertex, TestEdge> graph = new AdjacencyListsGraph<>(of(A, B, C, D),
                                                                       of());
         GraphPathSearch.Result<TestVertex, TestEdge> result =
-                graphSearch().search(graph, A, D, weight, GraphPathSearch.ALL_PATHS);
+                graphSearch().search(graph, A, D, weigher, GraphPathSearch.ALL_PATHS);
         Set<Path<TestVertex, TestEdge>> paths = result.paths();
         assertEquals("incorrect paths count", 0, paths.size());
     }
diff --git a/utils/misc/src/test/java/org/onlab/graph/TarjanGraphSearchTest.java b/utils/misc/src/test/java/org/onlab/graph/TarjanGraphSearchTest.java
index 2b6dec0..a3f47f5 100644
--- a/utils/misc/src/test/java/org/onlab/graph/TarjanGraphSearchTest.java
+++ b/utils/misc/src/test/java/org/onlab/graph/TarjanGraphSearchTest.java
@@ -49,14 +49,14 @@
     @Test
     public void singleCluster() {
         graph = new AdjacencyListsGraph<>(vertexes(),
-                                          of(new TestEdge(A, B, 1),
-                                             new TestEdge(B, C, 1),
-                                             new TestEdge(C, D, 1),
-                                             new TestEdge(D, E, 1),
-                                             new TestEdge(E, F, 1),
-                                             new TestEdge(F, G, 1),
-                                             new TestEdge(G, H, 1),
-                                             new TestEdge(H, A, 1)));
+                                          of(new TestEdge(A, B),
+                                             new TestEdge(B, C),
+                                             new TestEdge(C, D),
+                                             new TestEdge(D, E),
+                                             new TestEdge(E, F),
+                                             new TestEdge(F, G),
+                                             new TestEdge(G, H),
+                                             new TestEdge(H, A)));
 
         TarjanGraphSearch<TestVertex, TestEdge> gs = new TarjanGraphSearch<>();
         SccResult<TestVertex, TestEdge> result = gs.search(graph, null);
@@ -67,14 +67,14 @@
     @Test
     public void twoUnconnectedCluster() {
         graph = new AdjacencyListsGraph<>(vertexes(),
-                                          of(new TestEdge(A, B, 1),
-                                             new TestEdge(B, C, 1),
-                                             new TestEdge(C, D, 1),
-                                             new TestEdge(D, A, 1),
-                                             new TestEdge(E, F, 1),
-                                             new TestEdge(F, G, 1),
-                                             new TestEdge(G, H, 1),
-                                             new TestEdge(H, E, 1)));
+                                          of(new TestEdge(A, B),
+                                             new TestEdge(B, C),
+                                             new TestEdge(C, D),
+                                             new TestEdge(D, A),
+                                             new TestEdge(E, F),
+                                             new TestEdge(F, G),
+                                             new TestEdge(G, H),
+                                             new TestEdge(H, E)));
         TarjanGraphSearch<TestVertex, TestEdge> gs = new TarjanGraphSearch<>();
         SccResult<TestVertex, TestEdge> result = gs.search(graph, null);
         validate(result, 2);
@@ -85,15 +85,15 @@
     @Test
     public void twoWeaklyConnectedClusters() {
         graph = new AdjacencyListsGraph<>(vertexes(),
-                                          of(new TestEdge(A, B, 1),
-                                             new TestEdge(B, C, 1),
-                                             new TestEdge(C, D, 1),
-                                             new TestEdge(D, A, 1),
-                                             new TestEdge(E, F, 1),
-                                             new TestEdge(F, G, 1),
-                                             new TestEdge(G, H, 1),
-                                             new TestEdge(H, E, 1),
-                                             new TestEdge(B, E, 1)));
+                                          of(new TestEdge(A, B),
+                                             new TestEdge(B, C),
+                                             new TestEdge(C, D),
+                                             new TestEdge(D, A),
+                                             new TestEdge(E, F),
+                                             new TestEdge(F, G),
+                                             new TestEdge(G, H),
+                                             new TestEdge(H, E),
+                                             new TestEdge(B, E)));
         TarjanGraphSearch<TestVertex, TestEdge> gs = new TarjanGraphSearch<>();
         SccResult<TestVertex, TestEdge> result = gs.search(graph, null);
         validate(result, 2);
@@ -104,19 +104,21 @@
     @Test
     public void twoClustersConnectedWithIgnoredEdges() {
         graph = new AdjacencyListsGraph<>(vertexes(),
-                                          of(new TestEdge(A, B, 1),
-                                             new TestEdge(B, C, 1),
-                                             new TestEdge(C, D, 1),
-                                             new TestEdge(D, A, 1),
-                                             new TestEdge(E, F, 1),
-                                             new TestEdge(F, G, 1),
-                                             new TestEdge(G, H, 1),
-                                             new TestEdge(H, E, 1),
-                                             new TestEdge(B, E, -1),
-                                             new TestEdge(E, B, -1)));
+                                          of(new TestEdge(A, B),
+                                             new TestEdge(B, C),
+                                             new TestEdge(C, D),
+                                             new TestEdge(D, A),
+                                             new TestEdge(E, F),
+                                             new TestEdge(F, G),
+                                             new TestEdge(G, H),
+                                             new TestEdge(H, E),
+                                             new TestEdge(B, E,
+                                                     weigher.getNonViableWeight()),
+                                             new TestEdge(E, B,
+                                                     weigher.getNonViableWeight())));
 
         TarjanGraphSearch<TestVertex, TestEdge> gs = new TarjanGraphSearch<>();
-        SccResult<TestVertex, TestEdge> result = gs.search(graph, weight);
+        SccResult<TestVertex, TestEdge> result = gs.search(graph, weigher);
         validate(result, 2);
         validate(result, 0, 4, 4);
         validate(result, 1, 4, 4);
diff --git a/utils/misc/src/test/java/org/onlab/graph/TestDoubleWeight.java b/utils/misc/src/test/java/org/onlab/graph/TestDoubleWeight.java
new file mode 100644
index 0000000..54f9f17
--- /dev/null
+++ b/utils/misc/src/test/java/org/onlab/graph/TestDoubleWeight.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onlab.graph;
+
+import com.google.common.math.DoubleMath;
+
+import java.util.Objects;
+
+/**
+ * Test weight (based on double).
+ */
+public class TestDoubleWeight implements Weight {
+
+    /**
+     * Instance of negative test weight.
+     */
+    public static final TestDoubleWeight NEGATIVE_WEIGHT = new TestDoubleWeight(-1);
+
+    /**
+     * Instance of test weight to mark links/paths which
+     * can not be traversed.
+     */
+    public static final TestDoubleWeight NON_VIABLE_WEIGHT =
+            new TestDoubleWeight(Double.POSITIVE_INFINITY);
+
+    private final double value;
+
+    /**
+     * Creates a new test weight with the given double value.
+     * @param value double weight
+     */
+    public TestDoubleWeight(double value) {
+        this.value = value;
+    }
+
+    @Override
+    public Weight merge(Weight otherWeight) {
+        return new TestDoubleWeight(value + ((TestDoubleWeight) otherWeight).value);
+    }
+
+    @Override
+    public Weight subtract(Weight otherWeight) {
+        return new TestDoubleWeight(value - ((TestDoubleWeight) otherWeight).value);
+    }
+
+    @Override
+    public boolean isViable() {
+        return this != NON_VIABLE_WEIGHT;
+    }
+
+    @Override
+    public int compareTo(Weight otherWeight) {
+        return Double.compare(value, ((TestDoubleWeight) otherWeight).value);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return (DoubleMath.fuzzyEquals(value, ((TestDoubleWeight) obj).value, 0.1));
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(value);
+    }
+
+    @Override
+    public boolean isNegative() {
+        return value < 0;
+    }
+}
diff --git a/utils/misc/src/test/java/org/onlab/graph/TestEdge.java b/utils/misc/src/test/java/org/onlab/graph/TestEdge.java
index 7b48767..874b5eb 100644
--- a/utils/misc/src/test/java/org/onlab/graph/TestEdge.java
+++ b/utils/misc/src/test/java/org/onlab/graph/TestEdge.java
@@ -18,32 +18,45 @@
 import java.util.Objects;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
+import static org.onlab.graph.GraphTest.W1;
 
 /**
  * Test edge.
  */
 public class TestEdge extends AbstractEdge<TestVertex> {
 
-    private final double weight;
+    private final Weight weight;
 
     /**
-     * Creates a new edge between the specified source and destination vertexes.
+     * Creates a new edge between the specified source and destination vertexes
+     * with the given weight.
      *
      * @param src    source vertex
      * @param dst    destination vertex
      * @param weight edge weight
      */
-    public TestEdge(TestVertex src, TestVertex dst, double weight) {
+    public TestEdge(TestVertex src, TestVertex dst, Weight weight) {
         super(src, dst);
         this.weight = weight;
     }
 
     /**
+     * Creates a new edge between the specified source and destination vertexes
+     * with the default weight.
+     *
+     * @param src source vertex
+     * @param dst destination vertext
+     */
+    public TestEdge(TestVertex src, TestVertex dst) {
+        this(src, dst, W1);
+    }
+
+    /**
      * Returns the edge weight.
      *
      * @return edge weight
      */
-    public double weight() {
+    public Weight weight() {
         return weight;
     }