I am trying to solve a MIP with CBC using pyomo's solver factory, however running into some infeasibility issues. I wanted to first try configuring the tolerance level and see if that works before diving deep into the data points that could cause the infeasibility.
However when I use this command, the cbc solver outputs an error:
options = {
'tol': 0.0001
}
solver = SolverFactory(solver_type)
solver.options.update(options)
Can anyone help me with the understanding how to define tolerance level in cbc? Thanks!
So, it depends a bit. Assuming you are looking for the tolerance for a mixed integer program, the keyword for CBC is 'ratio'.
Here is a setup that runs 6 threads, max 20 seconds, ratio of 0.02 (2% gap)
### SOLVE
solver = pyo.SolverFactory('cbc')
solver.options = {'sec': 20, 'threads': 6, 'ratio': 0.02}
results = solver.solve(mdl)
print(results)
There are several different types of syntax that are acceptable here... You can pass the options in to the SolverFactory, etc... but this works fine for me.
As another trick, I always get hung up on the correct keywords for these solvers.... If you have CBC installed properly, you can just go to the terminal, open CBC with the command cbc, which should give you the 'coin' prompt and type "?" to see the commands. Then you can use the command and double '??' to get details. This also works for glpk which is super helpful.
For instance:
% cbc
Welcome to the CBC MILP Solver
Version: 2.10.5
Build Date: Dec 5 2021
CoinSolver takes input from arguments ( - switches to stdin)
Enter ? for list of commands or help
Coin:?
In argument list keywords have leading - , -stdin or just - switches to stdin
One command per line (and no -)
abcd? gives list of possibilities, if only one + explanation
abcd?? adds explanation, if only one fuller help
abcd without value (where expected) gives current value
abcd value sets value
Commands are:
Double parameters:
dualB(ound) dualT(olerance) primalT(olerance) primalW(eight) psi
zeroT(olerance)
Branch and Cut double parameters:
allow(ableGap) cuto(ff) inc(rement) integerT(olerance) preT(olerance)
pumpC(utoff) ratio(Gap) sec(onds)
Integer parameters:
force(Solution) idiot(Crash) maxF(actor) maxIt(erations) output(Format)
randomS(eed) slog(Level) sprint(Crash)
Branch and Cut integer parameters:
cutD(epth) cutL(ength) depth(MiniBab) hot(StartMaxIts) log(Level) maxN(odes)
maxSaved(Solutions) maxSo(lutions) passC(uts) passF(easibilityPump)
passT(reeCuts) pumpT(une) randomC(bcSeed) slow(cutpasses) strat(egy)
strong(Branching) trust(PseudoCosts)
Keyword parameters:
allC(ommands) chol(esky) crash cross(over) direction error(sAllowed)
fact(orization) keepN(ames) mess(ages) perturb(ation) presolve
printi(ngOptions) scal(ing) timeM(ode)
I have a system of ODE and want to find equilibrium points by using nonlinsolve() but when i run it by jubyter or spyder the program keep running without any result.
N,x1,x2,x3,x4,y1,y2,r1,r2,r3,r4,eta1,eta2,eta3,eta4,R,c1,c2,c3,c4,a11,a12,a21,a22,a31,a32,a41,a42,b12,h,h11,h12,h21,h22,h31,h32,h41,h42,s1,s2,s3,s4,epsilon1,epsilon2,omega1,omega2,K11,K22,beta11,beta21,beta31,beta41,beta12,beta22,beta32,beta42,gamma12=sp.symbols('x1,x2,x3,x4,y1,y2,r1,r2,r3,r4,eta1,eta2,eta3,eta4,N,R,c1,c2,c3,c4,a11,a12,a21,a22,a31,a32,a41,a42,b12,h,h11,h12,h21,h22,h31,h32,h41,h42,s1,s2,s3,s4,epsilon1,epsilon2,omega1,omega2,K11,K22,beta11,beta21,beta3a,beta41,beta12,beta22,beta32,beta42,gamma12')
F2=x1*(r1*(1-(eta1*x1+eta2*x2+eta3*x3+eta4*x4)/N)-(a11*y1)/(y1+a11*h11*x1)-(a12*y2)/(y2+a12*h12*x1))+s1
F3=x2*(r2*(1-(eta1*x1+eta2*x2+eta3*x3+eta4*x4)/N)-(a21*y1)/(y1+a21*h21*x2)-(a22*y2)/(y2+a22*h22*x2))+s2
F4=x3*(r3*(1-(eta1*x1+eta2*x2+eta3*x3+eta4*x4)/N)-(a31*y1)/(y1+a31*h31*x3)-(a32*y2)/(y2+a32*h32*x3))+s3
F5=x4*(r4*(1-(eta1*x1+eta2*x2+eta3*x3+eta4*x4)/N)-(a41*y1)/(y1+a42*h41*x4)-(a42*y2)/(y2+a42*h42*x4))+s4
F6=y1*(-epsilon1*(1+(y1+omega2*y2)/K11)-(b12*y2)/(y2+b12*h*y1)\
+beta11*(a11*x1)/(y1+a11*h11*x1)\
+beta21*(a21*x2)/(y1+a21*h21*x2)\
+beta31*(a31*x3)/(y1+a31*h31*x3)\
+beta41*(a41*x4)/(y1+a41*h41*x4))
F7=y2*(-epsilon2*(1+(omega1*y1+y2)/K22)+gamma12*(b12*y1)/(y2+b12*h*y1)\
+beta12*(a12*x1)/(y2+a12*h12*x1)\
+beta22*(a22*x2)/(y2+a22*h22*x2)\
+beta32*(a32*x3)/(y2+a32*h32*x3)\
+beta42*(a42*x4)/(y2+a42*h42*x4))
equ=(F2,F3,F4,F5,F6,F7)
sol=nonlinsolve(equ,x1,x2,x3,x4,y1,y2)
print(sol)
Is it possible to get the solution in terms of parameters?
Your system of equations can be recast as multivariate polynomial system if you multiply through by all of the denominators. Doing this for example in the case of F2 you would get
In [26]: F2.as_numer_denom()[0]
Out[26]:
s₁⋅x₁⋅(a₁₁⋅h₁₁⋅x₂ + y₂)⋅(a₁₂⋅h₁₂⋅x₂ + r₁) + x₂⋅(-a₁₁⋅x₁⋅y₂⋅(a₁₂⋅h₁₂⋅x₂ + r₁) - a₁₂⋅r₁⋅x₁⋅(a₁₁⋅h₁₁⋅x₂ + y₂) + r₂⋅(a₁₁⋅h₁₁⋅x₂ + y₂
)⋅(a₁₂⋅h₁₂⋅x₂ + r₁)⋅(-N⋅y₁ - η₂⋅x₂ - η₃⋅x₃ - η₄⋅x₄ + x₁))
We can see from here that the polynomial is of order 5 since it has terms like x2**3*N*y1 so broadly you have a system of 7 polynomials not of low order. I expect that a general closed form solution will not be possible unless you are lucky.
This question already has answers here:
floating point in python gives a wrong answer [duplicate]
(3 answers)
why am I getting an error using math.sin(math.pi) in python?
(1 answer)
Closed 5 years ago.
i tried to create polar array with math module ; but math.sin(math.pi) always give wrong result.
with python 2.7 or 3.5 the same wrong result :
import math
m = math.radians(180)
print (math.sin(m))
pi = math.pi
print (pi)
print (math.sin(pi))
1.2246467991473532e-16
3.141592653589793
1.2246467991473532e-16
this is my code and the same error:
import math
a = 180 #(degree)
r = 10
n = 8
b = float(a)/n
pi = math.radians(180)
print math.sin(pi)
for i in range(0,2*n+1):
print i
c1 = b*i
print c1
c2 = c1*math.pi/a #c : radians
print c2
sinb = math.sin(c2)
cosb = math.cos(c2)
x = r*sinb
y = r*cosb
#print (x, y)
the threads mentioned in the comment give explanation not a solution ; so i don't need explanation how and why without solution to solve my problem and the answer from cody give me the solution.
if you think that the other threads show the answer mention in these threads that are duplicate.
Since pi is an irrational number and goes on forever, the Python version is not actually exact pi. As a result, the sin of almost-pi is almost-0. Basically you can chalk it up to a Python rounding error.
Here's some more information on the topic in general:
Floating Point Arithmetic: Issues and Limitations
why am I getting an error using math.sin(math.pi) in python?
I suggest you put some rounding in to the nearest N units that will suffice for your module. The numerical value of what you got is 0.000000000000000122. Five digits after the decimal should be good for almost anything you could need the module for.
The following code (taken from - https://github.com/dennybritz/tf-rnn/blob/master/bidirectional_rnn.ipynb)
import tensorflow as tf
import numpy as np
tf.reset_default_graph()
# Create input data
X = np.random.randn(2, 10, 8)
# The second example is of length 6
X[1,6:] = 0
X_lengths = [10, 6]
cell = tf.contrib.rnn.LSTMCell(num_units=64, state_is_tuple=True)
outputs, states = tf.nn.bidirectional_dynamic_rnn(
cell_fw=cell,
cell_bw=cell,
dtype=tf.float64,
sequence_length=X_lengths,
inputs=X)
output_fw, output_bw = outputs
states_fw, states_bw = states
is giving the following error for
tensorflow - 1.1 for both 2.7 and 3.5
ValueError: Attempt to reuse RNNCell <tensorflow.contrib.rnn.python.ops.core_rnn_cell_impl.LSTMCell object at 0x10ce0c2b0>
with a different variable scope than its first use. First use of cell was with scope
'bidirectional_rnn/fw/lstm_cell', this attempt is with scope 'bidirectional_rnn/bw/lstm_cell'.
Please create a new instance of the cell if you would like it to use a different set of weights.
If before you were using: MultiRNNCell([LSTMCell(...)] * num_layers), change to:
MultiRNNCell([LSTMCell(...) for _ in range(num_layers)]). If before you were using the same cell
instance as both the forward and reverse cell of a bidirectional RNN, simply create two instances
(one for forward, one for reverse). In May 2017, we will start transitioning this cell's behavior to use
existing stored weights, if any, when it is called with scope=None (which can lead to silent model degradation,
so this error will remain until then.)
But it is working in
tensorflow - 1.0.1 for python 3.5 (did not test on python - 2.7)
I tried with multiple code examples I found online but
tf.nn.bidirectional_dynamic_rnn
is giving the same error with tensorflow - 1.1
Is there a bug in tensorflow 1.1 or am i just missing something?
Sorry you ran into this. I can confirm that the error appears in 1.1 (docker run -it gcr.io/tensorflow/tensorflow:1.1.0 python) but not in 1.2 RC0 (docker run -it gcr.io/tensorflow/tensorflow:1.2.0-rc0 python).
So it looks like either 1.2-rc0 or 1.0.1 are your options for the moment.
The GNU C Library has the function drem (alias remainder).
How can I simulate this function just using the modules supported by Google App Engine Python 2.7 runtime?
From the GNU manual for drem:
These functions are like fmod except that they round the internal quotient n to the nearest integer instead of towards zero to an integer. For example, drem (6.5, 2.3) returns -0.4, which is 6.5 minus 6.9.
From the GNU manual for fmod:
These functions compute the remainder from the division of numerator by denominator. Specifically, the return value is numerator - n * denominator, where n is the quotient of numerator divided by denominator, rounded towards zero to an integer. Thus, fmod (6.5, 2.3) returns 1.9, which is 6.5 minus 4.6.
Reading the documentation the following Python code should work:
def drem(x, y):
n = round(x / y)
return x - n * y
However with Python, drem(1.0, 2.0) == -1.0 and with C drem(1.0, 2.0) == 1.0. Note Python returns negative one and C returns positive one. This is almost certainly an internal difference in rounding floats. As far as I can tell both functions perform the same otherwise where parameters 2 * x != y.
How can I make my Python drem function work the same as its C equivalent?
The key to solving this problem is to realise that the drem/remainder function specification requires the internal rounding calculation to round to half even.
Therefore we cannot use the built-in round function in Python 2.x as it rounds away from 0. However the round function in Python 3.x has changed to round to half even. So the following Python 3.x code will be equivalent to the GNU C Library drem function but will not work in Python 2.x:
def drem(x, y):
n = round(x / y)
return x - n * y
To achieve the same with Python 2.x we can use the decimal module and its remainder_near function:
import decimal
def drem(x, y):
xd = decimal.Decimal(x)
yd = decimal.Decimal(y)
return float(xd.remainder_near(yd))
EDIT: I just read your first comment and see that you cannot use the ctypes module. Anyways, I learned a lot today by trying to find an answer to your problem.
Considering that numpy.round() rounds values exactly halfway between rounded decimal values to the next even integer, using numpy is not a good solution.
Also, drem internally calls this MONSTER function, which should be hard to implement in Python.
Inspired by this article, I would recommend you to call the drem function from the math library directly. Something along these lines should do the trick:
from ctypes import CDLL
# Use the C math library directly from Python
# This works for Linux, but the version might differ for some systems
libm = CDLL('libm.so.6')
# For Windows, try this instead:
# from ctypes import cdll
# libm = cdll.libc
# Make sure the return value is handled as double instead of the default int
libm.drem.restype = c_double
# Make sure the arguments are double by putting them inside c_double()
# Call your function and have fun!
print libm.drem(c_double(1.0), c_double(2.0))