diff --git a/rust_project/Cargo.lock b/rust_project/Cargo.lock index 76cc9c71..50e039a9 100644 --- a/rust_project/Cargo.lock +++ b/rust_project/Cargo.lock @@ -2124,7 +2124,7 @@ dependencies = [ [[package]] name = "loda-rust-cli" -version = "2023.11.25" +version = "2023.11.26" dependencies = [ "ahash", "alphanumeric-sort", diff --git a/rust_project/arc-competition/payload/.loda-rust/analytics-arc/analytics_log.txt b/rust_project/arc-competition/payload/.loda-rust/analytics-arc/analytics_log.txt index cccdee61..0ea840e0 100644 --- a/rust_project/arc-competition/payload/.loda-rust/analytics-arc/analytics_log.txt +++ b/rust_project/arc-competition/payload/.loda-rust/analytics-arc/analytics_log.txt @@ -32,4 +32,4 @@ optimize: 0, dontoptimize: 1, optimize/total: 0.0% AnalyzeProgramModified timestamps: 88 -subcommand_analytics finished, elapsed: 21 ms +subcommand_analytics finished, elapsed: 24 ms diff --git a/rust_project/arc-competition/payload/.loda-rust/analytics-arc/last_analytics_timestamp.txt b/rust_project/arc-competition/payload/.loda-rust/analytics-arc/last_analytics_timestamp.txt index d93ef37b..0a6a9702 100644 --- a/rust_project/arc-competition/payload/.loda-rust/analytics-arc/last_analytics_timestamp.txt +++ b/rust_project/arc-competition/payload/.loda-rust/analytics-arc/last_analytics_timestamp.txt @@ -1 +1 @@ -2023-11-25T18:24:46Z \ No newline at end of file +2023-11-26T21:00:17Z \ No newline at end of file diff --git a/rust_project/loda-rust-cli/Cargo.toml b/rust_project/loda-rust-cli/Cargo.toml index 4e5696b4..902c2769 100644 --- a/rust_project/loda-rust-cli/Cargo.toml +++ b/rust_project/loda-rust-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "loda-rust-cli" -version = "2023.11.25" +version = "2023.11.26" authors = ["Simon Strandgaard "] description = "Command line interface for LODA Rust" repository = "https://github.com/loda-lang/loda-rust" diff --git a/rust_project/loda-rust-cli/src/arc/arc_work_model.rs b/rust_project/loda-rust-cli/src/arc/arc_work_model.rs index 96a38b78..b3079e41 100644 --- a/rust_project/loda-rust-cli/src/arc/arc_work_model.rs +++ b/rust_project/loda-rust-cli/src/arc/arc_work_model.rs @@ -106,6 +106,7 @@ pub struct Input { // Future experiments to do. // least_popular_intersection_color + // density of each color, if it's noise the density is low, if it's a solid cluster the density is high. // // Resolving these properties is similar to a package manager, a DAG (directed acyclic graph). // One property may depend on another property that depends on a third property. diff --git a/rust_project/loda-rust-cli/src/arc/measure_density.rs b/rust_project/loda-rust-cli/src/arc/measure_density.rs new file mode 100644 index 00000000..9884ceca --- /dev/null +++ b/rust_project/loda-rust-cli/src/arc/measure_density.rs @@ -0,0 +1,58 @@ +use super::{Image, ImagePadding, convolution3x3, ImageHistogram, Histogram}; +use anyhow::bail; + +pub struct MeasureDensity { + pub density_any_direction: Image, +} + +impl MeasureDensity { + pub fn analyze(image: &Image) -> anyhow::Result { + if image.is_empty() { + bail!("image is empty. Must be 1x1 or larger"); + } + let padding: Image = image.padding_with_color(1, 255)?; + let density: Image = convolution3x3(&padding, conv3x3_measure_density_any_direction)?; + let instance = Self { + density_any_direction: density, + }; + Ok(instance) + } +} + +fn conv3x3_measure_density_any_direction(image: &Image) -> anyhow::Result { + let histogram: Histogram = image.histogram_all(); + let center: u8 = image.get(1, 1).unwrap_or(255); + let count: u32 = histogram.get(center).min(9).max(1) - 1; + Ok(count as u8) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::arc::ImageTryCreate; + + #[test] + fn test_10000_density_any_direction() { + // Arrange + let pixels: Vec = vec![ + 5, 3, 3, 3, + 3, 3, 3, 3, + 5, 5, 3, 3, + 3, 5, 3, 3, + ]; + let input: Image = Image::try_create(4, 4, pixels).expect("image"); + + // Act + let actual: MeasureDensity = MeasureDensity::analyze(&input).expect("image"); + + // Assert + let expected_pixels: Vec = vec![ + 0, 4, 5, 3, + 2, 5, 7, 5, + 2, 2, 6, 5, + 0, 2, 3, 3, + ]; + let expected: Image = Image::try_create(4, 4, expected_pixels).expect("image"); + assert_eq!(actual.density_any_direction, expected); + } +} \ No newline at end of file diff --git a/rust_project/loda-rust-cli/src/arc/mod.rs b/rust_project/loda-rust-cli/src/arc/mod.rs index fd901be0..0a626355 100644 --- a/rust_project/loda-rust-cli/src/arc/mod.rs +++ b/rust_project/loda-rust-cli/src/arc/mod.rs @@ -116,6 +116,7 @@ mod label; mod landmark_single_pixel; mod largest_interior_rectangle; mod linespan; +mod measure_density; mod ngram; mod number_to_image; mod object_with_different_color; @@ -265,6 +266,7 @@ pub use label::{ActionLabel, ActionLabelSet, GridLabel, ImageCorner, ImageEdge, pub use landmark_single_pixel::LandmarkSinglePixel; pub use largest_interior_rectangle::LargestInteriorRectangle; pub use linespan::{LineSpan, LineSpanDirection, LineSpanMode}; +pub use measure_density::MeasureDensity; pub use ngram::{ImageNgram, RecordBigram, RecordTrigram}; pub use number_to_image::NumberToImage; pub use object_with_different_color::ObjectWithDifferentColor; diff --git a/rust_project/loda-rust-cli/src/arc/solve_logisticregression.rs b/rust_project/loda-rust-cli/src/arc/solve_logisticregression.rs index 1e1f186a..fdaabd2b 100644 --- a/rust_project/loda-rust-cli/src/arc/solve_logisticregression.rs +++ b/rust_project/loda-rust-cli/src/arc/solve_logisticregression.rs @@ -1,6 +1,10 @@ //! Performs logistic regression of each input pixel with the corresponding classification for the output pixel. //! //! These older commits solves some of the tasks from the hidden ARC dataset, using logistic regression: +//! commit 2023-Nov-26: solves 2 of the hidden ARC tasks. This uses variant=0 and variant=1 and variant=2. Only variant=0 does something useful. +//! Since it uses multiple variants and doesn't solve more tasks than the previous commit, then it is not an improvement. +//! https://github.com/loda-lang/loda-rust/commit/01069f3a25770d4b12f6be5b27d2266948456275 +//! //! commit 2023-Nov-25: solves 2 of the hidden ARC tasks. This uses variant=0 and variant=1 and variant=2. Only variant=0 does something useful. //! Since it uses multiple variants and doesn't solve more tasks than the previous commit, then it is not an improvement. //! https://github.com/loda-lang/loda-rust/commit/d08069b56c92c54140c27d13f8e6ad0897824d5a @@ -80,7 +84,7 @@ //! * Provide `weight` to logistic regression, depending on how important each parameter is. use super::arc_json_model::GridFromImage; use super::arc_work_model::{Task, PairType, Pair}; -use super::{Image, ImageOverlay, arcathon_solution_coordinator, arc_json_model, ImageMix, MixMode, ObjectsAndMass, ImageCrop, Rectangle, ImageExtractRowColumn, ImageDenoise, TaskGraph, ShapeType, ImageSize, ShapeTransformation, SingleColorObject, ShapeIdentificationFromSingleColorObject, ImageDetectHole, ImagePadding, ImageRepairPattern, TaskNameToPredictionVec, CreateTaskWithSameSize, ImageReplaceColor, ImageCenterIndicator, ImageGravity, GravityDirection, DiagonalHistogram, RecordTrigram, ImageNgram, ImageExteriorCorners, LargestInteriorRectangle, ImageDrawRect, PropertyOutput, ImageProperty, ImageResize, ImageRepeat, rule, CellularAutomaton, ChangeItem}; +use super::{Image, ImageOverlay, arcathon_solution_coordinator, arc_json_model, ImageMix, MixMode, ObjectsAndMass, ImageCrop, Rectangle, ImageExtractRowColumn, ImageDenoise, TaskGraph, ShapeType, ImageSize, ShapeTransformation, SingleColorObject, ShapeIdentificationFromSingleColorObject, ImageDetectHole, ImagePadding, ImageRepairPattern, TaskNameToPredictionVec, CreateTaskWithSameSize, ImageReplaceColor, ImageCenterIndicator, ImageGravity, GravityDirection, DiagonalHistogram, RecordTrigram, ImageNgram, ImageExteriorCorners, LargestInteriorRectangle, ImageDrawRect, PropertyOutput, ImageProperty, ImageResize, ImageRepeat, rule, CellularAutomaton, ChangeItem, MeasureDensity}; use super::{ActionLabel, ImageLabel, ImageMaskDistance, LineSpan, LineSpanDirection, LineSpanMode, VerifyPrediction, VerifyPredictionWithTask}; use super::{HtmlLog, PixelConnectivity, ImageHistogram, Histogram, ImageEdge, ImageMask}; use super::{ImageNeighbour, ImageNeighbourDirection, ImageCornerAnalyze, ImageMaskGrow, Shape3x3}; @@ -1085,17 +1089,24 @@ impl SolveLogisticRegression { let enable_min_inbetween_max_inside_shape_connectivity4: bool = [false, false, false][v]; let enable_earlier_prediction_mass_connectivity4: bool = false; let enable_earlier_prediction_mass_connectivity8: bool = false; - let enable_change_happens_to_single_line: bool = [false, true, false][v]; - let enable_change_happens_to_single_line_row_or_column: bool = [false, true, false][v]; - let enable_change_happens_to_single_line_diagonal: bool = [false, true, false][v]; - let enable_change_happens_to_single_line_some_diagonal: bool = [false, true, false][v]; - let enable_change_happens_to_single_line_any_45degree_angle: bool = [false, true, false][v]; - let enable_nochange_happens_to_single_line: bool = [false, false, false][v]; - let enable_nochange_happens_to_single_line_row_or_column: bool = [false, false, false][v]; - let enable_nochange_happens_to_single_line_diagonal: bool = [false, false, false][v]; - let enable_nochange_happens_to_single_line_some_diagonal: bool = [false, false, false][v]; - let enable_nochange_happens_to_single_line_any_45degree_angle: bool = [false, false, false][v]; + let enable_change_happens_to_single_line: bool = [false, true, true][v]; + let enable_change_happens_to_single_line_row_or_column: bool = [false, true, true][v]; + let enable_change_happens_to_single_line_diagonal: bool = [false, true, true][v]; + let enable_change_happens_to_single_line_some_diagonal: bool = [false, true, true][v]; + let enable_change_happens_to_single_line_any_45degree_angle: bool = [false, true, true][v]; + let enable_nochange_happens_to_single_line: bool = [false, true, true][v]; + let enable_nochange_happens_to_single_line_row_or_column: bool = [false, true, true][v]; + let enable_nochange_happens_to_single_line_diagonal: bool = [false, true, true][v]; + let enable_nochange_happens_to_single_line_some_diagonal: bool = [false, true, true][v]; + let enable_nochange_happens_to_single_line_any_45degree_angle: bool = [false, true, true][v]; let enable_landmark_single_pixel: bool = [false, true, true][v]; + let enable_density_of_input: bool = [false, true, true][v]; + let enable_density_of_shapetype90: bool = [false, true, true][v]; + let enable_density_of_shapetype45: bool = [false, true, true][v]; + let enable_density_of_object_id: bool = [false, true, true][v]; + let enable_density_any_direction_of_denoise_type5_input: bool = [false, true, true][v]; + let enable_mostleast_popular_in_column: bool = [false, false, false][v]; + let enable_mostleast_popular_in_row: bool = [false, false, false][v]; let enable_histogram_diagonal: bool = enable_histogram_diagonal_a || enable_histogram_diagonal_b || enable_histogram_diagonal_c || @@ -1371,7 +1382,13 @@ impl SolveLogisticRegression { let image: Image = output.denoise_type5()?; denoise_type5_output_image = Some(image); } - + + let mut density_any_direction_of_input: Option = None; + if enable_density_of_input { + let measure_density: MeasureDensity = MeasureDensity::analyze(&input)?; + density_any_direction_of_input = Some(measure_density.density_any_direction); + } + let mut gameoflife_images = HashMap::::new(); if enable_gameoflife { for color in 0..=9u8 { @@ -1468,7 +1485,7 @@ impl SolveLogisticRegression { } let object_id_image_connectivity8: Image; - if enable_object_id_image_connectivity8 { + if enable_object_id_image_connectivity8 || enable_density_of_object_id { object_id_image_connectivity8 = Self::object_id_image(&task_graph, pair_index_u8, width, height, PixelConnectivity::Connectivity8)?; } else { object_id_image_connectivity8 = Image::empty(); @@ -1505,6 +1522,32 @@ impl SolveLogisticRegression { let shape_size_images_connectivity8: Vec = Self::shape_size_images(&task_graph, pair_index_u8, width, height, PixelConnectivity::Connectivity8)?; _ = shape_size_images_connectivity8; + let mut density_any_direction_of_shapetype90: Option = None; + if enable_density_of_shapetype90 { + let measure_density: MeasureDensity = MeasureDensity::analyze(&shape_type_image_connectivity8)?; + density_any_direction_of_shapetype90 = Some(measure_density.density_any_direction); + } + + let mut density_any_direction_of_shapetype45: Option = None; + if enable_density_of_shapetype45 { + let measure_density: MeasureDensity = MeasureDensity::analyze(&shape_type45_image_connectivity8)?; + density_any_direction_of_shapetype45 = Some(measure_density.density_any_direction); + } + + let mut density_any_direction_of_object_id: Option = None; + if enable_density_of_object_id { + let measure_density: MeasureDensity = MeasureDensity::analyze(&object_id_image_connectivity8)?; + density_any_direction_of_object_id = Some(measure_density.density_any_direction); + } + + let mut density_any_direction_of_denoise_type5_input: Option = None; + if enable_density_any_direction_of_denoise_type5_input { + if let Some(image) = &denoise_type5_input_image { + let measure_density: MeasureDensity = MeasureDensity::analyze(image)?; + density_any_direction_of_denoise_type5_input = Some(measure_density.density_any_direction); + } + } + // let mut repair_mask: Image = Image::zero(width, height); // if let Some(mask) = &pair.input.repair_mask { // repair_mask = repair_mask.overlay_with_position(mask, 0, 0)?; @@ -2720,6 +2763,46 @@ impl SolveLogisticRegression { } } + if enable_density_of_input { + let mut color: u8 = 255; + if let Some(image) = &density_any_direction_of_input { + color = image.get(xx, yy).unwrap_or(255); + } + record.serialize_onehot_discard_overflow(color, 9); + } + + if enable_density_of_shapetype90 { + let mut color: u8 = 255; + if let Some(image) = &density_any_direction_of_shapetype90 { + color = image.get(xx, yy).unwrap_or(255); + } + record.serialize_onehot_discard_overflow(color, 9); + } + + if enable_density_of_shapetype45 { + let mut color: u8 = 255; + if let Some(image) = &density_any_direction_of_shapetype45 { + color = image.get(xx, yy).unwrap_or(255); + } + record.serialize_onehot_discard_overflow(color, 9); + } + + if enable_density_of_object_id { + let mut color: u8 = 255; + if let Some(image) = &density_any_direction_of_object_id { + color = image.get(xx, yy).unwrap_or(255); + } + record.serialize_onehot_discard_overflow(color, 9); + } + + if enable_density_any_direction_of_denoise_type5_input { + let mut color: u8 = 255; + if let Some(image) = &density_any_direction_of_denoise_type5_input { + color = image.get(xx, yy).unwrap_or(255); + } + record.serialize_onehot_discard_overflow(color, 9); + } + if enable_gameoflife { for i in 0..10u8 { let mut color: u8 = 255; @@ -3916,32 +3999,31 @@ impl SolveLogisticRegression { // record.serialize_color_complex(rows_columns_agree_on_one_color.unwrap_or(255), obfuscated_color_offset, enable_serialize_color_complex); // record.serialize_onehot_discard_overflow(rows_columns_agree_on_one_color.unwrap_or(255), 10); - // { - // let mut most_popular_color_in_column: Option = None; - // let mut least_popular_color_in_column: Option = None; - // if let Some(histogram) = histogram_columns.get(x as usize) { - // most_popular_color_in_column = histogram.most_popular_color_disallow_ambiguous(); - // least_popular_color_in_column = histogram.least_popular_color_disallow_ambiguous(); - // } - // record.serialize_color_complex(most_popular_color_in_column.unwrap_or(255), obfuscated_color_offset, enable_serialize_color_complex); - // record.serialize_color_complex(least_popular_color_in_column.unwrap_or(255), obfuscated_color_offset, enable_serialize_color_complex); - // record.serialize_onehot_discard_overflow(most_popular_color_in_column.unwrap_or(255), 10); - // record.serialize_onehot_discard_overflow(least_popular_color_in_column.unwrap_or(255), 10); - // } - - // { - // let mut most_popular_color_in_row: Option = None; - // let mut least_popular_color_in_row: Option = None; - // if let Some(histogram) = histogram_rows.get(y as usize) { - // most_popular_color_in_row = histogram.most_popular_color_disallow_ambiguous(); - // least_popular_color_in_row = histogram.least_popular_color_disallow_ambiguous(); - // } - // record.serialize_color_complex(most_popular_color_in_row.unwrap_or(255), obfuscated_color_offset, enable_serialize_color_complex); - // record.serialize_color_complex(least_popular_color_in_row.unwrap_or(255), obfuscated_color_offset, enable_serialize_color_complex); - // record.serialize_onehot_discard_overflow(most_popular_color_in_row.unwrap_or(255), 10); - // record.serialize_onehot_discard_overflow(least_popular_color_in_row.unwrap_or(255), 10); - // } + if enable_mostleast_popular_in_column { + let mut most_popular_color_in_column: Option = None; + let mut least_popular_color_in_column: Option = None; + if let Some(histogram) = histogram_columns.get(x as usize) { + most_popular_color_in_column = histogram.most_popular_color_disallow_ambiguous(); + least_popular_color_in_column = histogram.least_popular_color_disallow_ambiguous(); + } + record.serialize_color_complex(most_popular_color_in_column.unwrap_or(255), obfuscated_color_offset, enable_serialize_color_complex); + record.serialize_color_complex(least_popular_color_in_column.unwrap_or(255), obfuscated_color_offset, enable_serialize_color_complex); + record.serialize_onehot_discard_overflow(most_popular_color_in_column.unwrap_or(255), 10); + record.serialize_onehot_discard_overflow(least_popular_color_in_column.unwrap_or(255), 10); + } + if enable_mostleast_popular_in_row { + let mut most_popular_color_in_row: Option = None; + let mut least_popular_color_in_row: Option = None; + if let Some(histogram) = histogram_rows.get(y as usize) { + most_popular_color_in_row = histogram.most_popular_color_disallow_ambiguous(); + least_popular_color_in_row = histogram.least_popular_color_disallow_ambiguous(); + } + record.serialize_color_complex(most_popular_color_in_row.unwrap_or(255), obfuscated_color_offset, enable_serialize_color_complex); + record.serialize_color_complex(least_popular_color_in_row.unwrap_or(255), obfuscated_color_offset, enable_serialize_color_complex); + record.serialize_onehot_discard_overflow(most_popular_color_in_row.unwrap_or(255), 10); + record.serialize_onehot_discard_overflow(least_popular_color_in_row.unwrap_or(255), 10); + } let mut is_full_column: bool = false; let mut is_full_row: bool = false; diff --git a/rust_project/loda-rust-cli/src/arc/solve_one_color.rs b/rust_project/loda-rust-cli/src/arc/solve_one_color.rs index 4e3e8f5a..e1f3b537 100644 --- a/rust_project/loda-rust-cli/src/arc/solve_one_color.rs +++ b/rust_project/loda-rust-cli/src/arc/solve_one_color.rs @@ -1,13 +1,15 @@ //! Solve tasks that outputs a single color. //! +//! Solves zero of the hidden ARC tasks. +//! //! The ARC 1 dataset contains 800 tasks, where 17 of the tasks outputs a single color. //! 1190e5a7, 1a2e2828, 239be575, 23b5c85d, 27a28665, 3194b014, 445eab21, 44f52bb0, 5582e5ca, 642d658d, //! 7039b2d7, 8597cfd7, b9b7f026, d631b094, d9fac9be, de1cd16c, e872b94a, //! -//! This solver is able to solve 16 of the 17 tasks. -//! Where 10 is solved with some confidence. -//! Where 6 of them is solved as a happy accident. -//! Where 1 task is not solved b9b7f026, because it has more than 4 colors to choose from, and chooses the wrong color. +//! This solver is able to solve 14 of the 17 tasks. +//! Where 9 is solved with some confidence. +//! Where 5 of them is solved as a happy accident. +//! Where 3 tasks is not solved 1a2e2828, 27a28665, b9b7f026, because it has more than 4 colors to choose from, and chooses the wrong color. //! //! Weakness: //! When there are 4 or more colors to choose from, then it doesn't do any prediction, and takes the 3 first colors. @@ -513,6 +515,10 @@ impl SolveOneColor { // Assign a low confidence score to these predictions, so they are ranked lower than other high confidence predictions. // Rule out the noise color, grid color, most dense colors. debug!("low confidence: task: {} - test_index: {} - available_colors: {:?}", task.id, test_index, the_colors); + // Taking the initial 3 colors doesn't solve any of the hidden ARC tasks. + // Here is a crappy 2nd guess. By reversing the_colors. + the_colors.reverse(); + the_colors.truncate(3); } } Ok(the_colors) diff --git a/rust_project/loda-rust-cli/src/arc/traverse_programs_and_models.rs b/rust_project/loda-rust-cli/src/arc/traverse_programs_and_models.rs index 18162dcd..b481ab88 100644 --- a/rust_project/loda-rust-cli/src/arc/traverse_programs_and_models.rs +++ b/rust_project/loda-rust-cli/src/arc/traverse_programs_and_models.rs @@ -1603,7 +1603,7 @@ impl TraverseProgramsAndModels { let resume_from_last_snapshot = false; // Solve tasks that outputs a single color. - // Not yet tried on the hidden ARC dataset, so I don't know if this doesn't solves any tasks. + // On the hidden ARC dataset, this doesn't solve any tasks. let try_solve_one_color = true; // Solve `splitview` like tasks.