Create multiple lists at once - python

I have 10 customers and one depot 0. For each customer I now want to create a shuttle route from depot, to customer and back to depot in the following format:
Shuttle_route_i = [0, i, 0]
But I don't want to create a dictionary, because later the routes will be changed, compiled, etc.
Is there any way to get this?
My previous code was:
def Generierung_Pendelrouten (Koordinaten):
d = {}
for i in range(1, len(Koordinaten)):
d['Pendelroute_{0}'.format(i)] = [0,i,0]
return d
With the result:
Pendelrouten:
{'Pendelroute_1': [0, 1, 0], 'Pendelroute_2': [0, 2, 0], 'Pendelroute_3': [0, 3, 0], 'Pendelroute_4': [0, 4, 0], 'Pendelroute_5': [0, 5, 0], 'Pendelroute_6': [0, 6, 0], 'Pendelroute_7': [0, 7, 0], 'Pendelroute_8': [0, 8, 0], 'Pendelroute_9': [0, 9, 0], 'Pendelroute_10': [0, 10, 0]}
But with the dictionary I can't then continue to work as desired.
My other idea was to work with a for loop:
for i in range (1,11):
route = []
route.append(0)
route.append(i)
route.append(0)
print(route)
But then you get only the last route [0, 10, 0] output. This is the format in which I want to have all 10 routes.

Related

How can I estimate the travel time of a route by using a travel time matrix?

I want to compute the travel time of a route by using a travel time matrix I already have. Specifically, I have a list of lists that indicates the routes' nodes.
routes= [[1, 2, 3, -1, -1],
[1, 2, 3, 4, -1]]
The -1 indicates that the route ends. So, in this example I have 2 routes:
Route 1: 1>2>3
Route 2: 1>2>3>4
Also, I have the following travel time matrix (list of lists):
tt= [[0, 4, 5, 1],
[5, 0, 9, 2],
[1, 1, 0, 1],
[1, 1, 1, 0]]
So what I want to achieve is to estimate the travel time of the routes. The result is the following:
Route 1= 4(1>2) + 9(2>3) + 0(because it's from 3 to -1) (=13)
Route 2= 4(1>2) + 9(2>3) + 1(3>4) + 0(because it's from 4 to -1) (=14)
Results can be stored in a list. Do you have any suggestions?
import pandas as pd
import numpy as np
routes= [[1, 2, 3, -1, -1], [1, 2, 3, 4, -1]]
tt = [[0, 4, 5, 1],
[5, 0, 9, 2],
[1, 1, 0, 1],
[1, 1, 1, 0]]
tt_sum = []
for route in routes:
counter = 0
tt_route = 0
for i in range(4):
if route[i+1] != -1:
tt_route += tt[counter][route[i]]
counter += 1
tt_sum.append(tt_route)
This gives tt_sum as [13, 14].

how to pick specific element in tensorflow?

I need to pick up the clicked item from a list, my input is like below:
item_arr=tf.constant([['item001', 'item010', 'item020', 'item030', 'item041', 'item051'],
['item101', 'item110', 'item120', 'item130', 'item140', 'item151']])
clicked_arr=tf.constant([[1, 0, 0, 0, 1, 1], [1, 0, 0, 0, 0, 1]])
the item_arr is batch data of items, and clicked_arr is clicked flag(1 is clicked, 0 is no clicked) corresponding to item_arr.
I hope to get the output that pick up the clicked items like that:
clicked_item_arr(for example, output shape is [2,4]):
[
['item001', 'item041', 'item051', 'item_placeholder'],
['item101', 'item151', 'item_placeholder', 'item_placeholder']
]
I also need to get to no-clicked items but the same solution of clicked items should be used.
I tried to use gather_nd and sparse_to_dense:
index_arr=tf.where(tf.equal(clicked_arr, 1))
>>> array([[0, 0],
[0, 4],
[0, 5],
[1, 0],
[1, 5]])
sparse_item_value= tf.gather_nd(item_arr, index_arr)
>>> array(['item001', 'item041', 'item051', 'item101', 'item151'],
dtype=object)
but I can't get the result I want, because I need sparse_indices like:
array([[0, 0],
[0, 1],
[0, 2],
[1, 0],
[1, 1]])
so that I can use:
tf.sparse_to_dense(
sparse_indices=sparse_indices,
sparse_values=sparse_item_value,
output_shape=[2, 10],
default_value='item_placeholder'
)
But I don't know how to get the sparse_indices. Hope you can give me some advice and thanks in advance.

How to vectorize this operation

Say I have two lists (always the same length):
l0 = [0, 4, 4, 4, 0, 0, 0, 8, 8, 0]
l1 = [0, 1, 1, 1, 0, 0, 0, 8, 8, 8]
I have the following rules for intersections and unions I need to apply when comparing these lists element-wise:
# union and intersect
uni = [0]*len(l0)
intersec = [0]*len(l0)
for i in range(len(l0)):
if l0[i] == l1[i]:
uni[i] = l0[i]
intersec[i] = l0[i]
else:
intersec[i] = 0
if l0[i] == 0:
uni[i] = l1[i]
elif l1[i] == 0:
uni[i] = l0[i]
else:
uni[i] = [l0[i], l1[i]]
Thus, the desired output is:
uni: [0, [4, 1], [4, 1], [4, 1], 0, 0, 0, 8, 8, 8]
intersec: [0, 0, 0, 0, 0, 0, 0, 8, 8, 0]
While this works, I need to do this with several hundred very large lists (each, with thousands of elements), so I am looking for a way to vectorize this. I tried using np.where and various masking strategies, but that went nowhere fast. Any suggestions would be most welcome.
* EDIT *
Regarding
uni: [0, [4, 1], [4, 1], [4, 1], 0, 0, 0, 8, 8, 8]
versus
uni: [0, [4, 1], [4, 1], [4, 1], 0, 0, 0, 8, 8, [0, 8]]
I'm still fighting the 8 versus [0, 8] in my mind. The lists are derived from BIO tags in system annotations (see IOB labeling of text chunks), where each list element is a character index in a document and the vakue is an assigned enumerated label. 0 represents a label representing no annotation (i.e., used for determining negatives in a confusion matrix); while non zero elements represent assigned enumerated labels for that character. Since I am ignoring true negatives, I think I can say 8 is equivalent to [0, 8]. As to whether this simplifies things, I am not yet sure.
* EDIT 2 *
I'm using [0, 8] to keep things simple and to keep the definitions of intersection and union consistent with set theory.
I would stay away from calling them 'intersection' and 'union', since those operations have well-defined meanings on sets and the operation you're looking to perform is neither of them.
However, to do what you want:
l0 = [0, 4, 4, 4, 0, 0, 0, 8, 8, 0]
l1 = [0, 1, 1, 1, 0, 0, 0, 8, 8, 8]
values = [
(x
if x == y else 0,
0
if x == y == 0
else x if y == 0
else y if x == 0
else [x, y])
for x, y in zip(l0, l1)
]
result_a, result_b = map(list, zip(*values))
print(result_a)
print(result_b)
This is more than enough for thousands, or even millions of elements since the operation is so basic. Of course, if we're talking billions, you may want to look at numpy anyway.
Semi vectorized solution for union and full for intersection:
import numpy as np
l0 = np.array(l0)
l1 = np.array(l1)
intersec = np.zeros(l0.shape[0])
intersec_idx = np.where(l0==l1)
intersec[intersec_idx] = l0[intersec_idx]
intersec = intersec.astype(int).tolist()
union = np.zeros(l0.shape[0])
union_idx = np.where(l0==l1)
union[union_idx] = l0[union_idx]
no_union_idx = np.where(l0!=l1)
union = union.astype(int).tolist()
for idx in no_union_idx[0]:
union[idx] = [l0[idx], l1[idx]]
and the output:
>>> intersection
[0, 0, 0, 0, 0, 0, 0, 8, 8, 0]
>>> union
[0, [4, 1], [4, 1], [4, 1], 0, 0, 0, 8, 8, [0, 8]]
NB: I think your original union solution is incorrect. See the last output 8 vs [0,8]

How to assign value to an element of 2d array with dynamic size?

I want to create an adjacency matrix for a graph without using any libraries. The problem is the size of the graph is not static and it increases over time. So I can not use a command like:
adj = [ [None for i in range(5)] for j in range(4) ]
and for example, assign 4 to element (1,1):
adj[1][1]=4
I have created an empty list called adj:
adj = []
now each time a node is added to the graph I add a list to adj:
adj.append([])
How can I assign a value to a specific element of the matrix, as I did with q[1][1]=4 when the size was fixed?
You can start with any default size and then use extend to add elements to a sublist, or add a new sublist.
adj = [ [0 for i in range(2)] for j in range(2) ]
print(adj)
#[[0, 0], [0, 0]]
adj[0].extend([1, 1])
#[[0, 0, 1, 1], [0, 0]]
print(adj)
adj.extend([[0, 0, 0, 0, 0]])
print(adj)
#[[0, 0, 1, 1], [0, 0], [0, 0, 0, 0, 0]]
Once you resize your list based on requirement, then you can assign your elements.
adj[0][0] = 2
adj[1][1] = 3
adj[2][2] = 4
print(adj)
#[[2, 0, 1, 1], [0, 3], [0, 0, 4, 0, 0]]

Python: List Index out of Range Reading from File

I'm using python 2.5 (I know it's an old version) and I keep getting a very frustrating 'List index out of range' exception. I'm working on a tile based game, and bellow is the code for creating the map I'm having issues with:
#Creates the list
def setMapSize(self):
l = raw_input('Custom Map length: ')
h = raw_input('Custom Map height: ')
if not(l=='')and not(h==''):
self.length = int(l)
self.height = int(h)
self.tileMap = [[i]*self.length for i in xrange(self.height)]
print self.tileMap
#Load each element of the list from a text file
def loadMap(self,filePath='template.txt'):
loadPath = raw_input('Load the map: ')
if loadPath =='':
self.directory = 'c:/Python25/PYGAME/TileRpg/Maps/' + filePath
print 'Loading map from ',self.directory
readFile = open(self.directory,'r')
for y in xrange(self.height):
for x in xrange(self.length):
#reads only 1 byte (1 char)
print '---Location: ',x,y
print self.tileMap
self.tileMap[x][y]=int(readFile.read(1))
print 'Loaded map:',self.tileMap
readFile.close()
print 'Map loaded\n'
Here is the output and error message I get, please tell me if you know what's going on:
Main began
Map began initialization
Map initialized
Custom Map length: 2
Custom Map height: 5
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]
Load the map:
Loading map from c:/Python25/PYGAME/TileRpg/Maps/template.txt
---Location: 0 0
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]
---Location: 1 0
[[9, 0], [0, 0], [0, 0], [0, 0], [0, 0]]
---Location: 0 1
[[9, 0], [9, 0], [0, 0], [0, 0], [0, 0]]
---Location: 1 1
[[9, 9], [9, 0], [0, 0], [0, 0], [0, 0]]
---Location: 0 2
[[9, 9], [9, 9], [0, 0], [0, 0], [0, 0]]
Traceback (most recent call last):
File "C:\Python25\PYGAME\TileRpg\LevelEditorMain.py", line 7, in <module>
class Main():
File "C:\Python25\PYGAME\TileRpg\LevelEditorMain.py", line 17, in Main
tileMap.loadMap()
File "C:\Python25\PYGAME\TileRpg\Map.py", line 48, in loadMap
self.tileMap[x][y]=int(readFile.read(1))
IndexError: list assignment index out of range
As you can see, the index I'm assigning to seems to exist, but I still get this error.
You swapped height and width; the outer list is of length height, not the inner. self.tileMap[0] is a list of length 2, so the maximum index you can use on it is 1, not 2.
Swapping x and y would solve this:
for x in xrange(self.height):
for y in xrange(self.length):
#reads only 1 byte (1 char)
print '---Location: ',x,y
print self.tileMap
self.tileMap[x][y]=int(readFile.read(1))
Not that you need to use indices here, you can alter the lists directly:
for row in self.tileMap:
row[:] = [readFile.read(1) for _ in row]
You can read a row at a time:
for row in self.tileMap:
row[:] = map(int, readFile.read(self.length))

Categories