Variable associated to "Optimization terminated successfully" in scipy.optimize.fmin_cg? - scipy

I am using scipy.optimize.fmin https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.optimize.fmin_cg.html.
What is the variable associated to "Optimization terminated successfully"?
I need it such that I could write something like:
if "optimization not succesful" then "stop the for loop"
Thank you.

Just follow the docs.
You are interested in warnflag (as mentioned by cel in the comments), the 5th element returned, so just index
(0-indexing in python!) the result with result[4] to obtain your value.
The docs also say that some of these are only returned when called with argument full_output=True, so do this.
Simple example:
import numpy as np
args = (2, 3, 7, 8, 9, 10) # parameter values
def f(x, *args):
u, v = x
a, b, c, d, e, f = args
return a*u**2 + b*u*v + c*v**2 + d*u + e*v + f
def gradf(x, *args):
u, v = x
a, b, c, d, e, f = args
gu = 2*a*u + b*v + d # u-component of the gradient
gv = b*u + 2*c*v + e # v-component of the gradient
return np.asarray((gu, gv))
x0 = np.asarray((0, 0)) # Initial guess.
from scipy import optimize
res1 = optimize.fmin_cg(f, x0, fprime=gradf, args=args, full_output=True) # full_output !!!
print(res1[4]) # index 4 !!!

Related

Is this scala function using right-fold or left-fold?

def calculate(f: Int => Int, sumProd:(Int, Int)=>Int, n: Int, a:Int, b:Int):Int =
if (a>b) n
else sumProd(f(a), calculate(f, sumProd, n, a+1, b))
This scala function can in a chosen number area (a to b) do chosen calculations with them:
example calling:
calculate(x=>2*x, (x,y)=>x+y, 0, 2 , 4)
this calculates: 2*2 + 2*3 + 2*4 = 18
Which folding(right- or left folding) is this function using? And how to see that?
further example callings for the function:
calculate(x=>2+x, (x,y)=>x*y,1, 2 , 4)
calculate(x=>2+x, (a,b)=>a+b,0, 1, 5)
calculate(x=>2*x, (a,b)=>a+b,0, 1, 5)
What you have is equivalent to, in pseudocode,
calculate(f, sumProd, n, a, b)
=
fold-right( sumProd, n, map(f, [a .. b]))
where [a .. b] denotes a list of numbers from a to b, inclusive, increasing by the step of 1. In other words, it is the same as
=
sumProd( f(a),
sumProd( f(a2),
sumProd( f(a3),
...
sumProd( f(b), n) ... )))

Root finding using a loop

I have one equation defined in the function
def fun(x, y, z, v, b):
Y = (z*(np.sign(x) * (np.abs(x))**(y-1))) - (v*np.sign(b) * (np.abs(b))**(v-1))/(1-b**v)
return Y.flatten()
that I want to solve for the value of x, given the values of Z0, SS (year 1: Z0=1.2, SS=2, ...) and different combinations of alpha and kappa, for which I am creating a grid.
Z0 = [1.2, 5, 3, 2.5, 4.2]
SS = [2, 3, 2.2, 3.5, 5]
ngrid = 10
kv = np.linspace(0.05, 2, ngrid)
av = np.linspace(1.5, 4, ngrid)
q0 = []
for z in range(len(Z0)):
zz = Z0[z]
ss = SS[z]
for i in range(ngrid):
for j in range(ngrid):
kappa = kv[i]
alpha = av[j]
res0 = root(lambda x: fun(x, alpha, zz, kappa, ss), x0=np.ones(range(ngrid)))
q0 = res0.x
print(q0)
where y = alpha; v=kappa, z = Z0; b = S.
I am getting all [], [], ....
Not sure what is going on. Thanks for your help
Before you attempt to use res0.x, check res0.success. In this case, you'll find that it is False in each case. When res0.success is False, take a look at res0.message for information about why root failed.
During development and debugging, you might also consider getting the solver working for just one set of parameter values before you embed root in three nested loops. For example, here are a few lines from an ipython session (variables were defined in previous lines, not shown):
In [37]: res0 = root(lambda x: fun(x, av[0], Z0[0], kv[0], SS[0]), x0=np.ones(range(ngrid)))
In [38]: res0.success
Out[38]: False
In [39]: res0.message
Out[39]: 'Improper input parameters were entered.'
The message suggests that something is wrong with the input parameters. You call root like this:
res0 = root(lambda x: fun(x, alpha, zz, kappa, ss), x0=np.ones(range(ngrid)))
A close look at that line shows the problem: the initial guess is np.ones(range(ngrid)):
In [41]: np.ones(range(ngrid))
Out[41]: array([], shape=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), dtype=float64)
That's not what you want! The use of range looks like a simple typo (or "thinko"). The initial guess should be
x0=np.ones(ngrid)
In ipython, we get:
In [50]: res0 = root(lambda x: fun(x, av[0], Z0[0], kv[0], SS[0]), x0=np.ones(ngrid))
In [51]: res0.success
Out[51]: True
In [52]: res0.x
Out[52]:
array([-0.37405428, -0.37405428, -0.37405428, -0.37405428, -0.37405428,
-0.37405428, -0.37405428, -0.37405428, -0.37405428, -0.37405428])
All the return values are the same (and this happens for other parameters values), which suggests that you are solving a scalar equation. A closer look at fun shows that you only use x in element-wise operations, so you are in fact solving just a scalar equation. In that case, you can use x0=1:
In [65]: res0 = root(lambda x: fun(x, av[0], Z0[0], kv[0], SS[0]), x0=1)
In [66]: res0.success
Out[66]: True
In [67]: res0.x
Out[67]: array([-0.37405428])
You could also consider using root_scalar instead of root.

Min-cost flow modification for arcs with fixed cost?

I have a min-cost flow network in which some arcs have a fixed charge, that is, if arc k has non-zero flow x_k, then the cost is c_k, independent of the amount of flow. A flow of 0 incurs 0 cost. These arcs do not have capacity constraints.
I know how to model this as a mixed integer program (MIP): Add a 0/1 variable y_k with cost c_k. Set the capacity on arc k to M * y_k, where M is larger than the sum of all supplies. So the fixed cost is incurred if and only if the arc has flow.
Can this be solved using a min-cost flow formulation, which would be more efficient than a general MIP implementation? Does OR-Tools (or any other package) have an extension to min-cost flow that accommodates this?
Cross-posted to the Google OR-Tools list.
Thanks,
Hershel
I'm not sure that I understand you (most likely due to my ignorance). - you will possibly get a better response from the OR-forum than here.
However, I think there may be a way of doing what you ask as a circuit via AddCircuit()
Essentially I believe one can maximise (or minimise) those arcs which are marked as having a cost.
Here is an example using the AddCircuit constraint, where one outgoing arc from each node has a fixed cost.
from ortools.sat.python import cp_model
class DiGraphSolver:
def __init__(self, desc):
self.model = cp_model.CpModel()
self.status = cp_model.UNKNOWN
self.timing = None
# AddCircuit needs a numeric index for each node.
# Here's two lazy key->index / index->key lookups.
self.keys = {k: i for i, k in enumerate(desc.nodes.keys()) }
self.revs = {i: k for k, i in self.keys.items() }
# Determine the start and stop nodes
self.start = self.keys[desc.start]
self.stop = self.keys[desc.stop]
# Store the nodes dict in it's indexed form.
self.nodes = {self.keys[head]: [self.keys[t] for t in tails] for head,tails in desc.nodes.items()}
self.heavies = [(self.keys[head],self.keys[tail]) for head,tail in desc.heavies.items()]
self.arcs = []
self.vars = []
self.result = []
self.heavy_arcs = []
self.weight = 0
def setup(self):
self.arcs = [
(head,tail, self.model.NewBoolVar(f'{head}:{tail}')) for head, tails in self.nodes.items() for tail in tails
]
self.heavy_arcs = [arc[2] for arc in self.arcs if arc[:-1] in self.heavies]
# vars is a list of all the arcs defined in the problem.
self.vars = [arc[2] for arc in self.arcs]
# Add self loops for all *optional* nodes (because AddCircuit requires a Hamiltonian Circuit)
# for this example, that's everywhere except for 'start' and 'stop'
# We just use the keys of self.revs (the index values).
loops = [(n, n, self.model.NewBoolVar(f'{n}:{n}')) for n in self.revs if n not in [self.start, self.stop]]
self.arcs += loops
# connect the stop variable to the start variable as a dummy arc to complete the hamiltonian circuit.
# Because start and stop are not self-closing (non-optional), we don't need to set truth values.
loop = (self.stop, self.start, self.model.NewBoolVar(f'loop'))
self.arcs.append(loop)
# Now add the circuit as a constraint.
self.model.AddCircuit(self.arcs)
# Now reduce weighted nodes.
self.model.Minimize(sum(self.heavy_arcs)) # look for the shortest network with the lightest weight.
def solve(self) -> bool:
cp_solver = cp_model.CpSolver()
cp_solver.parameters.max_time_in_seconds = 1
cp_solver.parameters.num_search_workers = 12
self.status = cp_solver.Solve(self.model)
return self.summarise(cp_solver)
def summarise(self, cp_solver) -> bool:
if self.status in (cp_model.OPTIMAL, cp_model.FEASIBLE):
self.store(cp_solver)
return True
else:
if self.status == cp_model.INFEASIBLE:
print(f"Challenge for {self.step_count} arc{'s ' if self.step_count > 1 else ' '}is infeasible after {cp_solver.WallTime()}s.")
else:
print(f"Solver ran out of time.")
return False
def store(self, cp_solver):
self.timing = cp_solver.WallTime()
used = [arc for arc in self.arcs if cp_solver.Value(arc[2])]
arc = None, self.start
while True:
arc = next((link for link in used if link[0] == arc[1]), None)
self.result.append(self.revs[arc[0]])
if arc[1] == self.start:
break
self.weight = cp_solver.ObjectiveValue()
self.step_count = len(self.result) - 1
def show(self):
print(f"{'-'.join(self.result)}")
print(f'Cost: {self.weight}')
class RandomDigraph:
"""
define a problem.
26 nodes, labelled 'a' ... 'z'
start at 'a', stop at 'z'
Each node other than 'z' has a 4 outgoing arcs (random but not going to 'a')
"""
def __init__(self):
from random import sample,randint #
names = 'abcdefghijklmnopqrstuvwxyz'
arcs = 4
self.steps = 1
self.start = 'a'
self.stop = 'z'
but_first = set(names) ^ set(self.start)
self.nodes = {v: sample(but_first - set(v), arcs) for v in names}
self.heavies = {v: self.nodes[v][randint(0, arcs - 1)] for v in names if v != self.stop}
self.nodes[self.stop] = []
def print_nodes(self):
for key, value in self.nodes.items():
vs = [f" {v} " if v != self.heavies[key] else f"*{v}*" for v in value]
print(f'{key}: {"".join(vs)}')
def solve_with_steps(problem) -> int:
solver = DiGraphSolver(problem)
solver.setup()
if solver.solve():
solver.show()
return solver.step_count
def solve_az_paths_of_a_random_digraph():
problem = RandomDigraph()
problem.print_nodes()
print()
solve_with_steps(problem)
if __name__ == '__main__':
solve_az_paths_of_a_random_digraph()
Example run (solving a..z) gives
# network: (heavy arcs are marked by the tail in **.)
# eg. a->p is a heavy arc.
a: *p* d i l
b: *t* u e y
c: r v *m* q
d: q t *f* l
e: k *o* y i
f: i p z *u*
g: s h i *x*
h: *g* l j d
i: x f e *k*
j: *g* r e p
k: d *c* g q
l: r f j *h*
m: *i* b d r
n: t v y *b*
o: s x q *w*
p: w g *h* n
q: o r *f* p
r: f *c* i m
s: y c w *p*
t: *y* d v i
u: *h* z w n
v: *d* x f t
w: l c *s* r
x: *j* r g m
y: b j *u* c
z:
Solution:
a-i-e-k-g-h-j-p-w-c-q-o-s-y-b-u-n-t-v-x-r-m-d-l-f-z
Cost: 0.0

How to know which Maple command automatically maps on list entries or not?

In Mathematica, almost all commands automatically thread (or map) over a list.
In Maple, how does one determine which command automatically acts over entries of a list or a set?
For example:
y+p*x=2*sqrt(x*y);
r:=[solve(%,y)];
This gives list of two entries (the solutions)
#r := [-p*x+(2*(1+sqrt(1-p)))*x, -p*x+(2*(1-sqrt(1-p)))*x]
Now I found that collect automatically maps on each list entry
collect(r,x);
# [(-p+2+2*sqrt(1-p))*x, (-p+2-2*sqrt(1-p))*x]
But another command does not (I just picked this one)
MmaTranslator[Mma][LeafCount](r);
#37
For the above one needs to explicitly iterate over the entries of a list or a set.
map(MmaTranslator[Mma][LeafCount],r)
#[17, 19]
Is there a way in Maple to find which command automatically threads over entries of a list or a set other than trial and error?
Maple 2018.1
I don't know of any place in the documentation that says exactly which commands will automatically map over a list.
But the collection of such commands is not large. The vast majority of commands will not automatically map over a list. Most of the ones which auto-map over a list relate to simplication or related manipulation of expressions. The collection of commands which auto-map over a list contains at least these:
collect, combine, expand,
evala, evalc, evalf,
factor, normal, radnormal, rationalize, simplify
The auto-mapping over lists for those commands is mostly a convenience to provide a shorter syntax than wrapping explicitly with the map command.
There are also commands which preserve structure (unless explicitly
told, via options, that the outer list structure is the thing to alter) and thus usually accomplish the same thing for a list as mapping over the list:
convert, eval, evalindets, subs, subsindets
Modern Maple has another shorter syntax which can map a command over a list (or a set, or a Vector, etc). It is called the "elementwise" operation, and its syntax consists of appending ~ (tilde) to the command.
Eg,
discont~( [ csc(x), sec(x) ], x );
[{Pi _Z1~}, {Pi _Z2~ + 1/2 Pi}]
As far as your other example goes, note that LeafCount computes a value (metric) for the first argument considered as a single expression. But a list of items is still a single expression. So it certainly should not be surprising that (without the ~) it acts on the list as a whole, rather than automatically mapping over it. It counts the enclosing list as an additional "leaf".
MmaTranslator:-Mma:-LeafCount( L0 );
8
L0 := [ sin(x), 1/2*x*cos(x) ]:
MmaTranslator:-Mma:-LeafCount~( L0 );
[2, 5]
map( MmaTranslator:-Mma:-LeafCount, L0 );
[2, 5]
For an example similar to your original there is no difference in applying collect (which auto-maps) and applying it elementwise with collect~. Here, the first two results are the same because the addtional argument, x, happens to be a scalar. Eg,
r := [p*x+(2*(x^2+p^2))*x, p*x+(2*(x^2-p^2))*x]:
collect(r, x);
3 2 3 2
[2 x + (2 p + p) x, 2 x + (-2 p + p) x]
collect~(r, x);
3 2 3 2
[2 x + (2 p + p) x, 2 x + (-2 p + p) x]
map(collect, r, x);
3 2 3 2
[2 x + (2 p + p) x, 2 x + (-2 p + p) x]
I should mention that the above examples will behave differently if the second argument is a list such as [x,p] rather than a scalar such as x.
s := [a*b+(2*(a^2*b+b^2))*a, a*b+(2*(a^2*b-b^2))*a]:
collect(s, [a,b]);
3 2 3 2
[2 b a + (2 b + b) a, 2 b a + (-2 b + b) a]
map(collect, s, [a,b]);
3 2 3 2
[2 b a + (2 b + b) a, 2 b a + (-2 b + b) a]
collect~(s, [a,b]);
3 2 2 3
[2 b a + (2 b + b) a, -2 a b + (2 a + a) b]
zip(collect, s, [a,b]);
3 2 2 3
[2 b a + (2 b + b) a, -2 a b + (2 a + a) b]
In the above, the elementiwise collect~ example acts like zip when the second argument is also a list. That is, the first item in the first argument is collected wrt the first item in the second argument, and the second item in the first argument is collected wrt to the second item in the second argument.
Another feature of the elementwise operator syntax is that it will not map the command over the operands of a scalar expression (ie. not a list, set, Vector, etc). This is in stark contrast to map, which can be used to map an operation over the operands of an expression.
Here are two examples where map applies the command to the operands of a scalar expression, while using elementwise ~ gets the command applied only to the scalar expression itself. In the first example the operands are the summands of a sum of terms. In the second example the operands are the arguments of an unevaluated function call.
T := x^2 * sin(x) + y^2 * cos(x):
F( T );
2 2
F(x sin(x) + y cos(x))
F~( T );
2 2
F(x sin(x) + y cos(x))
map( F, T );
2 2
F(x sin(x)) + F(y cos(x))
G( arctan(a, b) );
G(arctan(a, b))
G~( arctan(a, b) );
G(arctan(a, b))
map( G, arctan(a, b) );
arctan(G(a), G(b))
So, if you don't want to map a command inadvertantly over the operands of a scalar expression (addend, multiplicands, etc) then you can use the elementwise ~ syntax without having to first test whether the first expression is a scalar or a list (etc).
Again, if there is an additional argument then it makes a difference whether it is a scalar to a list.
F( T, a );
F(sin(x) + cos(x), a)
F~( T, a );
F(sin(x) + cos(x), a)
map( F, T, a );
F(sin(x), a) + F(cos(x), a)
F( T, [a,b] );
F(sin(x) + cos(x), [a, b])
map( F, T, [a,b] );
F(sin(x), [a, b]) + F(cos(x), [a, b])
F~( T, [a,b] );
[F(sin(x) + cos(x), a), F(sin(x) + cos(x), b)]
zip( F, T, [a,b] );
[F(sin(x) + cos(x), a), F(sin(x) + cos(x), b)]

Nim operator overloading

Just started programming in the Nim language (which I really like so far). As a learning exercise I am writing a small matrix library. I have a bunch more code, but I'll just show the part that's relevant to this question.
type
Matrix*[T; nrows, ncols: static[int]] = array[0 .. (nrows * ncols - 1), T]
# Get the index in the flattened array corresponding
# to row r and column c in the matrix
proc index(mat: Matrix, r, c: int): int =
result = r * mat.ncols + c
# Return the element at r, c
proc `[]`(mat: Matrix, r, c: int): Matrix.T =
result = mat[mat.index(r, c)]
# Set the element at r, c
proc `[]=`(mat: var Matrix, r, c: int, val: Matrix.T) =
mat[mat.index(r, c)] = val
# Add a value to every element in the matrix
proc `+=`(mat: var Matrix, val: Matrix.T) =
for i in 0 .. mat.high:
mat[i] += val
# Add a value to element at r, c
proc `[]+=`(mat: var Matrix, r, c: int, val: Matrix.T) =
mat[mat.index(r, c)] += val
# A test case
var mat: Matrix[float, 3, 4] # matrix with 3 rows and 4 columns
mat[1, 3] = 7.0
mat += 1.0
# add 8.0 to entry 1, 3 in matrix
`[]+=`(mat, 1, 3, 8.0) # works fine
All this works fine, but I'd like to be able to replace the last line with something like
mat[1, 3] += 4.0
This won't work (wasn't expecting it to either). If I try it, I get
Error: for a 'var' type a variable needs to be passed
How would I create an addition assignment operator that has this behavior? I'm guessing I need something other than a proc to accomplish this.
There are two ways you can do this:
Overload [] for var Matrix and return a var T (This requires the current devel branch of Nim):
proc `[]`(mat: Matrix, r, c: int): Matrix.T =
result = mat[mat.index(r, c)]
proc `[]`(mat: var Matrix, r, c: int): var Matrix.T =
result = mat[mat.index(r, c)]
Make [] a template instead:
template `[]`(mat: Matrix, r, c: int): expr =
mat[mat.index(r, c)]
This causes a problem when mat is not a value, but something more complex:
proc x: Matrix[float, 2, 2] =
echo "x()"
var y = x()[1, 0]
This prints x() twice.