// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ASH_POWER_AUTO_SCREEN_BRIGHTNESS_GAUSSIAN_TRAINER_H_
#define CHROME_BROWSER_ASH_POWER_AUTO_SCREEN_BRIGHTNESS_GAUSSIAN_TRAINER_H_
#include <memory>
#include "chrome/browser/ash/power/auto_screen_brightness/trainer.h"
namespace ash {
namespace power {
namespace auto_screen_brightness {
struct TrainingResult {
TrainingResult();
TrainingResult(const std::optional<MonotoneCubicSpline>& new_curve,
double error);
TrainingResult(const TrainingResult& result);
~TrainingResult();
// |new_curve| will be nullopt if trainer's curve stays unchanged after
// training.
std::optional<MonotoneCubicSpline> new_curve;
// Evaluation error of the latest curve (possibly updated) using the training
// data points.
double error;
};
// GaussianTrainer updates an existing brightness curve (a mapping from
// ambient light to screen brightness) using training data points that represent
// how user changes brightness following an ambient value change. The update
// procedure is Gaussian hence the name. It uses a global curve to check for
// outliers that may exist in training data. It also ensures new curves are
// monotone and also satisfy requirements on the slope.
class GaussianTrainer : public Trainer {
public:
// TODO(jiameng): revise default values.
struct Params {
Params();
// |brightness_bound_scale| and |brightness_bound_offset| are used to define
// training example outliers.
double brightness_bound_scale = 1.5;
double brightness_bound_offset = 40;
// |brightness_step_size| defines reasonable brightness change scale: a
// reasonable change would be between
// brightness_old/(1+|brightness_step_size|) and
// brightness_old*(1+|brightness_step_size|)
double brightness_step_size = 1.5;
// Similar to |brightness_step_size| except it defines reasonable brightness
// change scale between target brightness and model predicted brightness.
double model_brightness_step_size = 2.0;
// One training data point could modify all the points on the curve, but its
// effect is greatest on the point nearest to it (as measured by difference
// in ambient value). The effect on the other points decay with a Gaussian
// distribution with standard deviation |sigma|.
double sigma = 1;
// If log lux is below |low_log_lux_threshold| then we'll use
// |min_grad_low_lux| as gradient constraint.
double low_log_lux_threshold = 0.1;
double min_grad_low_lux = 0;
// If log lux is above |high_log_lux_threshold| then we'll use
// |min_grad_high_lux| as gradient constraint.
double high_log_lux_threshold = 7.5;
double min_grad_high_lux = 0;
// Min and max grad as a power of brightness ratios.
double min_grad = 0.25;
double max_grad = 1;
double min_brightness = 0;
};
GaussianTrainer();
GaussianTrainer(const GaussianTrainer&) = delete;
GaussianTrainer& operator=(const GaussianTrainer&) = delete;
~GaussianTrainer() override;
// Trainer overrides:
bool HasValidConfiguration() const override;
bool SetInitialCurves(const MonotoneCubicSpline& global_curve,
const MonotoneCubicSpline& current_curve) override;
MonotoneCubicSpline GetGlobalCurve() const override;
MonotoneCubicSpline GetCurrentCurve() const override;
TrainingResult Train(const std::vector<TrainingDataPoint>& data) override;
private:
// Returns whether initial personal curve (passed in by |SetInitialCurves|) is
// valid, i.e. satisfying min/max ratio constraints.
bool IsInitialPersonalCurveValid() const;
// Updates |brightness_| using |data|. It also sets |need_to_update_curve_|
// to true if |brightness_| is actually changed.
void AdjustCurveWithSingleDataPoint(const TrainingDataPoint& data);
// Called each time |AdjustCurveWithSingleDataPoint| changes |brightness_|.
// It ensures the curve is still monotone and also satisfies min/max grad
// constraints. It does this by changing points to the left and to the right
// of |center_index|.
void EnforceMonotonicity(size_t center_index);
// Calculates (possibly) updated curve's MAE error w.r.t. |data|. The error
// will be in the range of [0, 100].
double CalculateCurveError(const std::vector<TrainingDataPoint>& data) const;
// Default params_ are valid.
bool valid_params_ = true;
Params params_;
// |global_curve| does not change after |SetInitialCurves| is called.
std::optional<MonotoneCubicSpline> global_curve_;
// |current_curve_| initially is set by |SetInitialCurves| and then gets
// updated during training.
std::optional<MonotoneCubicSpline> current_curve_;
// Whether the |brightness_| has been updated since last time |Train| updated
// the curve.
bool need_to_update_curve_ = false;
// (|ambient_log_lux_|, |brightness_|) are the control points of
// |current_curve_|. |ambient_log_lux_| doesn't change, but |brightness_| may
// be updated during training.
std::vector<double> ambient_log_lux_;
std::vector<double> brightness_;
// Minimum and max brightness ratios of two adjacent control points. They are
// calculated from the global curve's brightness values.
std::vector<double> min_ratios_;
std::vector<double> max_ratios_;
};
} // namespace auto_screen_brightness
} // namespace power
} // namespace ash
#endif // CHROME_BROWSER_ASH_POWER_AUTO_SCREEN_BRIGHTNESS_GAUSSIAN_TRAINER_H_