Hi I am trying to index a range of a vector of symbols.
My first idea was to use a MatrixSymbol
A = MatrixSymbol('A',10,1)
B = Matrix(A[0:2]) # does not work!
Then I thought I could use an IndexBased, but how do I generate the submatrix B (I can't index a range)
A=IndexedBased('A')
B=Matrix([A[0],A[1]]) # works but I want to define a range
There must be a proper way to do this.
IndexedBase will give you a 1-d vector like symbol.
You could use a list comprehension with a range giving the indices:
>>> a = IndexedBase("A")
>>> Matrix([a[i] for i in range(2)])
Matrix([
[A[0]],
[A[1]]])
Since you are working in Python, you are free to modify routines to suit your needs if you want to use direct slicing on the IndexedBase:
def gi(self, slc):
if isinstance(slc, slice):
a,b,s=slc.start, slc.stop, slc.step
s = s or 1
a = a or 0
assert all(type(i) is int or i is None for i in (a,b,s))
assert b is not None
rv = []
for i in range(a,b,s):
rv.append(self[i])
return rv
return _gi(self, slc)
_gi = IndexedBase.__getitem__
IndexedBase.__getitem__ = gi
With that modification you ca now do:
>>> x = IndexedBase('x')
>>> x[0]
x[0]
>>> x[:2]
[x[0], x[1]]
(This does not attempt to handle the key words argument; it's more a proof of concept.)
Related
I want to get border of data in a list using python
For example I have this list :
a = [1,1,1,1,4,4,4,6,6,6,6,6,1,1,1]
I want a code that return data borders. for example:
a = [1,1,1,1,4,4,4,6,6,6,6,6,1,1,1]
^ ^ ^ ^
b = get_border_index(a)
print(b)
output:
[0,4,7,12]
How can I implement get_border_index(lst: list) -> list function?
The scalable answer that also works for very long lists or arrays is to use np.diff. In that case you should avoid a for loop at all costs.
import numpy as np
a = [1,1,1,1,4,4,4,6,6,6,6,6,1,1,1]
a = np.array(a)
# this is unequal 0 if there is a step
d = np.diff(a)
# boolean array where the steps are
is_step = d != 0
# get the indices of the steps (first one is trivial).
ics = np.where(is_step)
# get the first dimension and shift by one as you want
# the index of the element right of the step
ics_shift = ics[0] + 1
# and if you need a list
ics_list = ics_shift.tolist()
print(ics_list)
You can use for loop with enumerate
def get_border_index(a):
last_value = None
result = []
for i, v in enumerate(a):
if v != last_value:
last_value = v
result.append(i)
return result
a = [1,1,1,1,4,4,4,6,6,6,6,6,1,1,1]
b = get_border_index(a)
print(b)
Output
[0, 4, 7, 12]
This code will check if an element in the a list is different then the element before and if so it will append the index of the element to the result list.
I have a bunch of gurobi variables
y[0],y[1],...,y[n]
x[0],x[1],...,x[m].
I would like to be able to figure out the indices of the optimal y's that are not zero. In other words, if the optimal solution is y[0]=0, y[1]=5, y[2]=0, y[3]=1, I would like to return [1,3]. So far, I have
F = []
for v in model.getVars():
if v.varName[0]=='y' and v.x>0:
F.append[v.varName]
This, in the above example, would give me ['y[1]', 'y[3]']. Since this output is a string, I'm not sure how I can get the 1 and 3 out of it. Please help.
Thanks in advance!
I am using the following which works:
Index_List = []
for v in m.getVars():
if v.varName[0] == 'y' and v.x>0:
Index = int(v.varName[2])
for j in range(3,3+100)):
BOOL = False
try:
IndexNEW =int(v.varName[j])
Index = 10*Index+IndexNEW
BOOL = True
except ValueError:
()
if not BOOL:
break
Index_List.append(Index)
The resulting Index_List is as desired. There must be a better way though.
Assuming
from gurobipy import *
m = Model()
If you create a gurobi tupledict for your variables with
x = m.addVars(nx, vtype=GRB.INTEGER, name="x")
y = m.addVars(ny, vtype=GRB.INTEGER, name="y")
# ...your constraints and objective here..
then you can directly call the attributes for your variables (in your case the .X attribute for the variable value in the current solution). Using a list comprehension it could be done with:
m.optimize()
if m.status == GRB.OPTIMAL:
indices = [i for i in range(ny) if y[i].X > 0]
where nx and ny are the number of your variables.
thats what I get:
TypeError: 'float' object is unsubscriptable
Thats what I did:
import numpy as N
import itertools
#I created two lists, containing large amounts of numbers, i.e. 3.465
lx = [3.625, 4.625, ...]
ly = [41.435, 42.435, ...] #The lists are not the same size!
xy = list(itertools.product(lx,ly)) #create a nice "table" of my lists
#that iterttools gives me something like
print xy
[(3.625, 41.435), (3.625, 42.435), (... , ..), ... ]
print xy[0][0]
print xy[0][1] #that works just fine, I can access the varios values of the tuple in the list
#down here is where the error occurs
#I basically try to access certain points in "lon"/"lat" with values from xy through `b` and `v`with that iteration. lon/lat are read earlier in the script
b = -1
v = 1
for l in xy:
b += 1
idx = N.where(lon==l[b][b])[0][0]
idy = N.where(lat==l[b][v])[0][0]
lan/lot are read earlier in the script. I am working with a netCDF file and this is the latitude/longitude,read into lan/lot.
Its an array, build with numpy.
Where is the mistake?
I tried to convert b and v with int() to integers, but that did not help.
The N.where is accessing through the value from xy a certain value on a grid with which I want to proceed. If you need more code or some plots, let me know please.
Your problem is that when you loop over xy, each value of l is a single element of your xy list, one of the tuples. The value of l in the first iteration of the loop is (3.625, 41.435), the second is (3.625, 42.435), and so on.
When you do l[b], you get 3.625. When you do l[b][b], you try to get the first element of 3.625, but that is a float, so it has no indexes. That gives you an error.
To put it another way, in the first iteration of the loop, l is the same as xy[0], so l[0] is the same as xy[0][0]. In the second iteration, l is the same as xy[1], so l[0] is the same as xy[1][0]. In the third iteration, l is equivalent to xy[2], and so on. So in the first iteration, l[0][0] is the same as xy[0][0][0], but there is no such thing so you get an error.
To get the first and second values of the tuple, using the indexing approach you could just do:
x = l[0]
y = l[1]
Or, in your case:
for l in xy:
idx = N.where(lon==l[0])[0][0]
idy = N.where(lat==l[1])[0][0]
However, the simplest solution would be to use what is called "tuple unpacking":
for x, y in xy:
idx = N.where(lon==x)[0][0]
idy = N.where(lat==y)[0][0]
This is equivalent to:
for l in xy:
x, y = l
idx = N.where(lon==x)[0][0]
idy = N.where(lat==y)[0][0]
which in turn is equivalent to:
for l in xy:
x = l[0]
y = l[1]
idx = N.where(lon==x)[0][0]
idy = N.where(lat==y)[0][0]
from numpy import *
import collections
array = [28000,35200,35200,35200,35700,36000]
rng = range(35000,37000)
for elem in array:
print elem
35200 35700 36000
That gets me off to a good start, but I need only the duplicates from the range list, which would only be 35200. I tried adding a line under print elem, for example-
print elem
print [x for x, y in collections.Counter(a).items if y > 1]
But I get TypeError: 'numpy.float64' object is not iterable. The duplicate will be needed later for an equation. How can I narrow array down to just the duplicate within a range?
items is a function, you forgot the ():
counterItems = collections.Counter(a).items()
print [x for x, y in counterItems if y > 1]
Another way to do it:
In [15]: a = [28000,35200,35200,35200,35700,36000]
In [16]: set([x for x in a if a.count(x) > 1])
Out[16]: set([35200])
The numpy way of doing it will be:
>>> a=np.array([28000,35200,35200,35200,35700,36000])
>>> a[np.sum(a==a[...,np.newaxis], axis=1)>1]
array([35200, 35200, 35200])
>>> np.unique(a[np.sum(a==a[...,np.newaxis], axis=1)>1])
array([35200])
Under the assumption of a being sorted, this is probably the fastest way (with numpy), including the range restriction:
import numpy
a = numpy.array([28000,35000,35200,35200,35200,35200,35700,36000])
left = a.searchsorted(35000, "left")
right = a.searchsorted(37000, "right")
section = a[left:right]
numpy.unique(section[section[1:] == section[:-1]])
#>>> array([35200])
Similar speedups can be found by using the bisect module on regular non-numpy arrays.
If I have an input string and an array:
s = "to_be_or_not_to_be"
pos = [15, 2, 8]
I am trying to find the longest common prefix between the consecutive elements of the array pos referencing the original s. I am trying to get the following output:
longest = [3,1]
The way I obtained this is by computing the longest common prefix of the following pairs:
s[15:] which is _be and s[2:] which is _be_or_not_to_be giving 3 ( _be )
s[2:] which is _be_or_not_to_be and s[8:] which is _not_to_be giving 1 ( _ )
However, if s is huge, I don't want to create multiple copies when I do something like s[x:]. After hours of searching, I found the function buffer that maintains only one copy of the input string but I wasn't sure what is the most efficient way to utilize it here in this context. Any suggestions on how to achieve this?
Here is a method without buffer which doesn't copy, as it only looks at one character at a time:
from itertools import islice, izip
s = "to_be_or_not_to_be"
pos = [15, 2, 8]
length = len(s)
for start1, start2 in izip(pos, islice(pos, 1, None)):
pref = 0
for pos1, pos2 in izip(xrange(start1, length), xrange(start2, length)):
if s[pos1] == s[pos2]:
pref += 1
else:
break
print pref
# prints 3 1
I use islice, izip, and xrange in case you're talking about potentially very long strings.
I also couldn't resist this "One Liner" which doesn't even require any indexing:
[next((i for i, (a, b) in
enumerate(izip(islice(s, start1, None), islice(s, start2, None)))
if a != b),
length - max((start1, start2)))
for start1, start2 in izip(pos, islice(pos, 1, None))]
One final method, using os.path.commonprefix:
[len(commonprefix((buffer(s, n), buffer(s, m)))) for n, m in zip(pos, pos[1:])]
>>> import os
>>> os.path.commonprefix([s[i:] for i in pos])
'_'
Let Python to manage memory for you. Don't optimize prematurely.
To get the exact output you could do (as #agf suggested):
print [len(commonprefix([buffer(s, i) for i in adj_indexes]))
for adj_indexes in zip(pos, pos[1:])]
# -> [3, 1]
I think your worrying about copies is unfounded. See below:
>>> s = "how long is a piece of string...?"
>>> t = s[12:]
>>> print t
a piece of string...?
>>> id(t[0])
23295440
>>> id(s[12])
23295440
>>> id(t[2:20]) == id(s[14:32])
True
Unless you're copying the slices and leaving references to the copies hanging around, I wouldn't think it could cause any problem.
edit: There are technical details with string interning and stuff that I'm not really clear on myself. But I'm sure that a string slice is not always a copy:
>>> x = 'google.com'
>>> y = x[:]
>>> x is y
True
I guess the answer I'm trying to give is to just let python manage its memory itself, to begin with, you can look at memory buffers and views later if needed. And if this is already a real problem occurring for you, update your question with details of what the actual problem is.
One way of doing using buffer this is give below. However, there could be much faster ways.
s = "to_be_or_not_to_be"
pos = [15, 2, 8]
lcp = []
length = len(pos) - 1
for index in range(0, length):
pre = buffer(s, pos[index])
cur = buffer(s, pos[index+1], pos[index+1]+len(pre))
count = 0
shorter, longer = min(pre, cur), max(pre, cur)
for i, c in enumerate(shorter):
if c != longer[i]:
break
else:
count += 1
lcp.append(count)
print
print lcp