Open egpbos opened 5 years ago
I think the problem is that u[2]
is still an array with some shape, not a scalar. The constraint functions have to return a scalar. If I understand you correctly you want u[2] < h
for every point in u[2]
? If so, you have still got some work ahead of you ;). The naive solution would be to create a separate constraint at each point, but that will probably kill your performance.
To do more advanced stuff with a single constraint model, have a look at the alternative constructor as_constraint
. With this you can turn any model into a constraint, including a CallableNumericalModel which gives you a lot more freedom.
As a second point, as I understand it rot_{x, y, z} should be between -1 and 1 (since they're rotation angles)? If so, you should add the boundaries to their parameters (rot_x.min, rot_x.max = -1, 1
), that should make the fitting a bit easier as well.
Lastly, if you have some computational power to spare, you can try to use the DfiferentialEvolution minimizer, which should find the global minimum.
@tBuLi:
u[2]
is a scalar, u
itself is a vector:
To give a bit more context of what I'm doing: you can define an implicit function for a cone, which is the one I'm defining as cone_model
here. I don't think this completely characterizes a single cone (i.e. it can still give two directions and it doesn't really constrain height), which is why I'm adding the extra constraint. See Mathworld for some more context.
However, this is a cone with it's base (the circle) in the x-y plane and the central axis along the z-axis. I want to describe a general cone anywhere in space and rotated arbitrarily, so I add three coordinates for the location and two rotation angles for the orientation.
@pckroon:
Theoretically, the angles are boundless, since 0 equals 2\pi equals -2\pi equals (+/-)2^n\pi for any integer n. In practice, I guess it may help the solver if I would limit it to be just between 0 and 2\pi. Is this what you mean?
Ok, I should maybe be more precise.
When I say "base in the x-y plane" I actually mean in the "u[0]-u[1] plane" and "z-axis" would correspond to "u[2] axis". The simple implicit cone equation holds in this u
-vector coordinate system, but the coordinates of the points I'm trying to fit to the cone are in x, y, z coordinates. The mapping is done in the code by two rotation matrices and a simple translation (subtraction) of the desired base position.
I'm doing some debugging by inserting prints in scipy and indeed somehow something seems to think that there is a 400-dimensional thing going on (which undoubtedly corresponds to the 20x20(x3) sized xyz array)...
Theoretically, the angles are boundless, since 0 equals 2\pi equals -2\pi equals (+/-)2^n\pi for any integer n. In practice, I guess it may help the solver if I would limit it to be just between 0 and 2\pi. Is this what you mean?
Yes. Depending on things like the phase of the moon numerical minimizers can really suffer for degenerate answers. And bounds are easier than constraints.
Yes, it's a good idea, I'm using bounds now, thanks @pckroon
However, my problem still stands. The model doesn't fully constrain the cone, so I need an extra constraint, which still gives the same exception.
@egpbos , maybe I should've been more clear, indeed in your model u[2]
is a scalar, but numerically it is not since you call fit with
cone_fit = sf.Fit(cone_model, x=xyz[0], y=xyz[1], z=xyz[2], f=np.zeros_like(xyz[0]))
so x, y, z
are some kind of arrays. And so the output of u[2]
will be something of the same shape as x
. thanks to the wonder of ducktyping ;).
I see a few ways forward:
1) Make a constraint from a CallableNumericalModel
, as @tBuLi suggested
2) Change the constraint to something like sf.Max(u[2]**2) < h**2
, or reformulate it in some other way to reduce it to a single value (norm? average? The problem with Max is that it is not differentiable).
3) Get a good initial guess for h and u, for example based on the largest distance found between any two points in your data set, and hope for the best.
4) Run the fit twice: first unconstrained to get an initial guessed value for u and h, and use those to construct a constraint. Run the fit again to find the final answer. Note that this option feels very unsatisfactory.
Could you help me understand how CallableNumericalModel
can be used in this case?
Options 2-4 will not do. The problem, as I think I'm beginning to understand better now, is really that without the constraint, the model is underconstrained. The cone_model
equation by itself actually describes a double cone with infinite height, like this: http://mathworld.wolfram.com/DoubleCone.html
Without the height constraint, and in case the points are rather noisy, the cone is likely to find "better" fits than the actual generating single cone, because the upper half of the double cone will fit better to the points at the top of the single cone.
How can I use CallableNumericalModel
to make a constraint on u[2] (interpreted as a variable)?
Ah, now I understand your option 2. I tried it, but it gives the same Exception, unexpectedly...
Using CallableNumericalModel
you could write any pythonic function you might need. For example:
def constraint(u_2, h):
""" Do your magic here """
return np.sum(u_2 < h) - u_2.size
c, u_2 = variables('c, u_2')
constraint = CallableNumericalModel.as_constraint(
{c: constraint, u_2: u[2]},
connectivity_mapping={c: {u_2, h}},
constraint_type=LessThan,
model=model
)
I didn't think about if this is the right constraint at all but hopefully it will demonstrate how you can use this. (The constraint function is then assumed to be of the type lhs - rhs < 0.)
I'm trying to fit a point distribution to a cone shape. I use
ectopylasm
for this (can bepip install
ed as described in the README, it's only used in this issue for generating the point distribution). When I try to fit as follows it works, but the fit is often not great, the main problems being the height and the fact that often the x-axis rotation is $\pi$ away from what I'd like:This will print something like
This is all fine (not ideal, but not the problem I'm focusing on here). However, when I now try to improve my fit by adding the constraint that $|z| \le h$, or actually $u_2 \le h$, i.e. the non-rotated z-axis of the cone should not be higher than the height of the cone (which will hopefully simultaneously constrain the x-rotation and the height), in the following way:
I get the following error:
Any idea what's going wrong here?