I have used jgrapht to analyse some graph problems. Now I am working with big graph (with more than ten millions nodes ) and use CH algorithm.
What troubles me is the precomputation of CH is so long, nearly 2 hours. And I found the
preprocessed data is saved in ContractionHierarchy as below.
public static class ContractionHierarchy<V, E> {
private Graph<V, E> graph;
private Graph<ContractionVertex<V>, ContractionEdge<E>> contractionGraph;
private Map<V, ContractionVertex<V>> contractionMapping;
public Graph<V, E> getGraph() {
return this.graph;
}
public Graph<ContractionVertex<V>, ContractionEdge<E>> getContractionGraph() {
return this.contractionGraph;
}
public Map<V, ContractionVertex<V>> getContractionMapping() {
return this.contractionMapping;
}
ContractionHierarchy(Graph<V, E> graph, Graph<ContractionVertex<V>, ContractionEdge<E>> contractionGraph, Map<V, ContractionVertex<V>> contractionMapping) {
this.graph = graph;
this.contractionGraph = contractionGraph;
this.contractionMapping = contractionMapping;
}
public void unpackBackward(ContractionEdge<E> edge, LinkedList<V> vertexList, LinkedList<E> edgeList) {
if (edge.bypassedEdges == null) {
vertexList.addFirst(((ContractionVertex)this.contractionGraph.getEdgeSource(edge)).vertex);
edgeList.addFirst(edge.edge);
} else {
this.unpackBackward((ContractionEdge)edge.bypassedEdges.getSecond(), vertexList, edgeList);
this.unpackBackward((ContractionEdge)edge.bypassedEdges.getFirst(), vertexList, edgeList);
}
}
public void unpackForward(ContractionEdge<E> edge, LinkedList<V> vertexList, LinkedList<E> edgeList) {
if (edge.bypassedEdges == null) {
vertexList.addLast(((ContractionVertex)this.contractionGraph.getEdgeTarget(edge)).vertex);
edgeList.addLast(edge.edge);
} else {
this.unpackForward((ContractionEdge)edge.bypassedEdges.getFirst(), vertexList, edgeList);
this.unpackForward((ContractionEdge)edge.bypassedEdges.getSecond(), vertexList, edgeList);
}
}
}
So I wonder is there any way to export ContractionHierarchy to files so that I can use it next time without compile the precomputation and query directly.
Related
I have 2 Flowables (one which is giving me VelocityNed items, and other which I written to consume items from first one); the thing is I don't know how to make the second one right, since I still not feel sure with RxJava
my Flowable code:
private Flowable<Float> getIAS(Flowable<VelocityNed> velocityNed) {
Flowable<Float> flowable = Flowable.create(emitter->{
velocityNed.subscribeWith(new DisposableSubscriber<VelocityNed>() {
#Override public void onNext(VelocityNed v) {
float valueToEmit = (float)Math.sqrt(Math.pow(v.getDownMS(),2)+Math.pow(v.getEastMS(),2)+Math.pow(v.getNorthMS(),2));
//how to emit this
}
#Override public void onError(Throwable t) {
t.printStackTrace();
}
#Override public void onComplete() {
emitter.onComplete();
this.dispose();
}
});
}, BackpressureStrategy.BUFFER);
return flowable;
}
You don't need to create a Flowable manually just to transform the emissions. You can do originalFlowable.map(element -> { transform element however you want }).
In your case it would be something like:
Flowable<Float> flowable = velocityNed.map(v -> {
(float)Math.sqrt(Math.pow(v.getDownMS(),2)+Math.pow(v.getEastMS(),2)+Math.pow(v.getNorthMS(),2));
})
i search many place, did not find any solution.
so the question is.
i want a map in dart like this
var Map<String, String> data;
it will be a params init and passed in other place. but when pass the params, i want to limit the key in map only accept some special strings. like 'someA', 'someB'.
so,when call the function it like this.
functionA({'someA': 'xxxx', 'someB': 'xxxx'})
no other keys.
and also when i call the function i can just type some word and the IDE will show suggestion for me to select the key.
the all code like this (can not run).
var List<String> keyList = ['someA', 'someB'];
class Abc {
functionA({Map<valueOf keyList, String> data) {
}
}
Abc().functionA({'someA': 'xxxx', 'someB': 'xxxx'});
You can provide your own Map implementation (deriving from DelegatingMap from package:collection would make it a lot easier) and then override operator []= to throw if the supplied key should not be allowed. For example:
import 'package:collection/collection.dart';
/// A [Map] that allows only certain keys.
class LimitedMap<K, V> extends DelegatingMap<K, V> {
LimitedMap({Iterable<K> allowedKeys})
: allowedKeys = <K>{...allowedKeys},
super(<K, V>{});
final Set<K> allowedKeys;
/// Throws an exception if [key] is not allowed.
void _checkKey(K key) {
if (!allowedKeys.contains(key)) {
throw Exception('Invalid key: $key');
}
}
#override
void addAll(Map<K, V> other) => addEntries(other.entries);
#override
void addEntries(Iterable<MapEntry<K, V>> entries) {
for (var entry in entries) {
this[entry.key] = entry.value;
}
}
#override
V putIfAbsent(K key, V Function() ifAbsent) {
_checkKey(key);
return super.putIfAbsent(key, ifAbsent);
}
#override
V update(K key, V Function(V) update, {V Function() ifAbsent}) {
_checkKey(key);
return super.update(key, update, ifAbsent: ifAbsent);
}
#override
void operator []=(K key, V value) {
_checkKey(key);
super[key] = value;
}
}
class MyMap extends LimitedMap<String, String> {
MyMap([Map<String, String> initialMap])
: super(allowedKeys: {'foo', 'bar', 'baz'}) {
if (initialMap != null) {
addAll(initialMap);
}
}
}
Alternatively, if your keys are fixed, it'd be better to just make them properties on a custom class, and then you also would get the IDE autocompletion behavior that you want.
I am trying to create function which reads a object from realm and emit an empty observable if the object isn't found. The code below works to some degree because I can stop it with the debugger and see it hit the Observable.empty():
fun readFromRealm(id: String): Observable<Player> {
return realm.where(Player::class.java)
.equalTo("id", id)
.findFirstAsync()
.asObservable<Player>()
.filter { it.isLoaded }
.flatMap {
if (it.isValid)
Observable.just(it)
else
Observable.empty()
}
}
But when I try to use a switchIfEmpty on the Observable the code never emits defaultPlayer when it is not found in realm.
return readFromRealm(playerId)
.take(1)
.map{ // do something with emitted observable }
.switchIfEmpty(Observable.just(defaultPlayer)) // use this if no player found
The strange thing is that if I update the original method to include a first() prior to the flatMap :
fun readFromRealm(id: String): Observable<Player> {
return realm.where(Player::class.java)
.equalTo("id", id)
.findFirstAsync()
.asObservable<Player>()
.filter { it.isLoaded }
.first() // add first
.flatMap {
if (it.isValid)
Observable.just(it)
else
Observable.empty()
}
}
Everything starts working as expected, but I believe this version will kill auto updating because it will only capture the first result emitted after the filter.
I'm still trying to grok Realm and Rx so I'm probably doing something dumb.
EDIT: I have created a sample project which highlights the issue I'm seeing - https://github.com/donaldlittlepie/realm-async-issue
For reasons I don't totally understand. If you move take(1) just above the
flatMap and below the filter it should work correctly:
realm.where(Dog.class)
.equalTo("id", 0L)
.findFirstAsync()
.asObservable()
.cast(Dog.class)
.filter(new Func1<RealmObject, Boolean>() {
#Override
public Boolean call(RealmObject realmObject) {
return realmObject.isLoaded();
}
})
.take(1) // <== here
.flatMap(new Func1<Dog, Observable<Dog>>() {
#Override
public Observable<Dog> call(Dog realmObject) {
if (realmObject.isValid()) {
return Observable.just(realmObject);
} else {
return Observable.empty();
}
}
})
.map(new Func1<Dog, Dog>() {
#Override
public Dog call(Dog dog) {
dog.setName("mapped " + dog.getName());
return dog;
}
})
.switchIfEmpty(Observable.just(createDefaultDog()))
.subscribe(new Action1<Dog>() {
#Override
public void call(Dog dog) {
textView.setText(dog.getName());
}
}, new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
textView.setText(throwable.toString());
}
});
My best guess is that before, flatMap was called repeatedly, returning Observable.empty() multiple times. Perhaps that effects the Observable chain in some unexpected way.
Given a directed graph with
A root node
Some leaves nodes
Multiple nodes can be connected to the same node
Cycles can exist
We need to print all the paths from the root node to all the leaves nodes. This is the closest question I got to this problem
Find all paths between two graph nodes
If you actually care about ordering your paths from shortest path to longest path then it would be far better to use a modified A* or Dijkstra Algorithm. With a slight modification the algorithm will return as many of the possible paths as you want in order of shortest path first. So if what you really want are all possible paths ordered from shortest to longest then this is the way to go. The code I suggested above would be much slower than it needs to be if you care about ordering from shortest to longest, not to mention would take up more space then you'd want in order to store every possible path at once.
If you want an A* based implementation capable of returning all paths ordered from the shortest to the longest, the following will accomplish that. It has several advantages. First off it is efficient at sorting from shortest to longest. Also it computes each additional path only when needed, so if you stop early because you dont need every single path you save some processing time. It also reuses data for subsequent paths each time it calculates the next path so it is more efficient. Finally if you find some desired path you can abort early saving some computation time. Overall this should be the most efficient algorithm if you care about sorting by path length.
import java.util.*;
public class AstarSearch {
private final Map<Integer, Set<Neighbor>> adjacency;
private final int destination;
private final NavigableSet<Step> pending = new TreeSet<>();
public AstarSearch(Map<Integer, Set<Neighbor>> adjacency, int source, int destination) {
this.adjacency = adjacency;
this.destination = destination;
this.pending.add(new Step(source, null, 0));
}
public List<Integer> nextShortestPath() {
Step current = this.pending.pollFirst();
while( current != null) {
if( current.getId() == this.destination )
return current.generatePath();
for (Neighbor neighbor : this.adjacency.get(current.id)) {
if(!current.seen(neighbor.getId())) {
final Step nextStep = new Step(neighbor.getId(), current, current.cost + neighbor.cost + predictCost(neighbor.id, this.destination));
this.pending.add(nextStep);
}
}
current = this.pending.pollFirst();
}
return null;
}
protected int predictCost(int source, int destination) {
return 0; //Behaves identical to Dijkstra's algorithm, override to make it A*
}
private static class Step implements Comparable<Step> {
final int id;
final Step parent;
final int cost;
public Step(int id, Step parent, int cost) {
this.id = id;
this.parent = parent;
this.cost = cost;
}
public int getId() {
return id;
}
public Step getParent() {
return parent;
}
public int getCost() {
return cost;
}
public boolean seen(int node) {
if(this.id == node)
return true;
else if(parent == null)
return false;
else
return this.parent.seen(node);
}
public List<Integer> generatePath() {
final List<Integer> path;
if(this.parent != null)
path = this.parent.generatePath();
else
path = new ArrayList<>();
path.add(this.id);
return path;
}
#Override
public int compareTo(Step step) {
if(step == null)
return 1;
if( this.cost != step.cost)
return Integer.compare(this.cost, step.cost);
if( this.id != step.id )
return Integer.compare(this.id, step.id);
if( this.parent != null )
this.parent.compareTo(step.parent);
if(step.parent == null)
return 0;
return -1;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Step step = (Step) o;
return id == step.id &&
cost == step.cost &&
Objects.equals(parent, step.parent);
}
#Override
public int hashCode() {
return Objects.hash(id, parent, cost);
}
}
/*******************************************************
* Everything below here just sets up your adjacency *
* It will just be helpful for you to be able to test *
* It isnt part of the actual A* search algorithm *
********************************************************/
private static class Neighbor {
final int id;
final int cost;
public Neighbor(int id, int cost) {
this.id = id;
this.cost = cost;
}
public int getId() {
return id;
}
public int getCost() {
return cost;
}
}
public static void main(String[] args) {
final Map<Integer, Set<Neighbor>> adjacency = createAdjacency();
final AstarSearch search = new AstarSearch(adjacency, 1, 4);
System.out.println("printing all paths from shortest to longest...");
List<Integer> path = search.nextShortestPath();
while(path != null) {
System.out.println(path);
path = search.nextShortestPath();
}
}
private static Map<Integer, Set<Neighbor>> createAdjacency() {
final Map<Integer, Set<Neighbor>> adjacency = new HashMap<>();
//This sets up the adjacencies. In this case all adjacencies have a cost of 1, but they dont need to.
addAdjacency(adjacency, 1,2,1,5,1); //{1 | 2,5}
addAdjacency(adjacency, 2,1,1,3,1,4,1,5,1); //{2 | 1,3,4,5}
addAdjacency(adjacency, 3,2,1,5,1); //{3 | 2,5}
addAdjacency(adjacency, 4,2,1); //{4 | 2}
addAdjacency(adjacency, 5,1,1,2,1,3,1); //{5 | 1,2,3}
return Collections.unmodifiableMap(adjacency);
}
private static void addAdjacency(Map<Integer, Set<Neighbor>> adjacency, int source, Integer... dests) {
if( dests.length % 2 != 0)
throw new IllegalArgumentException("dests must have an equal number of arguments, each pair is the id and cost for that traversal");
final Set<Neighbor> destinations = new HashSet<>();
for(int i = 0; i < dests.length; i+=2)
destinations.add(new Neighbor(dests[i], dests[i+1]));
adjacency.put(source, Collections.unmodifiableSet(destinations));
}
}
The output from the above code is the following:
[1, 2, 4]
[1, 5, 2, 4]
[1, 5, 3, 2, 4]
Notice that each time you call nextShortestPath() it generates the next shortest path for you on demand. It only calculates the extra steps needed and doesnt traverse any old paths twice. Moreover if you decide you dont need all the paths and end execution early you've saved yourself considerable computation time. You only compute up to the number of paths you need and no more.
Finally it should be noted that the A* and Dijkstra algorithms do have some minor limitations, though I dont think it would effect you. Namely it will not work right on a graph that has negative weights.
Here is a link to JDoodle where you can run the code yourself in the browser and see it working. You can also change around the graph to show it works on other graphs as well: http://jdoodle.com/a/ukx
I am using Lucene.net in my Web App.
Everithing works fine, but now i have to show the number of occurrences of my 'searchstring' in every single document of the hits array.
How can i do this? I use usual BooleanQuery.
That is my search:
BooleanQuery bq = new BooleanQuery();
bq.Add(QueryParser.Parse(Lquery, "", CurIndexDescritor.GetLangAnalizer()), false,false);
BooleanQuery.SetMaxClauseCount(int.MaxValue);
IndexSearcher searcher = new IndexSearcher(indexPath);
Hits hits = (filter != null) ? searcher.Search(bq, filter) : searcher.Search(bq);
for (int i = 0; i < hits.Length(); i++)
{
Document doc = hits.Doc(i);
SearchResultItem MyDb = new SearchResultItem();
MyDb.key = doc.Get(KeyField);
MyDb.score = hits.Score(i);
result.Add(MyDb);
}
Where can i get the number of occurrences?
Thanks!
If you dont want the score back and dont want to order the results using score you could probably build a custom Similarity implementation.
I quickly tested the following code, and it appears to work fine with TermQueries and PhraseQueries, i didnt test more query types tho. A PhraseQuery hit counts as a single occurence.
public class OccurenceSimilarity : DefaultSimilarity
{
public override float Tf(float freq)
{
return freq;
}
public override float Idf(int docFreq, int numDocs)
{
return 1;
}
public override float Coord(int overlap, int maxOverlap)
{
return 1;
}
public override float QueryNorm(float sumOfSquaredWeights)
{
return 1;
}
public override Explanation.IDFExplanation idfExplain(System.Collections.ICollection terms, Searcher searcher)
{
return CACHED_IDF_EXPLAIN;
}
public override Explanation.IDFExplanation IdfExplain(Term term, Searcher searcher)
{
return CACHED_IDF_EXPLAIN;
}
public override float SloppyFreq(int distance)
{
return 1;
}
private static Explanation.IDFExplanation CACHED_IDF_EXPLAIN = new ExplainIt();
private class ExplainIt : Explanation.IDFExplanation
{
public override string Explain()
{
return "1";
}
public override float GetIdf()
{
return 1.0f;
}
}
}
To use it:
Similarity.SetDefault(new OccurenceSimilarity());