Rangarajan Posted April 20, 2016 Share Posted April 20, 2016 Very useful function. I have a few questions: 1) Why is it called “motif-map” instead of, say, “sequence-map” or “substitute-sequence”, because what it does is to replace a part of a sequence with another. 2) I expected it to use the “best match” when replacing. In the following case (motif-map '(((0 1 2) (a b c)) ((0 1 2 3) (p q r))) '(0 1 2 3 4 5 6 7 8 9 10 11) :otherwise 'x) => (a b c x x x x x x x x x) I thought it would give (p q r x x x x x x x x x) because (0 1 2 3) is (arguably) a better match than (0 1 2). However, when I did this (motif-map '(((0 1 2 3) (a b c)) ((0 1 2) (p q r))) '(0 1 2 3 4 5 6 7 8 9 10 11) :otherwise 'x) it gave me => (a b c x x x x x x x x) That means it checks from left to right. So, technically, the longest sequence matching can be done by just re-arranging the given sequences in decreasing order of length. Does it make sense to use the “longest” sequence logic? I am not sure. 3) If there are many sequence pairs to work with, does the replacement occur at the top level, or iteratively? For example, in this case: (motif-map '(((0 1 2 3) (a b c)) ((a b c) (p q r)) ((p q) (m n o))) '(0 1 2 3 4 5 6 7 8 9 10 11) :otherwise 'x) I was pleasantly surprised to see this answer: => (m n o r x x x x x x x x) That shows it works on successive replaced result. I like this, but it may be a good idea to take an optional keyword to decide which of the 2 possible behaviors will be applied. In this example, if the replacement only worked at the top level, the result would be: => (a b c x x x x x x x x) Whatever is the behaviour, it is a good idea to document it. - Rangarajan Quote Link to comment Share on other sites More sharing options...
opmo Posted April 20, 2016 Share Posted April 20, 2016 Think about motifs and patterns replacement. the "Motif" name is more musical :-) (motif-map '(((0 1 2) (a b c)) ((0 1 2 3) (p q r))) '(0 1 2 3 4 5 6 7 8 9 10 11) :otherwise 'x) 1st (motif-map '(((0 1 2) (a b c))) '(0 1 2 3 4 5 6 7 8 9 10 11)) => (a b c 3 4 5 6 7 8 9 10 11) 2nd (motif-map '(((0 1 2 3) (p q r))) '(a b c 3 4 5 6 7 8 9 10 11)) => (a b c 3 4 5 6 7 8 9 10 11) and finaly the 'x => (a b c x x x x x x x x x) Yes, it is from the left to right. I will add this to the documentation. Thank you for your suggestions and comments. Quote Link to comment Share on other sites More sharing options...
AM Posted April 20, 2016 Share Posted April 20, 2016 short question (i didn't read the whole documentation)... when i use/work with pattern-matching, i've done it with WILDCARDS ... is there any aspect of that in the motif-map function? or is a "ordinary pattern-matching-function" in OM? like that: pattern to search/replace '(0 1 ? 3) this is musically interesting, because it works with "fuzziness".... regards, andré Stephane Boussuge 1 Quote Link to comment Share on other sites More sharing options...
Rangarajan Posted April 21, 2016 Author Share Posted April 21, 2016 Andre, It doesn't do pattern matching (to the extent I have tested), although that could be a useful scenario. Would you like to post some examples showing how such a feature can be used? Regards, Rangarajan Quote Link to comment Share on other sites More sharing options...
AM Posted April 21, 2016 Share Posted April 21, 2016 dear rangarajan i think the motif-map-function has a PATTERN-MATCH inside, but it "replaces the MATCH", (like in a contextual-rewrite), but perhaps i don't use the name/expression "pattern-match" in a wright/correct way... i'm more composer/musician then programmer :-) here's a very basic example for am SIMPLE/PURE PATTERN MATCH: a rnd-gen-value-list (to show how you could use it), with a PATTERN-MATCH-prog who scans it. the next value - after a complete match - will be changed into a rest... but you also could start a sub-function then who do what ever you want...? (when you change the code) in a concrete project i coded it also in a more complex way - kind of "nontrivial-machines" (as an experiment) -> PATTERNmatch in pitches changes the DURATIONS, PATTERNmatch in durations changes pitches or timbre... and so on... like a "dynamic-interaction-network"... sorry for my bad english... regards andré FUNCTION - FOR A SIMPLE EXAMPLE (defun pattern_cogn (liste pattern) (loop for z in liste with cnt = 0 with pattern_cnt = 0 collect z ;;;check a value - if it's a match -> incf counter when (or (eq (nth cnt pattern) z) (eq '? (nth cnt pattern))) do (incf pattern_cnt) and do (incf cnt) else do (setq cnt (setq pattern_cnt 0)) ;;; if the pattern is MATCHED (=> counter = length pattern) -> the output changes ... for example, the next value will be a rest ;;; = consequence when (eq pattern_cnt (length pattern)) collect (* z -1) and do (setq cnt (setq pattern_cnt 0)))) FUNCTION-EVAL (pattern_cogn (loop repeat 100 collect (1+ (random 5))) ; generates rnd-values -> TO SEARCH IN IT '(4 ? 2)) ; pattern to search (here with wildcard) WHEN PATTERN MATCH THEN NEXT VALUE (* -1) Stephane Boussuge and opmo 2 Quote Link to comment Share on other sites More sharing options...
Rangarajan Posted April 21, 2016 Author Share Posted April 21, 2016 André, You are right, technically I suppose you can call what motif-map does as pattern matching. Often we use the term pattern matching when some wild card or other patterns are present (for example, regular expressions). Thanks for the code; I understand what you are trying to do. Quite interesting. Regards, Rangarajan Quote Link to comment Share on other sites More sharing options...
AM Posted April 21, 2016 Share Posted April 21, 2016 ...technically, such pattern-match-things are - for my opinion - interesting when you write one value after the other (step by step with all paramters parallel), and then check all the time (every gen-cycle) the output on PATTERNS, and when there is a match you can change the gen-rules... data-structure with EVENTS like that... (defstruct event duration pitch velocity rhy reading_rate optional_data) (setf bot-1 (make-event)) ... and in every cycle you could write/GENERATE an EVENT (Excerpt) do (setf bot-1 (make-event :duration data :pitch (setq pitch-1 (nth seq-cnt-1 pitchfield)) :velocity (rnd-walk-in-chord '(1 0 -1) velocityfield velocity) :rhy (rnd-walk-in-chord '(1 -1) rhyfield rhy-1) :reading_rate 1; (rnd-pick'(1 2 3)) :optional_data (rnd-pick '(a b c d e)))) and then you check it (every cycle) for patterns... and if MATCH you could change the GEN-part the GEN-rules ... like a small robot who tries "to move in the world or to recognize the world"... Quote Link to comment Share on other sites More sharing options...
Rangarajan Posted April 21, 2016 Author Share Posted April 21, 2016 Interesting. Looks like you have a small rule-engine in place! I have worked with LispWorks and they have a powerful ops5-like rule engine. Yes, this rule-based approach is desirable/suitable for certain classes of problems. Good luck! Regards, Rangarajan Quote Link to comment Share on other sites More sharing options...
opmo Posted April 23, 2016 Share Posted April 23, 2016 Version 1.1.1.18850 MOTIF-MAP with WILDCARD (?) and section. (setf pitch '((g5 fs5 g5 c5 ds5 g5 fs5 g5 a5 d5) (g5 fs5 g5 a5 c5 d5 ds5 d5 c5 as4) (ds5 d5 ds5 g4 gs4 f5 ds5 f5 a4 as4) (g5 f5 g5 b4 c5 d5 ds5 f5) (ds5 d5 c5 as4 gs4 g4 f4 gs5 g5 f5 ds5) (d5 ds5 f5 b4 c5 d5 b4 c5 g5))) (setf intervals (pitch-to-interval pitch)) => ((-1 1 -7 3 4 -1 1 2 -7) (5 -1 1 2 -9 2 1 -1 -2 -2) (5 -1 1 -8 1 9 -2 2 -8 1) (9 -2 2 -8 1 2 1 2) (-2 -1 -2 -2 -2 -1 -2 15 -1 -2 -2) (-1 1 2 -6 1 2 -3 1 7)) (setf imap '(((-1 ?) 3) ((1 -2) 2) ((1 1) (3 3)))) (setf new-intervals (motif-map imap intervals)) => ((3 -7 3 4 3 2 -7) (5 3 2 -9 2 1 3 -2) (5 3 -8 1 9 -2 2 -8 1) (9 -2 2 -8 1 2 1 2) (-2 3 -2 -2 3 15 3 -2) (3 2 -6 1 2 -3 1 7)) (interval-to-pitch new-intervals :start 'g5) => ((g5 bb5 eb5 fs5 bb5 cs6 eb6 gs5) (cs6 e6 fs6 a5 b5 c6 eb6 cs6) (fs6 a6 cs6 d6 b6 a6 b6 eb6 e6) (cs7 b6 cs7 f6 fs6 gs6 a6 b6) (a6 c7 bb6 gs6 b6 gs5 f5 g5) (e5 d5 gs5 g5 f5 gs5 g5 c5)) (setf imap2 '(((-1 ?) 3) ((1 -2) 2) ((-2 ?) (-4 -4)))) (motif-map imap2 intervals) => ((3 -7 3 4 3 2 -7) (5 3 2 -9 2 1 3 -2) (5 3 -8 1 9 -4 -4 -8 1) (9 -4 -4 -8 1 2 1 2) (-4 -4 -4 -4 3 15 3 -2) (3 2 -6 1 2 -3 1 7)) (motif-map imap2 intervals :otherwise '(13 -11)) => ((3 13 -11 13 3 -11 13) (13 3 -11 13 -11 13 3 -11) (13 3 -11 13 -11 -4 -4 13 -11) (13 -4 -4 -11 13 -11 13 -11) (-4 -4 -4 -4 3 13 3 -11) (3 13 -11 13 -11 13 -11 13)) lviklund 1 Quote Link to comment Share on other sites More sharing options...
Rangarajan Posted April 23, 2016 Author Share Posted April 23, 2016 Great! How come you forgot the other wildcard operators '+' and '*' (just kidding!) Regards, Rangarajan opmo and lviklund 2 Quote Link to comment Share on other sites More sharing options...
opmo Posted October 1, 2016 Share Posted October 1, 2016 MOTIF-MAP function name changed to PATTERN-MAP hujairi 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.