Skip to content

Commit

Permalink
Pad all tables to the same height
Browse files Browse the repository at this point in the history
Fix #10
  • Loading branch information
jan-ferdinand committed Sep 20, 2022
1 parent f3351e5 commit 338efcf
Show file tree
Hide file tree
Showing 15 changed files with 912 additions and 789 deletions.
18 changes: 9 additions & 9 deletions triton-vm/src/cross_table_arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::table::processor_table::PROCESSOR_TABLE_PERMUTATION_ARGUMENTS_COUNT;
use crate::table::table_collection::TableId::{
HashTable, InstructionTable, ProcessorTable, ProgramTable,
};
use crate::table::table_collection::{ExtTableCollection, TableId};
use crate::table::table_collection::{interpolant_degree, ExtTableCollection, TableId};
use crate::table::table_column::{
ExtHashTableColumn, ExtInstructionTableColumn, ExtJumpStackTableColumn, ExtOpStackTableColumn,
ExtProcessorTableColumn, ExtProgramTableColumn, ExtRamTableColumn, ExtU32OpTableColumn,
Expand Down Expand Up @@ -59,14 +59,14 @@ pub trait CrossTableArg {
.collect_vec()
}

fn quotient_degree_bound(&self, ext_codeword_tables: &ExtTableCollection) -> Degree {
let (from_table, _) = self.from();
let (to_table, _) = self.to();
let lhs_interpolant_degree = ext_codeword_tables.interpolant_degree(from_table);
let rhs_interpolant_degree = ext_codeword_tables.interpolant_degree(to_table);
let degree = std::cmp::max(lhs_interpolant_degree, rhs_interpolant_degree);

degree - 1
fn quotient_degree_bound(
&self,
ext_codeword_tables: &ExtTableCollection,
num_trace_randomizers: usize,
) -> Degree {
let interpolant_degree =
interpolant_degree(ext_codeword_tables.padded_height, num_trace_randomizers);
interpolant_degree - 1
}

fn evaluate_difference(&self, cross_table_slice: &[Vec<XFieldElement>]) -> XFieldElement {
Expand Down
13 changes: 7 additions & 6 deletions triton-vm/src/proof_item.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use super::table::challenges_endpoints::AllTerminals;
use itertools::Itertools;
use twenty_first::shared_math::b_field_element::BFieldElement;
use twenty_first::shared_math::x_field_element::XFieldElement;
use twenty_first::util_types::merkle_tree::PartialAuthenticationPath;
use twenty_first::util_types::proof_stream_typed::ProofStreamError;
use twenty_first::util_types::simple_hasher::{Hashable, Hasher};

use super::table::challenges_endpoints::AllTerminals;

type FriProof<Digest> = Vec<(PartialAuthenticationPath<Digest>, XFieldElement)>;
type AuthenticationStructure<Digest> = Vec<PartialAuthenticationPath<Digest>>;

Expand All @@ -28,7 +29,7 @@ where
RevealedCombinationElements(Vec<XFieldElement>),
FriCodeword(Vec<XFieldElement>),
FriProof(FriProof<H::Digest>),
PaddedHeights(Vec<BFieldElement>),
PaddedHeight(BFieldElement),
}

impl<H: Hasher> ProofItem<H>
Expand Down Expand Up @@ -157,11 +158,11 @@ where
}
}

pub fn as_padded_heights(&self) -> Result<Vec<BFieldElement>, Box<dyn std::error::Error>> {
pub fn as_padded_heights(&self) -> Result<BFieldElement, Box<dyn std::error::Error>> {
match self {
Self::PaddedHeights(padded_heights) => Ok(padded_heights.to_owned()),
Self::PaddedHeight(padded_height) => Ok(padded_height.to_owned()),
_ => Err(ProofStreamError::boxed(
"expected padded table heights, but got something else",
"expected padded table height, but got something else",
)),
}
}
Expand Down Expand Up @@ -218,7 +219,7 @@ where
ProofItem::TransposedExtensionElementVectors(xss) => {
bs_to_ts::<H>(&xss.into_iter().map(|xs| xs_to_bs(&xs)).concat()).into_iter()
}
ProofItem::PaddedHeights(padded_heights) => bs_to_ts::<H>(&padded_heights).into_iter(),
ProofItem::PaddedHeight(padded_height) => bs_to_ts::<H>(&[padded_height]).into_iter(),
}
}
}
Expand Down
195 changes: 95 additions & 100 deletions triton-vm/src/stark.rs

Large diffs are not rendered by default.

151 changes: 49 additions & 102 deletions triton-vm/src/table/base_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use std::ops::Range;
use twenty_first::shared_math::b_field_element::BFieldElement;
use twenty_first::shared_math::mpolynomial::{Degree, MPolynomial};
use twenty_first::shared_math::other::{is_power_of_two, roundup_npo2};
use twenty_first::shared_math::polynomial::Polynomial;
use twenty_first::shared_math::traits::{FiniteField, GetRandomElements};
use twenty_first::shared_math::x_field_element::XFieldElement;
Expand All @@ -17,15 +16,6 @@ pub struct Table<FieldElement: FiniteField> {
/// The width of each `data` row in the extended version of the table
full_width: usize,

/// The number of `data` rows after padding
padded_height: usize,

/// The number of random rows added for each row in the execution trace.
num_trace_randomizers: usize,

/// The generator of the ο-domain, which is used to interpolate the trace data.
omicron: FieldElement,

/// The table data (trace data). Represents every intermediate
matrix: Vec<Vec<FieldElement>>,

Expand All @@ -50,18 +40,12 @@ impl<DataPF: FiniteField> Table<DataPF> {
pub fn new(
base_width: usize,
full_width: usize,
padded_height: usize,
num_trace_randomizers: usize,
omicron: DataPF,
matrix: Vec<Vec<DataPF>>,
name: String,
) -> Self {
Table {
base_width,
full_width,
padded_height,
num_trace_randomizers,
omicron,
matrix,
name,
initial_constraints: None,
Expand All @@ -75,10 +59,6 @@ impl<DataPF: FiniteField> Table<DataPF> {
}
}

fn interpolant_degree(&self) -> Degree {
(self.padded_height + self.num_trace_randomizers - 1) as Degree
}

/// Create a `BaseTable<DataPF>` with the same parameters, but new `matrix` data.
pub fn with_data(&self, matrix: Vec<Vec<DataPF>>) -> Self {
Table {
Expand All @@ -101,22 +81,6 @@ pub trait InheritsFromTable<DataPF: FiniteField> {
self.inherited_table().full_width
}

fn padded_height(&self) -> usize {
self.inherited_table().padded_height
}

fn num_trace_randomizers(&self) -> usize {
self.inherited_table().num_trace_randomizers
}

fn interpolant_degree(&self) -> Degree {
self.inherited_table().interpolant_degree()
}

fn omicron(&self) -> DataPF {
self.inherited_table().omicron
}

fn data(&self) -> &Vec<Vec<DataPF>> {
&self.inherited_table().matrix
}
Expand All @@ -139,16 +103,15 @@ pub trait Extendable: TableLike<BFieldElement> {
Table::new(
self.base_width(),
self.full_width(),
self.padded_height(),
self.num_trace_randomizers(),
self.omicron().lift(),
matrix,
format!("{} with lifted matrix", self.name()),
)
}

fn pad(&mut self) {
while self.data().len() < padded_height(self.data().len()) {
/// Add padding to a table so that its height becomes the same as other tables. Uses
/// table-specific padding via `.get_padding_rows()`, which might specify an insertion index for
/// the padding row(s).
fn pad(&mut self, padded_height: usize) {
while self.data().len() != padded_height {
let (maybe_index, mut rows) = self.get_padding_rows();
match maybe_index {
Some(idx) => {
Expand All @@ -159,7 +122,7 @@ pub trait Extendable: TableLike<BFieldElement> {
None => self.mut_data().append(&mut rows),
}
}
assert_eq!(self.data().len(), padded_height(self.data().len()));
assert_eq!(padded_height, self.data().len());
}

/// Computes the degree bounds of the quotients given the AIR constraints and the interpolant
Expand All @@ -179,51 +142,56 @@ pub trait Extendable: TableLike<BFieldElement> {
fn get_initial_quotient_degree_bounds(
&self,
initial_constraints: &[MPolynomial<XFieldElement>],
interpolant_degree: Degree,
) -> Vec<Degree> {
let interpolant_degree = self.interpolant_degree();
let full_width = self.full_width();
Self::compute_degree_bounds(initial_constraints, interpolant_degree, full_width)
}

fn get_consistency_quotient_degree_bounds(
&self,
consistency_constraints: &[MPolynomial<XFieldElement>],
interpolant_degree: Degree,
) -> Vec<Degree> {
let interpolant_degree = self.interpolant_degree();
let full_width = self.full_width();
Self::compute_degree_bounds(consistency_constraints, interpolant_degree, full_width)
}

fn get_transition_quotient_degree_bounds(
&self,
transition_constraints: &[MPolynomial<XFieldElement>],
interpolant_degree: Degree,
) -> Vec<Degree> {
let interpolant_degree = self.interpolant_degree();
let full_width = self.full_width();
Self::compute_degree_bounds(transition_constraints, interpolant_degree, 2 * full_width)
}

fn get_terminal_quotient_degree_bounds(
&self,
terminal_constraints: &[MPolynomial<XFieldElement>],
interpolant_degree: Degree,
) -> Vec<Degree> {
let interpolant_degree = self.interpolant_degree();
let full_width = self.full_width();
Self::compute_degree_bounds(terminal_constraints, interpolant_degree, full_width)
}

fn extension(
&self,
extended_matrix: Vec<Vec<XFieldElement>>,
interpolant_degree: Degree,
initial_constraints: Vec<MPolynomial<XFieldElement>>,
consistency_constraints: Vec<MPolynomial<XFieldElement>>,
transition_constraints: Vec<MPolynomial<XFieldElement>>,
terminal_constraints: Vec<MPolynomial<XFieldElement>>,
) -> Table<XFieldElement> {
let bqdb = self.get_initial_quotient_degree_bounds(&initial_constraints);
let cqdb = self.get_consistency_quotient_degree_bounds(&consistency_constraints);
let tqdb = self.get_transition_quotient_degree_bounds(&transition_constraints);
let termqdb = self.get_terminal_quotient_degree_bounds(&terminal_constraints);
let bqdb =
self.get_initial_quotient_degree_bounds(&initial_constraints, interpolant_degree);
let cqdb = self
.get_consistency_quotient_degree_bounds(&consistency_constraints, interpolant_degree);
let tqdb =
self.get_transition_quotient_degree_bounds(&transition_constraints, interpolant_degree);
let termqdb =
self.get_terminal_quotient_degree_bounds(&terminal_constraints, interpolant_degree);
let new_table = self.new_from_lifted_matrix(extended_matrix);
Table {
initial_constraints: Some(initial_constraints),
Expand All @@ -239,23 +207,6 @@ pub trait Extendable: TableLike<BFieldElement> {
}
}

pub fn derive_omicron<DataPF: FiniteField>(padded_height: u64) -> DataPF {
debug_assert!(
0 == padded_height || is_power_of_two(padded_height),
"The padded height was: {}",
padded_height
);
DataPF::primitive_root_of_unity(padded_height).unwrap()
}

pub fn padded_height(height: usize) -> usize {
if height == 0 {
0
} else {
roundup_npo2(height as u64) as usize
}
}

fn disjoint_domain<DataPF: FiniteField>(
domain_length: usize,
disjoint_domain: &[DataPF],
Expand All @@ -282,57 +233,59 @@ where
self.inherited_table().name.clone()
}

/// Returns the relation between the FRI domain and the omicron domain
fn unit_distance(&self, omega_order: usize) -> usize {
if self.padded_height() == 0 {
0
} else {
omega_order / self.padded_height()
}
}

fn low_degree_extension(
&self,
fri_domain: &FriDomain<DataPF>,
omicron: DataPF,
padded_height: usize,
num_trace_randomizers: usize,
columns: Range<usize>,
) -> Vec<Vec<DataPF>> {
// FIXME: Table<> supports Vec<[DataPF; WIDTH]>, but FriDomain does not (yet).
self.interpolate_columns(fri_domain.omega, fri_domain.length, columns)
.par_iter()
.map(|polynomial| fri_domain.evaluate(polynomial))
.collect()
self.interpolate_columns(
fri_domain,
omicron,
padded_height,
num_trace_randomizers,
columns,
)
.par_iter()
.map(|polynomial| fri_domain.evaluate(polynomial))
.collect()
}

/// Return the interpolation of columns. The `column_indices` variable
/// must be called with *all* the column indices for this particular table,
/// if it is called with a subset, it *will* fail.
fn interpolate_columns(
&self,
omega: DataPF,
omega_order: usize,
fri_domain: &FriDomain<DataPF>,
omicron: DataPF,
padded_height: usize,
num_trace_randomizers: usize,
columns: Range<usize>,
) -> Vec<Polynomial<DataPF>> {
// FIXME: Inject `rng` instead.
let mut rng = rand::thread_rng();

// Ensure that `matrix` is set and padded before running this function
assert_eq!(
self.padded_height(),
padded_height,
self.data().len(),
"{}: Table data must be padded before interpolation",
self.name()
);

if self.padded_height() == 0 {
if padded_height == 0 {
return vec![Polynomial::zero(); columns.len()];
}

// FIXME: Unfold with multiplication instead of mapping with power.
let omicron_domain = (0..self.padded_height())
.map(|i| self.omicron().mod_pow_u32(i as u32))
let omicron_domain = (0..padded_height)
.map(|i| omicron.mod_pow_u32(i as u32))
.collect_vec();

let num_trace_randomizers = self.num_trace_randomizers();
let num_trace_randomizers = num_trace_randomizers;
let randomizer_domain = disjoint_domain(num_trace_randomizers, &omicron_domain);

let interpolation_domain = vec![omicron_domain, randomizer_domain].concat();
Expand All @@ -353,28 +306,22 @@ where

all_randomized_traces
.par_iter()
.map(|values| {
Polynomial::fast_interpolate(&interpolation_domain, values, &omega, omega_order)
.map(|randomized_trace| {
Polynomial::fast_interpolate(
&interpolation_domain,
randomized_trace,
&fri_domain.omega,
fri_domain.length,
)
})
.collect()
}
}

#[cfg(test)]
mod test_base_table {
use crate::table::base_table::{disjoint_domain, padded_height};
use crate::table::base_table::disjoint_domain;
use twenty_first::shared_math::b_field_element::BFieldElement;
use twenty_first::shared_math::other;

#[test]
fn pad_height_test() {
assert_eq!(0, padded_height(0));
for x in 1..=1025 {
let padded_x = padded_height(x);
assert_eq!(other::roundup_npo2(x as u64) as usize, padded_x);
assert_eq!(padded_x, padded_height(padded_x))
}
}

#[test]
fn disjoint_domain_test() {
Expand Down

0 comments on commit 338efcf

Please sign in to comment.