oat_rust 0.2.0

User-friendly tools for applied topology
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
//! Boundaries of filtered and unfiltered simplices


use crate::algebra::rings::traits::RingOperations;




//  ---------------------------------------------------------------------------
//  BOUNDARY VECTORS
//  ---------------------------------------------------------------------------



//  BOUNDARY VECTOR DESCENDING
//  ---------------------------------------------------------------------------


/// Iterates over the terms of the boundary of a simplex, in descending lexicographic order.
/// 
/// # Examples
/// 
/// ```
/// use oat_rust::topology::simplicial::boundary::SimplexBoundaryDescend;
/// use oat_rust::algebra::rings::types::field_prime_order::PrimeOrderField;
/// 
/// let ring_operator = PrimeOrderField::new(3);
/// let simplex = vec![0,1,2];
/// let boundary = SimplexBoundaryDescend::new( simplex, ring_operator );
/// 
/// itertools::assert_equal( boundary, vec![ (vec![1,2], 1), (vec![0,2], 2), (vec![0,1], 1) ]);
/// ```
pub struct SimplexBoundaryDescend
                < Vertex, RingOperator, >   
    where
        Vertex:         Clone + Ord,
        RingOperator:   RingOperations,
{
    facet_opt:              Option< Vec< Vertex > >, // a facet that will be returned when `.next()` is called
    vertex_removed:         Vertex, // the vertex that has been removed
    removal_locus:          usize,  // the slot from which that vertex has been removed
    coefficient:            RingOperator::Element,
    ring_operator:          RingOperator,
}


impl < Vertex, RingOperator, >
    
    SimplexBoundaryDescend
        < Vertex, RingOperator, >   

    where
        Vertex:         Clone + Ord,
        RingOperator:   RingOperations,
{
    /// Throws an error if `simplex` is an empty vector.
    pub fn new( mut simplex: Vec< Vertex >, ring_operator: RingOperator ) -> Self {

        // each vertex has empty boundary; handle this edge case separately
        if simplex.len() == 1 {
            return SimplexBoundaryDescend
            {
                facet_opt:              None,                               
                vertex_removed:         simplex[0].clone(),      // arbitrary values           
                removal_locus:          1,                       // arbitrary values           
                coefficient:            RingOperator::one(),     // arbitrary values      
                ring_operator,           // arbitrary values
            }                   
        }        

        let removal_locus = 0;
        let coefficient = RingOperator::one();                
        let vertex_removed = simplex.remove( removal_locus );
        simplex.shrink_to_fit();

        SimplexBoundaryDescend
        {
            facet_opt:              Some( simplex ), // a facet that will be returned when `.next()` is called
            vertex_removed, // the vertex that has been removed
            removal_locus,  // the slot from which that vertex has been removed
            coefficient,
            ring_operator,
        }        
    }
}        


//  IMPLEMENT ITERATOR
//  ------------------------------------------

impl < Vertex, RingOperator, >

    Iterator for
    
    SimplexBoundaryDescend
        < Vertex, RingOperator, >   

    where
        Vertex:         Clone + Ord,
        RingOperator:   RingOperations,  
{
    type Item = ( Vec< Vertex >, RingOperator::Element );

    fn next( &mut self ) -> Option< Self::Item > {

        match &mut self.facet_opt{
            Some( facet ) => {
                // make a copy of the term to return, before we update the internal state
                let return_value = (facet.clone(), self.coefficient.clone());  
                
                // if there is another vertex to remove, then remove it
                if self.removal_locus < facet.len() {
                    let new_removed = facet[ self.removal_locus ].clone();                    
                    facet[ self.removal_locus ] = self.vertex_removed.clone();
                    self.removal_locus += 1;
                    self.vertex_removed = new_removed;
                    self.coefficient = self.ring_operator.negate( self.coefficient.clone() );
                } 
                // otherwise mark that we have extracted the last facet
                else {
                    self.facet_opt = None;
                }

                Some( return_value )
            }
            None => { None }
        }
    }
}


// pub struct SimplexBoundaryDescend
//                 < Vertex, RingOperator, >   
//     where
//         Vertex:         Clone + Ord,
//         RingOperator:   Ring,
//         RingElement:    Clone,
// {
//     facet:                  Vec< Vertex >,
//     vertex_removed:         Vertex,
//     prior_removal_locus:    usize,
//     coefficient:            RingOperator::ElementOfRing,
//     ring_operator:          RingOperator,
// }


// impl < Vertex, RingOperator, >

//     Iterator for
    
//     SimplexBoundaryDescend
//         < Vertex, RingOperator, >   

//     where
//         Vertex:         Clone + Ord,
//         RingOperator:   Ring,
//         RingElement:    Clone,        
// {
//     type Item = ( Vec< Vertex >, RingElement );

//     fn next( &mut self ) -> Option< Self::Item > {

//         // if this case the internal state does not hold a valid facet
//         if self.prior_removal_locus > self.facet.len() { return None } 

//         // in this case the internal state holds the last facet; we return this value and do not update the internal state, except to mark that we have already returned the last facet (this is achieved by incrementing `prior_removal_locus`)
//         if self.prior_removal_locus == self.facet.len() { 
            
//             self.prior_removal_locus += 1;

//             return  Some( (self.facet.clone(), self.coefficient.clone()) )
//         } 

//         // in this case the internal state contains the next term of the boundary, and this is not the last term; therefore we will return a term, and update the internal state
        
//         // make a copy of the term we with to return, before updating the internal state
//         let return_value = (self.facet.clone(), self.coefficient.clone());

//         // update the internal state
//         let new_removed = self.facet[ self.prior_removal_locus ].clone(); // save a copy of the vertex we're about to remove
//         self.facet[ self.prior_removal_locus ] = self.vertex_removed.clone(); // place the last vertex that we had removed back into the simplex
//         self.coefficient = self.ring_operator.negate( self.coefficient.clone() ); // switch sign on the coefficient
//         self.prior_removal_locus += 1; // increment the locus of the next removal
//         self.vertex_removed = new_removed; // stash the value of the removed vertex in an internal state

//         return Some( return_value )
//     }
// }



// impl < Vertex, RingOperator, >
    
//     SimplexBoundaryDescend
//         < Vertex, RingOperator, >   

//     where
//         Vertex:         Clone + Ord,
//         RingOperator:   Ring,
//         RingElement:    Clone,  
// {
//     /// Throws an error if `simplex` is an empty vector.
//     pub fn new( mut simplex: Vec< Vertex >, ring_operator: RingOperator ) -> Self {

//         // each vertex has empty boundary; handle this edge case separately
//         if simplex.len() == 1 {
//             return SimplexBoundaryDescend
//             {
//                 facet:                  Vec::with_capacity(0), // a facet that will be returned when `.next()` is called
//                 vertex_removed:         simplex[0].clone(), // the vertex that has been removed
//                 prior_removal_locus:    1,  // the slot from which that vertex has been removed
//                 coefficient:            RingOperator::one(),
//                 ring_operator:          ring_operator,
//             }                   
//         }

//         // now handle simplices of dimension ≥ 1        
//         let removal_locus = 0;
//         let coefficient = RingOperator::one();                
//         let vertex_removed = simplex.remove(0);
//         simplex.shrink_to_fit();

//         SimplexBoundaryDescend
//         {
//             facet:                  simplex, // a facet that will be returned when `.next()` is called
//             vertex_removed:         vertex_removed, // the vertex that has been removed
//             prior_removal_locus:    removal_locus,  // the slot from which that vertex has been removed
//             coefficient:            coefficient,
//             ring_operator:          ring_operator,
//         }               
//     }
// }  





//  BOUNDARY VECTOR ASCENDING
//  ---------------------------------------------------------------------------

/// Iterates of the terms of the boundary of a simplex, in ascending lexicographic order.
/// 
/// # Examples
/// 
/// ```
/// use oat_rust::topology::simplicial::boundary::SimplexBoundaryAscend;
/// use oat_rust::algebra::rings::types::field_prime_order::PrimeOrderField;
/// 
/// let ring_operator = PrimeOrderField::new(3);
/// let simplex = vec![0,1,2];
/// let boundary = SimplexBoundaryAscend::new( simplex, ring_operator );
/// 
/// itertools::assert_equal( boundary, vec![ (vec![0,1], 1), (vec![0,2], 2), (vec![1,2], 1) ]);
/// ```
pub struct SimplexBoundaryAscend
                < Vertex, RingOperator, >   
    where
        Vertex:         Clone + Ord,
        RingOperator:   RingOperations,
{
    facet_opt:              Option< Vec< Vertex > >, // a facet that will be returned when `.next()` is called
    vertex_removed:         Vertex, // the vertex that has been removed
    removal_locus:          usize,  // the slot from which that vertex has been removed
    coefficient:            RingOperator::Element,
    ring_operator:          RingOperator,
}


impl < Vertex, RingOperator, >
    
    SimplexBoundaryAscend
        < Vertex, RingOperator, >   

    where
        Vertex:         Clone + Ord,
        RingOperator:   RingOperations,
{
    /// Throws an error if `simplex` is an empty vector.
    pub fn new( mut simplex: Vec< Vertex >, ring_operator: RingOperator ) -> Self {

        // each vertex has empty boundary; handle this edge case separately
        if simplex.len() == 1 {
            return SimplexBoundaryAscend
            {
                facet_opt:              None, // a facet that will be returned when `.next()` is called
                vertex_removed:         simplex[0].clone(), // the vertex that has been removed
                removal_locus:          1,  // the slot from which that vertex has been removed
                coefficient:            RingOperator::one(),
                ring_operator,
            }                   
        }        

        let removal_locus = simplex.len()-1;
        let coefficient = ring_operator.minus_one_to_power( removal_locus );                
        let vertex_removed = simplex.pop().unwrap();
        simplex.shrink_to_fit();

        SimplexBoundaryAscend
        {
            facet_opt:              Some( simplex ), // a facet that will be returned when `.next()` is called
            vertex_removed, // the vertex that has been removed
            removal_locus,  // the slot from which that vertex has been removed
            coefficient,
            ring_operator,
        }        
    }
}        


//  IMPLEMENT ITERATOR
//  ------------------------------------------

impl < Vertex, RingOperator, >

    Iterator for
    
    SimplexBoundaryAscend
        < Vertex, RingOperator, >   

    where
        Vertex:         Clone + Ord,
        RingOperator:   RingOperations,
{
    type Item = ( Vec< Vertex >, RingOperator::Element );

    fn next( &mut self ) -> Option< Self::Item > {

        match &mut self.facet_opt{
            Some( facet ) => {
                // make a copy of the term to return, before we update the internal state
                let return_value = (facet.clone(), self.coefficient.clone());  
                
                // if there is another vertex to remove, then remove it
                if self.removal_locus > 0 {
                    self.removal_locus -= 1;
                    let new_removed = facet[ self.removal_locus ].clone();
                    facet[ self.removal_locus ] = self.vertex_removed.clone();
                    self.vertex_removed = new_removed;
                    self.coefficient = self.ring_operator.negate( self.coefficient.clone() );
                }
                // otherwise mark that we have returned the last facet
                else {
                    self.facet_opt = None;
                }

                Some( return_value )
            }
            None => { None }
        }

        // match self.next_exchange_locus {
        //     Some( exchange_locus ) => {

        //         // make a copy of the term to return, before we update the internal state
        //         let return_value = (self.facet.clone(), self.coefficient.clone()); 



        //         // update the internal state
        //         let new_removed = self.facet[ self.prior_removal_locus ].clone(); // save a copy of the vertex we're about to remove
        //         self.facet[ self.prior_removal_locus ] = self.vertex_removed; // place the last vertex that we had removed back into the simplex
        //         self.coefficient = self.ring_operator.negate( self.coefficient ); // switch sign on the coefficient
        //         self.prior_removal_locus += 1; // increment the locus of the next removal
        //         self.vertex_removed = new_removed; // stash the value of the removed vertex in an internal state

        //         match exchange_locus == 0 {
                    
        //             true => {
        //                 //return value no update
        //             }
        //             false => {
        //                 // return value and update
        //             }
        //         }
        //     }
        //     None => {
        //         // don't return value
        //     }
        // }


        // // if this case the internal state does not hold a valid facet, because we have already returned the last facet
        // if self.prior_removal_locus > self.facet.len() { return None } 

        // // in this case the internal state holds the last facet; we return this value and do not update the internal state, except to mark that we have already returned the last facet
        // if self.prior_removal_locus == self.facet.len() { 
            
        //     self.prior_removal_locus += 1;

        //     return  Some( (self.facet.clone(), self.coefficient.clone()) )
        // } 

        // // in this case the internal state contains the next term of the boundary, and this is not the last term; therefore we will return a term, and update the internal state
        
        // // make a copy of the term we with to return, before updating the internal state
        // let return_value = (self.facet.clone(), self.coefficient.clone());

        // // update the internal state
        // let new_removed = self.facet[ self.prior_removal_locus ].clone(); // save a copy of the vertex we're about to remove
        // self.facet[ self.prior_removal_locus ] = self.vertex_removed; // place the last vertex that we had removed back into the simplex
        // self.coefficient = self.ring_operator.negate( self.coefficient ); // switch sign on the coefficient
        // self.prior_removal_locus += 1; // increment the locus of the next removal
        // self.vertex_removed = new_removed; // stash the value of the removed vertex in an internal state

        // return Some( return_value )
    }
}



//  ===========================================================================
//  ===========================================================================
//  BOUNDARY MATRIX INDEXED VIA A BIMAP
//  ===========================================================================
//  ===========================================================================