catboost-rust 0.3.7

Rust bindings for CatBoost, a gradient boosting library for machine learning. Downloads CatBoost binaries at runtime for cross-platform compatibility.
use catboost_rust::{CatBoostError, Model};
use std::fs;

fn main() -> Result<(), CatBoostError> {
    println!("CatBoost Rust Example - Advanced Usage");
    println!("======================================");

    // Check if we have a model file to load
    let model_path = "tmp/model.bin";
    if !fs::metadata(model_path).is_ok() {
        println!(
            "No model file found at {}. Please create a model first.",
            model_path
        );
        return Ok(());
    }

    // Load the model
    println!("Loading model from {}...", model_path);
    let model = Model::load(model_path)?;

    println!("Model loaded successfully!");

    // Display comprehensive model information
    display_model_info(&model)?;

    // Example 1: Get model statistics
    println!("\n=== Model Statistics ===");
    println!("Model statistics:");
    println!(
        "  - Number of float features: {}",
        model.get_float_features_count()
    );
    println!(
        "  - Number of categorical features: {}",
        model.get_cat_features_count()
    );
    println!(
        "  - Number of text features: {}",
        model.get_text_features_count()
    );
    println!(
        "  - Number of embedding features: {}",
        model.get_embedding_features_count()
    );
    println!("  - Number of trees: {}", model.get_tree_count());
    println!("  - Number of dimensions: {}", model.get_dimensions_count());

    // Example 2: Prediction with different feature types
    println!("\n=== Feature Type Examples ===");

    // Numeric features only
    let numeric_features = vec![vec![0.1, 0.2, 0.3, 0.4, 0.5]];
    let prediction = model.calc_model_prediction(numeric_features, vec![Vec::<String>::new()])?;
    println!("Numeric features only:");
    println!("  Features: {:?}", vec![0.1, 0.2, 0.3, 0.4, 0.5]);
    println!("  Prediction: {:.6}", prediction[0]);

    // Mixed numeric and categorical features
    let numeric_features = vec![vec![0.1, 0.2, 0.3, 0.4, 0.5]];
    let categorical_features = vec![vec![
        String::from("A"),
        String::from("B"),
        String::from("C"),
    ]];
    let prediction = model.calc_model_prediction(numeric_features, categorical_features)?;
    println!("Mixed features:");
    println!("  Numeric: {:?}", vec![0.1, 0.2, 0.3, 0.4, 0.5]);
    println!("  Categorical: {:?}", vec!["A", "B", "C"]);
    println!("  Prediction: {:.6}", prediction[0]);

    // Example 3: Batch predictions with error handling
    println!("\n=== Batch Predictions ===");
    let batch_features = vec![
        vec![1.0, 2.0, 3.0, 4.0, 5.0],
        vec![2.0, 3.0, 4.0, 5.0, 6.0],
        vec![3.0, 4.0, 5.0, 6.0, 7.0],
        vec![4.0, 5.0, 6.0, 7.0, 8.0],
    ];

    match model.calc_model_prediction(
        batch_features,
        vec![
            Vec::<String>::new(),
            Vec::<String>::new(),
            Vec::<String>::new(),
            Vec::<String>::new(),
        ],
    ) {
        Ok(predictions) => {
            for (i, pred) in predictions.iter().enumerate() {
                println!(
                    "  Sample {}: {:?} -> {:.6}",
                    i + 1,
                    vec![
                        1.0 + i as f32,
                        2.0 + i as f32,
                        3.0 + i as f32,
                        4.0 + i as f32,
                        5.0 + i as f32
                    ],
                    pred
                );
            }
        }
        Err(e) => println!("  Batch prediction error: {}", e),
    }

    // Example 4: Model validation
    println!("\n=== Model Validation ===");
    validate_model(&model)?;

    println!("\nAdvanced examples completed successfully!");
    Ok(())
}

fn display_model_info(model: &Model) -> Result<(), CatBoostError> {
    println!("Model Information:");
    println!(
        "  - Number of float features: {}",
        model.get_float_features_count()
    );
    println!(
        "  - Number of categorical features: {}",
        model.get_cat_features_count()
    );
    println!(
        "  - Number of text features: {}",
        model.get_text_features_count()
    );
    println!(
        "  - Number of embedding features: {}",
        model.get_embedding_features_count()
    );
    println!("  - Number of trees: {}", model.get_tree_count());
    println!("  - Number of dimensions: {}", model.get_dimensions_count());

    Ok(())
}

fn validate_model(model: &Model) -> Result<(), CatBoostError> {
    println!("Validating model...");

    // Test with valid features (should succeed)
    let num_features = model.get_float_features_count();
    let valid_features = vec![vec![0.0; num_features]];
    match model.calc_model_prediction(valid_features, vec![Vec::<String>::new()]) {
        Ok(predictions) => println!(
            "  ✅ Valid features accepted, prediction: {:.6}",
            predictions[0]
        ),
        Err(e) => println!("  ❌ Valid features failed: {}", e),
    }

    Ok(())
}