Google/OR-Tools Get Duration And Distance - or-tools

I'm trying to understand the solution call in the MVRP examples
I have two matrixes, duration and distance that have been returned via calls to google
My solution is based on distance but given that i have the data already returned i want to find the index associated with the duration.
unfortunately I'm not sure completely what is going on under the hood of the the Routing Calls so hoping for a simple fast answer for look up and what index to use
for simplicity sake I will show the google example rather than my code and highlight what im looking for:
public string PrintSolution()
{
// Inspect solution.
string ret = "";
long maxRouteDistance = 0;
for (int i = 0; i < _data.Drivers; ++i)
{
ret += $"Route for Vehicle {i}:";
ret += Environment.NewLine;
long routeDistance = 0;
var index = _routing.Start(i);
while (_routing.IsEnd(index) == false)
{
ret += $"{_manager.IndexToNode((int) index)} -> ";
var previousIndex = index;
index = _solution.Value(_routing.NextVar(index));
long legDistance = _routing.GetArcCostForVehicle(previousIndex, index, i);
//LOOKING FOR
//long legDuration = ??? what index am is using here to find in my duration matrix which is built the same as indexes as distance
ret += " leg distance: " + legDistance;
routeDistance += legDistance;
}
ret += $"{_manager.IndexToNode((int) index)}";
ret += Environment.NewLine;
ret += $"Distance of the route: {routeDistance}m";
ret += Environment.NewLine;
ret += Environment.NewLine;
maxRouteDistance = Math.Max(routeDistance, maxRouteDistance);
}
ret += $"Maximum distance of the routes: {maxRouteDistance}m";
ret += Environment.NewLine;
return ret;
}
#Mizux

disclaimer: This is a simplification but should help you to understand.
In OR-Tools Routing there is a primal "hidden" dimension without name but you can retrieve the cost using RoutingModel::GetArcCostForVehicle()
For any "regular" dimension you can get inspect the CumulVar at each node.
e.g. supposing you have created two dimensions using RoutingModel::AddDimension() whose name were "Distance" and "Duration".
note: CumulVar is an accumulator so if you want the "arc cost" you'll need something like this dim.CumulVar(next_index) - dim.CumulVar(index)
Then in you PrintFunction you can use:
public string PrintSolution()
{
...
RoutingDimension distanceDimension = routing.GetMutableDimension("Distance");
RoutingDimension durationDimension = routing.GetMutableDimension("Duration");
for (int i = 0; i < _manager.getNumberOfVehicles(); ++i)
{
while (_routing.IsEnd(index) == false)
{
...
IntVar distanceVar = distanceDimension.CumulVar(index);
IntVar durationVar = durationDimension.CumulVar(index);
long distance = _solution.Value(distanceVar);
long duration = _solution.Value(durationVar);
...
}
}
}

Related

Restricting movement to a specific section

I am currently trying to working with restricting the agents to on 1/4 of the whole Manhattan map. The idea is simple and as follows;
Let us say we have 10 agents, their names being v1, v2 ... v10. I want them to move only in a specific section. Currently the method in whcih the MapBasedMovement has been made is such that it moves in all the place, but I need it to move in only specified coordinates.
Thanks,
I tried picking a specific set of coordinates i.e. (0, 0) and (700, 700). Tried to find all the MapNode that are between them and then ask the DTNNode to select only the MapNode in these coordinates. But this does not give me the correct results.
Adding code below
public Path getPath() {
Path p = new Path(generateSpeed());
MapNode curNode = lastMapNode;
MapNode prevNode = lastMapNode;
MapNode nextNode = null;
List<MapNode> neighbors;
Coord nextCoord;
assert lastMapNode != null: "Tried to get a path before placement";
// start paths from current node
p.addWaypoint(curNode.getLocation());
int pathLength = rng.nextInt(maxPathLength-minPathLength) +
minPathLength;
for (int i=0; i<pathLength; i++)
{
// neighbors = curNode.getNeighbors();
neighbors = host.possibleNodes;
Vector<MapNode> n2 = new Vector<MapNode>(neighbors);
if (!this.backAllowed)
{
n2.remove(prevNode); // to prevent going back
}
if (okMapNodeTypes != null) { //remove neighbor nodes that aren't ok
for (int j=0; j < n2.size(); ){
if (!n2.get(j).isType(okMapNodeTypes)) {
n2.remove(j);
}
else {
j++;
}
}
}
if (n2.size() == 0) { // only option is to go back
nextNode = prevNode;
}
else
{
// choose a random node from remaining neighbors
//nextNode = n2.get(rng.nextInt(n2.size()));
nextNode = host.possibleNodes.get(rng.nextInt(host.possibleNodes.size()));
System.out.println(lastMapNode);
List<MapNode> nodePath = pathFinder.getShortestPath(lastMapNode, nextNode);
for (MapNode node : nodePath)
{ // create a Path from the shortest path
p.addWaypoint(node.getLocation());
}
lastMapNode = nextNode;
prevNode = curNode;
nextCoord = nextNode.getLocation();
curNode = nextNode;
return p;
}
prevNode = curNode;
nextCoord = nextNode.getLocation();
curNode = nextNode;
p.addWaypoint(nextCoord);
}
lastMapNode = curNode;
return p;
}
Here, the parts where the host.possibleNodes have been mentioned are a method that I have made which basically tries to get the coordinates of each node and bins to a specific region. I can add that method as well if needed.

Bad address error when comparing Strings within BPF

I have an example program I am running here to see if the substring matches the string and then print them out. So far, I am having trouble running the program due to a bad address. I am wondering if there is a way to fix this problem? I have attached the entire code but my problem is mostly related to isSubstring.
#include <uapi/linux/bpf.h>
#define ARRAYSIZE 64
struct data_t {
char buf[ARRAYSIZE];
};
BPF_ARRAY(lookupTable, struct data_t, ARRAYSIZE);
//char name[20];
//find substring in a string
static bool isSubstring(struct data_t stringVal)
{
char substring[] = "New York";
int M = sizeof(substring);
int N = sizeof(stringVal.buf) - 1;
/* A loop to slide pat[] one by one */
for (int i = 0; i <= N - M; i++) {
int j;
/* For current index i, check for
pattern match */
for (j = 0; j < M; j++)
if (stringVal.buf[i + j] != substring[j])
break;
if (j == M)
return true;
}
return false;
}
int Test(void *ctx)
{
#pragma clang loop unroll(full)
for (int i = 0; i < ARRAYSIZE; i++) {
int k = i;
struct data_t *line = lookupTable.lookup(&k);
if (line) {
// bpf_trace_printk("%s\n", key->buf);
if (isSubstring(*line)) {
bpf_trace_printk("%s\n", line->buf);
}
}
}
return 0;
}
My python code here:
import ctypes
from bcc import BPF
b = BPF(src_file="hello.c")
lookupTable = b["lookupTable"]
#add hello.csv to the lookupTable array
f = open("hello.csv","r")
contents = f.readlines()
for i in range(0,len(contents)):
string = contents[i].encode('utf-8')
print(len(string))
lookupTable[ctypes.c_int(i)] = ctypes.create_string_buffer(string, len(string))
f.close()
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="Test")
b.trace_print()
Edit: Forgot to add the error: It's really long and can be found here: https://pastebin.com/a7E9L230
I think the most interesting part of the error is near the bottom where it mentions:
The sequence of 8193 jumps is too complex.
And a little bit farther down mentions: Bad Address.
The verifier checks all branches in your program. Each time it sees a jump instruction, it pushes the new branch to its “stack of branches to check”. This stack has a limit (BPF_COMPLEXITY_LIMIT_JMP_SEQ, currently 8192) that you are hitting, as the verifier tells you. “Bad Address” is just the translation of kernel's errno value which is set to -EFAULT in that case.
Not sure how to fix it though, you could try:
With smaller strings, or
On a 5.3+ kernel (which supports bounded loops): without unrolling the loop with clang (I don't know if it would help).

CS50 pset 3: Tideman sort_pairs function

I need some assistance in understanding the logic behind this function. This is my current sort_pairs function in Tideman:
// Sort pairs in decreasing order by the strength of victory
void sort_pairs(void)
{
qsort(pairs, pair_count, sizeof(pair), compare);
return;
}
// Function for sort_pairs
int compare(const void *a, const void *b)
{
const pair *p1 = (const pair *) a;
const pair *p2 = (const pair *) b;
if (p1->winner < p2->winner)
{
return -1;
}
else if (p1->winner > p2->winner)
{
return 1;
}
else
{
return 0;
}
}
This does not clear check50 and I looked online to find how to approach this problem. It seems that most functions compare the values from the preferences array instead (eg preferences[pairs[i].winner][pairs[i].loser]) . My previous functions vote, record_preferences, and add_pairs all clear check50. I have not advanced beyond sort_pairs yet.
Why can't I compare the strength of victory directly from the pairs array instead since I already have the data stored there?
You don't need to make this so complex, you can use your own sorting here. Let's try a simple insertion sort-
void sort_pairs()
{
pair temp;
for (int i = 1, j; i < pair_count; i++)
{
temp = pairs[i];
j = i - 1;
for (; j >= 0 && preferences[pairs[j].winner][pairs[j].loser] < preferences[temp.winner][temp.loser]; j--)
{
pairs[j + 1] = pairs[j];
}
pairs[j + 1] = temp;
}
}
The pair struct looks like-
typedef struct
{
int winner;
int loser;
}
pair;
Explanation:-
We go through each pair of elements inside the pairs array - starting at 1 since I'm going to compare with the previous element (j = i - 1)
Now we check all the previous elements from the current element and compare them with the key - preferences[pairs[INDEX].winner][pairs[INDEX].loser]
This is the key you should be sorting by. preferences[WINNER_ID][LOSER_ID] means the amount of people that prefer WINNER_ID over LOSER_ID.
And that's pretty much it!, it's simply a insertion sort but the key is the important part.

Studio won't print array elements when I test. (Java)

I'm working with eclipse and when I want the program to print either all the array elements or just a single array element via indexing. It doesn't return an error or even an address when I run the program.
import java.util.Scanner;
public class FavoriteListMaker {
public static void main(String[] args)
{
Scanner inputDevice = new Scanner(System.in);
System.out.println("This program is to help you order a favorites list. Please enter the amount of items on the list.");
int ListSize = inputDevice.nextInt();
String [] TopXA = new String [ListSize + 1];
int [] TopXB = new int[ListSize + 1];
for (int x = 0; x < TopXA.length; ++ x)
{
System.out.println("Please enter an item to be organized on the list");
String item = inputDevice.nextLine();
TopXA[x] = item;
System.out.println("You have " + (ListSize - x) + " items left to fill on the list.");
}
System.out.println("Now we will compare each item on the list with every item on the list one at a time.");
System.out.println("We will ask you a series a question on whether you like item A better then item B and tally the score.");
System.out.println("At the end the item with the most points wins.");
for (int y = 0; y < TopXA.length; ++ y)
for (int z = 0; z < TopXA.length; ++ z)
{
String compareA = TopXA[y];
String compareB = TopXA[z];
System.out.println("Do you prefer " + compareA + " or " + compareB + " .");
System.out.println("If you prefer " + compareA + "Please press 1. If you prefer " + compareB + " please press 2.");
int choice = inputDevice.nextInt();
switch(choice)
{
case 1:
TopXB[y] =+ 1;
break;
case 2:
TopXB[z] =+ 2;
break;
default:
System.out.print("I'm sorry but that is not a valid input.");
}
}
When I run the code it will print out. "Do you prefer or ." instead of the array element.
Disclaimer - I don't have eclipse, I dont program in Java
Please check two things
1) The for loop for y doesn't have curly brackets
2) Please check array 'TopXA' to see if 'item' is being populated in array once you input it.
3) Are CompareA and CompareB being assigned values?
EDIT - found problem
Add scanner.nextLine(); after the nextINt line.
Your problem is that the nextInt() method is not consuming the newline character (see other question). This leads to the fact that your first element in the list is empty. In the first iteration (y=0, z=0) of the nested for-loops this empty element gets printed two times.
Try adding inputDevice.nextLine() after each nextInt() call and you will see that it is working ;)
And PLEASE: Don't name variables uppercase!
import java.util.Scanner;
public class FavoriteListMaker {
public static void main(String[] args)
{
Scanner inputDevice = new Scanner(System.in);
System.out.println("This program is to help you order a favorites list. Please enter the amount of items on the list.");
int listSize = inputDevice.nextInt();
inputDevice.nextLine();
String [] topXA = new String [listSize];
int [] topXB = new int[listSize];
for (int x = 0; x < topXA.length; ++x)
{
System.out.println("Please enter an item to be organized on the list");
String item = inputDevice.nextLine();
topXA[x] = item;
System.out.println("You have " + (listSize - x) + " items left to fill on the list.");
}
System.out.println("Now we will compare each item on the list with every item on the list one at a time.");
System.out.println("We will ask you a series a question on whether you like item A better then item B and tally the score.");
System.out.println("At the end the item with the most points wins.");
for (int y = 0; y < topXA.length; ++y)
{
for (int z = 0; z < topXA.length; ++z)
{
String compareA = topXA[y];
String compareB = topXA[z];
System.out.println("Do you prefer " + compareA + " or " + compareB + " .");
System.out.println("If you prefer " + compareA + "Please press 1. If you prefer " + compareB + " please press 2.");
int choice = inputDevice.nextInt();
inputDevice.nextLine();
switch(choice)
{
case 1:
topXB[y] =+ 1;
break;
case 2:
topXB[z] =+ 2;
break;
default:
System.out.print("I'm sorry but that is not a valid input.");
}
}
}
}
}

How to make 'ő' and 'ű' work in Java?

String word = inputField.getText();
int wordLength = word.length();
boolean backWord = false;
boolean longWord = false;
String backArray[]=new String[6];
backArray[0] = "a";
backArray[1] = "á";
backArray[2] = "ö";
backArray[3] = "ő";
backArray[4] = "ü";
backArray[5] = "ű";
for (int i = 0;i < wordLength ;i ++ ) {
String character = word.substring(i, i + 1);
for (int j = 0;j < 5;j ++) {
if (character.equals(backArray[j])) {
backWord = true;
}
}
}
if (backWord) {
outputField.setText(word+"ban");
}
else {
outputField.setText(word+"ben");
}
This is the code I wrote for an applet for conjugating Hungarian nouns while taking vowel harmony into consideration. For the unaware, the TL;DR of vowel harmony is that Hungarian has lots of suffixes and you can determine which suffix to use based on the vowels in a word.
This code works fine for all the vowels, except for ő and ű. So if my input is 'szálloda', the output will be 'szállodaban'. However, if my input is 'idő' (weather) the output will be 'időben', though it should be 'időban' according to the code.
I assumed this is because java somehow doesn't recognize these two letters because the code works fine for the other ones. Is that the problem? And if so, how do I solve it?