Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Requesting merge of group-related exercises. #15

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
30 changes: 20 additions & 10 deletions dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
bin = [
{ name = "intro1", path = "../exercises/intro/intro1.rs" },
{ name = "intro1_sol", path = "../solutions/intro/intro1.rs" },
{ name = "01_basic_modulo", path = "../exercises/math/01_basic_modulo.md" },
{ name = "01_basic_modulo_sol", path = "../solutions/math/01_basic_modulo.md" },
{ name = "02_negative_modulo", path = "../exercises/math/02_negative_modulo.md" },
{ name = "02_negative_modulo_sol", path = "../solutions/math/02_negative_modulo.md" },
{ name = "03_modular_addition", path = "../exercises/math/03_modular_addition.md" },
{ name = "03_modular_addition_sol", path = "../solutions/math/03_modular_addition.md" },
{ name = "04_modular_subtraction", path = "../exercises/math/04_modular_subtraction.md" },
{ name = "04_modular_subtraction_sol", path = "../solutions/math/04_modular_subtraction.md" },
{ name = "05_negative_subtraction", path = "../exercises/math/05_negative_subtraction.md" },
{ name = "05_negative_subtraction_sol", path = "../solutions/math/05_negative_subtraction.md" },
{ name = "01_basic_modulo", path = "../exercises/finite_fields/00_modulo/01_basic_modulo.rs" },
{ name = "01_basic_modulo_sol", path = "../solutions/finite_fields/00_modulo/01_basic_modulo.rs" },
{ name = "02_negative_modulo", path = "../exercises/finite_fields/00_modulo/02_negative_modulo.rs" },
{ name = "02_negative_modulo_sol", path = "../solutions/finite_fields/00_modulo/02_negative_modulo.rs" },
{ name = "03_modular_addition", path = "../exercises/finite_fields/00_modulo/03_modular_addition.rs" },
{ name = "03_modular_addition_sol", path = "../solutions/finite_fields/00_modulo/03_modular_addition.rs" },
{ name = "04_modular_subtraction", path = "../exercises/finite_fields/00_modulo/04_modular_subtraction.rs" },
{ name = "04_modular_subtraction_sol", path = "../solutions/finite_fields/00_modulo/04_modular_subtraction.rs" },
{ name = "05_negative_subtraction", path = "../exercises/finite_fields/00_modulo/05_negative_subtraction.rs" },
{ name = "05_negative_subtraction_sol", path = "../solutions/finite_fields/00_modulo/05_negative_subtraction.rs" },
{ name = "01_signals", path = "../exercises/circom/01_signals/01_signals.circom" },
{ name = "01_signals_sol", path = "../solutions/circom/01_signals/01_signals.circom" },
{ name = "02_signals", path = "../exercises/circom/01_signals/02_signals.circom" },
Expand All @@ -20,6 +20,16 @@ bin = [
{ name = "01_constraints_sol", path = "../solutions/circom/02_constraints/01_constraints.circom" },
{ name = "01_templates", path = "../exercises/circom/03_templates/01_templates.circom" },
{ name = "01_templates_sol", path = "../solutions/circom/03_templates/01_templates.circom" },
{ name = "01_binary_operations", path = "../exercises/finite_fields/01_sets_and_groups/01_binary_operations.rs" },
{ name = "01_binary_operations_sol", path = "../solutions/finite_fields/01_sets_and_groups/01_binary_operations.rs" },
{ name = "02_identity", path = "../exercises/finite_fields/01_sets_and_groups/02_identity.rs" },
{ name = "02_identity_sol", path = "../solutions/finite_fields/01_sets_and_groups/02_identity.rs" },
{ name = "03_inverse", path = "../exercises/finite_fields/01_sets_and_groups/03_inverse.rs" },
{ name = "03_inverse_sol", path = "../solutions/finite_fields/01_sets_and_groups/03_inverse.rs" },
{ name = "04_associative", path = "../exercises/finite_fields/01_sets_and_groups/04_associative.rs" },
{ name = "04_associative_sol", path = "../solutions/finite_fields/01_sets_and_groups/04_associative.rs" },
{ name = "05_group", path = "../exercises/finite_fields/01_sets_and_groups/05_group.rs" },
{ name = "05_group_sol", path = "../solutions/finite_fields/01_sets_and_groups/05_group.rs" },
{ name = "dlp1", path = "../exercises/zk-protocols-basics/01_discrete_log_problem/dlp1.rs" },
{ name = "dlp1_sol", path = "../solutions/zk-protocols-basics/01_discrete_log_problem/dlp1.rs" },
{ name = "dlp2", path = "../exercises/zk-protocols-basics/01_discrete_log_problem/dlp2.rs" },
Expand Down
18 changes: 18 additions & 0 deletions exercises/finite_fields/00_modulo/01_basic_modulo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Note: The modulo operator differs from the % (i.e. remainder) operator, where modulo always returns a non-negative result.
// In the syntax below, modulo(7, 4) equals to 7 mod 4.

fn main() {
let a: i32 = modulo(7, 4);

// TODO: Determine the result of the modulo operation.
assert_eq!(a, XXX, "Your result is wrong.");
}

// No need to change anything in the code below.
fn modulo(a: i32, m: i32) -> i32 {
let mut result = a % m;
if result < 0 {
result += m;
}
result
}
15 changes: 15 additions & 0 deletions exercises/finite_fields/00_modulo/02_negative_modulo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
fn main() {
let a: i32 = modulo(-9, 5);

// TODO: Determine the result of the modulo operation.
assert_eq!(a, XXX, "Your result is wrong.");
}

// No need to change anything in the code below.
fn modulo(a: i32, m: i32) -> i32 {
let mut result = a % m;
if result < 0 {
result += m;
}
result
}
15 changes: 15 additions & 0 deletions exercises/finite_fields/00_modulo/03_modular_addition.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
fn main() {
let a: i32 = modulo(14 + 27, 10);

// TODO: Determine the result of the modulo operation.
assert_eq!(a, XXX, "Your result is wrong.");
}

// No need to change anything in the code below.
fn modulo(a: i32, m: i32) -> i32 {
let mut result = a % m;
if result < 0 {
result += m;
}
result
}
15 changes: 15 additions & 0 deletions exercises/finite_fields/00_modulo/04_modular_subtraction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
fn main() {
let a: i32 = modulo(27 - 14, 10);

// TODO: Determine the result of the modulo operation.
assert_eq!(a, XXX, "Your result is wrong.");
}

// No need to change anything in the code below.
fn modulo(a: i32, m: i32) -> i32 {
let mut result = a % m;
if result < 0 {
result += m;
}
result
}
15 changes: 15 additions & 0 deletions exercises/finite_fields/00_modulo/05_negative_subtraction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
fn main() {
let a: i32 = modulo(14 - 27, 10);

// TODO: Determine the result of the modulo operation.
assert_eq!(a, XXX, "Your result is wrong.");
}

// No need to change anything in the code below.
fn modulo(a: i32, m: i32) -> i32 {
let mut result = a % m;
if result < 0 {
result += m;
}
result
}
File renamed without changes.
74 changes: 74 additions & 0 deletions exercises/finite_fields/01_sets_and_groups/01_binary_operations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Sets and groups

// A group is the combination of a set and a binary operation.

// What is a binary operation? A binary operation can be understood as a function f (a, b) that applies two elements of the same set S, such that the result will also be an element of the set S.

// Exercise 1: The following are different operations on different sets. Identify the non-binary operations and fix them.

use std::vec::Vec;
use std::any::type_name;
use std::any::Any;

fn main() {
// Set of integers
let _set_integers: Vec<i32> = vec![-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5];

// Set of strings
let _set_strings: Vec<String> = vec![
"apple".to_string(),
"banana".to_string(),
"cherry".to_string(),
"date".to_string(),
];

// Set of floating-point numbers
let _set_floats: Vec<f64> = vec![0.1, 0.2, 0.3, 0.4, 0.5];
}


// TODO: Find the non-binary operations and fix it.
fn add_operation(a: i32, b: f64) -> f64 {
(a as f64) + b
}

fn multiply_operation(a: f64, b: f64) -> f64 {
a * b
}

fn concat_operation(a: &str, b: i32) -> String {
format!("{}{}", a, b)
}

#[cfg(test)]
mod tests {
use super::*;

fn type_of<T: ?Sized + Any>(_: &T) -> String {
type_name::<T>().to_string()
}

#[test]
fn test_add_operation_inputs() {
let a: i32 = 5;
let b: i32 = 3;
assert_eq!(type_of(&a), type_of(&b), "Input types for add_operation should be the same");
add_operation(a, b); // Just to ensure the function is called
}

#[test]
fn test_multiply_operation_inputs() {
let a: f64 = 0.5;
let b: f64 = 0.3;
assert_eq!(type_of(&a), type_of(&b), "Input types for multiply_operation should be the same");
multiply_operation(a, b); // Just to ensure the function is called
}

#[test]
fn test_concat_operation_inputs() {
let a: &str = "hello";
let b: &str = "world";
assert_eq!(type_of(&a), type_of(&b), "Input types for concat_operation should be the same");
concat_operation(&a, &b); // Just to ensure the function is called
}
}
28 changes: 28 additions & 0 deletions exercises/finite_fields/01_sets_and_groups/02_identity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Identity Property: There exists an element e in the group such that for every element a in the group, e * a = a * e = a.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also add for the additive operation as well?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know if we should make more clear that from a set we can make a group for the multiplicative operation and another group for the additive operation

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, let me think about it and we can discuss it tomorrow whenever you are available.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we haven't discussed this, have you thought about it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have been working on basically turning your previous modulo exercises into rust exercises.

I would then combine all exercises under a combined finite_fields folder rather than a math folder (math seems very general). I could also do it the other way around if you prefer.

So in that case the setup would be:

exercises/finite_fields/00_modulo
exercises/finite_fields/01_sets_and_groups
exercises/finite_fields/02_finite_fields

At the same time, I will adjust my exercises briefly to also use mod within the exercises to have a common theme that you also describe in the previous math README.

As for the additive operation, I wil also add it.


// Exercise 1: Find the identity of the following set.

// TODO: replace XXX with the identity element.
const IDENTITY: f32 = XXX;

fn main() {
let set: Vec<f32> = vec![-5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0];
}

fn multiply_operation(a: f32, b: f32) -> f32 {
a * b
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_for_identity() {
let a = 2.0;
let result1 = multiply_operation(a, IDENTITY);
let result2 = multiply_operation(IDENTITY, a);
assert_eq!(result1, a, "Identity element is not correct");
assert_eq!(result2, a, "Identity element is not correct");
}
}
29 changes: 29 additions & 0 deletions exercises/finite_fields/01_sets_and_groups/03_inverse.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Inverse Property: For each element a in the group, there exists an element b in the group such that a * b = b * a = e, where e is the identity element.

// Exercise 1: Find the inverse of the following element.

const IDENTITY: f32 = 1.0;
// TODO: Find the inverse for the rational number 2.
const INVERSE_OF_TWO: f32 = XXX;

fn main() {
let set: Vec<f32> = vec![-5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0];
}

fn multiply_operation(a: f32, b: f32) -> f32 {
a * b
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_for_inverse() {
let a = 2.0;
let result1 = multiply_operation(a, INVERSE_OF_TWO);
let result2 = multiply_operation(INVERSE_OF_TWO, a);
assert_eq!(result1, IDENTITY, "Inverse element is not correct");
assert_eq!(result2, IDENTITY, "Inverse element is not correct");
}
}
18 changes: 18 additions & 0 deletions exercises/finite_fields/01_sets_and_groups/04_associative.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Sets and groups

// Associative Property: For all elements a, b, and c in the group, (a * b) * c = a * (b * c).

// Exercise 1: Prove that the set has the associative property.

fn main() {
let set: Vec<f32> = vec![-5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0];

// TODO: pass the test.
let left_side = multiply_operation(multiply_operation(XXX, XXX), XXX);
let right_side = multiply_operation(XXX, multiply_operation(XXX, XXX));
assert!(left_side == right_side, "associative property doesnt hold");
}

fn multiply_operation(a: f32, b: f32) -> f32 {
a * b
}
45 changes: 45 additions & 0 deletions exercises/finite_fields/01_sets_and_groups/05_group.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Sets and groups

// Exercise 1: Finalise the tests for the identity, inverse and associative properties.

fn main()
{
let set: Vec<f32> = vec![-5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0];
let identity_element = 1.0;
test_for_identity(set[0], identity_element);
test_for_inverse(set[0], identity_element, identity_element / set[0]);
test_for_associative(set[0], set[1], set[2]);
}

fn multiply_operation(a: f32, b: f32) -> f32 {
a * b
}

fn test_for_identity(a: f32, identity: f32) -> bool {
// TODO: Check for the identity property

}

fn test_for_inverse(a: f32, identity: f32, inverse: f32) -> bool {
// TODO: Check for the inverse property

}

fn test_for_associative(a: f32, b: f32, c: f32) -> bool {
// TODO: Check for the associative property

}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_checkers() {
let set: Vec<f32> = vec![-5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0];
let identity_element = 1.0;
assert_eq!(test_for_identity(set[0], identity_element), true, "Identity element is not correct");
assert_eq!(test_for_inverse(set[0], identity_element, (identity_element / set[0])), true, "Inverse element is not correct");
assert_eq!(test_for_associative(set[0], set[1], set[2]), true, "Associative property does not hold");
}
}
20 changes: 20 additions & 0 deletions exercises/finite_fields/01_sets_and_groups/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## Groups and Their Relevance to Finite Fields

**Groups** are fundamental algebraic structures that consist of a set equipped with a binary operation satisfying certain axioms. Understanding groups is essential for grasping the properties of finite fields, which are pivotal in cryptography and zero-knowledge proofs.

### Why Groups Matter

In the context of finite fields, groups help us understand how elements interact under specific operations. This understanding is crucial for constructing cryptographic algorithms and protocols that rely on the predictable behavior of these operations.

### Group Axioms

The exercises in this chapter focus on the following group axioms:

- **Closure**: For any two elements in the set, the result of the operation is also in the set.
- **Identity**: There exists an element in the set that, when used in the operation with any other element, leaves the other element unchanged.
- **Inverse**: For each element in the set, there exists another element that, when used in the operation, results in the identity element.
- **Associativity**: The way in which elements are grouped in the operation does not affect the result.

These properties are explored through various exercises to build a solid foundation in understanding how groups function within finite fields.

By mastering these concepts, you'll gain valuable insights into the mathematical structures that underpin many cryptographic systems.
5 changes: 5 additions & 0 deletions exercises/finite_fields/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Finite Fields

**Finite fields** are a core element of cryptography and crucial when working with zero knowledge proofs. The goal within this chapter is to develop an intuition of the properties of a finite fiels and why they are important.

We will start by looking at groups, which are the building blocks of finite fields.
9 changes: 0 additions & 9 deletions exercises/math/01_basic_modulo.md

This file was deleted.

9 changes: 0 additions & 9 deletions exercises/math/02_negative_modulo.md

This file was deleted.

9 changes: 0 additions & 9 deletions exercises/math/03_modular_addition.md

This file was deleted.

Loading