Open In App

What are Retroactive Data Structures?

Last Updated : 08 Mar, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Retroactive Data structures are a type of data structure that supports efficient modifications performed on a data structure, in this new data structuring paradigm, the operations performed on the data structure are not only in present but also in the past which means the operations can be altered and modified even in the pastime interval. 

These data structures give us great comfort in terms of flexibility while working on complex applications that need regular updates as adjusting the structure can be adjusted according to the working model of the program, in the real world there are various cases where there is a need to modify a past operation from a sequence of operations.

Need For Retroactive Data Structures:

  • For Implementing Dynamization: Generally, some algorithms that are in static nature demand a dynamic data structure to process their input and retroactive data structure can be the best solution for making these algorithms dynamic.
  • For performing Approximate Range Searching: Retroactive data structures help in implementing operations that require updates like insert and delete at any point of time and to return the input in an approximate range of time t.
  • To avoid extra O(log n) Overhead: Retroactive data structures help us in avoiding extra O(log n) overhead and enables applications to perform operations such as building a high-degree segment tree over segments, Augmenting root with traditional data structures, Augment nodes with CDFC structures.
  • Altering historical sequence of transactions: Retroactive data structures make the applications efficiently adaptable to conditions such as undo of errors that were previously made without redoing all the work since then.

Comparison With Persistent Data Structures:

Even though the notion of persistent data structures and retroactive data structures may look similar as they take the dimension of time into account, still the way they handle the element of time makes them stand different from each other. 

  • A persistent data structure maintains several versions of data structures and the operation can be implemented on one version of data to create another version.
  • In the case of retroactive data structures, changes are made directly to previous versions and there is no creation of other modified previous versions that were subjected to data change in the past.

Types of Retroactivity:

1. Partially Retroactive: Any data structure can be made partially retroactive by general transformations. For example, the following inserts a partially retroactive list with an initial state [1,2,3,4,5]. We can then add or remove the operation in present.

Below is the Python pseudo-code for the above concept:

# Python program to implement  
# the above approach  
x = PartiallyRetroactive([1, 2, 3, 4, 5])  
def appendOne(lst):
 return lst + [1]

# Three appendOnes by applying  
# insertAgo()
x.insertAgo(appendOne, tminus = 0)
x.insertAgo(appendOne, tminus = 0)
x.insertAgo(appendOne, tminus = 0)
x.query()

# Three appendOnes by applying insertAgo()
[1, 2, 3, 4, 5, 1, 1, 1]   

Output:

>>x.query() :
[1, 2, 3, 4, 5, 1, 1, 1]

We can also add or remove operations from the past:

def MethodForAppendNum(lst):
       return lst + [6]
       
 ## For Inserting into  *two* operations ago
 a.insertAgo(appendSix, tminus=2)   
 a.query()
 [1, 2, 3, 4, 5, 1, 6, 1, 1]
 
 ## For Deleting the first appendOne
 a.deleteAgo(tminus=3)   
 a.query()
 [1, 2, 3, 4, 5, 6, 1, 1]

Output:

>>a.query() :
[1, 2, 3, 4, 5, 1, 6, 1, 1]

2. General Full Retroactivity: Full Retroactive data structures are similar to their siblings Partial Retroactive Data Structures, in that they permit retroactive insertion and deletion of operations. However, fully-retroactive data structures also permit querying into the past instead of just the present.

Below is the Python pseudo-code for the above approach:

b = MethodForFullyRetroactive([1,2,3])
b.insertAgo(appendOne, tminus = 0)
 
## This one should come last
b.insertAgo(appendSix, tminus = 0) 

## This one should come first
b.insertAgo(appendTen, tminus =2)
 
b.query()

## The current state of the data structure
[1, 2, 3, 10, 1, 6]   
b.query(1)
[1, 2, 3, 10, 1]
b.query(2)
[1, 2, 3, 10]
b.query(3)

## The state of the data structure way back
## in the past
[1, 2, 3]   

Output:

>>b.query(1) :
[1, 2, 3, 10, 1, 6]
>>b.query(2) :
[1, 2, 3, 10]
>>b.query(3) :
[1, 2, 3]

Applications: Some applications of retroactive data structures are listed below

  • Recovery: If we have a hardware chip that was damaged and the data on it was lost, but it was now repaired, and we can read data from the sensor, and we want data to be inserted back into the system as if the hardware was never damaged.
  • Error Correction: In case of incorrect input of data, the data must be corrected and the secondary effects of the wrong input must be eliminated.
  • Data Manipulation in pastime intervals: Modifying data in pastime can help in the prevention of damage control in cases where false data has been injected due to system error or manual error.
  • Bad Data: When dealing with entering data in a large system particularly in systems such as sensors in weather network malfunctions which take large amounts of automated data transfer, garbage and incorrect data could cause great damage to applications, the ideal solution will be removing bad data in past operations by using retroactive data structures to create a scenario like if bad data never occurred.

Advantages Of Retroactive Data Structures:

  • Provides us flexibility in correcting time-based updates without the use of cost-effective rollback operations whenever a data crash happens.
  • These data structures can be most effectively applied for searching problems such as maintaining set k of some unknown objects which are subjected to operations like insert, delete, and query(x, s) as here we can have the privilege of modifying the data structure by going back again in time sequence and retrieving our desired query.
  • These data structures help us in solving decomposed search problems like performing queries of the form query(x, AuB) = f(query(x, A), query(x, B)) which runs in O(1) time.
  • They help to dynamize static Algorithms effectively.

Disadvantages of Retroactive Data Structures:

  • These data structures demand high storage and computing resources as they run in higher polynomial times.
  • These data structures work fine on complex applications that thrive solely on time-based updates without proper order based objectives but not recommended on simple and scalable applications that generate strict-rule based timely updates like Employee Attendance Management System, One-Time password generator because implementing this data structure can create bugs for changing and modifying the information.
  • Involves high maintenance costs due to the execution of high polynomial transformations.
  • If the applications implemented with Retroactive data structures were not covered with effective encryption-algorithm standards, then there is a high chance for intentional data manipulation that can not be even traced as there will be no time records available.

Automatic Retroactivity: There comes a natural doubt in our minds about the possibility of converting data structures automatically into retroactive form by using a general technique for example like converting a pointer-machine model into an effective partially retroactive data structure? Such a general technique would nicely complement existing persistence data structures but in the case of retroactive data structures, the retroactivity is fundamentally different from persistence, and generally known techniques do not apply.

One simple approach to this general problem is the rollback method, where auxiliary information is stored as all changes for the data structures are made by each operation in such a way that each change could be reversed dynamically, For example, to enable a rollback for the memory-write operation we store the value that was previously at the address, therefore their performances act differently depending upon the retroactive change.

Retroactive Running Times: Take a number of operations performed by the data structure for determining the running time of retroactive data structures. For example, let m be a number of operations performed on the structure and let r be numbers of operations performed before the retroactive operations, and n be the maximum number of elements present in the structure at any time.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads