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

Optimizing More than one Param #569

Open
ramtinkh opened this issue Feb 15, 2025 · 6 comments
Open

Optimizing More than one Param #569

ramtinkh opened this issue Feb 15, 2025 · 6 comments

Comments

@ramtinkh
Copy link

ramtinkh commented Feb 15, 2025

I'm using NelderMead for my optimizing problem. I wanted to use the struct below.

impl CostFunction for MyStruct
{
    type Param = Vec<f64>;
    type Output = f64;

    fn cost(&self, input: &Self::Param) -> Result<Self::Output, Error> {
        let out = input[0].cos() + input[0].sin() * (input[1] / 100.0);
        Ok(out)
    }
}

Then I tried to define my solver like the code below. despite the documents of NelderMead for optimizing 2 parameters I should define 3 initial points.

let solver = NelderMead::new(vec![vec![0_f64, 70.0], vec![1_f64, 80.0], vec![2_f64, 90.0]]).with_sd_tolerance(vec![0.0001, 1.0]).unwrap();

after running this code I got errors mentioned here:

the trait `argmin_math::ArgminMul<_, Vec<f64>>` is not implemented for `Vec<f64>

What do you recommend me to do? Is it even possible for your CostFunction Trait to accept more than one parameter? Because vector doesn't implement ArgminMul, ...
Even when I copy the example in the document I got these errors.

use argmin::solver::neldermead::NelderMead;
    use argmin::core::Error;
    fn main() -> Result<(), Error> {
    let vec_of_parameters = vec![vec![1.0], vec![2.0], vec![3.0]];
    let nm: NelderMead<Vec<f64>, f64> =
        NelderMead::new(vec_of_parameters).with_sd_tolerance(1e-6)?;
    Ok(())
    }
@ramtinkh
Copy link
Author

Even the example in this link failed with this error. Any ideas?

the trait `argmin_math::ArgminMul<_, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not implemented for `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>`

@GermanHeim
Copy link
Contributor

Hello,

In your code you have .with_sd_tolerance(vec![0.0001, 1.0]) but sd_tolerance should be a float (https://docs.rs/argmin/latest/argmin/solver/neldermead/struct.NelderMead.html)

The example works for me:

OptimizationResult:
    Solver:        Nelder-Mead method
    param (best):  [1.0033431432617184, 1.0073634384738885], shape=[2], strides=[1], layout=CFcf (0xf), const ndim=1 
    cost (best):   0.00005552892269447157
    iters (best):  50
    iters (total): 54
    termination:   Solver converged
    time:          1.8594ms

Modifying the code inside the example to take your function also worked for me:

OptimizationResult:
    Solver:        Nelder-Mead method
    param (best):  [4.023193359375, 110.23193359375]
    cost (best):   -1.486640128657184
    iters (best):  11
    iters (total): 15
    termination:   Solver converged
    time:          677.1µs

Code:

use argmin::{
    core::{observers::ObserverMode, CostFunction, Error, Executor},
    solver::neldermead::NelderMead,
};
use argmin_observer_slog::SlogLogger;

struct MyStruct {}

impl CostFunction for MyStruct {
    type Param = Vec<f64>;
    type Output = f64;

    fn cost(&self, input: &Self::Param) -> Result<Self::Output, Error> {
        let out = input[0].cos() + input[0].sin() * (input[1] / 100.0);
        Ok(out)
    }
}

fn run() -> Result<(), Error> {
    // Define cost function
    let cost = MyStruct {};

    let solver = NelderMead::new(vec![
        vec![0_f64, 70.0],
        vec![1_f64, 80.0],
        vec![2_f64, 90.0],
    ])
    .with_sd_tolerance(0.0001)?;

    // Run solver
    let res = Executor::new(cost, solver)
        .configure(|state| state.max_iters(100))
        .add_observer(SlogLogger::term(), ObserverMode::Always)
        .run()?;

    // Print result
    println!("{res}");
    Ok(())
}

fn main() {
    if let Err(ref e) = run() {
        println!("{e}");
        std::process::exit(1);
    }
}

In my cargo.toml I have the following dependencies:

[dependencies]
argmin = { version = "0.10.0" }
argmin-math = { version = "0.4.0", features = ["ndarray_latest-nolinalg"] }
argmin-observer-slog = { version = "*" }
argmin_testfunctions = { version = "*" }
ndarray = "0.15.6" # Only useful for the example, not your problem

Could you check if that works for you?

@ramtinkh
Copy link
Author

When I updated the code and run, it still return the following errors.

the trait `argmin_math::ArgminMul<_, Vec<f64>>` is not implemented for `Vec<f64>

Then I updated the dependencies from the details mentioned below to your dependencies.

[dependencies]
argmin = "0.10.0"
argmin-observer-slog = "0.1.0"
argmin_testfunctions = "0.2.0"
num-traits = "0.2.19"
ndarray = "0.15.6"

And now it works. Thank you so much.
But I didn't understand which dependency creates the previous error. If you had any idea let me know.
Thanks for your time.

@GermanHeim
Copy link
Contributor

What were your previous dependencies?

@ramtinkh
Copy link
Author

I’ve added my previous dependencies in the previous comment.

@GermanHeim
Copy link
Contributor

Oh, sorry, I didn't read that right.
I think you were missing argmin-math.

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

No branches or pull requests

2 participants