File: jump_along_path.cpp

package info (click to toggle)
vg 1.30.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 267,848 kB
  • sloc: cpp: 446,974; ansic: 116,148; python: 22,805; cs: 17,888; javascript: 11,031; sh: 5,866; makefile: 4,039; java: 1,415; perl: 1,303; xml: 442; lisp: 242
file content (120 lines) | stat: -rw-r--r-- 5,436 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/**
 * \file jump_along_path.cpp
 *
 * Contains implementation of jump_along_closest_path algorithm
 */

#include "jump_along_path.hpp"

//#define debug_algorithms

namespace vg {
namespace algorithms {

using namespace std;

    vector<pos_t> jump_along_closest_path(const PathPositionHandleGraph* graph,
                                          const pos_t& pos, int64_t jump_dist,
                                          size_t max_search_dist) {
#ifdef debug_algorithms
        cerr << "jumping " << jump_dist << " from " << pos << " with a max search dist of " << max_search_dist << endl;
#endif
        
        // intialize the return value
        vector<pos_t> to_return;
        
        function<bool(handle_t,int64_t,bool)> look_for_jumpable_paths = [&](handle_t handle, int64_t search_dist, bool search_left) {
            
            bool found_jumpable_path = false;
            
#ifdef debug_algorithms
            cerr << "checking for jumpable paths for " << graph->get_id(handle) << (graph->get_is_reverse(handle) ? "-" : "+") << " at search dist " << search_dist << " from searching " << (search_left ? "leftwards" : "rightwards") << endl;
#endif
            
            for (const step_handle_t& step : graph->steps_of_handle(handle)) {
                bool path_rev_strand = (graph->get_is_reverse(graph->get_handle_of_step(step))
                                        != graph->get_is_reverse(handle));
                
                int64_t dist_to_jump;
                if (path_rev_strand && search_left) {
                    dist_to_jump = -jump_dist - search_dist;
                }
                else if (path_rev_strand) {
                    dist_to_jump = -jump_dist + search_dist + graph->get_length(handle);
                }
                else if (search_left) {
                    dist_to_jump = jump_dist + search_dist + graph->get_length(handle);
                }
                else {
                    dist_to_jump = jump_dist - search_dist;
                }
                
                int64_t target_path_pos = graph->get_position_of_step(step) + dist_to_jump;
                if (target_path_pos >= 0
                    && target_path_pos < graph->get_path_length(graph->get_path_handle_of_step(step))) {
                    
                    step_handle_t jump_step = graph->get_step_at_position(graph->get_path_handle_of_step(step),
                                                                          target_path_pos);
                    
                    
                    size_t step_offset = graph->get_position_of_step(jump_step);
                    handle_t jump_handle = graph->get_handle_of_step(jump_step);
                    
                    to_return.emplace_back(graph->get_id(jump_handle),
                                           graph->get_is_reverse(jump_handle) != path_rev_strand,
                                           path_rev_strand
                                              ? graph->get_position_of_step(jump_step) + graph->get_length(jump_handle) - target_path_pos
                                              : target_path_pos - graph->get_position_of_step(jump_step));
                    
                    found_jumpable_path = true;
#ifdef debug_algorithms
                    cerr << "found jump position " << to_return.back() << " at forward path offset " << target_path_pos << endl;
#endif
                }
            }
            
            return found_jumpable_path;
        };
        
        // records of (handle, searching left) prioritized by distance
        // all distances are measured to the left end of the node
        structures::RankPairingHeap<pair<handle_t, bool>, size_t> queue;
        
        handle_t handle = graph->get_handle(id(pos), is_rev(pos));
        
        // add in the initial traversals in both directions from the start position
        queue.push_or_reprioritize(make_pair(handle, true), offset(pos));
        queue.push_or_reprioritize(make_pair(handle, false), graph->get_length(handle) - offset(pos));
        
        bool found_jumpable_path = false;
        while (!queue.empty() && !found_jumpable_path) {
            // get the queue that has the next shortest path
            
            auto here = queue.top();
            queue.pop();
            
#ifdef debug_algorithms
            cerr << "traversing " << graph->get_id(here.first.first) << (graph->get_is_reverse(here.first.first) ? "-" : "+") << " in " << (here.first.second ? "leftward" : "rightward") << " direction at distance " << here.second << endl;
#endif
            
            graph->follow_edges(here.first.first, here.first.second, [&](const handle_t& next) {
#ifdef debug_algorithms
                cerr << "\tfollowing edge to " << graph->get_id(next) << (graph->get_is_reverse(next) ? "-" : "+") << " at dist " << here.second << endl;
#endif
                
                found_jumpable_path = look_for_jumpable_paths(next, here.second, here.first.second);
                
                int64_t dist_thru = here.second + graph->get_length(next);
                if (dist_thru <= (int64_t) max_search_dist) {
                    queue.push_or_reprioritize(make_pair(next, here.first.second), dist_thru);
                }
                
                return !found_jumpable_path;
            });
        }
        
        return to_return;
        
    }
}
}