Most efficient way of translating OID's in varBinds to MIB's - python-3.x

After my SNMP transaction is completed and results are stored in varBinds, I'd like to assign the MIB and the value to their own variables for further processing. When I try:
for x in varBinds
print x
the OID is translated, however, I need the mib and the value to be assigned to individual variables when I try:
for oid, val in varBinds
print oid, val
the OID is NOT translated. I have not figured out how to use .loadMibs, so I created a function to translate the OID that I invoke on oid:
T = oid2mib(oid)
def oid2mib(oid_str):
oid_tuple = tuple(oid_str)
mib_builder = builder.MibBuilder()
compiler.addMibCompiler(mib_builder)
mib_builder.loadModules('SNMPv2-MIB')
mib_view = view.MibViewController(mib_builder)
a, b, c = mib_view.getNodeName(oid_tuple)
return b[-1] + '.' + '.'.join(map(str, c))
print('Mib:%s Value:%s' % (T, val))
This works and it translates my OID to MIB, but I am wondering if this is the most efficient way of achieving my desired result? Perhaps .loadMibs might be more efficient?
UPDATE
I Just tried the following,
for x in varBinds
a, b = str(x).split('=')
print(a.rstrip(), b.rstrip(), sep=' => ')
What are the pros and cons of this approach?

Since you get your var-bindings translated in the first case, I suspect you have proper MIB loaded already.
So try this:
for oid, val in varBinds
a, b = str(oid), str(val)
print(a, b, sep=' => ')
You will need to call loadMibs() if you happen to run into the OID for which the MIB is not loaded.

Related

How can one represent distinct non-numeric symbols in sympy?

I am experimenting with the representation of a trivial statistics problem in Sympy:
For a sample space S, there are 6 possible distinct outcomes
a,b,c,d,e,f. We can define event A as having occurred if any of
a,b,c have, and event B as having ocurred if any of b,c,d have.
Given a probability mass function pmf defined over S, what is the
probability of event A?
When attempting to implement this symbolically, I receive the following error:
~/project/.envs/dev/lib/python3.6/site-packages/sympy/stats/frv.py in _test(self, elem)
164 elif val.is_Equality:
165 return val.lhs == val.rhs
--> 166 raise ValueError("Undecidable if %s" % str(val))
167
168 def __contains__(self, other):
ValueError: Undecidable if Eq(d, a) | Eq(d, b) | Eq(d, c)
The problem is implemented as follows with comments on the failing lines of code:
from sympy import Eq, Function, symbols
from sympy.logic import Or
from sympy.sets import FiniteSet, Union
from sympy.stats import FiniteRV, P
# 1. Define a sample space S with outcomes: a,b,c,d,e,f; Define events A, B
A = FiniteSet(*symbols('a b c'))
B = FiniteSet(*symbols('b c d'))
S = Union(A, B, FiniteSet(*symbols('e f')))
display("Sample Space", S)
pmfFunc = Function("pmf")
pmfDict = {v: pmfFunc(v) for v in S}
X = FiniteRV('X', pmfDict)
a,b = symbols('a b')
# 2. P(X = a) = pmf(a)
display(P(Eq(X,a)))
# 3. A.as_relational(X) yields `(X=a) \lor (X=b) \lor (X=c)`
display(A.as_relational(X))
# 4. P(X = a \lor X = b) = pmf(a) + pmf(b)
# - Actual Output: ValueError: Undecidable if Eq(c, a) | Eq(c, b)
display(P(Or(Eq(X,a), Eq(X,b)))) # [FAILS]
# 5. P(A) = pmf(a) + pmf(b) + pmf(c)
# - Actual Output: ValueError: Undecidable if Eq(d, a) | Eq(d, b) | Eq(d, c)
display(P(A.as_relational(X))) # [FAILS]
I obtain expected output up to display(A.as_relational(X)):
Interpreting the failure message suggests that Sympy is unable to tell that the set members are distinct. Replacing the symbols with integers resolves the error and I get output similar to what I desire.
A = FiniteSet(1, 2, 3)
B = FiniteSet(2, 3, 4)
S = Union(A, B, FiniteSet(5, 6))
If I am not misunderstanding the error or the fundamental use of the library, is there a way to tell Sympy that a collection of symbols is entirely distinct? I have attempted to replace the symbols with Dummy instances without success, and I have also attempted to leverage the assumptions module without success:
facts = [Eq(a,b) if a is b else Not(Eq(a,b)) for a, b in itertools.product(S, S)]
with assuming(*facts):
I would like to avoid confusing mappings between integers and symbolic forms, as user error may not be apparent when the results are printed as latex. I am willing to adopt some burden in a workaround (e.g., as it would have been maintaining a collection of Dummy instances), but I have yet to find an acceptable workaround.
Interesting question. Maybe it can be done with with assuming(Ne(a,b), ...): context but I take a more pragmatic approach: replace symbols with cos(non-zero integer) which SymPy can easily distinguish as equal or not:
>>> reps = dict(zip(var('a:f'),(cos(i) for i in range(1,7))))
>>> ireps = {v:k for k,v in reps.items()}
>>> a,b,c,d,e,f = [reps[i] for i in var('a:f')]
Then remove your a, b = symbols... line and replace display(x) with display(x.subs(ireps) to get
('Sample Space', FiniteSet(a, b, c, d, e, f))
(pmf(a),)
(Eq(X, a) | Eq(X, b) | Eq(X, c),)
(pmf(a) + pmf(b),)
(I use cos(int) instead of int because I am not sure whether any computation would result in addition of two elements and I want to make sure they stay distinct.)
Another approach would be to define a constant class that derives from Symbol:
class con(Symbol):
def __hash__(self):
return id(self)
def __eq__(a,b):
if isinstance(b, con):
return a.name == b.name
_eval_Eq = __eq__
a,b,c,d,e,f=map(con,'abcdef')
display=lambda*x:print(x)
from sympy import Eq, Function, symbols
from sympy.logic import Or
from sympy.sets import FiniteSet, Union
from sympy.stats import FiniteRV, P
A = FiniteSet(a,b,c)
B = FiniteSet(b,c,d)
S = Union(A, B, FiniteSet(e,f))
pmfFunc = Function("pmf")
pmfDict = {v: pmfFunc(v) for v in S}
X = FiniteRV('X', pmfDict)
display("Sample Space", S)
display(P(Eq(X,a)))
display(A.as_relational(X))
display(P(Or(Eq(X,a), Eq(X,b))))
display(P(A.as_relational(X)))
gives
('Sample Space', FiniteSet(a, b, c, d, e, f))
(pmf(a),)
(Eq(X, a) | Eq(X, b) | Eq(X, c),)
(pmf(a) + pmf(b),)
(pmf(a) + pmf(b) + pmf(c),)

python finding the greatest common divisor of two numbers program

I am a new Python learner. I am trying to finding the greatest common divisor of two numbers (a =1071 and b = 462 for example). I have written two programs for this. the first one is working but the second one gives the wrong answer. what is the problem with my program??
# first program (works)
a, b = 1071, 462
while b:
a, b = b, a % b
print(a)
# second program (doesn't work truly)
a = 1071
b = 462
while b:
a = b
b = a % b
print(a)
Explanation:
Yes, HSK is right. In the 2nd loop:
while b:
a = b
b = a % b
print(a)
First a is changed to b and then what you do is b = b% b. But here:
a, b = b, a % b
it is executed as one-line so a is still a.
Solution:
So just add a third variable:
a = 1071
b = 462
while b:
c = a
a = b
b = c % b
print(c)
One thing that distinguishes Python from other programming languages is that it is interpreted rather than compiled. This means that it is executed line by line.
The second doesn't work because, for the calculation of b, you need to use the old a, not the new a that got generated on the line before (this is actually set to b so you will get b % b, which will generally be zero). The equivalent to the first loop would be:
while b:
oldA = a
a = b
b = oldA % b
print(a)
The tuple assignment in Python can be considered an atomic operation where all the values on the right side are loaded up, then assigned to all the variables on the left side.
def divisor(n):
if n ==1 or n ==2 or n ==3:
return []
else:
result=[]
aux=2
while aux <= n:
if n % aux == 0:
result.append(aux)
aux=aux+1
return result
def func (m,n):
div1=divisor(m)
div2=divisor(n)
result =[]
for x in div1:
for y in div2:
if x == y:
result.append(x)
return result
print(func (x,y))

Pulling values from lists nested in a dictionary using for loop

Background on what I am doing for context:
I used a scraping tool to return prices for items on various sites to compare them. The information was originally stored as nested dictionaries of the form
{'55" 4K HDR': {'BEST BUY': 279.99, "KOHL'S": 279.99,'TARGET': 279.99},
'55" 4K UHD LED': {'BEST BUY': 329.99,'COSTCO': 349.99,'TARGET': 329.99, 'WALMART': 328.0}...}
and so on. I used for loops to then reorder the nested dictionaries to only have the lowest price, but in doing so converted them to lists.
def sortKey(keyValue):
g = {}
for k, subdic in keyValue.items():
g[k] = {}
for subk, v in sorted(subdic.items(), key=lambda x: x[1], reverse=True):
g[k] = [subk, v]
return g
This resulted in the following output
{'55" 4K HDR': ['BEST BUY', 279.99],
'55" 4K UHD LED': ['WALMART', 328.0]...}
Now I am trying to switch the format of the nested lists into a single dictionary so I can use a greedy algorithm to find all the ways I can spend a certain budget. I am hoping to get an output like
{'55" 4K HDR': 279.99, '55" 4K UHD LED': 328.0...}
and so on. I am trying to use a similar for loop to the one I used before
def greedyKey(keyGreed):
f= {}
for g, subGreed in keyGreed.items():
f[g] = ()
for subg, v in subGreed:
f = v
return f
but am getting
ValueError: too many values to unpack (expected 2)
I know this has to do with the values of my lists, but I am confused because I thought each nested list only had 2 values
['WALMART', 328.0]
minimal executable example
import pprint
dataDict = {'55" 4K HDR': {'BEST BUY': 279.99, "KOHL'S": 279.99,'TARGET': 279.99},
'55" 4K UHD LED': {'BEST BUY': 329.99,'COSTCO': 349.99,'TARGET': 329.99, 'WALMART': 328.0}}
def sortKey(keyValue):
g = {}
for k, subdic in keyValue.items():
g[k] = {}
for subk, v in sorted(subdic.items(), key=lambda x: x[1], reverse=True):
g[k] = [subk, v]
return g
def greedyKey(keyGreed):
f= {}
for g, subGreed in keyGreed.items():
f[g] = ()
for subg, v in subGreed:
f = v
return f
masterList = sortKey(dataDict)
pprint.pprint(masterList)
greedyList = greedyKey(masterList)
pprint.pprint(greedyList)
Please refer to this answer which states:
Python employs assignment unpacking when you have an iterable being assigned to multiple variables.
Essentially, subg, v = subGreed is equivalent to subg, v = subGreed[0], subGreed[1], which is what I think you're looking for here.
There is no need to make f[g] a tuple, either.
def greedyKey(keyGreed):
f = {}
for g, subGreed in keyGreed.items():
subg, v = subGreed
f[g] = v
return f

Whats wrong in this code to remove vowels?

def anti_vowel(t):
v = "aeiouAEIOU"
g = ""
for i in t:
for c in v:
if i == c:
g = g + i
print(g)
anti_vowel("umbrella")
o/p : uea
Why am I getting the o/p with only vowels but i wanted to do the exact opposite?
To make your code work, you can either switch to using in, or use a for-else statement and break if you do have a vowel match:
def anti_vowel(t):
v = "aeiouAEIOU"
g = ""
for i in t:
for c in v:
if i == c:
break
else:
g += i
return g
which does now give the intended output! :)
If you were after something slightly more efficient, you could use a generator with str.join:
def anti_vowel(t):
v = "aeiouAEIOU"
return ''.join(c for c in t if c not in v)
which we can see works:
>>> anti_vowel("umbrella")
'mbrll'
Note that using in is faster than a for-loop as the operation is much more optimised at the low-level. It also produces much more readable (or Pythonic) code.
Oh and btw I believe functions should always have an output - even if the intention is to print that output, so I have used returns instead.
Try this.
def anti_vowel(t):
v = "aeiouAEIOU"
r=[t]
[r.append(r[-1].replace(l,'')) for l in v]
return r[-1]

back solve for a variable using python

I'm trying to write a function to back solve for a variable from another function in python, kind of like what Excel solver does.
To simplify my example, I have a function takes in several variables then calculate a price. I will be passing actual values (a,b,c,d,x) into this function so it returns a numeric value.
def calc_price(a,b,c,d,x):
value = a+b*c-d + x
return value
Now I'm given a target price, and a,b,c,d. Only unknown is variable x, so I want to back solve variable x. I want to build this into a function that takes into the same variables as calc_price, with an additional variable target_price.
def solve(target_price, a,b,c,d):
#this function takes in values for target_price, a,b,c,d
#and should do something like this:
target_price = calc_price(a,b,c,d,x)
solve for x <---------this is the part I'm not sure how to do
return x
I created a function like this below to back solve the value x by a loop but it's inefficient in calculating large datasets, so I'm looking for a more efficient solution.
def solve(target_price,a,b,c,d):
x = 0.01
while x < 1:
if abs(target_price - calc_price(a,b,c,d,x)) < 0.001:
return x
x += 0.001
Thank you!
Consider this a demo (as your task is still a bit unclear to me) and make sure to read scipy's docs to learn about the basic guarantees these method provides.
One could argue, that an approach based on root-finding is more appropriate (we are minimizing a function here; therefore the abs-construction in the residual-function), but this approach here does not need you to give some bracketing-interval.
Code:
import numpy as np
from scipy.optimize import minimize_scalar
np.random.seed(0)
""" Utils """
def calc_price(x, a, b, c, d):
value = a+b*c-d + x
return value
def calc_price_res(x, target, a, b, c, d):
value = a+b*c-d + x
return abs(value - target) # we are looking for f(x) == 0
""" Create fake-data (typically the job of OP!) """
a, b, c, d, x = np.random.random(size=5)
fake_target = calc_price(x, a, b, c, d)
print('a, b, c, d: ', a, b, c, d)
print('real x: ', x)
print('target: ', fake_target)
print('noisy obj (just to be sure): ', calc_price_res(x, fake_target, a, b, c, d))
""" Solve """
res = minimize_scalar(calc_price_res, args=(fake_target, a, b, c, d))
print('optimized x: ', res.x)
print('optimized fun: ', res.fun)
Output:
a, b, c, d: 0.548813503927 0.715189366372 0.602763376072 0.544883182997
real x: 0.423654799339
target: 0.858675077275
noisy obj (just to be sure): 0.0
optimized x: 0.423654796297
optimized fun: 3.04165614917e-09

Resources