progetta un modello per un sistema di variabili dipendenti

3

Ho a che fare con un sistema di modellazione (finanziario) che ha dozzine di variabili. Alcune variabili sono indipendenti e funzionano come input per il sistema; la maggior parte di essi sono calcolati da altre variabili (indipendenti e calcolate) nel sistema.

Quello che sto cercando è un modo pulito ed elegante per:

  1. definisce la funzione di ogni variabile dipendente nel sistema
  2. attiva un nuovo calcolo, ogni volta che cambia una variabile, delle variabili che dipendono da esso

Un modo ingenuo per farlo sarebbe scrivere una singola classe che implementa INotifyPropertyChanged , e usa un'enorme dichiarazione di caso che elenca tutti i nomi delle variabili x1, x2, ... xn da cui dipendono gli altri, e, ogni volta che una variabile xi cambia, attiva un ricalcolo di ciascuna delle dipendenze di quella variabile.

Sento che questo approccio ingenuo è imperfetto e che deve esserci un modo più pulito. Ho iniziato il percorso di definizione di una classe CalculationManager<TModel> , che sarebbe stata utilizzata (in un semplice esempio) come segue:

public class Model : INotifyPropertyChanged
{
    private CalculationManager<Model> _calculationManager = new CalculationManager<Model>(); 

    // each setter triggers a "PropertyChanged" event
    public double? Height { get; set; }
    public double? Weight { get; set; }
    public double? BMI { get; set; }

    public Model()
    {
        _calculationManager.DefineDependency<double?>(
            forProperty: model => model.BMI,
            usingCalculation: (height, weight) => weight / Math.Pow(height, 2),
            withInputs: model => model.Height, model.Weight);
    }

    // INotifyPropertyChanged implementation here
}

Non riprodurrò CalculationManager<TModel> qui, ma l'idea di base è che imposta una mappa delle dipendenze, ascolta gli eventi PropertyChanged e aggiorna le proprietà dipendenti secondo necessità. Sento ancora che mi manca qualcosa di importante qui, e che questo non è l'approccio giusto:

  1. l'uso (errato) di INotifyPropertyChanged mi sembra un odore di codice
  2. il parametro withInputs è definito come params Expression<Func<TModel, T>>[] args , il che significa che l'elenco di argomenti di usingCalculation non è selezionato al momento della compilazione
  3. l'elenco degli argomenti (peso, altezza) è definito in modo ridondante in usingCalculation e withInputs

Sono sicuro che questo tipo di sistema di variabili dipendenti deve essere comune in matematica computazionale, fisica, finanza e altri campi. Qualcuno sa di una serie di idee consolidate che si occupano di ciò che sto afferrando qui? Questa sarebbe un'applicazione adatta per un linguaggio funzionale come F #?

Modifica

Altro contesto:

Il modello esiste attualmente in un foglio di calcolo di Excel e viene migrato in un'applicazione C #. Viene eseguito su richiesta e le variabili possono essere modificate dall'utente dall'interfaccia utente dell'applicazione. Il suo scopo è recuperare le variabili a cui è interessata l'azienda, dati gli input correnti dai mercati e i parametri del modello impostati dall'azienda.

    
posta McGarnagle 26.10.2012 - 19:33
fonte

2 risposte

2

Supponendo che puoi modellare le dipendenze come grafico aciclico diretto , puoi quindi utilizzare un Ordinamento topologico per ordinarli. La mia comprensione è che i fogli di calcolo usano questa idea.

Sembra che F # sarebbe una buona scelta.

    
risposta data 26.10.2012 - 19:37
fonte
1

Un modo più pulito (a seconda del modello di utilizzo) è quello di non memorizzare il valore di BMI. Basta avere un getter che guarda le sue dipendenze e calcola il risultato quando si accede. Questo è molto meglio se gli input sono cambiati molto più di quanto gli output siano letti.

Questo ti lascia ancora con l'aggiornamento dell'interfaccia utente quando cambia lo stato di una proprietà (e / o le sue dipendenze). Per alcune UI un aggiornamento completo andrà bene poiché quasi tutto sta cambiando comunque. In caso contrario, è probabile che tu costruisci il tuo grafico (si spera tramite riflessione o marcatura degli attributi) e firmi gli eventi di cambiamento (spero non a mano ) per l'interfaccia utente. L'ho fatto per un setup simile e funziona davvero bene, anche se non in un ambiente molto mutevole come la modellazione finanziaria.

    
risposta data 26.10.2012 - 21:22
fonte