Skip to content

Commit

Permalink
Merge pull request #3730 from marecabo/clean-disallowednextlinks
Browse files Browse the repository at this point in the history
Add cleaning method for DisallowedNextLinks
  • Loading branch information
marecabo authored Feb 14, 2025
2 parents 9402f16 + ac479e1 commit fa2c3e2
Show file tree
Hide file tree
Showing 2 changed files with 289 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,68 @@ public static boolean isValid(Network network) {
return errors.isEmpty();
}

/**
* Remove link sequences of DisallowedNextLinks which contain missing links or
* wrong modes.
*
* @param network
*/
public static void clean(Network network) {
Map<Id<Link>, ? extends Link> links = network.getLinks();

links.values().forEach(link -> {

DisallowedNextLinks dnl = NetworkUtils.getDisallowedNextLinks(link);
if (dnl == null) {
return;
}

// remove link sequences for modes, that are not allowed on this link
for (Entry<String, List<List<Id<Link>>>> entry : dnl.getAsMap().entrySet()) {
final String mode = entry.getKey();
final int linkSequencesCount = entry.getValue().size();

if (!link.getAllowedModes().contains(mode)) {
dnl.removeDisallowedLinkSequences(mode);
LOG.info("Link {}: Removed all {} disallowed next link sequences of mode {}"
+ " because {} is not allowed", link.getId(), linkSequencesCount, mode, mode);
}
}

// keep only valid link sequences
for (Entry<String, List<List<Id<Link>>>> entry : dnl.getAsMap().entrySet()) {
final String mode = entry.getKey();
final List<List<Id<Link>>> linkSequences = entry.getValue();

// find valid link sequences
List<List<Id<Link>>> validLinkSequences = linkSequences.stream()
// links of sequence exist in network
.filter(linkIds -> linkIds.stream().allMatch(links::containsKey))
// links all have mode in allowed modes
.filter(linkIds -> linkIds.stream()
.map(links::get)
.map(Link::getAllowedModes)
.allMatch(allowedModes -> allowedModes.contains(mode)))
.toList();

// update mode with valid link sequences
final int invalidLinkSequencesCount = linkSequences.size() - validLinkSequences.size();
if (invalidLinkSequencesCount > 0) {
dnl.removeDisallowedLinkSequences(mode);
validLinkSequences.forEach(linkIds -> dnl.addDisallowedLinkSequence(mode, linkIds));
LOG.info("Link {}: Removed {} disallowed next link sequences for mode {}",
link.getId(), invalidLinkSequencesCount, mode);
}
}

// remove attribute completely, if it contains no link sequences anymore.
if (dnl.isEmpty()) {
NetworkUtils.removeDisallowedNextLinks(link);
}

});
}

// Helpers

private static List<String> getErrors(Map<Id<Link>, ? extends Link> links, Id<Link> linkId,
Expand All @@ -60,9 +122,15 @@ private static List<String> getErrors(Map<Id<Link>, ? extends Link> links, Id<Li

Link link = links.get(linkId);
for (Entry<String, List<List<Id<Link>>>> entry : disallowedNextLinks.getAsMap().entrySet()) {
String mode = entry.getKey();
List<List<Id<Link>>> linkSequences = entry.getValue();

for (List<Id<Link>> linkSequence : linkSequences) {
// check for (1) link sequences being a valid sequence and (2) links existing
errors.addAll(isNextLinkSequenceOf(links, link, linkSequence));

// check for allowedModes on this and next links
errors.addAll(isInAllowedModes(links, mode, link, linkSequence));
}
}
return errors;
Expand Down Expand Up @@ -98,4 +166,25 @@ private static boolean isNextLinkOf(Link link, Id<Link> nextLinkId) {
return toNode.getOutLinks().get(nextLinkId) != null;
}

private static List<String> isInAllowedModes(Map<Id<Link>, ? extends Link> links, String mode, Link link,
List<Id<Link>> nextLinkIds) {

List<String> messages = new ArrayList<>();

if (!link.getAllowedModes().contains(mode)) {
messages.add(String.format("Link %s does not allow mode %s",
link.getId(), mode));
}

for (Id<Link> nextLinkId : nextLinkIds) {
Link nextLink = links.get(nextLinkId);
if (nextLink != null && !nextLink.getAllowedModes().contains(mode)) {
messages.add(String.format("Next link %s does not allow mode %s",
nextLink.getId(), mode));
}
}

return messages;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,32 @@

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.matsim.api.core.v01.Coord;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.TransportMode;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.network.Node;
import org.matsim.core.network.turnRestrictions.DisallowedNextLinks;
import org.matsim.core.network.turnRestrictions.DisallowedNextLinksUtils;

public class DisallowedNextLinksUtilsTest {

Network n = DisallowedNextLinksTest.createNetwork();
class DisallowedNextLinksUtilsTest {

@Test
void testEquals1() {
Network n = DisallowedNextLinksTest.createNetwork();
Network n2 = DisallowedNextLinksTest.createNetwork();

Assertions.assertTrue(NetworkUtils.compare(n, n2));
}

@Test
void testEquals2() {

Network n1 = DisallowedNextLinksTest.createNetwork();
{
Link l1 = n1.getLinks().get(Id.createLinkId("1"));
Expand All @@ -44,6 +47,7 @@ void testEquals2() {

@Test
void testNotEquals() {
Network n = DisallowedNextLinksTest.createNetwork();
Network n2 = DisallowedNextLinksTest.createNetwork();
Link l1 = n2.getLinks().get(Id.createLinkId("1"));
DisallowedNextLinks dnl0 = NetworkUtils.getOrCreateDisallowedNextLinks(l1);
Expand All @@ -54,11 +58,13 @@ void testNotEquals() {

@Test
void testNoDisallowedNextLinks() {
Network n = DisallowedNextLinksTest.createNetwork();
Assertions.assertTrue(DisallowedNextLinksUtils.isValid(n));
}

@Test
void testIsNotValid1() {
Network n = DisallowedNextLinksTest.createNetwork();
Map<Id<Link>, ? extends Link> links = n.getLinks();
Link l1 = links.get(Id.createLinkId("1"));
Link l3 = links.get(Id.createLinkId("3"));
Expand All @@ -72,6 +78,7 @@ void testIsNotValid1() {

@Test
void testIsNotValid2() {
Network n = DisallowedNextLinksTest.createNetwork();
Map<Id<Link>, ? extends Link> links = n.getLinks();
Link l1 = links.get(Id.createLinkId("1"));
Link l3 = links.get(Id.createLinkId("3"));
Expand All @@ -85,15 +92,204 @@ void testIsNotValid2() {

@Test
void testIsValid() {
Network n = DisallowedNextLinksTest.createNetwork();
Map<Id<Link>, ? extends Link> links = n.getLinks();
Link l1 = links.get(Id.createLinkId("1"));
Link l3 = links.get(Id.createLinkId("3"));
Link l5 = links.get(Id.createLinkId("5"));
NetworkUtils.addAllowedMode(l1, "bike");
NetworkUtils.addAllowedMode(l3, "bike");

DisallowedNextLinks dnl = NetworkUtils.getOrCreateDisallowedNextLinks(l1);
dnl.addDisallowedLinkSequence("car", List.of(l3.getId(), l5.getId()));
dnl.addDisallowedLinkSequence("bike", List.of(l3.getId()));

Assertions.assertTrue(DisallowedNextLinksUtils.isValid(n));
}

@Test
void testClean() {

Network network = createNetwork();

Link l01 = network.getLinks().get(Id.createLinkId("01"));
DisallowedNextLinks dnl01 = NetworkUtils.getOrCreateDisallowedNextLinks(l01);
dnl01.addDisallowedLinkSequence(TransportMode.car, List.of(Id.createLinkId("12"), Id.createLinkId("23")));
dnl01.addDisallowedLinkSequence(TransportMode.car, List.of(Id.createLinkId("14")));

network.removeLink(Id.createLinkId("23"));

Assertions.assertNotNull(NetworkUtils.getDisallowedNextLinks(l01));
Assertions.assertFalse(DisallowedNextLinksUtils.isValid(network));

// * --------------------------------------------------

DisallowedNextLinksUtils.clean(network);

// * --------------------------------------------------

Assertions.assertTrue(DisallowedNextLinksUtils.isValid(network));

DisallowedNextLinks dnl = NetworkUtils
.getOrCreateDisallowedNextLinks(network.getLinks().get(Id.createLinkId("01")));
Assertions.assertEquals(List.of(List.of(Id.createLinkId("14"))),
dnl.getDisallowedLinkSequences(TransportMode.car));

}

@Test
void testCleanCompletely() {

Network network = createNetwork();

Link l01 = network.getLinks().get(Id.createLinkId("01"));
DisallowedNextLinks dnl01 = NetworkUtils.getOrCreateDisallowedNextLinks(l01);
dnl01.addDisallowedLinkSequence(TransportMode.car, List.of(Id.createLinkId("12"), Id.createLinkId("23")));

network.removeLink(Id.createLinkId("23"));

Assertions.assertFalse(DisallowedNextLinksUtils.isValid(network));

// * --------------------------------------------------

DisallowedNextLinksUtils.clean(network);

// * --------------------------------------------------

Assertions.assertTrue(DisallowedNextLinksUtils.isValid(network));

Assertions.assertTrue(network.getLinks().values().stream()
.map(NetworkUtils::getDisallowedNextLinks)
.allMatch(Objects::isNull));

}

@Test
void testCleanWrongMode() {

Network network = createNetwork();

Link l01 = network.getLinks().get(Id.createLinkId("01"));
DisallowedNextLinks dnl01 = NetworkUtils.getOrCreateDisallowedNextLinks(l01);
dnl01.addDisallowedLinkSequence(TransportMode.bike, List.of(Id.createLinkId("12"), Id.createLinkId("23")));

Assertions.assertFalse(DisallowedNextLinksUtils.isValid(network));

// * --------------------------------------------------

DisallowedNextLinksUtils.clean(network);

// * --------------------------------------------------

Assertions.assertTrue(DisallowedNextLinksUtils.isValid(network));

Assertions.assertTrue(network.getLinks().values().stream()
.map(NetworkUtils::getDisallowedNextLinks)
.allMatch(Objects::isNull));

}

@Test
void testCleanWrongModeOnNextLink() {

Network network = createNetwork();

Link l01 = network.getLinks().get(Id.createLinkId("01"));
DisallowedNextLinks dnl01 = NetworkUtils.getOrCreateDisallowedNextLinks(l01);
dnl01.addDisallowedLinkSequence(TransportMode.car, List.of(Id.createLinkId("12"), Id.createLinkId("23")));

Link l12 = network.getLinks().get(Id.createLinkId("12"));
l12.setAllowedModes(Set.of(TransportMode.bike));

Assertions.assertFalse(DisallowedNextLinksUtils.isValid(network));

// * --------------------------------------------------

DisallowedNextLinksUtils.clean(network);

// * --------------------------------------------------

Assertions.assertTrue(DisallowedNextLinksUtils.isValid(network));

Assertions.assertTrue(network.getLinks().values().stream()
.map(NetworkUtils::getDisallowedNextLinks)
.allMatch(Objects::isNull));

}

// Helpers

static Network createNetwork() {
Network network = NetworkUtils.createNetwork();

Node n0 = NetworkUtils.createNode(Id.createNodeId("0"), new Coord(0, -0));
Node n1 = NetworkUtils.createNode(Id.createNodeId("1"), new Coord(0, -1));
Node n2 = NetworkUtils.createNode(Id.createNodeId("2"), new Coord(-1, -2));
Node n3 = NetworkUtils.createNode(Id.createNodeId("3"), new Coord(-1, -3));
Node n4 = NetworkUtils.createNode(Id.createNodeId("4"), new Coord(0, -4));
Node n5 = NetworkUtils.createNode(Id.createNodeId("5"), new Coord(1, -1));
Node n6 = NetworkUtils.createNode(Id.createNodeId("6"), new Coord(0, -6));

network.addNode(n0);
network.addNode(n1);
network.addNode(n2);
network.addNode(n3);
network.addNode(n4);
network.addNode(n5);
network.addNode(n6);

// * n0
// l01 l10 (0110)
// * n1 - l15 l51 (1551) - n5
// l12 l21 (1221) \
// * n2
// l23 l32 (2332) | l14 l41 (1441)
// * n3
// l34 l43 (3443) /
// * n4
// l46 l64 (4664)
// * n6

Link l01 = NetworkUtils.createLink(Id.createLinkId("01"), n0, n1, network, 1, 1, 300, 1);
Link l10 = NetworkUtils.createLink(Id.createLinkId("10"), n1, n0, network, 1, 1, 300, 1);

Link l12 = NetworkUtils.createLink(Id.createLinkId("12"), n1, n2, network, 1, 1, 300, 1);
Link l21 = NetworkUtils.createLink(Id.createLinkId("21"), n2, n1, network, 1, 1, 300, 1);

Link l14 = NetworkUtils.createLink(Id.createLinkId("14"), n1, n4, network, 1, 1, 300, 1);
Link l41 = NetworkUtils.createLink(Id.createLinkId("41"), n4, n1, network, 1, 1, 300, 1);

Link l23 = NetworkUtils.createLink(Id.createLinkId("23"), n2, n3, network, 1, 1, 300, 1);
Link l32 = NetworkUtils.createLink(Id.createLinkId("32"), n3, n2, network, 1, 1, 300, 1);

Link l34 = NetworkUtils.createLink(Id.createLinkId("34"), n3, n4, network, 1, 1, 300, 1);
Link l43 = NetworkUtils.createLink(Id.createLinkId("43"), n4, n3, network, 1, 1, 300, 1);

Link l15 = NetworkUtils.createLink(Id.createLinkId("15"), n1, n5, network, 1, 1, 300, 1);
Link l51 = NetworkUtils.createLink(Id.createLinkId("51"), n5, n1, network, 1, 1, 300, 1);

Link l46 = NetworkUtils.createLink(Id.createLinkId("46"), n4, n6, network, 1, 1, 300, 1);
Link l64 = NetworkUtils.createLink(Id.createLinkId("64"), n6, n4, network, 1, 1, 300, 1);

network.addLink(l01);
network.addLink(l10);
network.addLink(l12);
network.addLink(l21);
network.addLink(l14);
network.addLink(l41);
network.addLink(l23);
network.addLink(l32);
network.addLink(l34);
network.addLink(l43);
network.addLink(l15);
network.addLink(l51);
network.addLink(l46);
network.addLink(l64);

for (Link link : network.getLinks().values()) {
link.setAllowedModes(Set.of(TransportMode.car));
}

return network;
}
}

0 comments on commit fa2c3e2

Please sign in to comment.