def test_save_and_load_weights_w_encoders(self, tmpdir_fn):
        """
        Verify that save/load does not break encoders.

        Note: since load_weights() calls load_weights_from_checkpoint(), it will be used
        for all but one test.
        Note: Using DLinear since it supports both past and future covariates
        """
        model_dir = os.path.join(tmpdir_fn)
        manual_name = "save_manual"
        auto_name = "save_auto"
        auto_name_other = "save_auto_other"
        # create manually saved model checkpoints folder
        checkpoint_path_manual = os.path.join(model_dir, manual_name)
        os.mkdir(checkpoint_path_manual)
        checkpoint_file_name = "checkpoint_0.pth.tar"
        model_path_manual = os.path.join(checkpoint_path_manual, checkpoint_file_name)

        # define encoders sets
        encoders_past = {
            "datetime_attribute": {"past": ["day"]},
            "transformer": Scaler(),
        }
        encoders_other_past = {
            "datetime_attribute": {"past": ["hour"]},
            "transformer": Scaler(),
        }
        encoders_past_noscaler = {
            "datetime_attribute": {"past": ["day"]},
        }
        encoders_past_other_transformer = {
            "datetime_attribute": {"past": ["day"]},
            "transformer": BoxCox(lmbda=-0.7),
        }
        encoders_2_past = {
            "datetime_attribute": {"past": ["hour", "day"]},
            "transformer": Scaler(),
        }
        encoders_past_n_future = {
            "datetime_attribute": {"past": ["day"], "future": ["dayofweek"]},
            "transformer": Scaler(),
        }

        model_auto_save = self.helper_create_DLinearModel(
            work_dir=tmpdir_fn,
            model_name=auto_name,
            save_checkpoints=True,
            add_encoders=encoders_past,
        )
        model_auto_save.fit(self.series, epochs=1)

        model_manual_save = self.helper_create_DLinearModel(
            work_dir=tmpdir_fn,
            model_name=manual_name,
            save_checkpoints=False,
            add_encoders=encoders_past,
        )
        model_manual_save.fit(self.series, epochs=1)
        model_manual_save.save(model_path_manual)

        model_auto_save_other = self.helper_create_DLinearModel(
            work_dir=tmpdir_fn,
            model_name=auto_name_other,
            save_checkpoints=True,
            add_encoders=encoders_other_past,
        )
        model_auto_save_other.fit(self.series, epochs=1)

        # prediction are different when using different encoders
        assert model_auto_save.predict(n=4) != model_auto_save_other.predict(n=4)

        # model with undeclared encoders
        model_no_enc = self.helper_create_DLinearModel(
            work_dir=tmpdir_fn, model_name="no_encoder", add_encoders=None
        )
        # weights were trained with encoders, new model must be instantiated with encoders
        with pytest.raises(ValueError):
            model_no_enc.load_weights_from_checkpoint(
                auto_name,
                work_dir=tmpdir_fn,
                best=False,
                load_encoders=False,
                map_location="cpu",
            )
        # overwrite undeclared encoders
        model_no_enc.load_weights_from_checkpoint(
            auto_name,
            work_dir=tmpdir_fn,
            best=False,
            load_encoders=True,
            map_location="cpu",
        )
        self.helper_equality_encoders(
            model_auto_save.add_encoders, model_no_enc.add_encoders
        )
        self.helper_equality_encoders_transfo(
            model_auto_save.add_encoders, model_no_enc.add_encoders
        )
        # cannot directly verify equality between encoders, using predict as proxy
        assert model_auto_save.predict(n=4) == model_no_enc.predict(
            n=4, series=self.series
        )

        # model with identical encoders (fittable)
        model_same_enc_noload = self.helper_create_DLinearModel(
            work_dir=tmpdir_fn,
            model_name="same_encoder_noload",
            add_encoders=encoders_past,
        )
        model_same_enc_noload.load_weights(
            model_path_manual,
            load_encoders=False,
            map_location="cpu",
        )
        # cannot predict because of un-fitted encoder
        with pytest.raises(ValueError):
            model_same_enc_noload.predict(n=4, series=self.series)

        model_same_enc_load = self.helper_create_DLinearModel(
            work_dir=tmpdir_fn,
            model_name="same_encoder_load",
            add_encoders=encoders_past,
        )
        model_same_enc_load.load_weights(
            model_path_manual,
            load_encoders=True,
            map_location="cpu",
        )
        assert model_manual_save.predict(n=4) == model_same_enc_load.predict(
            n=4, series=self.series
        )

        # model with different encoders (fittable)
        model_other_enc_load = self.helper_create_DLinearModel(
            work_dir=tmpdir_fn,
            model_name="other_encoder_load",
            add_encoders=encoders_other_past,
        )
        # cannot overwrite different declared encoders
        with pytest.raises(ValueError):
            model_other_enc_load.load_weights(
                model_path_manual,
                load_encoders=True,
                map_location="cpu",
            )

        # model with different encoders but same dimensions (fittable)
        model_other_enc_noload = self.helper_create_DLinearModel(
            work_dir=tmpdir_fn,
            model_name="other_encoder_noload",
            add_encoders=encoders_other_past,
        )
        model_other_enc_noload.load_weights(
            model_path_manual,
            load_encoders=False,
            map_location="cpu",
        )
        self.helper_equality_encoders(
            model_other_enc_noload.add_encoders, encoders_other_past
        )
        self.helper_equality_encoders_transfo(
            model_other_enc_noload.add_encoders, encoders_other_past
        )
        # new encoders were instantiated
        assert isinstance(model_other_enc_noload.encoders, SequentialEncoder)
        # since fit() was not called, new fittable encoders were not trained
        with pytest.raises(ValueError):
            model_other_enc_noload.predict(n=4, series=self.series)

        # predict() can be called after fit()
        model_other_enc_noload.fit(self.series, epochs=1)
        model_other_enc_noload.predict(n=4, series=self.series)

        # model with same encoders but no scaler (non-fittable)
        model_new_enc_noscaler_noload = self.helper_create_DLinearModel(
            work_dir=tmpdir_fn,
            model_name="same_encoder_noscaler",
            add_encoders=encoders_past_noscaler,
        )
        model_new_enc_noscaler_noload.load_weights(
            model_path_manual,
            load_encoders=False,
            map_location="cpu",
        )

        self.helper_equality_encoders(
            model_new_enc_noscaler_noload.add_encoders, encoders_past_noscaler
        )
        self.helper_equality_encoders_transfo(
            model_new_enc_noscaler_noload.add_encoders, encoders_past_noscaler
        )
        # predict() can be called directly since new encoders don't contain scaler
        model_new_enc_noscaler_noload.predict(n=4, series=self.series)

        # model with same encoders but different transformer (fittable)
        model_new_enc_other_transformer = self.helper_create_DLinearModel(
            work_dir=tmpdir_fn,
            model_name="same_encoder_other_transform",
            add_encoders=encoders_past_other_transformer,
        )
        # cannot overwrite different declared encoders
        with pytest.raises(ValueError):
            model_new_enc_other_transformer.load_weights(
                model_path_manual,
                load_encoders=True,
                map_location="cpu",
            )

        model_new_enc_other_transformer.load_weights(
            model_path_manual,
            load_encoders=False,
            map_location="cpu",
        )
        # since fit() was not called, new fittable encoders were not trained
        with pytest.raises(ValueError):
            model_new_enc_other_transformer.predict(n=4, series=self.series)

        # predict() can be called after fit()
        model_new_enc_other_transformer.fit(self.series, epochs=1)
        model_new_enc_other_transformer.predict(n=4, series=self.series)

        # model with encoders containing more components (fittable)
        model_new_enc_2_past = self.helper_create_DLinearModel(
            work_dir=tmpdir_fn,
            model_name="encoder_2_components_past",
            add_encoders=encoders_2_past,
        )
        # cannot overwrite different declared encoders
        with pytest.raises(ValueError):
            model_new_enc_2_past.load_weights(
                model_path_manual,
                load_encoders=True,
                map_location="cpu",
            )
        # new encoders have one additional past component
        with pytest.raises(ValueError):
            model_new_enc_2_past.load_weights(
                model_path_manual,
                load_encoders=False,
                map_location="cpu",
            )

        # model with encoders containing past and future covs (fittable)
        model_new_enc_past_n_future = self.helper_create_DLinearModel(
            work_dir=tmpdir_fn,
            model_name="encoder_past_n_future",
            add_encoders=encoders_past_n_future,
        )
        # cannot overwrite different declared encoders
        with pytest.raises(ValueError):
            model_new_enc_past_n_future.load_weights(
                model_path_manual,
                load_encoders=True,
                map_location="cpu",
            )
        # identical past components, but different future components
        with pytest.raises(ValueError):
            model_new_enc_past_n_future.load_weights(
                model_path_manual,
                load_encoders=False,
                map_location="cpu",
            )

        Verify that save/load does not break encoders.

        Note: since load_weights() calls load_weights_from_checkpoint(), it will be used
        for all but one test.
        Note: Using DLinear since it supports both past and future covariates
        
darts/tests/models/forecasting/test_torch_forecasting_model.py