From b3dc67843c9f286018dc8331978484c471a2e9c1 Mon Sep 17 00:00:00 2001 From: Gaston Zanitti Date: Wed, 11 Dec 2024 13:18:00 -0300 Subject: [PATCH 1/8] optimize until fixpoint --- ast/src/analyzed/mod.rs | 43 ++++++++++++++++---------- backend/src/plonky3/stark.rs | 24 +-------------- pilopt/src/lib.rs | 60 ++++++++++++++++++++++++++++++------ 3 files changed, 79 insertions(+), 48 deletions(-) diff --git a/ast/src/analyzed/mod.rs b/ast/src/analyzed/mod.rs index a2291b3009..8b0772a89c 100644 --- a/ast/src/analyzed/mod.rs +++ b/ast/src/analyzed/mod.rs @@ -901,7 +901,7 @@ impl Children for NamedType { } } -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Hash)] pub struct PublicDeclaration { pub id: u64, pub source: SourceRef, @@ -921,7 +921,9 @@ impl PublicDeclaration { } } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, JsonSchema)] +#[derive( + Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, JsonSchema, Hash, +)] pub struct SelectedExpressions { pub selector: AlgebraicExpression, pub expressions: Vec>, @@ -947,7 +949,7 @@ impl Children> for SelectedExpressions { } } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema, Hash)] pub struct PolynomialIdentity { // The ID is globally unique among identities. pub id: u64, @@ -964,7 +966,7 @@ impl Children> for PolynomialIdentity { } } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema, Hash)] pub struct LookupIdentity { // The ID is globally unique among identities. pub id: u64, @@ -986,7 +988,7 @@ impl Children> for LookupIdentity { /// /// This identity is used as a replacement for a lookup identity which has been turned into challenge-based polynomial identities. /// This is ignored by the backend. -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema, Hash)] pub struct PhantomLookupIdentity { // The ID is globally unique among identities. pub id: u64, @@ -1015,7 +1017,7 @@ impl Children> for PhantomLookupIdentity { } } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema, Hash)] pub struct PermutationIdentity { // The ID is globally unique among identities. pub id: u64, @@ -1037,7 +1039,7 @@ impl Children> for PermutationIdentity { /// /// This identity is used as a replacement for a permutation identity which has been turned into challenge-based polynomial identities. /// This is ignored by the backend. -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema, Hash)] pub struct PhantomPermutationIdentity { // The ID is globally unique among identities. pub id: u64, @@ -1055,7 +1057,7 @@ impl Children> for PhantomPermutationIdentity { } } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema, Hash)] pub struct ConnectIdentity { // The ID is globally unique among identities. pub id: u64, @@ -1073,7 +1075,9 @@ impl Children> for ConnectIdentity { } } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema, PartialOrd, Ord)] +#[derive( + Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema, PartialOrd, Ord, Hash, +)] pub struct ExpressionList(pub Vec>); impl Children> for ExpressionList { @@ -1085,7 +1089,7 @@ impl Children> for ExpressionList { } } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, JsonSchema, Hash)] pub struct PhantomBusInteractionIdentity { // The ID is globally unique among identities. pub id: u64, @@ -1111,6 +1115,7 @@ impl Children> for PhantomBusInteractionIdentity { Serialize, Deserialize, JsonSchema, + Hash, derive_more::Display, derive_more::From, derive_more::TryInto, @@ -1305,7 +1310,9 @@ impl Hash for AlgebraicReference { } } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, JsonSchema)] +#[derive( + Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, JsonSchema, Hash, +)] pub enum AlgebraicExpression { Reference(AlgebraicReference), PublicReference(String), @@ -1315,7 +1322,9 @@ pub enum AlgebraicExpression { UnaryOperation(AlgebraicUnaryOperation), } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, JsonSchema)] +#[derive( + Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, JsonSchema, Hash, +)] pub struct AlgebraicBinaryOperation { pub left: Box>, pub op: AlgebraicBinaryOperator, @@ -1341,7 +1350,9 @@ impl From> for AlgebraicExpression { } } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, JsonSchema)] +#[derive( + Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, JsonSchema, Hash, +)] pub struct AlgebraicUnaryOperation { pub op: AlgebraicUnaryOperator, pub expr: Box>, @@ -1525,7 +1536,7 @@ impl AlgebraicExpression { } #[derive( - Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize, JsonSchema, + Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize, JsonSchema, Hash, )] pub struct Challenge { /// Challenge ID @@ -1534,7 +1545,7 @@ pub struct Challenge { } #[derive( - Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize, JsonSchema, + Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize, JsonSchema, Hash, )] pub enum AlgebraicBinaryOperator { Add, @@ -1572,7 +1583,7 @@ impl TryFrom for AlgebraicBinaryOperator { } #[derive( - Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize, JsonSchema, + Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize, JsonSchema, Hash, )] pub enum AlgebraicUnaryOperator { Minus, diff --git a/backend/src/plonky3/stark.rs b/backend/src/plonky3/stark.rs index 7e0d0b679e..9e641ba3e6 100644 --- a/backend/src/plonky3/stark.rs +++ b/backend/src/plonky3/stark.rs @@ -414,7 +414,7 @@ mod tests { col witness x; col witness y; col witness z; - y - 1 = 0; + y - 1 = 1; x = 0; x + y = z; @@ -465,28 +465,6 @@ mod tests { run_test(content); } - #[test] - fn two_tables() { - // This test is a bit contrived but witgen wouldn't allow a more direct example - let content = r#" - namespace Add(8); - col witness x; - col witness y; - col witness z; - x = 0; - y = 0; - x + y = z; - 1 $ [ x, y, z ] in 1 $ [ Mul::x, Mul::y, Mul::z ]; - - namespace Mul(16); - col witness x; - col witness y; - col witness z; - x * y = z; - "#; - run_test(content); - } - #[test] fn challenge() { let content = r#" diff --git a/pilopt/src/lib.rs b/pilopt/src/lib.rs index 5db5a81aaf..5b14e7570a 100644 --- a/pilopt/src/lib.rs +++ b/pilopt/src/lib.rs @@ -2,6 +2,7 @@ use std::cmp::Ordering; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::hash::{DefaultHasher, Hash, Hasher}; use itertools::Itertools; use powdr_ast::analyzed::{ @@ -22,16 +23,20 @@ use referenced_symbols::{ReferencedSymbols, SymbolReference}; pub fn optimize(mut pil_file: Analyzed) -> Analyzed { let col_count_pre = (pil_file.commitment_count(), pil_file.constant_count()); + let mut pil_hash = 0; remove_unreferenced_definitions(&mut pil_file); - remove_constant_fixed_columns(&mut pil_file); - deduplicate_fixed_columns(&mut pil_file); - simplify_identities(&mut pil_file); - extract_constant_lookups(&mut pil_file); - remove_constant_witness_columns(&mut pil_file); - simplify_identities(&mut pil_file); - remove_trivial_identities(&mut pil_file); - remove_duplicate_identities(&mut pil_file); - remove_unreferenced_definitions(&mut pil_file); + while pil_hash != hash_pil_state(&pil_file) { + pil_hash = hash_pil_state(&pil_file); + remove_constant_fixed_columns(&mut pil_file); + deduplicate_fixed_columns(&mut pil_file); + simplify_identities(&mut pil_file); + extract_constant_lookups(&mut pil_file); + remove_constant_witness_columns(&mut pil_file); + simplify_identities(&mut pil_file); + remove_trivial_identities(&mut pil_file); + remove_duplicate_identities(&mut pil_file); + remove_unreferenced_definitions(&mut pil_file); + } let col_count_post = (pil_file.commitment_count(), pil_file.constant_count()); log::info!( "Removed {} witness and {} fixed columns. Total count now: {} witness and {} fixed columns.", @@ -43,6 +48,43 @@ pub fn optimize(mut pil_file: Analyzed) -> Analyzed { pil_file } +fn hash_pil_state(pil: &Analyzed) -> u64 { + let mut hasher = DefaultHasher::new(); + + for identity in &pil.identities { + identity.hash(&mut hasher); + } + + let mut keys: Vec<_> = pil.definitions.keys().collect(); + keys.sort(); + for key in keys { + key.hash(&mut hasher); + if let Some(v) = &pil.definitions[key].1 { + v.hash(&mut hasher); + } + } + + let mut keys: Vec<_> = pil.intermediate_columns.keys().collect(); + keys.sort(); + for key in keys { + key.hash(&mut hasher); + pil.intermediate_columns[key].1.hash(&mut hasher); + } + + for pf in &pil.prover_functions { + pf.hash(&mut hasher); + } + + let mut keys: Vec<_> = pil.public_declarations.keys().collect(); + keys.sort(); + for key in keys { + key.hash(&mut hasher); + pil.public_declarations[key].hash(&mut hasher); + } + + hasher.finish() +} + /// Removes all definitions that are not referenced by an identity, public declaration /// or witness column hint. fn remove_unreferenced_definitions(pil_file: &mut Analyzed) { From af154f2a1bfe9f1fea54ba2fe7e115cbd4aee212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Zanitti?= Date: Thu, 12 Dec 2024 10:44:56 -0300 Subject: [PATCH 2/8] Update pilopt/src/lib.rs Co-authored-by: chriseth --- pilopt/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pilopt/src/lib.rs b/pilopt/src/lib.rs index 5b14e7570a..9fbf516250 100644 --- a/pilopt/src/lib.rs +++ b/pilopt/src/lib.rs @@ -55,9 +55,7 @@ fn hash_pil_state(pil: &Analyzed) -> u64 { identity.hash(&mut hasher); } - let mut keys: Vec<_> = pil.definitions.keys().collect(); - keys.sort(); - for key in keys { + for (key, value) in pil.definitions.iter().sorted() { key.hash(&mut hasher); if let Some(v) = &pil.definitions[key].1 { v.hash(&mut hasher); From c4dd3a3136e0f69e4d37e4a69b0d8a836e8ca65f Mon Sep 17 00:00:00 2001 From: Gaston Zanitti Date: Thu, 12 Dec 2024 12:27:13 -0300 Subject: [PATCH 3/8] General improvements --- ast/src/parsed/mod.rs | 4 +++- pilopt/src/lib.rs | 21 +++++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/ast/src/parsed/mod.rs b/ast/src/parsed/mod.rs index cde8f52794..b3988024a7 100644 --- a/ast/src/parsed/mod.rs +++ b/ast/src/parsed/mod.rs @@ -421,7 +421,9 @@ impl Children> for EnumVariant> { } } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, JsonSchema)] +#[derive( + Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, JsonSchema, Hash, +)] pub struct TraitImplementation { pub name: SymbolPath, pub source_ref: SourceRef, diff --git a/pilopt/src/lib.rs b/pilopt/src/lib.rs index 9fbf516250..feb744fe06 100644 --- a/pilopt/src/lib.rs +++ b/pilopt/src/lib.rs @@ -23,10 +23,9 @@ use referenced_symbols::{ReferencedSymbols, SymbolReference}; pub fn optimize(mut pil_file: Analyzed) -> Analyzed { let col_count_pre = (pil_file.commitment_count(), pil_file.constant_count()); - let mut pil_hash = 0; - remove_unreferenced_definitions(&mut pil_file); - while pil_hash != hash_pil_state(&pil_file) { - pil_hash = hash_pil_state(&pil_file); + loop { + let pil_hash = hash_pil_state(&pil_file); + remove_unreferenced_definitions(&mut pil_file); remove_constant_fixed_columns(&mut pil_file); deduplicate_fixed_columns(&mut pil_file); simplify_identities(&mut pil_file); @@ -35,8 +34,12 @@ pub fn optimize(mut pil_file: Analyzed) -> Analyzed { simplify_identities(&mut pil_file); remove_trivial_identities(&mut pil_file); remove_duplicate_identities(&mut pil_file); - remove_unreferenced_definitions(&mut pil_file); + + if pil_hash == hash_pil_state(&pil_file) { + break; + } } + let col_count_post = (pil_file.commitment_count(), pil_file.constant_count()); log::info!( "Removed {} witness and {} fixed columns. Total count now: {} witness and {} fixed columns.", @@ -55,7 +58,9 @@ fn hash_pil_state(pil: &Analyzed) -> u64 { identity.hash(&mut hasher); } - for (key, value) in pil.definitions.iter().sorted() { + let mut keys: Vec<_> = pil.definitions.keys().collect(); + keys.sort(); + for key in keys { key.hash(&mut hasher); if let Some(v) = &pil.definitions[key].1 { v.hash(&mut hasher); @@ -80,6 +85,10 @@ fn hash_pil_state(pil: &Analyzed) -> u64 { pil.public_declarations[key].hash(&mut hasher); } + for _impl in &pil.trait_impls { + _impl.hash(&mut hasher); + } + hasher.finish() } From b345808bbd088d50995e339cd24a58d5ac607b2e Mon Sep 17 00:00:00 2001 From: Gaston Zanitti Date: Thu, 12 Dec 2024 12:57:56 -0300 Subject: [PATCH 4/8] Better hash & minor fixes --- ast/src/analyzed/mod.rs | 6 +++--- pilopt/src/lib.rs | 27 ++++++++++++++------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/ast/src/analyzed/mod.rs b/ast/src/analyzed/mod.rs index 8b0772a89c..ec881aa97f 100644 --- a/ast/src/analyzed/mod.rs +++ b/ast/src/analyzed/mod.rs @@ -139,7 +139,7 @@ impl Analyzed { self.definitions_in_source_order(PolynomialType::Committed) } - fn intermediate_polys_in_source_order( + pub fn intermediate_polys_in_source_order( &self, ) -> impl Iterator>)> { self.source_order.iter().filter_map(move |statement| { @@ -771,7 +771,7 @@ impl DegreeRange { } } -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Hash)] pub struct Symbol { pub id: u64, pub source: SourceRef, @@ -831,7 +831,7 @@ impl Symbol { /// The "kind" of a symbol. In the future, this will be mostly /// replaced by its type. #[derive( - Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema, + Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema, Hash, )] pub enum SymbolKind { /// Fixed, witness or intermediate polynomial diff --git a/pilopt/src/lib.rs b/pilopt/src/lib.rs index feb744fe06..1d86f1e113 100644 --- a/pilopt/src/lib.rs +++ b/pilopt/src/lib.rs @@ -23,9 +23,9 @@ use referenced_symbols::{ReferencedSymbols, SymbolReference}; pub fn optimize(mut pil_file: Analyzed) -> Analyzed { let col_count_pre = (pil_file.commitment_count(), pil_file.constant_count()); + remove_unreferenced_definitions(&mut pil_file); loop { let pil_hash = hash_pil_state(&pil_file); - remove_unreferenced_definitions(&mut pil_file); remove_constant_fixed_columns(&mut pil_file); deduplicate_fixed_columns(&mut pil_file); simplify_identities(&mut pil_file); @@ -58,31 +58,32 @@ fn hash_pil_state(pil: &Analyzed) -> u64 { identity.hash(&mut hasher); } - let mut keys: Vec<_> = pil.definitions.keys().collect(); - keys.sort(); - for key in keys { + for (key, value) in pil.constant_polys_in_source_order() { key.hash(&mut hasher); - if let Some(v) = &pil.definitions[key].1 { + if let Some(v) = &value { v.hash(&mut hasher); } } - let mut keys: Vec<_> = pil.intermediate_columns.keys().collect(); - keys.sort(); - for key in keys { + for (key, value) in pil.committed_polys_in_source_order() { key.hash(&mut hasher); - pil.intermediate_columns[key].1.hash(&mut hasher); + if let Some(v) = &value { + v.hash(&mut hasher); + } + } + + for (key, value) in pil.intermediate_polys_in_source_order() { + key.hash(&mut hasher); + value.hash(&mut hasher); } for pf in &pil.prover_functions { pf.hash(&mut hasher); } - let mut keys: Vec<_> = pil.public_declarations.keys().collect(); - keys.sort(); - for key in keys { + for (key, value) in pil.public_declarations_in_source_order() { key.hash(&mut hasher); - pil.public_declarations[key].hash(&mut hasher); + value.hash(&mut hasher); } for _impl in &pil.trait_impls { From c577f2b6550c60d1ac8890d2bad4cc422df6aad1 Mon Sep 17 00:00:00 2001 From: Gaston Zanitti Date: Thu, 12 Dec 2024 13:28:58 -0300 Subject: [PATCH 5/8] sorted_by --- pilopt/src/lib.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/pilopt/src/lib.rs b/pilopt/src/lib.rs index 1d86f1e113..e4b620d203 100644 --- a/pilopt/src/lib.rs +++ b/pilopt/src/lib.rs @@ -23,9 +23,9 @@ use referenced_symbols::{ReferencedSymbols, SymbolReference}; pub fn optimize(mut pil_file: Analyzed) -> Analyzed { let col_count_pre = (pil_file.commitment_count(), pil_file.constant_count()); - remove_unreferenced_definitions(&mut pil_file); loop { let pil_hash = hash_pil_state(&pil_file); + remove_unreferenced_definitions(&mut pil_file); remove_constant_fixed_columns(&mut pil_file); deduplicate_fixed_columns(&mut pil_file); simplify_identities(&mut pil_file); @@ -58,21 +58,18 @@ fn hash_pil_state(pil: &Analyzed) -> u64 { identity.hash(&mut hasher); } - for (key, value) in pil.constant_polys_in_source_order() { + for (key, (_, value)) in pil.definitions.iter().sorted_by(|a, b| a.0.cmp(b.0)) { key.hash(&mut hasher); - if let Some(v) = &value { + if let Some(v) = value { v.hash(&mut hasher); } } - for (key, value) in pil.committed_polys_in_source_order() { - key.hash(&mut hasher); - if let Some(v) = &value { - v.hash(&mut hasher); - } - } - - for (key, value) in pil.intermediate_polys_in_source_order() { + for (key, (_, value)) in pil + .intermediate_columns + .iter() + .sorted_by(|a, b| a.0.cmp(b.0)) + { key.hash(&mut hasher); value.hash(&mut hasher); } @@ -81,7 +78,11 @@ fn hash_pil_state(pil: &Analyzed) -> u64 { pf.hash(&mut hasher); } - for (key, value) in pil.public_declarations_in_source_order() { + for (key, value) in pil + .public_declarations + .iter() + .sorted_by(|a, b| a.0.cmp(b.0)) + { key.hash(&mut hasher); value.hash(&mut hasher); } From 4d5f264dfd242be765f6a21b67ead7db3de4a07b Mon Sep 17 00:00:00 2001 From: Gaston Zanitti Date: Tue, 17 Dec 2024 08:56:59 -0300 Subject: [PATCH 6/8] Analyzed hash --- ast/src/analyzed/mod.rs | 53 +++++++++++++++++++++++++++++++++++++- pilopt/src/lib.rs | 56 ++++++++--------------------------------- 2 files changed, 63 insertions(+), 46 deletions(-) diff --git a/ast/src/analyzed/mod.rs b/ast/src/analyzed/mod.rs index ec881aa97f..5733f431de 100644 --- a/ast/src/analyzed/mod.rs +++ b/ast/src/analyzed/mod.rs @@ -25,7 +25,7 @@ use crate::parsed::{ TraitDeclaration, TraitImplementation, TypeDeclaration, }; -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash)] pub enum StatementIdentifier { /// Either an intermediate column or a definition. Definition(String), @@ -518,6 +518,57 @@ impl Analyzed { } } +impl Hash for Analyzed { + fn hash(&self, state: &mut H) { + for identity in &self.identities { + identity.hash(state); + } + + for (key, (_, value)) in self.definitions.iter().sorted_by(|a, b| a.0.cmp(b.0)) { + key.hash(state); + if let Some(v) = value { + v.hash(state); + } + } + + for (key, (_, value)) in self + .intermediate_columns + .iter() + .sorted_by(|a, b| a.0.cmp(b.0)) + { + key.hash(state); + for v in value.iter() { + v.hash(state); + } + } + + for pf in &self.prover_functions { + pf.hash(state); + } + + for (key, value) in self + .public_declarations + .iter() + .sorted_by(|a, b| a.0.cmp(b.0)) + { + key.hash(state); + value.hash(state); + } + + for _impl in &self.trait_impls { + _impl.hash(state); + } + + for order in &self.source_order { + order.hash(state); + } + + for symbol in self.auto_added_symbols.iter().sorted() { + symbol.hash(state); + } + } +} + /// Takes identities as values and inlines intermediate polynomials everywhere, returning a vector of the updated identities /// TODO: this could return an iterator fn substitute_intermediate( diff --git a/pilopt/src/lib.rs b/pilopt/src/lib.rs index e4b620d203..fde7a3c0f2 100644 --- a/pilopt/src/lib.rs +++ b/pilopt/src/lib.rs @@ -24,7 +24,11 @@ use referenced_symbols::{ReferencedSymbols, SymbolReference}; pub fn optimize(mut pil_file: Analyzed) -> Analyzed { let col_count_pre = (pil_file.commitment_count(), pil_file.constant_count()); loop { - let pil_hash = hash_pil_state(&pil_file); + let pil_hash = { + let mut hasher = DefaultHasher::new(); + pil_file.hash(&mut hasher); + hasher.finish() + }; remove_unreferenced_definitions(&mut pil_file); remove_constant_fixed_columns(&mut pil_file); deduplicate_fixed_columns(&mut pil_file); @@ -35,7 +39,12 @@ pub fn optimize(mut pil_file: Analyzed) -> Analyzed { remove_trivial_identities(&mut pil_file); remove_duplicate_identities(&mut pil_file); - if pil_hash == hash_pil_state(&pil_file) { + let new_hash = { + let mut hasher = DefaultHasher::new(); + pil_file.hash(&mut hasher); + hasher.finish() + }; + if pil_hash == new_hash { break; } } @@ -51,49 +60,6 @@ pub fn optimize(mut pil_file: Analyzed) -> Analyzed { pil_file } -fn hash_pil_state(pil: &Analyzed) -> u64 { - let mut hasher = DefaultHasher::new(); - - for identity in &pil.identities { - identity.hash(&mut hasher); - } - - for (key, (_, value)) in pil.definitions.iter().sorted_by(|a, b| a.0.cmp(b.0)) { - key.hash(&mut hasher); - if let Some(v) = value { - v.hash(&mut hasher); - } - } - - for (key, (_, value)) in pil - .intermediate_columns - .iter() - .sorted_by(|a, b| a.0.cmp(b.0)) - { - key.hash(&mut hasher); - value.hash(&mut hasher); - } - - for pf in &pil.prover_functions { - pf.hash(&mut hasher); - } - - for (key, value) in pil - .public_declarations - .iter() - .sorted_by(|a, b| a.0.cmp(b.0)) - { - key.hash(&mut hasher); - value.hash(&mut hasher); - } - - for _impl in &pil.trait_impls { - _impl.hash(&mut hasher); - } - - hasher.finish() -} - /// Removes all definitions that are not referenced by an identity, public declaration /// or witness column hint. fn remove_unreferenced_definitions(pil_file: &mut Analyzed) { From 85689817f5457ad625d1e3c184e7b61a1cb04b07 Mon Sep 17 00:00:00 2001 From: Gaston Zanitti Date: Tue, 17 Dec 2024 11:19:25 -0300 Subject: [PATCH 7/8] fix test --- pilopt/tests/optimizer.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pilopt/tests/optimizer.rs b/pilopt/tests/optimizer.rs index 0903e77300..893f1c2f3c 100644 --- a/pilopt/tests/optimizer.rs +++ b/pilopt/tests/optimizer.rs @@ -40,8 +40,7 @@ fn replace_intermediate() { "#; let expectation = r#"namespace N(65536); col witness X; - col other_intermediate = 0; - N::X' = N::X + 1 + N::other_intermediate; + N::X' = N::X + 1; "#; let optimized = optimize(analyze_string::(input).unwrap()).to_string(); assert_eq!(optimized, expectation); From 7361bac7f00aeb681256e62e6b63f72e9f0296dc Mon Sep 17 00:00:00 2001 From: Gaston Zanitti Date: Fri, 20 Dec 2024 20:16:01 -0300 Subject: [PATCH 8/8] improvemnts --- ast/src/analyzed/mod.rs | 2 +- pilopt/src/lib.rs | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/ast/src/analyzed/mod.rs b/ast/src/analyzed/mod.rs index 5733f431de..c8c60b34b2 100644 --- a/ast/src/analyzed/mod.rs +++ b/ast/src/analyzed/mod.rs @@ -518,7 +518,7 @@ impl Analyzed { } } -impl Hash for Analyzed { +impl Hash for Analyzed { fn hash(&self, state: &mut H) { for identity in &self.identities { identity.hash(state); diff --git a/pilopt/src/lib.rs b/pilopt/src/lib.rs index 953165b353..46d952391e 100644 --- a/pilopt/src/lib.rs +++ b/pilopt/src/lib.rs @@ -23,12 +23,8 @@ use referenced_symbols::{ReferencedSymbols, SymbolReference}; pub fn optimize(mut pil_file: Analyzed) -> Analyzed { let col_count_pre = (pil_file.commitment_count(), pil_file.constant_count()); + let mut pil_hash = hash_pil_state(&pil_file); loop { - let pil_hash = { - let mut hasher = DefaultHasher::new(); - pil_file.hash(&mut hasher); - hasher.finish() - }; remove_unreferenced_definitions(&mut pil_file); remove_constant_fixed_columns(&mut pil_file); deduplicate_fixed_columns(&mut pil_file); @@ -40,14 +36,11 @@ pub fn optimize(mut pil_file: Analyzed) -> Analyzed { remove_trivial_identities(&mut pil_file); remove_duplicate_identities(&mut pil_file); - let new_hash = { - let mut hasher = DefaultHasher::new(); - pil_file.hash(&mut hasher); - hasher.finish() - }; + let new_hash = hash_pil_state(&pil_file); if pil_hash == new_hash { break; } + pil_hash = new_hash; } let col_count_post = (pil_file.commitment_count(), pil_file.constant_count()); log::info!( @@ -60,6 +53,12 @@ pub fn optimize(mut pil_file: Analyzed) -> Analyzed { pil_file } +fn hash_pil_state(pil_file: &Analyzed) -> u64 { + let mut hasher = DefaultHasher::new(); + pil_file.hash(&mut hasher); + hasher.finish() +} + /// Removes all definitions that are not referenced by an identity, public declaration /// or witness column hint. fn remove_unreferenced_definitions(pil_file: &mut Analyzed) {