Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

method to generate an initial guess. Fixes #354 #365

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

Peter230655
Copy link
Contributor

Is it o.k. to be a method, or should I make it a property?

@moorepants
Copy link
Member

Is there a good choice of one of the existing examples to add this to? You can show how it is used to the user.

@Peter230655
Copy link
Contributor Author

Is there a good choice of one of the existing examples to add this to? You can show how it is used to the user.

You mean in examples-gallery?
If yes, surely I will find an example.
Would you have to merge this first, or would I include the example I find in this PR #365?

@moorepants
Copy link
Member

You can include the change to the example here.


Returns
-------
initial_guess : (n*N + q*N + r + s)-ndarray
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
initial_guess : (n*N + q*N + r + s)-ndarray
initial_guess : ndarray, shape(n*N + q*N + r + s,)

ux: (-1.0, 1.0),
y: (-4.0, 4.0),
uy: (-1.0, 1.0),
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Easier to compare if placed here:

image

x.func(t1) - 1.5*b1,
y.func(t1) - 4.0,
ux.func(t1) - 1.0+b2,
uy.func(t1) - 4.5,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case I would expect uy to go from 0.0 to 4.5 to 0.0., but you set it to 4.5 to 4.5 to 4.5.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i.e. if not specified, the guess should be at zero

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but maybe this more a design question. if there is only one instance constraint, what assumption to we make about any other values of time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but maybe this more a design question. if there is only one instance constraint, what assumption to we make about any other values of time?

My assumption was that if there is only one instance constraint for a state variable it will have this value at all times. I thought this was the most reasonable one.


# A2: np.inf, -np.inf in bounds
bounds[a1] = (-np.inf, 10.0)
bounds[a2] = (-10.0, np.inf)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a1 and a2 are parameters, so it wouldn't affect the initial guess, right? i get same guess as first test:

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a1, a2 are unknown parameters. I set their initial value like this: if there is a bound {a1: (s, t)} I set it at (s + t) /2.
If one of s or t is np.inf I set it to the other (finite) value.
I did not consider bounds which have np.inf on both ends, as they do not make sense in my opinion.

Parameters do not show in the plots.


x.func(tf) + 1.0,
ux.func(tf) + 5.0,
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

y: (-4.0, 4.0),
uy: (-1.0, 1.0),
h: (1.0, 2.0),
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image


# B2: np.inf, -np.inf in bounds
bounds[a1] = (-np.inf, 10.0)
bounds[a2] = (-10.0, np.inf)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

initial_guess = prob.create_linear_initial_guess()
np.testing.assert_allclose(initial_guess, expected_guess)

# B3: no bounds
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 'peak' plots happen like this If there is no bound for h, h is assumed to be zero.
So, all times ti = integer * h = 0.
The plots for u1, u2 should have a dot at (0 | 0).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess h should never be zero, right? So maybe we should always assume a value for it...but what value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess h should never be zero, right? So maybe we should always assume a value for it...but what value?

I have found, that one should always bound h to be non-negative, to avoid senseless 'solutions'.
If there is a bound, say, {h: (0, 0.5)} I set h = 0.25.
So, maybe this would not be a bad default value?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without the user giving some idea of what the total duration of the simulation might be, it's hard (or impossible) to pick a starting number. If someone is simulating molecular dynamics, maybe their duration is a tenth of a second. I guess we could default to some very small value of h. Or this function could take an extract kwarg: expected_duration=10.0 where the user can give us a bit more info.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expected duration could default to 1.0 second (just as a simple number).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expected duration could default to 1.0 second (just as a simple number).

I will do so.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you like the idea of the kwarg to give a clue on duration?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you like the idea of the kwarg to give a clue on duration?

I like it! I did not think of it, as you normally do not like them.
Default would be false?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't dislike kwargs.

Default would be 1.0.


x.func(tf0) + 1.0,
ux.func(tf0) + 5.0,
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

@moorepants
Copy link
Member

I added a commit, so pull this branch before you edit more. You can now do:

In [1]: from opty.tests.test_direct_collocation import test_linear_initial_guess

In [2]: test_linear_initial_guess(plot=True)

In [3]: import matplotlib.pyplot as plt

In [4]: plt.show()

to quickly plot your guesses.

@Peter230655
Copy link
Contributor Author

I added a commit, so pull this branch before you edit more. You can now do:

In [1]: from opty.tests.test_direct_collocation import test_linear_initial_guess

In [2]: test_linear_initial_guess(plot=True)

In [3]: import matplotlib.pyplot as plt

In [4]: plt.show()

to quickly plot your guesses.

Not sure I totally understand (you know my computer skills...or lack thereof...)
So, I first update my remote branch
Then I update my local master
Then I go to the branch where this is, I called it linear-initial-guess
Then I do your steps?

@moorepants
Copy link
Member

All your do is git pull origin linear-initial-guess. Then you are fine to continue.

@Peter230655
Copy link
Contributor Author

All your do is git pull origin linear-initial-guess. Then you are fine to continue.

Thanks!
I would do this when I am in the correct local branch, that is in create-linear-guess ?

@moorepants
Copy link
Member

The branch associated with this PR is named linear-initial-guess:

image

@Peter230655
Copy link
Contributor Author

Just found a MAJOR plunder! Have to go back to the drawing board.

@Peter230655
Copy link
Contributor Author

Peter230655 commented Feb 19, 2025

  • corrected (hopefully) a problem with instance constraints of the form x(ti) - 0.0
  • set variable time intervall = 1 / (num_nodes - 1) if there are no bounds for it, so duration is 1.
  • set a kwarg: plot with default = False. If set to True, the initial guess will be plotted
  • corrected the test function accordingly
  • added two examples with this method: plot_pendulum_swing_up_fixed_duration and plot_sliding_block. Interestingly, with plot_pendulum_swing_up_variable_duration the linear initial guess did not lead to convergence, while the all zero initial guess works fine.

NB:
This shows once again, how important a good initial guess is.
Maybe a random initial guess could be like this:

  • start with a linear interpolation.
  • at each node take a random normally distributed value, with mean = value of the linear interpolation, sigma and a 'strength' to be user-settable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants