MATSIM
NetworkMergeDoubleLinks.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * NetworkMergeDoubleLinks.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2007 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.core.network.algorithms;
22 
23 import com.google.common.base.Verify;
24 import org.apache.logging.log4j.LogManager;
25 import org.apache.logging.log4j.Logger;
26 import org.matsim.api.core.v01.Id;
34 
35 import java.util.*;
36 
37 public final class NetworkMergeDoubleLinks implements NetworkRunnable {
38 
39  public enum MergeType {
45  MAXIMUM }
46 
47  public enum LogInfoLevel {
51  MAXIMUM
52  }
53 
54  private final static Logger log = LogManager.getLogger(NetworkMergeDoubleLinks.class);
55 
57  // member variables
59 
60  private final MergeType mergetype;
61  private final LogInfoLevel logInfoLevel;
62 
64  // constructors
66 
69  }
70 
71  public NetworkMergeDoubleLinks(final MergeType mergetype) {
73  }
74 
75  public NetworkMergeDoubleLinks(final MergeType mergetype, final LogInfoLevel logInfoLevel) {
76  this.mergetype = mergetype;
77  this.logInfoLevel = logInfoLevel;
78  }
79 
81  // private methods
83 
84  private void mergeLink2IntoLink1(Link link1, Link link2, Network network) {
85  switch (this.mergetype) {
86  case REMOVE:
87  if (logInfoLevel.equals(LogInfoLevel.MAXIMUM)) {
88  log.info(" Link id=" + link2.getId() + " removed because of Link id=" + link1.getId());
89  }
90 
91  network.removeLink(link2.getId());
92  break;
93  case ADDITIVE:
94  {
95  if (logInfoLevel.equals(LogInfoLevel.MAXIMUM)) {
96  log.info(" Link id=" + link2.getId() + " merged (additive) into Link id=" + link1.getId());
97  }
98 
99  double cap = link1.getCapacity() + link2.getCapacity();
100  double fs = Math.max(link1.getFreespeed(),link2.getFreespeed());
102  double length = Math.max(link1.getLength(),link2.getLength());
103  // String origid = "add-merge(" + link1.getId() + "," + link2.getId() + ")";
104  link1.setCapacity(cap);
105  link1.setFreespeed(fs);
106  link1.setNumberOfLanes(lanes);
107  link1.setLength(length);
108  network.removeLink(link2.getId());
109  }
110  break;
111  case MAXIMUM:
112  if (logInfoLevel.equals(LogInfoLevel.MAXIMUM)) {
113  log.info(" Link id=" + link2.getId() + " merged (maximum) into Link id=" + link1.getId());
114  }
115 
116  {
117  double cap = Math.max(link1.getCapacity(),link2.getCapacity());
118  double fs = Math.max(link1.getFreespeed(),link2.getFreespeed());
119  int lanes = Math.max(NetworkUtils.getNumberOfLanesAsInt(link1), NetworkUtils.getNumberOfLanesAsInt(link2));
120  double length = Math.max(link1.getLength(),link2.getLength());
121  // String origid = "max-merge(" + link1.getId() + "," + link2.getId() + ")";
122  link1.setCapacity(cap);
123  link1.setFreespeed(fs);
124  link1.setNumberOfLanes(lanes);
125  link1.setLength(length);
126  network.removeLink(link2.getId());
127  }
128  break;
129  default:
130  throw new IllegalArgumentException("'mergetype' not known!");
131  }
132  }
133 
135  // run methods
137 
138  @Override
139  public void run(Network network) {
140 
141  Map<Id<Link>, Replacement> replacedLinks = new HashMap<>();
142  for (Node n : network.getNodes().values()) {
143  Iterator<? extends Link> l1_it = n.getOutLinks().values().iterator();
144  while (l1_it.hasNext()) {
145  Link l1 = l1_it.next();
146  Iterator<? extends Link> l2_it = n.getOutLinks().values().iterator();
147  while (l2_it.hasNext()) {
148  Link l2 = l2_it.next();
149  if (!l2.equals(l1)) {
150  if (l2.getToNode().equals(l1.getToNode())) {
151  if (logInfoLevel.equals(LogInfoLevel.MAXIMUM)) {
152  log.info(" Node id=" + n.getId());
153  }
154 
155  this.mergeLink2IntoLink1(l1, l2, network);
156  replacedLinks.put(l2.getId(), new Replacement(l2, l1));
157  // restart
158  l1_it = n.getOutLinks().values().iterator();
159  l2_it = n.getOutLinks().values().iterator();
160  }
161  }
162  }
163  }
164  }
165 
166  handleTurnRestrictions(network, replacedLinks);
167  }
168 
169  private void handleTurnRestrictions(Network network, Map<Id<Link>, Replacement> replacedLinks) {
170 
171  for (Replacement mergedLinks : replacedLinks.values()) {
172  mergeTurnRestrictions(mergedLinks.substitute, mergedLinks.orginal, replacedLinks);
173  }
174 
175  for (Link link : network.getLinks().values()) {
176  DisallowedNextLinks disallowedNextLinks = NetworkUtils.getDisallowedNextLinks(link);
177 
178  if(disallowedNextLinks != null) {
179 
180  Map<String, List<List<Id<Link>>>> restrictionsPerMode = disallowedNextLinks.getAsMap();
181  Map<String, List<List<Id<Link>>>> restrictionsPerModeCopy = new HashMap<>();
182 
183  for (Map.Entry<String, List<List<Id<Link>>>> restrictions : restrictionsPerMode.entrySet()) {
184  List<List<Id<Link>>> restrictionsCopy = new ArrayList<>();
185  for (List<Id<Link>> restriction : restrictions.getValue()) {
186  List<Id<Link>> restrictionCopy = new ArrayList<>();
187  for (Id<Link> linkId : restriction) {
188  if(replacedLinks.containsKey(linkId)) {
189  restrictionCopy.add(replacedLinks.get(linkId).substitute.getId());
190  } else {
191  restrictionCopy.add(linkId);
192  }
193  }
194  restrictionsCopy.add(restrictionCopy);
195  }
196  restrictionsPerModeCopy.put(restrictions.getKey(), restrictionsCopy);
197  }
198 
199  disallowedNextLinks.clear();
200  restrictionsPerModeCopy.forEach((mode, sequences) ->
201  sequences.forEach(sequence ->
202  disallowedNextLinks.addDisallowedLinkSequence(mode, sequence)
203  )
204  );
205  }
206  }
207 
208  Verify.verify(DisallowedNextLinksUtils.isValid(network));
209  }
210 
211  private static void mergeTurnRestrictions(Link link1, Link link2, Map<Id<Link>, Replacement> replacedLinks) {
212  DisallowedNextLinks disallowedNextLinks1 = NetworkUtils.getDisallowedNextLinks(link1);
213  DisallowedNextLinks disallowedNextLinks2 = NetworkUtils.getDisallowedNextLinks(link2);
214  if (disallowedNextLinks1 != null) {
215  if (disallowedNextLinks2 != null) {
216 
217  Map<String, List<List<Id<Link>>>> perMode1 = disallowedNextLinks1.getAsMap();
218  Map<String, List<List<Id<Link>>>> perMode2 = disallowedNextLinks2.getAsMap();
219  Map<String, List<List<Id<Link>>>> merged = new HashMap<>();
220 
221  for (Map.Entry<String, List<List<Id<Link>>>> restrictionsPerMode : perMode1.entrySet()) {
222  if (perMode2.containsKey(restrictionsPerMode.getKey())) {
223  for (List<Id<Link>> forbiddenSequence : restrictionsPerMode.getValue()) {
224  Id<Link> target = forbiddenSequence.getLast();
225  if(replacedLinks.containsKey(target)) {
226  target = replacedLinks.get(target).substitute.getId();
227  }
228 
229  for (List<Id<Link>> forbiddenSequence2 : perMode2.get(restrictionsPerMode.getKey())) {
230  Id<Link> target2 = forbiddenSequence2.getLast();
231  if(replacedLinks.containsKey(target2)) {
232  target2 = replacedLinks.get(target2).substitute.getId();
233  }
234  if(target.equals(target2)) {
235  merged.computeIfAbsent(restrictionsPerMode.getKey(), k -> new ArrayList<>()).add(forbiddenSequence);
236  }
237  }
238  }
239  }
240  }
241  disallowedNextLinks1.clear();
242  merged.forEach((mode, sequences) -> sequences.forEach(sequence -> disallowedNextLinks1.addDisallowedLinkSequence(mode, sequence)));
243  } else {
245  }
246  }
247  }
248 
249  private record Replacement(Link orginal, Link substitute){}
250 
251 }
static int getNumberOfLanesAsInt(final double time, final Link link)
static< T > Id< T > get(int index, final Class< T > type)
Definition: Id.java:112
Map< Id< Node >, ? extends Node > getNodes()
Link removeLink(final Id< Link > linkId)
static void removeDisallowedNextLinks(Link link)
static DisallowedNextLinks getDisallowedNextLinks(Link link)
Map< Id< Link >, ? extends Link > getLinks()
boolean equals(Object obj)
Definition: Id.java:139