RsBundle  Diff

Differences From Artifact [7348ac40b4]:

  • File src/solver.rs — part of check-in [8b9adfcbb9] at 2017-03-06 16:35:25 on branch trunk — solver: silence a clippy warning. (user: fifr size: 33389)

To Artifact [96f26bc075]:

  • File src/solver.rs — part of check-in [ce9ab8ec19] at 2017-03-06 16:50:42 on branch trunk — Add `MoveVariable` update. The `Solver` struct accepts these updates and handles them. However, they are not passed to the master problem, yet. (user: fifr size: 34756)

78
79
80
81
82
83
84






85
86
87
88
89
90
91
        }

        /// The value of a variable is outside its bounds.
        ViolatedBounds(lower: Real, upper: Real, value: Real) {
            description("violated bounds")
            display("Violated bounds, lower:{} upper:{} value:{}", lower, upper, value)
        }






    }
}


/// Result type for solvers.
pub type Result<T> = result::Result<T, Error>;








>
>
>
>
>
>







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
        }

        /// The value of a variable is outside its bounds.
        ViolatedBounds(lower: Real, upper: Real, value: Real) {
            description("violated bounds")
            display("Violated bounds, lower:{} upper:{} value:{}", lower, upper, value)
        }

        /// The variable index is out of bounds.
        InvalidVariable(index: usize, nvars: usize) {
            description("invalid variable")
            display("Variable index out of bounds, got:{} must be < {}", index, nvars)
        }
    }
}


/// Result type for solvers.
pub type Result<T> = result::Result<T, Error>;

362
363
364
365
366
367
368



369
370
371
372
373
374
375
    pub params: SolverParams,

    /// Termination predicate.
    pub terminator: Box<Terminator>,

    /// Weighter heuristic.
    pub weighter: Box<Weighter>,




    /// Current center of stability.
    cur_y: DVector,

    /// Function value in current point.
    cur_val: Real,








>
>
>







368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
    pub params: SolverParams,

    /// Termination predicate.
    pub terminator: Box<Terminator>,

    /// Weighter heuristic.
    pub weighter: Box<Weighter>,

    /// Lower and upper bounds of all variables.
    bounds: Vec<(Real, Real)>,

    /// Current center of stability.
    cur_y: DVector,

    /// Function value in current point.
    cur_val: Real,

455
456
457
458
459
460
461

462
463
464
465
466
467
468
     */
    pub fn new_params(problem: P, params: SolverParams) -> Result<Solver<P, Pr, E>> {
        Ok(Solver {
            problem: problem,
            params: params,
            terminator: Box::new(StandardTerminator { termination_precision: 1e-3 }),
            weighter: Box::new(HKWeighter::new()),

            cur_y: dvec![],
            cur_val: 0.0,
            cur_mod: 0.0,
            cur_vals: dvec![],
            cur_mods: dvec![],
            cur_valid: false,
            nxt_d: dvec![],







>







464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
     */
    pub fn new_params(problem: P, params: SolverParams) -> Result<Solver<P, Pr, E>> {
        Ok(Solver {
            problem: problem,
            params: params,
            terminator: Box::new(StandardTerminator { termination_precision: 1e-3 }),
            weighter: Box::new(HKWeighter::new()),
            bounds: vec![],
            cur_y: dvec![],
            cur_val: 0.0,
            cur_mod: 0.0,
            cur_vals: dvec![],
            cur_mods: dvec![],
            cur_valid: false,
            nxt_d: dvec![],
515
516
517
518
519
520
521


522
523
524
525
526
527
528
529
530
531
532
533
534

535
536
537
538
539
540
541
        if self.cur_y.len() != self.problem.num_variables() {
            self.cur_valid = false;
            self.cur_y.init0(self.problem.num_variables());
        }

        let lb = self.problem.lower_bounds();
        let ub = self.problem.upper_bounds();


        for i in 0..self.cur_y.len() {
            let lb_i = lb.as_ref().map(|x| x[i]).unwrap_or(NEG_INFINITY);
            let ub_i = ub.as_ref().map(|x| x[i]).unwrap_or(INFINITY);
            if lb_i > ub_i {
                return Err(Error::InvalidBounds(lb_i, ub_i));
            }
            if self.cur_y[i] < lb_i {
                self.cur_valid = false;
                self.cur_y[i] = lb_i;
            } else if self.cur_y[i] > ub_i {
                self.cur_valid = false;
                self.cur_y[i] = ub_i;
            }

        }

        let m = self.problem.num_subproblems();
        self.cur_vals.init0(m);
        self.cur_mods.init0(m);
        self.nxt_vals.init0(m);
        self.nxt_mods.init0(m);







>
>













>







525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
        if self.cur_y.len() != self.problem.num_variables() {
            self.cur_valid = false;
            self.cur_y.init0(self.problem.num_variables());
        }

        let lb = self.problem.lower_bounds();
        let ub = self.problem.upper_bounds();
        self.bounds.clear();
        self.bounds.reserve(self.cur_y.len());
        for i in 0..self.cur_y.len() {
            let lb_i = lb.as_ref().map(|x| x[i]).unwrap_or(NEG_INFINITY);
            let ub_i = ub.as_ref().map(|x| x[i]).unwrap_or(INFINITY);
            if lb_i > ub_i {
                return Err(Error::InvalidBounds(lb_i, ub_i));
            }
            if self.cur_y[i] < lb_i {
                self.cur_valid = false;
                self.cur_y[i] = lb_i;
            } else if self.cur_y[i] > ub_i {
                self.cur_valid = false;
                self.cur_y[i] = ub_i;
            }
            self.bounds.push((lb_i, ub_i));
        }

        let m = self.problem.num_subproblems();
        self.cur_vals.init0(m);
        self.cur_mods.init0(m);
        self.nxt_vals.init0(m);
        self.nxt_mods.init0(m);
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619











620
621
622
623
624
625
626
627
628
629
630
631
632


633




634
635
636

637
638
639
640
641
642
643
                    let value = if lower > 0.0 {
                        lower
                    } else if upper < 0.0 {
                        upper
                    } else {
                        0.0
                    };
                    newvars.push((lower - value, upper - value, value));
                }
                Update::AddVariableValue { lower, upper, value } => {
                    if lower > upper {
                        return Err(Error::InvalidBounds(lower, upper));
                    }
                    if value < lower || value > upper {
                        return Err(Error::ViolatedBounds(lower, upper, value));
                    }
                    newvars.push((lower - value, upper - value, value));











                }
            }
        }

        if !newvars.is_empty() {
            let mut problem = &mut self.problem;
            let minorants = &self.minorants;
            self.master.add_vars(&newvars.iter().map(|v| (v.0, v.1)).collect::<Vec<_>>(),
                                 &mut move |fidx, minidx, vars| {
                                     problem.extend_subgradient(minorants[fidx][minidx].primal.as_ref().unwrap(), vars)
                                         .map(DVector)
                                         .unwrap()
                                 });


            let newn = self.cur_y.len() + newvars.len();




            self.cur_y.extend(newvars.iter().map(|v| v.2));
            self.nxt_d.resize(newn, 0.0);
            self.nxt_y.extend(newvars.iter().map(|v| v.2));

            Ok(true)
        } else {
            Ok(false)
        }
    }

    /// Return the current aggregated primal information for a subproblem.







|








|
>
>
>
>
>
>
>
>
>
>
>







|





>
>
|
>
>
>
>
|
<
|
>







616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664

665
666
667
668
669
670
671
672
673
                    let value = if lower > 0.0 {
                        lower
                    } else if upper < 0.0 {
                        upper
                    } else {
                        0.0
                    };
                    newvars.push((None, lower - value, upper - value, value));
                }
                Update::AddVariableValue { lower, upper, value } => {
                    if lower > upper {
                        return Err(Error::InvalidBounds(lower, upper));
                    }
                    if value < lower || value > upper {
                        return Err(Error::ViolatedBounds(lower, upper, value));
                    }
                    newvars.push((None, lower - value, upper - value, value));
                }
                Update::MoveVariable { index, value } => {
                    if index >= self.bounds.len() {
                        return Err(Error::InvalidVariable(index, self.bounds.len()));
                    }
                    let (lower, upper) = self.bounds[index];
                    if value < lower || value > upper {
                        return Err(Error::ViolatedBounds(lower, upper, value));
                    }
                    newvars.push((Some(index), lower - value, upper - value, value));
                    unimplemented!()
                }
            }
        }

        if !newvars.is_empty() {
            let mut problem = &mut self.problem;
            let minorants = &self.minorants;
            self.master.add_vars(&newvars.iter().map(|v| (v.1, v.2)).collect::<Vec<_>>(),
                                 &mut move |fidx, minidx, vars| {
                                     problem.extend_subgradient(minorants[fidx][minidx].primal.as_ref().unwrap(), vars)
                                         .map(DVector)
                                         .unwrap()
                                 });
            // modify moved variables
            for (index, val) in newvars.iter().filter_map(|v| v.0.map(|i| (i, v.3))) {
                self.cur_y[index] = val;
                self.nxt_y[index] = val;
                self.nxt_d[index] = 0.0;
            }
            // add new variables
            self.cur_y.extend(newvars.iter().filter(|v| v.0.is_none()).map(|v| v.3));

            self.nxt_y.extend(newvars.iter().filter(|v| v.0.is_none()).map(|v| v.3));
            self.nxt_d.resize(self.nxt_y.len(), 0.0);
            Ok(true)
        } else {
            Ok(false)
        }
    }

    /// Return the current aggregated primal information for a subproblem.